def save_to_file(title, result): """Save results to either h5 file (if DataFrame), otherwise to npy file.""" from src.utils.file_io import create_dir create_dir("results", timestamp=False) path = os.path.join('results', title) if type(result) is list: np.save(path + '.npy', result) elif type(result) is pd.DataFrame: result.to_hdf(path, 'table') else: raise RuntimeError(f"saving failed for {result}") logger.info("saved")
def run_NEURON(exc_weight=1, inh_weight=1, timestamp=False, **kwargs): """ Run NEURON simulations where the number of inhibitory and excitatory synapses are varied independently. Note that results are added to a txt file, so repeated calls will only run values not present in the file already. To force a re-rerun, set timestamp=True :param exc_weight: The weighting of the synapses. If `None`, `check_synapse_strengths` is called :type exc_weight: int or None :param inh_weight: The weighting of the synapses. If `None`, `check_synapse_strengths` is called :type inh_weight: int or None :param timestamp: Include a timestamp in output file (forces re-run). :type timestamp: bool :param kwargs: Further keyword arguments to be passed to the sub-method `check_num_synapses` - exc_weight, inh_weight - exc_syn_list, inh_syn_list - exc_freq, inh_freq - exc_noise, inh_noise - num_runs=5 - max_num_runs=15 - upper_bound=15 - break_bound=True :return: List of full-path file names for analysis. :rtype: list[str] """ from neuron import h date = datetime.strftime(datetime.now(), '%Y-%m-%d_%Hh%M') # get output from NEURON (save to file for quicker re-analysis) if settings.NEURON_GUI: h.showV() h.showRunControl() create_dir(FOLDER_NAME, timestamp=False) try: h.hoc_stdout(os.path.join(FOLDER_NAME, f"hoc_stdout_{date}.txt")) except RuntimeError: pass files = [] for synapse_type in ["distal_KCC2", "proximal_KCC2"]: if timestamp: f_name = os.path.join(FOLDER_NAME, f"{synapse_type}_{date}.txt") else: f_name = os.path.join(FOLDER_NAME, f"{synapse_type}.txt") if not os.path.exists(f_name): with open(f_name, 'w') as _f: _f.write(date) logger.info("="*20 + f_name + "="*20) with open(f_name, 'r+') as f: if exc_weight is None: exc_weight, inh_weight = check_synapse_strengths(f) logger.info(f"best weights = E:{exc_weight}, I:{inh_weight}") check_num_synapses(f, synapse_type, exc_weight, inh_weight, **kwargs) files.append(f_name) return files
import os import time from matplotlib import pyplot as plt from src.utils.file_io import create_dir shared.INIT_NEURON() # fix python only using one core # (https://stackoverflow.com/questions/15639779/why-does-multiprocessing-use-only-a-single-core-after-i-import-numpy) os.system("taskset -p 0xff %d" % os.getpid()) fig_time = time.strftime('%Y_%m_%d_%Hh%Mm') is_menu = 0 save_location = "results_plots/" create_dir(save_location) # noinspection PyArgumentEqualDefault def iotime( file_name="distal", ifr_windowsize=0.02, time_points=None, synapse_type=1, # 1 for persistent synapse_numbers=(100, 100), exc_input=None, inh_input=None, diam=None, trials=5, save=True): from src.iocurves.sim import show_menu
def run_protocol(protocol, root=None, run_using_python=True, record_output=True, timestamp=True, **kwargs): """ run a test file or method :param protocol: the protocol to run :param root: name to give the run (optional) :param run_using_python: option for test to be processed using python or command line NEURON (default True) :param record_output: option to record output or not (default True) :param timestamp: include a timestamp for output directory :param kwargs: keyword arguments to be passed to test method if it is a python method """ global switched_output # Create dir to_path = create_dir(root=root, timestamp=timestamp) date = datetime.strftime(datetime.now(), '%Y-%m-%d_%Hh%M') hoc_output = 'hoc_output_{}.txt'.format(date) print("directory: {} created".format(to_path)) # Filter files included_extenstions = ['hoc', 'mod', 'py', 'm', 'txt', 'dll'] src = 'src/' if os.path.exists('src') else '' file_names = [] for ext in included_extenstions: file_names += glob.glob(f"{src}hoc_files/**/*.{ext}", recursive=True) # Copy files for file_name in file_names: copy_file(file_name, to_path) print("files copied") # Change directory, stop if error with cd(to_path): print("changed directory\nusing environment:") try: if run_using_python: print('Python + NEURON') print("----------------------------------------------------------------------------------------") # load neuron standard run environment (not needed if 'from neuron import gui' used) h.load_file('stdrun.hoc') if record_output and not switched_output: # to see output, open the file in an editor that can view files as they update (e.g. Sublime Text) h.hoc_stdout(hoc_output) switched_output = True if isinstance(protocol, str): # protocol is a hoc file print("running protocol:{}".format(protocol)) h.load_file(protocol) else: print("running protocol:{}".format(protocol.__name__)) result = start(protocol, **kwargs) h.hoc_stdout() # reset output else: print("running protocol:{}".format(protocol)) if platform.system() == 'Windows': print('Windows NEURON') cmds = ["c:\\nrn\\bin\\nrniv"] else: print('Unix NEURON') cmds = ["nrniv"] cmds.append(protocol) # Record shell/terminal output (best method for large output) if record_output: logging.basicConfig(filename=hoc_output) # set logging to output to file import tempfile import subprocess # no realtime output # Sub_TODO: fix using http://www.cyberciti.biz/faq/python-run-external-command-and-get-output/ with tempfile.TemporaryFile() as tempf: proc = subprocess.Popen(cmds, stdout=tempf, stderr=tempf) proc.wait() tempf.seek(0) logger.info(tempf.read()) else: os.system(" ".join(cmds)) print("----------------------------------------------------------------------------------------") print("finished running NEURON") except Exception as e: print("Exception occured: {}".format(e)) finally: # Exclude specific files from being zipped and deleted: file_names.remove('config.hoc') # Zip files (not data files, log files or dlls) # data (dat) and log (txt) files created AFTER file_names list was generated with zipfile.ZipFile('files.zip', 'w', zipfile.ZIP_DEFLATED) as zip_name: for file_name in file_names: # exclude files from being zipped if not file_name.endswith('dll'): zip_name.write(file_name) print("code files zipped...") # Clean up for file_name in file_names: os.remove(file_name) print("and removed") print("done with python script") return to_path
ss_port = int(config.get("ServiceServer", "ss_port")) ss_debug = bool(config.get("ServiceServer", "ss_debug")) dc_ip = config.get("DataCollectorServer", "dc_ip") dc_port = config.get("DataCollectorServer", "dc_port") app = Flask(__name__) app.config['SECRET_KEY'] = "A0Zr98j/3yX R~XHH!jmN]LWX/,?RT" app.config["SQLALCHEMY_DATABASE_URI"] = f'mysql+pymysql://{db_id}:{db_pw}@{db_ip}:{db_port}/{db_name}' app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True db = SQLAlchemy(app) create_dir(stored_notice_board_file_path) create_dir(stored_free_board_file_path) create_dir(stored_archive_board_file_path) @app.route("/") def index(): return "Welcome iPLAT service server" app.register_blueprint(construct_user_blueprint(db)) # User app.register_blueprint(construct_device_blueprint(db)) # Device app.register_blueprint(construct_sensor_blueprint(db)) # Sensor app.register_blueprint(construct_data_blueprint(db, stored_data_path)) # Data app.register_blueprint(construct_free_board_blueprint(db, stored_free_board_file_path)) # Free Board app.register_blueprint(construct_notice_board_blueprint(db, stored_notice_board_file_path)) # Notice Board app.register_blueprint(construct_archive_blueprint(db, stored_archive_board_file_path)) # Archive
def figure_v_traces(inh_region="distal", KCC2=True, show_cli=False, base=True, synapse_type=0, synapse_numbers=(100, 100), hz=None, mean=False, savefig=False, **kwargs): """ Display voltage traces for an inhibitory input region (e.g. "distal") and (E, I) synapse pairs. Optionally include an axis for [Cl-]i. :param inh_region: Region for inhibitory synapses. Only those in hoc_files/cells/ are supported. :type inh_region: str :param KCC2: Open the '_KCC2' version of the hoc file instead if True. :type KCC2: bool :param show_cli: Include a plot for [Cl-]i. Only applicable when KCC2 is True. :type show_cli: bool :param base: Find steady-state values for vm and cli (`True`), provide the steady-state values (`(<vm value>, <cli value>)`), use defaults of -71 mV and 4.25 mM for vm and cli, respectively(`False`). :type base: bool or tuple of float :param synapse_type: Use frequency-based synapses (`0`) or persistant synapses (`1`). :type synapse_type: int :param synapse_numbers: Synapses numbers for the neuron in (E, I) format. A list of (E,I) pairs can be provided for multiple traces. :type synapse_numbers: list of (tuple of (int)) or tuple of int :param hz: Frequency of synapses (if `synapse_type` is `0`) or the relative conductance (if `synapse_type` is `1`). :type hz: dict :param mean: Additionally plot the mean vm and cli values using `plot_v_trace` :type mean: bool :param savefig: Save the figure to results_plots :type savefig: bool :param kwargs: Keyword arguments to pass to `get_trace` :type kwargs: dict :return: Steady-state voltage and [Cl-]i used for this simulation :rtype: """ if hz is None: hz = {'in': 5, 'ex': 5} logger.info( f"figure_v_traces(inh_region={inh_region} KCC2={KCC2}, synapse_numbers={synapse_numbers}, hz={hz})" ) cmap_name = "Blues" if inh_region == "distal" else "Greens" cmap = sns.color_palette(cmap_name, n_colors=len(synapse_numbers)) if mean: cmap = None filename = inh_region if KCC2: filename += "_KCC2" else: show_cli = False logger.info("getting base vm cli") if base: if type(base) is tuple: vm, cli = base else: vm, cli = get_base_vm_cli(f"{inh_region}_KCC2", load=True) else: vm, cli = -71., 4.25 if type(synapse_numbers) is tuple: synapse_numbers = [synapse_numbers] dynamic_data = [] spikes = [] for syn_num in synapse_numbers: trace_kwargs = dict(synapse_type=synapse_type, synapse_numbers=syn_num, hz=hz, space_plot=False, **kwargs) dynamic_data.append(get_trace(filename, vm=vm, cli=cli, **trace_kwargs)) spikes.append(h.apc.n) logger.info("plotting voltage") fig, ax = plot_v_trace(*dynamic_data, show_cli=show_cli, cmap=cmap, mean=mean) if not mean: for i, (spike_num, syn_num) in enumerate(zip(spikes, synapse_numbers)): ax[i, 0].text(ax[i, 0].get_xlim()[1], 0, f"{spike_num:.0f}", ha="left") ax[i, 0].set_title(str(syn_num).replace("(", "").replace(")", ""), fontsize='small', va='top') title = filename + str(hz) title = title.replace("{", "\n(").replace("}", ")").replace("'", "").replace(": ", "=") if synapse_type == 0: title = title.replace(",", " Hz,").replace(")", " Hz)") fig.suptitle(title, fontsize='medium') fig.align_ylabels(ax[:, 0]) sns.despine(fig, bottom=True, left=True) for _ax in ax[:-1, 0]: _ax.xaxis.set_visible(False) _ax.yaxis.set_visible(False) sns.despine(ax=ax[-1, 0]) fig.subplots_adjust(left=0.15, bottom=0.15) if savefig: create_dir("results_plots") fig.savefig(f"results_plots/figure_trace_{title}.png", bbox_inches='tight', facecolor='None') fig.savefig(f"results_plots/figure_trace_{title}.pdf", bbox_inches='tight', facecolor='None') return vm, cli
def figure_cli_heatmaps(distal, proximal, freqs=(5, 10, 25, 50), n_trials=1, show_fr=False, vmin=0, vmax=None, savefig=False): """ Heatmaps of [Cl-]i for different frequencies and (E,I) synapse pairs and for both proximal and distal. :param distal: List (E,I) synapse number pairs for distal input. :type distal: list of (tuple of (float)) :param proximal: List (E,I) synapse number pairs for proximal input. :type proximal: list of (tuple of (float)) :param freqs: :type freqs: list of Number or tuple of Number :param n_trials: Nomber of repeated runs. :type n_trials: int :param show_fr: Show the firing rate to the right of the heatmaps when plotting. True shows the firing rate as an arrow and text. Any value greater than 1 shows the firing rate as a heatmap cell (different colormap) :type show_fr: bool or int :param vmin: Minimum [Cl-]i for color range. :type vmin: float :param vmax: Maximum [Cl-]i for color range. :type vmax: float :param savefig: Whether to save the figure to results_plots :type savefig: bool """ logger.info(f"figure_cli_heatmaps(distal={distal}, proximal={proximal}, " f"n_trials={n_trials}, show_fr={show_fr})") fig, ax2d = plt.subplots(nrows=2, ncols=len(distal) + 1 + int(show_fr > 1), figsize=(8, 5), gridspec_kw={ 'width_ratios': [15] * len(distal) + [2] * (1 + int(show_fr > 1)) }) cmap = sns.cubehelix_palette(16, start=2.7, rot=-.2, light=0.98, dark=0.40, as_cmap=True) cmap_fr = sns.color_palette("Reds" if show_fr > 1 else "magma", n_colors=200, desat=1) vmax_fr = 5 # h.hoc_stdout("hoc_output_traces.txt") for fdx, (filename, synapse_numbers) in enumerate( zip(["distal_KCC2", "proximal_KCC2"], [distal, proximal])): ax = ax2d[fdx, :] cbar_ax = ax[-1 - int(show_fr > 1)] vm, cli = get_base_vm_cli(filename, load=True) d_cli = {} fr = {} stddev = {} for i, syn_n in enumerate(synapse_numbers): kwargs = dict(synapse_type=0, synapse_numbers=syn_n, space_plot=True) for hz in freqs: n_spikes = [] sec_means = [0, 0, 0, 0] # 4 sections [ldend, bdend, soma, axon] for t in range(n_trials): logger.info( f"filename={filename} syn_n={syn_n} hz={hz} t={t}") _, _, _, data = get_trace(filename, vm=vm, cli=cli, hz={ 'in': hz, 'ex': hz }, **kwargs) n_spikes.append(h.apc.n) x, y = space_from_dict(data) # separate x into regions based on known lengths ldend = x <= -50 bdend = np.logical_and(-50 <= x, x <= 0) soma = np.logical_and(0 <= x, x <= 15) axon = x >= 15 for s, sec in enumerate([ldend, bdend, soma, axon]): sec_means[s] += y[sec].mean() sec_means = [m / n_trials for m in sec_means] d_cli[(f"{syn_n[0]:>3.0f}:{syn_n[1]:>3.0f}", hz)] = sec_means fr[(f"{syn_n[0]:>3.0f}:{syn_n[1]:>3.0f}", hz)] = sum(n_spikes) / n_trials stddev[(f"{syn_n[0]:>3.0f}:{syn_n[1]:>3.0f}", hz)] = np.std(n_spikes) df = pd.DataFrame.from_dict( d_cli, orient='index', columns=["Distal\nDendrite", "Proximal\nDendrite", "Soma", "Axon"]) df_fr = pd.DataFrame.from_dict(fr, orient='index', columns=["Output"]) df = df.reindex(pd.MultiIndex.from_tuples(df.index)) df_fr = df_fr.reindex(pd.MultiIndex.from_tuples(df_fr.index)) vmin = vmin or df.values.min() vmax = vmax or df.values.max() vmin_fr = 0 vmax_fr = max( vmax_fr, df_fr.values.max()) * 1.1 # give a 10% buffer for the cmap logger.info("plotting cli_heatmaps") for i, syn_n in enumerate(df.index.levels[0]): df_syn = df.loc[syn_n] df_fr_syn = df_fr.loc[syn_n] sns.heatmap( df_syn, ax=ax[i], annot=False, fmt=".1f", square=True, annot_kws=dict(fontsize='xx-small'), vmin=vmin, vmax=vmax, cmap=cmap, cbar=(i == 0), cbar_ax=None if i > 0 else cbar_ax, ) if show_fr > 1: new_df = pd.concat([df_syn, df_fr_syn], axis='columns') mask = np.ones(df_syn.shape) mask = np.append(mask, np.zeros(df_fr_syn.shape), axis=1) cbar_fr_ax = ax[-1] sns.heatmap( new_df, ax=ax[i], annot=True, fmt=".1f", square=False, annot_kws=dict(fontsize='xx-small'), vmin=vmin_fr, vmax=vmax_fr, cmap=cmap_fr, mask=mask, cbar=(i == 0), cbar_ax=cbar_fr_ax, cbar_kws={'label': "Firing rate (Hz)"}, ) elif show_fr: for j, _fr in enumerate(df_fr_syn['Output']): idx = (len(cmap_fr) - 1) * (_fr - vmin_fr) // (vmax_fr - vmin_fr) c = cmap_fr[int(idx)] text = ax[i].annotate(f"{_fr:>2.1f}", xy=(4, j + 0.5), xytext=(4.6, j + 0.5), color=c, alpha=1, arrowprops={'arrowstyle': '<-'}, fontsize='x-small', va='center') # path effects can sometimes make text clearer, but it can also make things worse... # text.set_path_effects([path_effects.Stroke(linewidth=0.5, foreground='black', alpha=0.5), # path_effects.Normal()]) ax[i].set_xticklabels(ax[i].get_xticklabels(), fontsize="small", rotation=45) ax[i].set_title(syn_n, fontsize='small') if i == 0: ax[i].set(ylabel='Balanced Input (Hz)') ax[i].set_yticklabels(df_syn.index, rotation=0) else: ax[i].set_yticklabels([]) if i == 0: cbar_ax.set_xlabel(f'{settings.CLI} (mM)', ha='center') cbar_ax.xaxis.set_label_position('top') fig.tight_layout() if savefig: create_dir("results_plots", timestamp=False) fig.savefig(f"results_plots/figure_cli_heatmaps_{int(show_fr)}.png", bbox_inches='tight', facecolor='None') fig.savefig(f"results_plots/figure_cli_heatmaps_{int(show_fr)}.pdf", bbox_inches='tight', facecolor='None')
def figure_cli_distribution( syn_n_dist=(250, 300), syn_n_prox=(330, 90), savefig=False): """ Plot the distribution of [Cl-]i along a neuron for distal and proximal inhibitory input. :param syn_n_dist: Number of (E, I) synapses for the distal input simulation. :type syn_n_dist: tuple :param syn_n_prox: Number of (E, I) synapses for the proximal input simulation. :type syn_n_prox: tuple :param savefig: Whether to save the figure to results_plots. :type savefig: bool """ txt = f"figure_cli_distribution(syn_n_dist={syn_n_dist}, syn_n_prox={syn_n_prox})" logger.info(txt) fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(8, 3.5), sharey=True, sharex=True) fig.subplots_adjust(hspace=0.5) for filename, syn_n, _ax in zip(['distal_KCC2', 'proximal_KCC2'], [syn_n_dist, syn_n_prox], ax): # steady state vm and [Cl-]i vm, cli = get_base_vm_cli(filename, load=True) trace_kwargs = dict( synapse_type=0, # frequency-based synapse_numbers=syn_n, # (E,I) space_plot=True) # compute spatial component for cli # run simulations for different frequencies _, _, _, inh = get_trace(filename, vm=vm, cli=cli, hz={ 'in': 5, 'ex': 0 }, **trace_kwargs) _, _, _, exc = get_trace(filename, vm=vm, cli=cli, hz={ 'in': 0, 'ex': 5 }, **trace_kwargs) _, _, _, equal = get_trace(filename, vm=vm, cli=cli, hz={ 'in': 5, 'ex': 5 }, **trace_kwargs) logger.info(f"space plot {filename}") space_plot(exc, ax=_ax, color=COLOR.E, label='5 : 0') space_plot(inh, ax=_ax, color=COLOR.I, label='0 : 5') space_plot(equal, ax=_ax, color=COLOR.E_I, label='5 : 5') # display some info on figure name = filename.split("_")[0].capitalize() _ax.set_title( f"{name} input (E: I) (# of synapses)\n" f"{syn_n[0]}:{syn_n[1]:>3.0f}", va='top', fontsize='medium') # light adjustments ax[0].set_xlabel("") # ax[0].set_xticklabels([]) ax[0].set_xlim(-550, 500) # 0 is soma(0) ax[-1].legend(title='Input (E : I) (Hz)', loc='upper right', frameon=False) if savefig: create_dir("results_plots", timestamp=False) fig.savefig(f"results_plots/{txt}.png", bbox_inches='tight', frameon=False) fig.savefig(f"results_plots/{txt}.pdf", bbox_inches='tight', frameon=False)