├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── biophys_optimize ├── __init__.py ├── cell.hoc ├── check_fi_shift.py ├── compare_optimization_results.py ├── consolidate_passive_fits.py ├── environment.py ├── fit_styles │ ├── f12_fit_style.json │ ├── f12_noapic_fit_style.json │ ├── f13_fit_style.json │ ├── f13_noapic_fit_style.json │ ├── f6_fit_style.json │ ├── f6_noapic_fit_style.json │ ├── f9_fit_style.json │ └── f9_noapic_fit_style.json ├── model_selection.py ├── modfiles │ ├── CaDynamics.mod │ ├── Ca_HVA.mod │ ├── Ca_LVA.mod │ ├── Ih.mod │ ├── Im.mod │ ├── Im_v2.mod │ ├── K_P.mod │ ├── K_T.mod │ ├── Kd.mod │ ├── KdT.mod │ ├── Kv2like.mod │ ├── Kv3_1.mod │ ├── Kv3_1T.mod │ ├── NaTa.mod │ ├── NaTs.mod │ ├── NaV.mod │ ├── NaV2.mod │ ├── Nap.mod │ └── SK.mod ├── neuron_parallel.py ├── neuron_passive_fit.py ├── optimize.py ├── passive │ ├── circuit.ses │ ├── fixnseg.hoc │ ├── iclamp.ses │ ├── mrf.ses │ ├── mrf.ses.fd1 │ ├── mrf.ses.ft1 │ ├── mrf2.ses │ ├── mrf2.ses.fd1 │ ├── mrf2.ses.ft1 │ ├── mrf3.ses │ ├── mrf3.ses.fd1 │ ├── mrf3.ses.ft1 │ ├── mrf_fixcm.ses.ft1 │ ├── params.hoc │ ├── pyr_params.hoc │ └── setup.hoc ├── population_selection.py ├── preprocess.py ├── scripts │ ├── __init__.py │ ├── hack_consolidate_passive_strategy.py │ ├── hack_optimize_input.py │ ├── hack_population_selection_input.py │ ├── hack_preprocess_input.py │ ├── hack_preprocess_to_passive_strategy.py │ ├── run_consolidate_passive_fitting.py │ ├── run_model_selection.py │ ├── run_optimize.py │ ├── run_passive_fitting.py │ ├── run_population_selection.py │ ├── run_preprocessing.py │ ├── run_python_cluster.sh │ └── run_python_mpi_cluster.sh ├── step_analysis.py ├── sweep_functions.py ├── tests │ └── test_preprocess.py └── utils.py ├── config └── minimum_feature_standard_deviations.yaml.example ├── docs ├── Makefile ├── conf.py ├── getting_started.rst ├── index.rst ├── make.bat └── source │ └── reference │ ├── index.rst │ ├── optimize.rst │ ├── passive.rst │ ├── preprocess.rst │ └── scripts.rst ├── requirements.txt ├── setup.py ├── test_input_files ├── test_compare_input.json ├── test_consolidate_input.json ├── test_optimize_input.json ├── test_passive_input.json ├── test_passive_input_1.json ├── test_passive_input_2.json ├── test_passive_input_elec.json ├── test_population_input.json ├── test_population_selection_input.json ├── test_preprocess_input.json └── test_select_input.json └── test_storage ├── passive_fit_1_results.json ├── passive_info.json └── preprocess_results.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.csv 3 | *.png 4 | *.yaml 5 | build/ 6 | dist/ 7 | biophys_optimize.egg-info 8 | __pycache__ 9 | x86_64/ 10 | docs/_build/ 11 | docs/source/reference/generated/* -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Allen Institute Contribution Agreement 2 | 3 | This document describes the terms under which you may make “Contributions” — 4 | which may include without limitation, software additions, revisions, bug fixes, configuration changes, 5 | documentation, or any other materials — to any of the projects owned or managed by the Allen Institute. 6 | If you have questions about these terms, please contact us at terms@alleninstitute.org. 7 | 8 | You certify that: 9 | 10 | * Your Contributions are either: 11 | 12 | 1. Created in whole or in part by you and you have the right to submit them under the designated license 13 | (described below); or 14 | 2. Based upon previous work that, to the best of your knowledge, is covered under an appropriate 15 | open source license and you have the right under that license to submit that work with modifications, 16 | whether created in whole or in part by you, under the designated license; or 17 | 18 | 3. Provided directly to you by some other person who certified (1) or (2) and you have not modified them. 19 | 20 | * You are granting your Contributions to the Allen Institute under the terms of the [2-Clause BSD license](https://opensource.org/licenses/BSD-2-Clause) 21 | (the “designated license”). 22 | 23 | * You understand and agree that the Allen Institute projects and your Contributions are public and that 24 | a record of the Contributions (including all metadata and personal information you submit with them) is 25 | maintained indefinitely and may be redistributed consistent with the Allen Institute’s mission and the 26 | 2-Clause BSD license. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Allen Institute Software License – This software license is the 2-clause BSD license 2 | plus a third clause that prohibits redistribution for commercial purposes without further permission. 3 | 4 | Copyright © 2017. Allen Institute. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 10 | following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 13 | following disclaimer in the documentation and/or other materials provided with the distribution. 14 | 15 | 3. Redistributions for commercial purposes are not permitted without the Allen Institute’s written permission. 16 | For purposes of this license, commercial purposes is the incorporation of the Allen Institute's software into 17 | anything for which you will charge fees or other compensation. Contact terms@alleninstitute.org for commercial 18 | licensing opportunities. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 21 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 26 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # biophys_optimize 2 | Optimization of single-cell biophysically detailed models 3 | 4 | ## NWB1 and NWB2 data files 5 | 6 | We are transitioning from supporting electrophysiology data files in the NWB1 format to the NWB2 format. 7 | [New data](https://portal.brain-map.org/explore/classes/multimodal-characterization) has been released 8 | to the DANDI archive in the newer NWB2 format. We have released IPFX v1.0 to support that data format, which is available on PyPI. 9 | 10 | However, the data files in the [Allen Cell Types Database](http://celltypes.brain-map.org) are still in NWB1 format at this time. IPFX 1.0 does not 11 | support NWB1 files. Therefore, to work with those older files, you must install an earlier version of IPFX, which is not available on PyPI (v.1.0 was the first 12 | IPFX version to be deployed via PyPI). 13 | 14 | This version of `biphys_optimize` is intended to work with the Allen Cell Types Database NWB1 files. We are updating `biophys_optimize` to work with NWB2 and IPFX v1.0 15 | in a [new branch](https://github.com/AllenInstitute/biophys_optimize/tree/ipfx_1.0_changes). Eventually, this will be the main branch for biophys_optimize as well; we 16 | plan to make that switch when the files for the cells in the Allen Cell Types Database are available in NWB2 format. 17 | 18 | 19 | ## Installation 20 | 21 | You will need the [IPFX](https://github.com/alleninstitute/ipfx) package to perform feature extraction in this package. Specifically, you will need an older version of IPFX that supports NWB1 files, which is not available via PyPI. 22 | 23 | If you do not yet have the IPFX repository cloned, do the following: 24 | ```bash 25 | $ git clone --branch=nwb1-support https://github.com/AllenInstitute/ipfx.git 26 | $ cd ipfx 27 | $ pip install -e . 28 | ``` 29 | 30 | If you already have a local IPFX repository, do the following in that repository to switch to an earlier version with NWB1 support: 31 | ```bash 32 | $ git checkout tags/nwb1-support -b nwb1-support 33 | ``` 34 | 35 | In either case, you can then install `biophys_optimize` by: 36 | ```bash 37 | $ git clone https://github.com/AllenInstitute/biophys_optimize.git 38 | $ cd biophys_optimize 39 | $ pip install -e . 40 | ``` 41 | 42 | 43 | ## 1) Pre-process 44 | 45 | Run: 46 | ```bash 47 | $ python -m biophys_optimize.scripts.run_preprocessing --help 48 | ``` 49 | to get command line options. There are a handful of JSON files for examples in test_input_files. 50 | 51 | ###a) Download data using AllenSDK and edit JSON file 52 | Follow the Jupyter Notebook at https://github.com/latimerb/GeneralTutorials/blob/master/AllenSDK/cell_types.ipynb to download electrophysiology and SWC data. The specimen ID needs to be added to the test_input_files/test_preprocess_input.json file and you need to update the paths to the data. The sweep IDs are unique for each specimen so you may need to look these up. 53 | 54 | ### b) Run test_preprocessing.py 55 | ```bash 56 | $ python -m biophys_optimize.scripts.run_preprocessing --input_json ./test_input_files/test_preprocess_input.json 57 | ``` 58 | ## 2) Passive fitting 59 | 60 | ### a) Edit the passive JSON file 61 | Change all the paths in the /test_input_files/test_passive_input.json file just as in step 1a. Other parameters should still be the same. Then run: 62 | ```bash 63 | $ python -m biophys_optimize.scripts.run_passive_fitting --input_json ./test_input_files/test_passive_input_1.json 64 | ``` 65 | -------------------------------------------------------------------------------- /biophys_optimize/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.0" 2 | -------------------------------------------------------------------------------- /biophys_optimize/cell.hoc: -------------------------------------------------------------------------------- 1 | begintemplate cell 2 | 3 | public init 4 | public soma, dend, apic, axon 5 | public all, somatic, basal, apical, axonal, dendritic, somatic_axonal 6 | 7 | objref all, somatic, basal, apical, axonal, dendritic, somatic_axonal 8 | objref this 9 | 10 | proc init() {localobj nl, import 11 | all = new SectionList() 12 | somatic = new SectionList() 13 | basal = new SectionList() 14 | apical = new SectionList() 15 | axonal = new SectionList() 16 | dendritic = new SectionList() 17 | somatic_axonal = new SectionList() 18 | forall delete_section() 19 | } 20 | 21 | proc simplify_axon() { 22 | forsec axonal { delete_section() } 23 | create axon[2] 24 | forsec "axon" { 25 | all.append() 26 | axonal.append() 27 | somatic_axonal.append() 28 | } 29 | } 30 | 31 | create soma[1] 32 | create dend[1] 33 | create apic[1] 34 | create axon[1] 35 | 36 | endtemplate cell -------------------------------------------------------------------------------- /biophys_optimize/check_fi_shift.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from collections import Counter 3 | 4 | from biophys_optimize import sweep_functions as sf 5 | from .step_analysis import StepAnalysis 6 | 7 | 8 | def fi_curve(sweep_set, start, end): 9 | """ Estimate the f-I curve from a set of sweeps 10 | 11 | Parameters 12 | ---------- 13 | sweep_set: SweepSet 14 | start: float 15 | Start time of stimulus interval 16 | end: float 17 | End time of stimulus interval 18 | 19 | Returns 20 | ------- 21 | amps: array 22 | rates: array 23 | """ 24 | step_analysis = StepAnalysis(start, end) 25 | step_analysis.analyze(sweep_set) 26 | sweep_features = step_analysis.sweep_features() 27 | 28 | amps = sweep_features["stim_amp"].values 29 | rates = sweep_features["avg_rate"].values 30 | sorter = np.argsort(amps) 31 | return amps[sorter], rates[sorter] 32 | 33 | 34 | def fi_shift(c1_amps, c1_rates, c2_amps, c2_rates): 35 | """Estimate the shift between two f-I curves 36 | 37 | Parameters 38 | ---------- 39 | c1_amps: array 40 | Stimulus amplitudes of first set of sweeps 41 | 42 | c1_rates: array 43 | Firing rates of first set of sweeps 44 | 45 | c2_amps: array 46 | Stimulus amplitudes of second set of sweeps 47 | 48 | c2_rates: array 49 | Firing rates of second set of sweeps 50 | 51 | Returns 52 | ------- 53 | amp_shift: float 54 | Estimated shift of f-I curve along amplitude axis 55 | """ 56 | # Linear fit to original fI curve 57 | if np.all(c1_rates == 0): 58 | # First f-I curve is all zero, so can't figure out shift 59 | return np.nan 60 | if np.all(c2_rates == 0): 61 | # Second f-I curve is all zero, so can't figure out shift 62 | return np.nan 63 | 64 | # Fit f-I curve slope including largest-amplitude subthreshold point 65 | last_zero_index = np.flatnonzero(c1_rates)[0] - 1 66 | A = np.vstack([c1_amps[last_zero_index:], 67 | np.ones_like(c1_amps[last_zero_index:])]).T 68 | m, c = np.linalg.lstsq(A, c1_rates[last_zero_index:], rcond=None)[0] 69 | 70 | # Relative error of later traces to best-fit line 71 | mask = c2_fi_rates > 0 # Can't assess zero firing rate points 72 | amp_shift = c2_amps[mask] - (c2_rates[mask] - c) / m 73 | return amp_shift.mean() 74 | 75 | 76 | def estimate_fi_shift(core_1_lsq, core_1_start, core_1_end, 77 | core_2_lsq, core_2_start, core_2_end): 78 | """Estimate the amount the f-I curve shifted between Core 1 and Core 2 sweeps 79 | 80 | Parameters 81 | ---------- 82 | core_1_lsq: SweepSet 83 | "Core 1" long-square sweeps (1 second long stimulus, no repeats expected) 84 | core_1_start: float 85 | Start time of stimulus interval for Core 1 sweeps 86 | core_1_end: float 87 | End time of stimulus interval for Core 1 sweeps 88 | core_2_lsq: SweepSet 89 | "Core 2" long-square sweeps (2 seconds long stimulus, repeats expected) 90 | core_2_start: float 91 | Start time of stimulus interval for Core 2 sweeps 92 | core_2_end: float 93 | End time of stimulus interval for Core 2 sweeps 94 | 95 | Returns 96 | ------- 97 | amp_shift: float 98 | Estimated f-I shift between Core 2 and Core 1 sweeps 99 | """ 100 | 101 | # Calculate f-I curves using same duration for both types of sweeps 102 | c1_dur = core_1_end - core_1_start 103 | c2_dur = core_2_end - core_2_start 104 | common_dur = min(c1_dur, c2_dur) 105 | 106 | c1_fi_amps, c1_fi_rates = fi_curve(core_1_lsq, core_1_start, core_1_start + common_dur) 107 | c2_fi_amps, c2_fi_rates = fi_curve(core_2_lsq, core_2_start, core_2_start + common_dur) 108 | 109 | return fi_shift(c1_fi_amps, c1_fi_rates, c2_fi_amps, c2_fi_rates) 110 | 111 | -------------------------------------------------------------------------------- /biophys_optimize/compare_optimization_results.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import numpy as np 5 | import json 6 | 7 | 8 | def main(input_file, output_file): 9 | with open(input_file, "r") as f: 10 | input = json.load(f) 11 | 12 | fit_types = input["fit_types"] 13 | 14 | best_pop = {} 15 | best_file = "" 16 | for fit_type in fit_types: 17 | best_pop[fit_type] = {} 18 | best_error = 1e12 19 | for seed_results in input["paths"][fit_type]: 20 | hof_fit_file = seed_results["hof_fit"] 21 | hof_fit = np.loadtxt(hof_fit_file) 22 | best_for_seed = np.min(hof_fit) 23 | if best_for_seed < best_error: 24 | best_file = seed_results["hof"] 25 | best_error = best_for_seed 26 | best_pop[fit_type]["best"] = best_file 27 | 28 | output = { 29 | "paths": best_pop 30 | } 31 | with open(output_file, "w") as f: 32 | json.dump(output, f, indent=2) 33 | 34 | 35 | if __name__ == "__main__": 36 | parser = argparse.ArgumentParser(description='Start a DEAP optimization run.') 37 | parser.add_argument('input', type=str) 38 | parser.add_argument('output', type=str) 39 | args = parser.parse_args() 40 | 41 | main(args.input, args.output) 42 | -------------------------------------------------------------------------------- /biophys_optimize/consolidate_passive_fits.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import argparse 5 | import logging 6 | import os.path 7 | 8 | 9 | logging.basicConfig(level=logging.DEBUG) 10 | logger = logging.getLogger(__name__) 11 | 12 | 13 | def compare_runs(fit_1, fit_2, fit_3, is_spiny): 14 | """ Choose a particular fitting outcome by comparing the results of three options 15 | 16 | Generally, the fit with the lowest error is used, but the fit without an electrode (`fit_1`) 17 | could be used even if the absolute error is higher if the cm results are within 10% of 18 | the fit with an electrode modeled (`fit_3`). 19 | 20 | If the neuron is spiny (`is_spiny` == True), then the calculation assumes that the soma has 21 | a Cm = 1 uF/cm2 and that the dendrites have an effectively higher Cm (due to the 22 | presence of dendritic spines, which are not explicitly modeled) 23 | 24 | Parameters 25 | ---------- 26 | fit_1, fit_2, fit_3 : :class:`PassiveFitResults` 27 | Passive fitting results from a fit of all three passive parameters (`fit_1`), 28 | a fit witih a fixed Ra = 100 Ohm-cm (`fit_2`), and a fit with a simulated 29 | electrode (`fit_3`) 30 | is_spiny : bool 31 | Whether the neuron has dendritic spines (and a correspondingly higher effective Cm 32 | in the dendrites) 33 | 34 | Returns 35 | ------- 36 | ra : float 37 | Axial resistivity 38 | cm1 : float 39 | Specific membrane capacitance of somatic / axonal compartments. Set to 1.0 if 40 | `is_spiny` is True. 41 | cm2 : float 42 | Effective specific membrane capacitance of dendritic compartments. If `is_spiny` is 43 | false, `cm1` will equal `cm2`. 44 | """ 45 | # Check for various fitting outcomes and pick best results 46 | cm_rel_delta = (fit_1.cm - fit_3.cm) / fit_1.cm 47 | if fit_2.err < fit_1.err: 48 | logger.info("Fixed Ri gave better results than original") 49 | if fit_2.err < fit_3.err: 50 | logger.info("Using fixed Ri results") 51 | fit_for_next_step = fit_2 52 | else: 53 | logger.info("Using electrode results") 54 | fit_for_next_step = fit_3 55 | elif abs(cm_rel_delta) > 0.1: 56 | logger.info("Original and electrode fits not in agreement") 57 | logger.debug("original Cm: %g", fit_1.cm) 58 | logger.debug("w/ electrode Cm: %g", fit_3.cm) 59 | if fit_1.err < fit_3.err: 60 | logger.info("Original has lower error") 61 | fit_for_next_step = fit_1 62 | else: 63 | logger.info("Electrode has lower error") 64 | fit_for_next_step = fit_3 65 | else: 66 | fit_for_next_step = fit_1 67 | 68 | ra = fit_for_next_step.ra 69 | if is_spiny: 70 | combo_cm = fit_for_next_step.cm 71 | a1 = fit_for_next_step.a1 72 | a2 = fit_for_next_step.a2 73 | cm1 = 1.0 74 | cm2 = (combo_cm * (a1 + a2) - a1) / a2 75 | else: 76 | cm1 = fit_for_next_step.cm 77 | cm2 = fit_for_next_step.cm 78 | 79 | return ra, cm1, cm2 80 | 81 | 82 | -------------------------------------------------------------------------------- /biophys_optimize/environment.py: -------------------------------------------------------------------------------- 1 | from builtins import object 2 | import logging 3 | from neuron import h 4 | 5 | 6 | class NeuronEnvironment(object): 7 | """ Class to configure cell-independent NEURON parameters 8 | 9 | Parameters 10 | ---------- 11 | hoc_files_to_load : list 12 | List of HOC files for NEURON to load 13 | mod_library_path : str 14 | Path to compiled .mod file library 15 | 16 | Attributes 17 | ---------- 18 | h : NEURON simulation object 19 | """ 20 | 21 | _log = logging.getLogger(__name__) 22 | 23 | def __init__(self, hoc_files_to_load, mod_library_path): 24 | self.h = h 25 | if mod_library_path: 26 | self.h.nrn_load_dll(mod_library_path.encode('ascii', 'ignore')) 27 | for file in hoc_files_to_load: 28 | self.h.load_file(file.encode('ascii', 'ignore')) 29 | 30 | def activate_variable_time_step(self): 31 | """ Toggle on variable time step integration""" 32 | self.h.cvode_active(1) 33 | self.h.cvode.atolscale("cai", 1e-4) 34 | self.h.cvode.maxstep(10) 35 | 36 | def deactivate_variable_time_step(self): 37 | """ Toggle off variable time step integration""" 38 | self.h.cvode_active(0) 39 | 40 | def set_temperature(self, celsius_temperature): 41 | """ Set temperature of simulation (in degC)""" 42 | self.h.celsius = celsius_temperature 43 | -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f12_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f12", 3 | "check_depol_block": false, 4 | "features": [ 5 | "avg_rate", 6 | "peak_v", 7 | "fast_trough_v", 8 | "slow_trough_delta_v", 9 | "slow_trough_norm_t", 10 | "v_baseline", 11 | "width" 12 | ], 13 | "channels": [ 14 | { "mechanism": "Ih", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 15 | { "mechanism": "NaV", "section": "soma", "parameter": "gbar", "min": 0, "max": 15 }, 16 | { "mechanism": "Kd", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 17 | { "mechanism": "Kv2like", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 18 | { "mechanism": "Kv3_1", "section": "soma", "parameter": "gbar", "min": 0, "max": 3.0 }, 19 | { "mechanism": "K_T", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 20 | { "mechanism": "Im_v2", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 21 | { "mechanism": "SK", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 22 | { "mechanism": "Ca_HVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-3 }, 23 | { "mechanism": "Ca_LVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-2 } 24 | ], 25 | "addl_params": [ 26 | { "parameter": "gamma", "section": "soma", "mechanism": "CaDynamics", "min": 1e-7, "max": 0.05 }, 27 | { "parameter": "decay", "section": "soma", "mechanism": "CaDynamics", "min":20, "max": 1000 }, 28 | { "parameter": "g_pas", "section": "soma", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 29 | { "parameter": "g_pas", "section": "axon", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 30 | { "parameter": "g_pas", "section": "dend", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 31 | { "parameter": "g_pas", "section": "apic", "mechanism": "", "min": 1e-7, "max": 1e-3 } 32 | ], 33 | "conditions": { 34 | "celsius": 34.0, 35 | "erev": [{ 36 | "ena": 53.0, 37 | "section": "soma", 38 | "ek": -107.0 39 | }], 40 | "v_init": -80 41 | } 42 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f12_noapic_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f12", 3 | "check_depol_block": false, 4 | "features": [ 5 | "avg_rate", 6 | "peak_v", 7 | "fast_trough_v", 8 | "slow_trough_delta_v", 9 | "slow_trough_norm_t", 10 | "v_baseline", 11 | "width" 12 | ], 13 | "channels": [ 14 | { "mechanism": "Ih", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 15 | { "mechanism": "NaV", "section": "soma", "parameter": "gbar", "min": 0, "max": 15 }, 16 | { "mechanism": "Kd", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 17 | { "mechanism": "Kv2like", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 18 | { "mechanism": "Kv3_1", "section": "soma", "parameter": "gbar", "min": 0, "max": 3.0 }, 19 | { "mechanism": "K_T", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 20 | { "mechanism": "Im_v2", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 21 | { "mechanism": "SK", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 22 | { "mechanism": "Ca_HVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-3}, 23 | { "mechanism": "Ca_LVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-2 } 24 | ], 25 | "addl_params": [ 26 | { "parameter": "gamma", "section": "soma", "mechanism": "CaDynamics", "min": 1e-7, "max": 0.05 }, 27 | { "parameter": "decay", "section": "soma", "mechanism": "CaDynamics", "min":20, "max": 1000 }, 28 | { "parameter": "g_pas", "section": "soma", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 29 | { "parameter": "g_pas", "section": "axon", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 30 | { "parameter": "g_pas", "section": "dend", "mechanism": "", "min": 1e-7, "max": 1e-3 } 31 | ], 32 | "conditions": { 33 | "celsius": 34.0, 34 | "erev": [{ 35 | "ena": 53.0, 36 | "section": "soma", 37 | "ek": -107.0 38 | }], 39 | "v_init": -80 40 | } 41 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f13_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f13", 3 | "check_depol_block": true, 4 | "features": [ 5 | "avg_rate", 6 | "peak_v", 7 | "fast_trough_v", 8 | "slow_trough_delta_v", 9 | "slow_trough_norm_t", 10 | "v_baseline", 11 | "width", 12 | "adapt", 13 | "latency", 14 | "isi_cv", 15 | "mean_isi", 16 | "first_isi" 17 | ], 18 | "channels": [ 19 | { "mechanism": "Ih", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 20 | { "mechanism": "NaV", "section": "soma", "parameter": "gbar", "min": 0, "max": 15 }, 21 | { "mechanism": "Kd", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 22 | { "mechanism": "Kv2like", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 23 | { "mechanism": "Kv3_1", "section": "soma", "parameter": "gbar", "min": 0, "max": 3.0 }, 24 | { "mechanism": "K_T", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 25 | { "mechanism": "Im_v2", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 26 | { "mechanism": "SK", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 27 | { "mechanism": "Ca_HVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-3 }, 28 | { "mechanism": "Ca_LVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-2 } 29 | ], 30 | "addl_params": [ 31 | { "parameter": "gamma", "section": "soma", "mechanism": "CaDynamics", "min": 1e-7, "max": 0.05 }, 32 | { "parameter": "decay", "section": "soma", "mechanism": "CaDynamics", "min":20, "max": 1000 }, 33 | { "parameter": "g_pas", "section": "soma", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 34 | { "parameter": "g_pas", "section": "axon", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 35 | { "parameter": "g_pas", "section": "dend", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 36 | { "parameter": "g_pas", "section": "apic", "mechanism": "", "min": 1e-7, "max": 1e-3 } 37 | ], 38 | "conditions": { 39 | "celsius": 34.0, 40 | "erev": [{ 41 | "ena": 53.0, 42 | "section": "soma", 43 | "ek": -107.0 44 | }], 45 | "v_init": -80 46 | } 47 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f13_noapic_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f13", 3 | "check_depol_block": true, 4 | "features": [ 5 | "avg_rate", 6 | "peak_v", 7 | "fast_trough_v", 8 | "slow_trough_delta_v", 9 | "slow_trough_norm_t", 10 | "v_baseline", 11 | "width", 12 | "adapt", 13 | "latency", 14 | "isi_cv", 15 | "mean_isi", 16 | "first_isi" 17 | ], 18 | "channels": [ 19 | { "mechanism": "Ih", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 20 | { "mechanism": "NaV", "section": "soma", "parameter": "gbar", "min": 0, "max": 15 }, 21 | { "mechanism": "Kd", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 22 | { "mechanism": "Kv2like", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 23 | { "mechanism": "Kv3_1", "section": "soma", "parameter": "gbar", "min": 0, "max": 3.0 }, 24 | { "mechanism": "K_T", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 25 | { "mechanism": "Im_v2", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-1 }, 26 | { "mechanism": "SK", "section": "soma", "parameter": "gbar", "min": 0, "max": 1.0 }, 27 | { "mechanism": "Ca_HVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-3 }, 28 | { "mechanism": "Ca_LVA", "section": "soma", "parameter": "gbar", "min": 0, "max": 1e-2 } 29 | ], 30 | "addl_params": [ 31 | { "parameter": "gamma", "section": "soma", "mechanism": "CaDynamics", "min": 1e-7, "max": 0.05 }, 32 | { "parameter": "decay", "section": "soma", "mechanism": "CaDynamics", "min":20, "max": 1000 }, 33 | { "parameter": "g_pas", "section": "soma", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 34 | { "parameter": "g_pas", "section": "axon", "mechanism": "", "min": 1e-7, "max": 1e-3 }, 35 | { "parameter": "g_pas", "section": "dend", "mechanism": "", "min": 1e-7, "max": 1e-3 } 36 | ], 37 | "conditions": { 38 | "celsius": 34.0, 39 | "erev": [{ 40 | "ena": 53.0, 41 | "section": "soma", 42 | "ek": -107.0 43 | }], 44 | "v_init": -80 45 | } 46 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f6_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f6", 3 | "check_depol_block": false, 4 | "channels": [ 5 | { 6 | "max": 0.1, 7 | "section": "soma", 8 | "parameter": "gbar", 9 | "mechanism": "Im", 10 | "min": 0 11 | }, 12 | { 13 | "max": 0.1, 14 | "section": "soma", 15 | "parameter": "gbar", 16 | "mechanism": "Ih", 17 | "min": 0 18 | }, 19 | { 20 | "max": 15, 21 | "section": "soma", 22 | "parameter": "gbar", 23 | "mechanism": "NaTs", 24 | "min": 0 25 | }, 26 | { 27 | "max": 0.1, 28 | "section": "soma", 29 | "parameter": "gbar", 30 | "mechanism": "Nap", 31 | "min": 0 32 | }, 33 | { 34 | "max": 1.0, 35 | "section": "soma", 36 | "parameter": "gbar", 37 | "mechanism": "K_P", 38 | "min": 0 39 | }, 40 | { 41 | "max": 1.0, 42 | "section": "soma", 43 | "parameter": "gbar", 44 | "mechanism": "K_T", 45 | "min": 0 46 | }, 47 | { 48 | "max": 1.0, 49 | "section": "soma", 50 | "parameter": "gbar", 51 | "mechanism": "SK", 52 | "min": 0 53 | }, 54 | { 55 | "max": 3.0, 56 | "section": "soma", 57 | "parameter": "gbar", 58 | "mechanism": "Kv3_1", 59 | "min": 0 60 | }, 61 | { 62 | "max": 0.001, 63 | "section": "soma", 64 | "parameter": "gbar", 65 | "mechanism": "Ca_HVA", 66 | "min": 0 67 | }, 68 | { 69 | "max": 0.01, 70 | "section": "soma", 71 | "parameter": "gbar", 72 | "mechanism": "Ca_LVA", 73 | "min": 0 74 | } 75 | ], 76 | "features": [ 77 | "avg_rate", 78 | "peak_v", 79 | "fast_trough_v", 80 | "slow_trough_delta_v", 81 | "slow_trough_norm_t", 82 | "v_baseline", 83 | "width" 84 | ], 85 | "addl_params": [ 86 | { 87 | "max": 0.05, 88 | "section": "soma", 89 | "parameter": "gamma", 90 | "mechanism": "CaDynamics", 91 | "min": 0 92 | }, 93 | { 94 | "max": 1000, 95 | "section": "soma", 96 | "parameter": "decay", 97 | "mechanism": "CaDynamics", 98 | "min": 20 99 | }, 100 | { 101 | "max": 0.001, 102 | "section": "soma", 103 | "parameter": "g_pas", 104 | "mechanism": "", 105 | "min": 1e-07 106 | }, 107 | { 108 | "max": 0.001, 109 | "section": "axon", 110 | "parameter": "g_pas", 111 | "mechanism": "", 112 | "min": 1e-07 113 | }, 114 | { 115 | "max": 0.001, 116 | "section": "dend", 117 | "parameter": "g_pas", 118 | "mechanism": "", 119 | "min": 1e-07 120 | }, 121 | { 122 | "max": 0.001, 123 | "section": "apic", 124 | "parameter": "g_pas", 125 | "mechanism": "", 126 | "min": 1e-07 127 | } 128 | ], 129 | "conditions": { 130 | "celsius": 34.0, 131 | "erev": [{ 132 | "ena": 53.0, 133 | "section": "soma", 134 | "ek": -107.0 135 | }], 136 | "v_init": -80 137 | } 138 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f6_noapic_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f6", 3 | "check_depol_block": false, 4 | "channels": [ 5 | { 6 | "max": 0.1, 7 | "section": "soma", 8 | "parameter": "gbar", 9 | "mechanism": "Im", 10 | "min": 0 11 | }, 12 | { 13 | "max": 0.1, 14 | "section": "soma", 15 | "parameter": "gbar", 16 | "mechanism": "Ih", 17 | "min": 0 18 | }, 19 | { 20 | "max": 15, 21 | "section": "soma", 22 | "parameter": "gbar", 23 | "mechanism": "NaTs", 24 | "min": 0 25 | }, 26 | { 27 | "max": 0.1, 28 | "section": "soma", 29 | "parameter": "gbar", 30 | "mechanism": "Nap", 31 | "min": 0 32 | }, 33 | { 34 | "max": 1.0, 35 | "section": "soma", 36 | "parameter": "gbar", 37 | "mechanism": "K_P", 38 | "min": 0 39 | }, 40 | { 41 | "max": 1.0, 42 | "section": "soma", 43 | "parameter": "gbar", 44 | "mechanism": "K_T", 45 | "min": 0 46 | }, 47 | { 48 | "max": 1.0, 49 | "section": "soma", 50 | "parameter": "gbar", 51 | "mechanism": "SK", 52 | "min": 0 53 | }, 54 | { 55 | "max": 3.0, 56 | "section": "soma", 57 | "parameter": "gbar", 58 | "mechanism": "Kv3_1", 59 | "min": 0 60 | }, 61 | { 62 | "max": 0.001, 63 | "section": "soma", 64 | "parameter": "gbar", 65 | "mechanism": "Ca_HVA", 66 | "min": 0 67 | }, 68 | { 69 | "max": 0.01, 70 | "section": "soma", 71 | "parameter": "gbar", 72 | "mechanism": "Ca_LVA", 73 | "min": 0 74 | } 75 | ], 76 | "features": [ 77 | "avg_rate", 78 | "peak_v", 79 | "fast_trough_v", 80 | "slow_trough_delta_v", 81 | "slow_trough_norm_t", 82 | "v_baseline", 83 | "width" 84 | ], 85 | "addl_params": [ 86 | { 87 | "max": 0.05, 88 | "section": "soma", 89 | "parameter": "gamma", 90 | "mechanism": "CaDynamics", 91 | "min": 0 92 | }, 93 | { 94 | "max": 1000, 95 | "section": "soma", 96 | "parameter": "decay", 97 | "mechanism": "CaDynamics", 98 | "min": 20 99 | }, 100 | { 101 | "max": 0.001, 102 | "section": "soma", 103 | "parameter": "g_pas", 104 | "mechanism": "", 105 | "min": 1e-07 106 | }, 107 | { 108 | "max": 0.001, 109 | "section": "axon", 110 | "parameter": "g_pas", 111 | "mechanism": "", 112 | "min": 1e-07 113 | }, 114 | { 115 | "max": 0.001, 116 | "section": "dend", 117 | "parameter": "g_pas", 118 | "mechanism": "", 119 | "min": 1e-07 120 | } 121 | ], 122 | "conditions": { 123 | "celsius": 34.0, 124 | "erev": [{ 125 | "ena": 53.0, 126 | "section": "soma", 127 | "ek": -107.0 128 | }], 129 | "v_init": -80 130 | } 131 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f9_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f9", 3 | "check_depol_block": true, 4 | "channels": [ 5 | { 6 | "max": 0.1, 7 | "section": "soma", 8 | "parameter": "gbar", 9 | "mechanism": "Im", 10 | "min": 0 11 | }, 12 | { 13 | "max": 0.1, 14 | "section": "soma", 15 | "parameter": "gbar", 16 | "mechanism": "Ih", 17 | "min": 0 18 | }, 19 | { 20 | "max": 15, 21 | "section": "soma", 22 | "parameter": "gbar", 23 | "mechanism": "NaTs", 24 | "min": 0 25 | }, 26 | { 27 | "max": 0.1, 28 | "section": "soma", 29 | "parameter": "gbar", 30 | "mechanism": "Nap", 31 | "min": 0 32 | }, 33 | { 34 | "max": 1.0, 35 | "section": "soma", 36 | "parameter": "gbar", 37 | "mechanism": "K_P", 38 | "min": 0 39 | }, 40 | { 41 | "max": 1.0, 42 | "section": "soma", 43 | "parameter": "gbar", 44 | "mechanism": "K_T", 45 | "min": 0 46 | }, 47 | { 48 | "max": 1.0, 49 | "section": "soma", 50 | "parameter": "gbar", 51 | "mechanism": "SK", 52 | "min": 0 53 | }, 54 | { 55 | "max": 3.0, 56 | "section": "soma", 57 | "parameter": "gbar", 58 | "mechanism": "Kv3_1", 59 | "min": 0 60 | }, 61 | { 62 | "max": 0.001, 63 | "section": "soma", 64 | "parameter": "gbar", 65 | "mechanism": "Ca_HVA", 66 | "min": 0 67 | }, 68 | { 69 | "max": 0.01, 70 | "section": "soma", 71 | "parameter": "gbar", 72 | "mechanism": "Ca_LVA", 73 | "min": 0 74 | } 75 | ], 76 | "features": [ 77 | "avg_rate", 78 | "peak_v", 79 | "fast_trough_v", 80 | "slow_trough_delta_v", 81 | "slow_trough_norm_t", 82 | "v_baseline", 83 | "width", 84 | "adapt", 85 | "latency", 86 | "isi_cv", 87 | "mean_isi", 88 | "first_isi" 89 | ], 90 | "addl_params": [ 91 | { 92 | "max": 0.05, 93 | "section": "soma", 94 | "parameter": "gamma", 95 | "mechanism": "CaDynamics", 96 | "min": 0 97 | }, 98 | { 99 | "max": 1000, 100 | "section": "soma", 101 | "parameter": "decay", 102 | "mechanism": "CaDynamics", 103 | "min": 20 104 | }, 105 | { 106 | "max": 0.001, 107 | "section": "soma", 108 | "parameter": "g_pas", 109 | "mechanism": "", 110 | "min": 1e-07 111 | }, 112 | { 113 | "max": 0.001, 114 | "section": "axon", 115 | "parameter": "g_pas", 116 | "mechanism": "", 117 | "min": 1e-07 118 | }, 119 | { 120 | "max": 0.001, 121 | "section": "dend", 122 | "parameter": "g_pas", 123 | "mechanism": "", 124 | "min": 1e-07 125 | }, 126 | { 127 | "max": 0.001, 128 | "section": "apic", 129 | "parameter": "g_pas", 130 | "mechanism": "", 131 | "min": 1e-07 132 | } 133 | ], 134 | "conditions": { 135 | "celsius": 34.0, 136 | "erev": [{ 137 | "ena": 53.0, 138 | "section": "soma", 139 | "ek": -107.0 140 | }], 141 | "v_init": -80 142 | } 143 | } -------------------------------------------------------------------------------- /biophys_optimize/fit_styles/f9_noapic_fit_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_name": "f9", 3 | "check_depol_block": true, 4 | "channels": [ 5 | { 6 | "max": 0.1, 7 | "section": "soma", 8 | "parameter": "gbar", 9 | "mechanism": "Im", 10 | "min": 0 11 | }, 12 | { 13 | "max": 0.1, 14 | "section": "soma", 15 | "parameter": "gbar", 16 | "mechanism": "Ih", 17 | "min": 0 18 | }, 19 | { 20 | "max": 15, 21 | "section": "soma", 22 | "parameter": "gbar", 23 | "mechanism": "NaTs", 24 | "min": 0 25 | }, 26 | { 27 | "max": 0.1, 28 | "section": "soma", 29 | "parameter": "gbar", 30 | "mechanism": "Nap", 31 | "min": 0 32 | }, 33 | { 34 | "max": 1.0, 35 | "section": "soma", 36 | "parameter": "gbar", 37 | "mechanism": "K_P", 38 | "min": 0 39 | }, 40 | { 41 | "max": 1.0, 42 | "section": "soma", 43 | "parameter": "gbar", 44 | "mechanism": "K_T", 45 | "min": 0 46 | }, 47 | { 48 | "max": 1.0, 49 | "section": "soma", 50 | "parameter": "gbar", 51 | "mechanism": "SK", 52 | "min": 0 53 | }, 54 | { 55 | "max": 3.0, 56 | "section": "soma", 57 | "parameter": "gbar", 58 | "mechanism": "Kv3_1", 59 | "min": 0 60 | }, 61 | { 62 | "max": 0.001, 63 | "section": "soma", 64 | "parameter": "gbar", 65 | "mechanism": "Ca_HVA", 66 | "min": 0 67 | }, 68 | { 69 | "max": 0.01, 70 | "section": "soma", 71 | "parameter": "gbar", 72 | "mechanism": "Ca_LVA", 73 | "min": 0 74 | } 75 | ], 76 | "features": [ 77 | "avg_rate", 78 | "peak_v", 79 | "fast_trough_v", 80 | "slow_trough_delta_v", 81 | "slow_trough_norm_t", 82 | "v_baseline", 83 | "width", 84 | "adapt", 85 | "latency", 86 | "isi_cv", 87 | "mean_isi", 88 | "first_isi" 89 | ], 90 | "addl_params": [ 91 | { 92 | "max": 0.05, 93 | "section": "soma", 94 | "parameter": "gamma", 95 | "mechanism": "CaDynamics", 96 | "min": 0 97 | }, 98 | { 99 | "max": 1000, 100 | "section": "soma", 101 | "parameter": "decay", 102 | "mechanism": "CaDynamics", 103 | "min": 20 104 | }, 105 | { 106 | "max": 0.001, 107 | "section": "soma", 108 | "parameter": "g_pas", 109 | "mechanism": "", 110 | "min": 1e-07 111 | }, 112 | { 113 | "max": 0.001, 114 | "section": "axon", 115 | "parameter": "g_pas", 116 | "mechanism": "", 117 | "min": 1e-07 118 | }, 119 | { 120 | "max": 0.001, 121 | "section": "dend", 122 | "parameter": "g_pas", 123 | "mechanism": "", 124 | "min": 1e-07 125 | } 126 | ], 127 | "conditions": { 128 | "celsius": 34.0, 129 | "erev": [{ 130 | "ena": 53.0, 131 | "section": "soma", 132 | "ek": -107.0 133 | }], 134 | "v_init": -80 135 | } 136 | } -------------------------------------------------------------------------------- /biophys_optimize/model_selection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | from builtins import range 5 | import argparse 6 | import json 7 | import os.path 8 | import numpy as np 9 | import pandas as pd 10 | from pandas import DataFrame, Series 11 | 12 | from allensdk.core.nwb_data_set import NwbDataSet 13 | from biophys_optimize.utils import Utils 14 | from biophys_optimize import sweep_functions as sf 15 | 16 | 17 | def select_model(fit_results, path_info, passive, v_init, noise_1_sweeps, 18 | noise_2_sweeps, max_attempts=20): 19 | """Choose model with best error that does not exhibit depolarization block 20 | on noise sweeps 21 | 22 | Parameters 23 | ---------- 24 | fit_results : list 25 | List of dictionaries containing individual model fit information 26 | path_info : dict 27 | Dictionary of file paths 28 | passive : dict 29 | Dictionary of passive parameters 30 | v_init : float 31 | Initial voltage for stimulation (mV) 32 | noise_1_sweeps, noise_2_sweeps : list 33 | List of sweep numbers that used "Noise 1" and "Noise 2" protocols. Used to look 34 | for depolarization block that was not evoked by high-amplitude step currents. 35 | max_attempts : int, optional 36 | Number of models to evaluate before giving up 37 | 38 | Returns 39 | ------- 40 | dict 41 | Dictionary with best-fit model information 42 | """ 43 | 44 | errs = np.array([d["err"] for d in fit_results]) 45 | sorted_order = np.argsort(errs) 46 | if len(noise_1_sweeps) == 0 and len(noise_2_sweeps) == 0: 47 | print("No noise stimulus available to test - selecting the model with lowest error") 48 | return fit_results[sorted_order[0]] 49 | 50 | nwb_path = path_info["nwb"] 51 | swc_path = path_info["swc"] 52 | 53 | fit_style_data = {} 54 | for fit_type in path_info["fit_styles"]: 55 | with open(path_info["fit_styles"][fit_type], "r") as f: 56 | fit_style_data[fit_type] = json.load(f) 57 | 58 | data_set = NwbDataSet(nwb_path) 59 | noise_stim = [] 60 | max_t = 0 61 | dt = 0 62 | if len(noise_1_sweeps) > 0: 63 | v, i, t = sf.get_sweep_v_i_t_from_set(data_set, noise_1_sweeps[-1]) 64 | i *= 1e-3 # to nA 65 | noise_stim.append(i) 66 | if np.max(t) > max_t: 67 | max_t = np.max(t) 68 | dt = t[1] - t[0] 69 | 70 | if len(noise_2_sweeps) > 0: 71 | v, i, t = sf.get_sweep_v_i_t_from_set(data_set, noise_2_sweeps[-1]) 72 | i *= 1e-3 # to nA 73 | noise_stim.append(i) 74 | if np.max(t) > max_t: 75 | max_t = np.max(t) 76 | dt = t[1] - t[0] 77 | max_t *= 1e3 # to ms 78 | dt *= 1e3 # to ms 79 | print("Max t = ", max_t) 80 | 81 | # Set up 82 | if max_attempts > len(sorted_order): 83 | max_attempts = len(sorted_order) 84 | 85 | for ind in sorted_order[:max_attempts]: 86 | print("Testing model ", ind) 87 | 88 | fit = fit_results[ind] 89 | depol_okay = True 90 | 91 | utils = Utils(path_info["hoc_files"], 92 | path_info["compiled_mod_library"]) 93 | h = utils.h 94 | utils.generate_morphology(swc_path) 95 | utils.load_cell_parameters(passive, 96 | fit_style_data[fit["fit_type"]]["conditions"], 97 | fit_style_data[fit["fit_type"]]["channels"], 98 | fit_style_data[fit["fit_type"]]["addl_params"]) 99 | utils.insert_iclamp() 100 | utils.set_iclamp_params(0, 0, 1e12) 101 | 102 | h.tstop = max_t 103 | h.celsius = fit_style_data[fit["fit_type"]]["conditions"]["celsius"] 104 | h.v_init = v_init 105 | h.dt = dt 106 | h.cvode.atolscale("cai", 1e-4) 107 | h.cvode.maxstep(10) 108 | v_vec, i_vec, t_vec = utils.record_values() 109 | 110 | for i in noise_stim: 111 | i_stim_vec = h.Vector(i) 112 | i_stim_vec.play(utils.stim._ref_amp, dt) 113 | utils.set_actual_parameters(fit["params"]) 114 | print("Starting run") 115 | h.finitialize() 116 | h.run() 117 | print("Finished run") 118 | i_stim_vec.play_remove() 119 | if has_noise_block(v_vec.as_numpy(), t_vec.as_numpy()): 120 | depol_okay = False 121 | 122 | if depol_okay: 123 | print("Did not detect depolarization block on noise traces") 124 | return fit 125 | 126 | print("Failed to find model after looking at best {:d} organisms".format(max_attempts)) 127 | return None 128 | 129 | 130 | def build_fit_data(genome_vals, passive, preprocess, fit_style_info): 131 | """ Create dictionary for saving model info in JSON format 132 | 133 | Parameters 134 | ---------- 135 | genome_vals : list-like 136 | List of numerical model parameters 137 | passive : dict 138 | Dictionary of passive parameters 139 | preprocess : dict 140 | Dictionary with pre-processing output 141 | fit_style_info : 142 | Dictionary with fit style parameters 143 | 144 | Returns 145 | ------- 146 | dict 147 | Dictionary of model parameters in standard format 148 | """ 149 | json_data = {} 150 | 151 | # passive 152 | json_data["passive"] = [{}] 153 | json_data["passive"][0]["ra"] = passive["ra"] 154 | json_data["passive"][0]["e_pas"] = passive["e_pas"] 155 | json_data["passive"][0]["cm"] = [] 156 | for k in passive["cm"]: 157 | json_data["passive"][0]["cm"].append({"section": k, "cm": passive["cm"][k]}) 158 | 159 | # fitting 160 | json_data["fitting"] = [{}] 161 | json_data["fitting"][0]["sweeps"] = preprocess["sweeps_to_fit"] 162 | json_data["fitting"][0]["junction_potential"] = preprocess["junction_potential"] 163 | 164 | # conditions 165 | json_data["conditions"] = [fit_style_info["conditions"]] 166 | json_data["conditions"][0]["v_init"] = passive["e_pas"] 167 | 168 | # genome 169 | all_params = fit_style_info["channels"] + fit_style_info["addl_params"] 170 | json_data["genome"] = [] 171 | for i, p in enumerate(all_params): 172 | if len(p["mechanism"]) > 0: 173 | param_name = p["parameter"] + "_" + p["mechanism"] 174 | else: 175 | param_name = p["parameter"] 176 | json_data["genome"].append({"value": genome_vals[i], 177 | "section": p["section"], 178 | "name": param_name, 179 | "mechanism": p["mechanism"] 180 | }) 181 | 182 | return json_data 183 | 184 | 185 | def has_noise_block(v, t, depol_block_threshold=-50.0, block_min_duration = 50.0): 186 | """ Determine whether the model exhibits depolarization block with noise stimuli 187 | 188 | Parameters 189 | ---------- 190 | v : array-like 191 | Voltage response of model 192 | t : array-like 193 | Time points for `v` 194 | depol_block_threshold : float, optional 195 | Minimum value to identify depolarized periods in `v` 196 | block_min_duration : float, optional 197 | Minimum value of depolarized period to count as depolarization block (in ms) 198 | 199 | Returns 200 | ------- 201 | bool 202 | Whether depolarization block was found 203 | """ 204 | stim_start_idx = 0 205 | stim_end_idx = len(t) - 1 206 | bool_v = np.array(v > depol_block_threshold, dtype=int) 207 | up_indexes = np.flatnonzero(np.diff(bool_v) == 1) 208 | down_indexes = np.flatnonzero(np.diff(bool_v) == -1) 209 | if len(up_indexes) > len(down_indexes): 210 | down_indexes = np.append(down_indexes, [stim_end_idx]) 211 | 212 | if len(up_indexes) != 0: 213 | max_depol_duration = np.max([t[down_indexes[k]] - t[up_idx] for k, up_idx in enumerate(up_indexes)]) 214 | if max_depol_duration > block_min_duration: 215 | print("Encountered depolarization block") 216 | return True 217 | 218 | return False 219 | 220 | 221 | def fit_info(fits): 222 | """ Create list with individual model info as dictionaries 223 | 224 | Parameters 225 | ---------- 226 | fits : dict 227 | Dictionary with fitting output path information 228 | 229 | Returns 230 | ------- 231 | list 232 | List of model information dictionaries 233 | """ 234 | info = [] 235 | for fit in fits: 236 | fit_type = fit["fit_type"] 237 | hof_fit = np.loadtxt(fit["hof_fit"]) 238 | hof = np.loadtxt(fit["hof"]) 239 | for i in range(len(hof_fit)): 240 | info.append({ 241 | "fit_type": fit_type, 242 | "err": hof_fit[i], 243 | "params": hof[i, :], 244 | }) 245 | return info 246 | 247 | 248 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/CaDynamics.mod: -------------------------------------------------------------------------------- 1 | : Dynamics that track inside calcium concentration 2 | : modified from Destexhe et al. 1994 3 | 4 | NEURON { 5 | SUFFIX CaDynamics 6 | USEION ca READ ica WRITE cai 7 | RANGE decay, gamma, minCai, depth 8 | } 9 | 10 | UNITS { 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | FARADAY = (faraday) (coulombs) 14 | (molar) = (1/liter) 15 | (mM) = (millimolar) 16 | (um) = (micron) 17 | } 18 | 19 | PARAMETER { 20 | gamma = 0.05 : percent of free calcium (not buffered) 21 | decay = 80 (ms) : rate of removal of calcium 22 | depth = 0.1 (um) : depth of shell 23 | minCai = 1e-4 (mM) 24 | } 25 | 26 | ASSIGNED {ica (mA/cm2)} 27 | 28 | INITIAL { 29 | cai = minCai 30 | } 31 | 32 | STATE { 33 | cai (mM) 34 | } 35 | 36 | BREAKPOINT { SOLVE states METHOD cnexp } 37 | 38 | DERIVATIVE states { 39 | cai' = -(10000)*(ica*gamma/(2*FARADAY*depth)) - (cai - minCai)/decay 40 | } 41 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Ca_HVA.mod: -------------------------------------------------------------------------------- 1 | : Reference: Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 2 | 3 | NEURON { 4 | SUFFIX Ca_HVA 5 | USEION ca READ eca WRITE ica 6 | RANGE gbar, g, ica 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | } 18 | 19 | ASSIGNED { 20 | v (mV) 21 | eca (mV) 22 | ica (mA/cm2) 23 | g (S/cm2) 24 | mInf 25 | mTau 26 | mAlpha 27 | mBeta 28 | hInf 29 | hTau 30 | hAlpha 31 | hBeta 32 | } 33 | 34 | STATE { 35 | m 36 | h 37 | } 38 | 39 | BREAKPOINT { 40 | SOLVE states METHOD cnexp 41 | g = gbar*m*m*h 42 | ica = g*(v-eca) 43 | } 44 | 45 | DERIVATIVE states { 46 | rates() 47 | m' = (mInf-m)/mTau 48 | h' = (hInf-h)/hTau 49 | } 50 | 51 | INITIAL{ 52 | rates() 53 | m = mInf 54 | h = hInf 55 | } 56 | 57 | PROCEDURE rates(){ 58 | UNITSOFF 59 | : if((v == -27) ){ 60 | : v = v+0.0001 61 | : } 62 | :mAlpha = (0.055*(-27-v))/(exp((-27-v)/3.8) - 1) 63 | mAlpha = 0.055 * vtrap(-27 - v, 3.8) 64 | mBeta = (0.94*exp((-75-v)/17)) 65 | mInf = mAlpha/(mAlpha + mBeta) 66 | mTau = 1/(mAlpha + mBeta) 67 | hAlpha = (0.000457*exp((-13-v)/50)) 68 | hBeta = (0.0065/(exp((-v-15)/28)+1)) 69 | hInf = hAlpha/(hAlpha + hBeta) 70 | hTau = 1/(hAlpha + hBeta) 71 | UNITSON 72 | } 73 | 74 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 75 | UNITSOFF 76 | if (fabs(x / y) < 1e-6) { 77 | vtrap = y * (1 - x / y / 2) 78 | } else { 79 | vtrap = x / (exp(x / y) - 1) 80 | } 81 | UNITSON 82 | } -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Ca_LVA.mod: -------------------------------------------------------------------------------- 1 | : Comment: LVA ca channel. Note: mtau is an approximation from the plots 2 | : Reference: Avery and Johnston 1996, tau from Randall 1997 3 | : Comment: shifted by -10 mv to correct for junction potential 4 | : Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 5 | 6 | NEURON { 7 | SUFFIX Ca_LVA 8 | USEION ca READ eca WRITE ica 9 | RANGE gbar, g, ica 10 | } 11 | 12 | UNITS { 13 | (S) = (siemens) 14 | (mV) = (millivolt) 15 | (mA) = (milliamp) 16 | } 17 | 18 | PARAMETER { 19 | gbar = 0.00001 (S/cm2) 20 | } 21 | 22 | ASSIGNED { 23 | v (mV) 24 | eca (mV) 25 | ica (mA/cm2) 26 | g (S/cm2) 27 | celsius (degC) 28 | mInf 29 | mTau 30 | hInf 31 | hTau 32 | } 33 | 34 | STATE { 35 | m 36 | h 37 | } 38 | 39 | BREAKPOINT { 40 | SOLVE states METHOD cnexp 41 | g = gbar*m*m*h 42 | ica = g*(v-eca) 43 | } 44 | 45 | DERIVATIVE states { 46 | rates() 47 | m' = (mInf-m)/mTau 48 | h' = (hInf-h)/hTau 49 | } 50 | 51 | INITIAL{ 52 | rates() 53 | m = mInf 54 | h = hInf 55 | } 56 | 57 | PROCEDURE rates(){ 58 | LOCAL qt 59 | qt = 2.3^((celsius-21)/10) 60 | 61 | UNITSOFF 62 | v = v + 10 63 | mInf = 1.0000/(1+ exp((v - -30.000)/-6)) 64 | mTau = (5.0000 + 20.0000/(1+exp((v - -25.000)/5)))/qt 65 | hInf = 1.0000/(1+ exp((v - -80.000)/6.4)) 66 | hTau = (20.0000 + 50.0000/(1+exp((v - -40.000)/7)))/qt 67 | v = v - 10 68 | UNITSON 69 | } 70 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Ih.mod: -------------------------------------------------------------------------------- 1 | : Reference: Kole,Hallermann,and Stuart, J. Neurosci. 2006 2 | 3 | NEURON { 4 | SUFFIX Ih 5 | NONSPECIFIC_CURRENT ihcn 6 | RANGE gbar, g, ihcn 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | ehcn = -45.0 (mV) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ihcn (mA/cm2) 23 | g (S/cm2) 24 | mInf 25 | mTau 26 | mAlpha 27 | mBeta 28 | } 29 | 30 | STATE { 31 | m 32 | } 33 | 34 | BREAKPOINT { 35 | SOLVE states METHOD cnexp 36 | g = gbar*m 37 | ihcn = g*(v-ehcn) 38 | } 39 | 40 | DERIVATIVE states { 41 | rates() 42 | m' = (mInf-m)/mTau 43 | } 44 | 45 | INITIAL{ 46 | rates() 47 | m = mInf 48 | } 49 | 50 | PROCEDURE rates(){ 51 | UNITSOFF 52 | : if(v == -154.9){ 53 | : v = v + 0.0001 54 | : } 55 | :mAlpha = 0.001*6.43*(v+154.9)/(exp((v+154.9)/11.9)-1) 56 | mAlpha = 0.001 * 6.43 * vtrap(v + 154.9, 11.9) 57 | mBeta = 0.001*193*exp(v/33.1) 58 | mInf = mAlpha/(mAlpha + mBeta) 59 | mTau = 1/(mAlpha + mBeta) 60 | UNITSON 61 | } 62 | 63 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 64 | UNITSOFF 65 | if (fabs(x / y) < 1e-6) { 66 | vtrap = y * (1 - x / y / 2) 67 | } else { 68 | vtrap = x / (exp(x / y) - 1) 69 | } 70 | UNITSON 71 | } 72 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Im.mod: -------------------------------------------------------------------------------- 1 | : Reference: Adams et al. 1982 - M-currents and other potassium currents in bullfrog sympathetic neurones 2 | : Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 3 | 4 | NEURON { 5 | SUFFIX Im 6 | USEION k READ ek WRITE ik 7 | RANGE gbar, g, ik 8 | } 9 | 10 | UNITS { 11 | (S) = (siemens) 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | } 15 | 16 | PARAMETER { 17 | gbar = 0.00001 (S/cm2) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ek (mV) 23 | ik (mA/cm2) 24 | g (S/cm2) 25 | celsius (degC) 26 | mInf 27 | mTau 28 | mAlpha 29 | mBeta 30 | } 31 | 32 | STATE { 33 | m 34 | } 35 | 36 | BREAKPOINT { 37 | SOLVE states METHOD cnexp 38 | g = gbar*m 39 | ik = g*(v-ek) 40 | } 41 | 42 | DERIVATIVE states { 43 | rates() 44 | m' = (mInf-m)/mTau 45 | } 46 | 47 | INITIAL{ 48 | rates() 49 | m = mInf 50 | } 51 | 52 | PROCEDURE rates(){ 53 | LOCAL qt 54 | qt = 2.3^((celsius-21)/10) 55 | 56 | UNITSOFF 57 | mAlpha = 3.3e-3*exp(2.5*0.04*(v - -35)) 58 | mBeta = 3.3e-3*exp(-2.5*0.04*(v - -35)) 59 | mInf = mAlpha/(mAlpha + mBeta) 60 | mTau = (1/(mAlpha + mBeta))/qt 61 | UNITSON 62 | } 63 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Im_v2.mod: -------------------------------------------------------------------------------- 1 | : Based on Im model of Vervaeke et al. (2006) 2 | 3 | NEURON { 4 | SUFFIX Im_v2 5 | USEION k READ ek WRITE ik 6 | RANGE gbar, g, ik 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | } 18 | 19 | ASSIGNED { 20 | v (mV) 21 | ek (mV) 22 | ik (mA/cm2) 23 | g (S/cm2) 24 | celsius (degC) 25 | mInf 26 | mTau 27 | mAlpha 28 | mBeta 29 | } 30 | 31 | STATE { 32 | m 33 | } 34 | 35 | BREAKPOINT { 36 | SOLVE states METHOD cnexp 37 | g = gbar * m 38 | ik = g * (v - ek) 39 | } 40 | 41 | DERIVATIVE states { 42 | rates() 43 | m' = (mInf - m) / mTau 44 | } 45 | 46 | INITIAL{ 47 | rates() 48 | m = mInf 49 | } 50 | 51 | PROCEDURE rates() { 52 | LOCAL qt 53 | qt = 2.3^((celsius-30)/10) 54 | mAlpha = 0.007 * exp( (6 * 0.4 * (v - (-48))) / 26.12 ) 55 | mBeta = 0.007 * exp( (-6 * (1 - 0.4) * (v - (-48))) / 26.12 ) 56 | 57 | mInf = mAlpha / (mAlpha + mBeta) 58 | mTau = (15 + 1 / (mAlpha + mBeta)) / qt 59 | } 60 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/K_P.mod: -------------------------------------------------------------------------------- 1 | : Comment: The persistent component of the K current 2 | : Reference: Voltage-gated K+ channels in layer 5 neocortical pyramidal neurones from young rats:subtypes and gradients,Korngreen and Sakmann, J. Physiology, 2000 3 | 4 | 5 | NEURON { 6 | SUFFIX K_P 7 | USEION k READ ek WRITE ik 8 | RANGE gbar, g, ik 9 | } 10 | 11 | UNITS { 12 | (S) = (siemens) 13 | (mV) = (millivolt) 14 | (mA) = (milliamp) 15 | } 16 | 17 | PARAMETER { 18 | gbar = 0.00001 (S/cm2) 19 | vshift = 0 (mV) 20 | tauF = 1 21 | } 22 | 23 | ASSIGNED { 24 | v (mV) 25 | ek (mV) 26 | ik (mA/cm2) 27 | g (S/cm2) 28 | celsius (degC) 29 | mInf 30 | mTau 31 | hInf 32 | hTau 33 | } 34 | 35 | STATE { 36 | m 37 | h 38 | } 39 | 40 | BREAKPOINT { 41 | SOLVE states METHOD cnexp 42 | g = gbar*m*m*h 43 | ik = g*(v-ek) 44 | } 45 | 46 | DERIVATIVE states { 47 | rates() 48 | m' = (mInf-m)/mTau 49 | h' = (hInf-h)/hTau 50 | } 51 | 52 | INITIAL{ 53 | rates() 54 | m = mInf 55 | h = hInf 56 | } 57 | 58 | PROCEDURE rates() { 59 | LOCAL qt 60 | qt = 2.3^((celsius-21)/10) 61 | UNITSOFF 62 | mInf = 1 / (1 + exp(-(v - (-14.3 + vshift)) / 14.6)) 63 | if (v < -50 + vshift){ 64 | mTau = tauF * (1.25+175.03*exp(-(v - vshift) * -0.026))/qt 65 | } else { 66 | mTau = tauF * (1.25+13*exp(-(v - vshift) * 0.026))/qt 67 | } 68 | hInf = 1/(1 + exp(-(v - (-54 + vshift))/-11)) 69 | hTau = (360+(1010+24*(v - (-55 + vshift)))*exp(-((v - (-75 + vshift))/48)^2))/qt 70 | UNITSON 71 | } 72 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/K_T.mod: -------------------------------------------------------------------------------- 1 | : Comment: The transient component of the K current 2 | : Reference: Voltage-gated K+ channels in layer 5 neocortical pyramidal neurones from young rats:subtypes and gradients,Korngreen and Sakmann, J. Physiology, 2000 3 | 4 | NEURON { 5 | SUFFIX K_T 6 | USEION k READ ek WRITE ik 7 | RANGE gbar, g, ik 8 | } 9 | 10 | UNITS { 11 | (S) = (siemens) 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | } 15 | 16 | PARAMETER { 17 | gbar = 0.00001 (S/cm2) 18 | vshift = 0 (mV) 19 | mTauF = 1.0 20 | hTauF = 1.0 21 | } 22 | 23 | ASSIGNED { 24 | v (mV) 25 | ek (mV) 26 | ik (mA/cm2) 27 | g (S/cm2) 28 | celsius (degC) 29 | mInf 30 | mTau 31 | hInf 32 | hTau 33 | } 34 | 35 | STATE { 36 | m 37 | h 38 | } 39 | 40 | BREAKPOINT { 41 | SOLVE states METHOD cnexp 42 | g = gbar*m*m*m*m*h 43 | ik = g*(v-ek) 44 | } 45 | 46 | DERIVATIVE states { 47 | rates() 48 | m' = (mInf-m)/mTau 49 | h' = (hInf-h)/hTau 50 | } 51 | 52 | INITIAL{ 53 | rates() 54 | m = mInf 55 | h = hInf 56 | } 57 | 58 | PROCEDURE rates(){ 59 | LOCAL qt 60 | qt = 2.3^((celsius-21)/10) 61 | 62 | UNITSOFF 63 | mInf = 1/(1 + exp(-(v - (-47 + vshift)) / 29)) 64 | mTau = (0.34 + mTauF * 0.92*exp(-((v+71-vshift)/59)^2))/qt 65 | hInf = 1/(1 + exp(-(v+66-vshift)/-10)) 66 | hTau = (8 + hTauF * 49*exp(-((v+73-vshift)/23)^2))/qt 67 | UNITSON 68 | } 69 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Kd.mod: -------------------------------------------------------------------------------- 1 | : Based on Kd model of Foust et al. (2011) 2 | 3 | 4 | NEURON { 5 | SUFFIX Kd 6 | USEION k READ ek WRITE ik 7 | RANGE gbar, g, ik 8 | } 9 | 10 | UNITS { 11 | (S) = (siemens) 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | } 15 | 16 | PARAMETER { 17 | gbar = 0.00001 (S/cm2) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ek (mV) 23 | ik (mA/cm2) 24 | g (S/cm2) 25 | celsius (degC) 26 | mInf 27 | mTau 28 | hInf 29 | hTau 30 | } 31 | 32 | STATE { 33 | m 34 | h 35 | } 36 | 37 | BREAKPOINT { 38 | SOLVE states METHOD cnexp 39 | g = gbar * m * h 40 | ik = g * (v - ek) 41 | } 42 | 43 | DERIVATIVE states { 44 | rates() 45 | m' = (mInf - m) / mTau 46 | h' = (hInf - h) / hTau 47 | } 48 | 49 | INITIAL{ 50 | rates() 51 | m = mInf 52 | h = hInf 53 | } 54 | 55 | PROCEDURE rates() { 56 | LOCAL qt 57 | qt = 2.3^((celsius-23)/10) 58 | mInf = 1 - 1 / (1 + exp((v - (-43)) / 8)) 59 | mTau = 1 60 | hInf = 1 / (1 + exp((v - (-67)) / 7.3)) 61 | hTau = 1500 62 | } 63 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/KdT.mod: -------------------------------------------------------------------------------- 1 | : Based on Kd model of Foust et al. (2011) 2 | : Working temperature dependency 3 | 4 | NEURON { 5 | SUFFIX KdT 6 | USEION k READ ek WRITE ik 7 | RANGE gbar, g, ik 8 | } 9 | 10 | UNITS { 11 | (S) = (siemens) 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | } 15 | 16 | PARAMETER { 17 | gbar = 0.00001 (S/cm2) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ek (mV) 23 | ik (mA/cm2) 24 | g (S/cm2) 25 | celsius (degC) 26 | mInf 27 | mTau 28 | hInf 29 | hTau 30 | } 31 | 32 | STATE { 33 | m 34 | h 35 | } 36 | 37 | BREAKPOINT { 38 | SOLVE states METHOD cnexp 39 | g = gbar * m * h 40 | ik = g * (v - ek) 41 | } 42 | 43 | DERIVATIVE states { 44 | rates() 45 | m' = (mInf - m) / mTau 46 | h' = (hInf - h) / hTau 47 | } 48 | 49 | INITIAL{ 50 | rates() 51 | m = mInf 52 | h = hInf 53 | } 54 | 55 | PROCEDURE rates() { 56 | LOCAL qt 57 | qt = 2.3^((celsius-37)/10) 58 | mInf = 1 - 1 / (1 + exp((v - (-43)) / 8)) 59 | mTau = 1 / qt 60 | hInf = 1 / (1 + exp((v - (-67)) / 7.3)) 61 | hTau = 1500 / qt 62 | } 63 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Kv2like.mod: -------------------------------------------------------------------------------- 1 | : Kv2-like channel 2 | : Adapted from model implemented in Keren et al. 2005 3 | : Adjusted parameters to be similar to guangxitoxin-sensitive current in mouse CA1 pyramids from Liu and Bean 2014 4 | 5 | 6 | NEURON { 7 | SUFFIX Kv2like 8 | USEION k READ ek WRITE ik 9 | RANGE gbar, g, ik 10 | } 11 | 12 | UNITS { 13 | (S) = (siemens) 14 | (mV) = (millivolt) 15 | (mA) = (milliamp) 16 | } 17 | 18 | PARAMETER { 19 | gbar = 0.00001 (S/cm2) 20 | } 21 | 22 | ASSIGNED { 23 | v (mV) 24 | ek (mV) 25 | ik (mA/cm2) 26 | g (S/cm2) 27 | celsius (degC) 28 | mInf 29 | mAlpha 30 | mBeta 31 | mTau 32 | hInf 33 | h1Tau 34 | h2Tau 35 | } 36 | 37 | STATE { 38 | m 39 | h1 40 | h2 41 | } 42 | 43 | BREAKPOINT { 44 | SOLVE states METHOD cnexp 45 | g = gbar * m * m * (0.5 * h1 + 0.5 * h2) 46 | ik = g * (v - ek) 47 | } 48 | 49 | DERIVATIVE states { 50 | rates() 51 | m' = (mInf - m) / mTau 52 | h1' = (hInf - h1) / h1Tau 53 | h2' = (hInf - h2) / h2Tau 54 | } 55 | 56 | INITIAL{ 57 | rates() 58 | m = mInf 59 | h1 = hInf 60 | h2 = hInf 61 | } 62 | 63 | PROCEDURE rates() { 64 | LOCAL qt 65 | qt = 2.3^((celsius-21)/10) 66 | UNITSOFF 67 | mAlpha = 0.12 * vtrap( -(v - 43), 11.0) 68 | mBeta = 0.02 * exp(-(v + 1.27) / 120) 69 | mInf = mAlpha / (mAlpha + mBeta) 70 | mTau = 2.5 * (1 / (qt * (mAlpha + mBeta))) 71 | 72 | hInf = 1/(1 + exp((v + 58) / 11)) 73 | h1Tau = (360 + (1010 + 23.7 * (v + 54)) * exp(-((v + 75) / 48)^2)) / qt 74 | h2Tau = (2350 + 1380 * exp(-0.011 * v) - 210 * exp(-0.03 * v)) / qt 75 | if (h2Tau < 0) { 76 | h2Tau = 1e-3 77 | } 78 | UNITSON 79 | } 80 | 81 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 82 | UNITSOFF 83 | if (fabs(x / y) < 1e-6) { 84 | vtrap = y * (1 - x / y / 2) 85 | } else { 86 | vtrap = x / (exp(x / y) - 1) 87 | } 88 | UNITSON 89 | } -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Kv3_1.mod: -------------------------------------------------------------------------------- 1 | : Comment: Kv3-like potassium current 2 | 3 | NEURON { 4 | SUFFIX Kv3_1 5 | USEION k READ ek WRITE ik 6 | RANGE gbar, g, ik 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | vshift = 0 (mV) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ek (mV) 23 | ik (mA/cm2) 24 | g (S/cm2) 25 | mInf 26 | mTau 27 | } 28 | 29 | STATE { 30 | m 31 | } 32 | 33 | BREAKPOINT { 34 | SOLVE states METHOD cnexp 35 | g = gbar*m 36 | ik = g*(v-ek) 37 | } 38 | 39 | DERIVATIVE states { 40 | rates() 41 | m' = (mInf-m)/mTau 42 | } 43 | 44 | INITIAL{ 45 | rates() 46 | m = mInf 47 | } 48 | 49 | PROCEDURE rates(){ 50 | UNITSOFF 51 | mInf = 1/(1+exp(((v -(18.700 + vshift))/(-9.700)))) 52 | mTau = 0.2*20.000/(1+exp(((v -(-46.560 + vshift))/(-44.140)))) 53 | UNITSON 54 | } 55 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Kv3_1T.mod: -------------------------------------------------------------------------------- 1 | : Comment: Kv3-like potassium current 2 | 3 | NEURON { 4 | SUFFIX Kv3_1T 5 | USEION k READ ek WRITE ik 6 | RANGE gbar, g, ik 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | vshift = 0 (mV) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ek (mV) 23 | ik (mA/cm2) 24 | g (S/cm2) 25 | mInf 26 | mTau 27 | celsius (degC) 28 | } 29 | 30 | STATE { 31 | m 32 | } 33 | 34 | BREAKPOINT { 35 | SOLVE states METHOD cnexp 36 | g = gbar*m 37 | ik = g*(v-ek) 38 | } 39 | 40 | DERIVATIVE states { 41 | rates() 42 | m' = (mInf-m)/mTau 43 | } 44 | 45 | INITIAL{ 46 | rates() 47 | m = mInf 48 | } 49 | 50 | PROCEDURE rates(){ 51 | LOCAL qt 52 | qt = 2.3 ^ ((celsius - 23) / 10) 53 | UNITSOFF 54 | mInf = 1 / (1 + exp(((v - (18.700 + vshift)) / -9.700))) 55 | mTau = (0.2 / qt) * 20.0 / (1 + exp(((v - (-46.560 + vshift)) / -44.140))) 56 | UNITSON 57 | } 58 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/NaTa.mod: -------------------------------------------------------------------------------- 1 | : Reference: Colbert and Pan 2002 2 | 3 | NEURON { 4 | SUFFIX NaTa 5 | USEION na READ ena WRITE ina 6 | RANGE gbar, g, ina 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | 18 | malphaF = 0.182 19 | mbetaF = 0.124 20 | mvhalf = -48 (mV) 21 | mk = 6 (mV) 22 | 23 | halphaF = 0.015 24 | hbetaF = 0.015 25 | hvhalf = -69 (mV) 26 | hk = 6 (mV) 27 | } 28 | 29 | ASSIGNED { 30 | v (mV) 31 | ena (mV) 32 | ina (mA/cm2) 33 | g (S/cm2) 34 | celsius (degC) 35 | mInf 36 | mTau 37 | mAlpha 38 | mBeta 39 | hInf 40 | hTau 41 | hAlpha 42 | hBeta 43 | } 44 | 45 | STATE { 46 | m 47 | h 48 | } 49 | 50 | BREAKPOINT { 51 | SOLVE states METHOD cnexp 52 | g = gbar*m*m*m*h 53 | ina = g*(v-ena) 54 | } 55 | 56 | DERIVATIVE states { 57 | rates() 58 | m' = (mInf-m)/mTau 59 | h' = (hInf-h)/hTau 60 | } 61 | 62 | INITIAL{ 63 | rates() 64 | m = mInf 65 | h = hInf 66 | } 67 | 68 | PROCEDURE rates(){ 69 | LOCAL qt 70 | qt = 2.3^((celsius-23)/10) 71 | 72 | UNITSOFF 73 | mAlpha = malphaF * vtrap(-(v - mvhalf), mk) 74 | mBeta = mbetaF * vtrap((v - mvhalf), mk) 75 | 76 | mInf = mAlpha/(mAlpha + mBeta) 77 | mTau = (1/(mAlpha + mBeta))/qt 78 | 79 | hAlpha = halphaF * vtrap(v - hvhalf, hk) : ng - adjusted this to match actual Colbert & Pan values for soma model 80 | hBeta = hbetaF * vtrap(-(v - hvhalf), hk) : ng - adjusted this to match actual Colbert & Pan values for soma model 81 | 82 | hInf = hAlpha/(hAlpha + hBeta) 83 | hTau = (1/(hAlpha + hBeta))/qt 84 | UNITSON 85 | } 86 | 87 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 88 | UNITSOFF 89 | if (fabs(x / y) < 1e-6) { 90 | vtrap = y * (1 - x / y / 2) 91 | } else { 92 | vtrap = x / (exp(x / y) - 1) 93 | } 94 | UNITSON 95 | } -------------------------------------------------------------------------------- /biophys_optimize/modfiles/NaTs.mod: -------------------------------------------------------------------------------- 1 | : Reference: Colbert and Pan 2002 2 | 3 | NEURON { 4 | SUFFIX NaTs 5 | USEION na READ ena WRITE ina 6 | RANGE gbar, g, ina 7 | } 8 | 9 | UNITS { 10 | (S) = (siemens) 11 | (mV) = (millivolt) 12 | (mA) = (milliamp) 13 | } 14 | 15 | PARAMETER { 16 | gbar = 0.00001 (S/cm2) 17 | 18 | malphaF = 0.182 19 | mbetaF = 0.124 20 | mvhalf = -40 (mV) 21 | mk = 6 (mV) 22 | 23 | halphaF = 0.015 24 | hbetaF = 0.015 25 | hvhalf = -66 (mV) 26 | hk = 6 (mV) 27 | } 28 | 29 | ASSIGNED { 30 | v (mV) 31 | ena (mV) 32 | ina (mA/cm2) 33 | g (S/cm2) 34 | celsius (degC) 35 | mInf 36 | mTau 37 | mAlpha 38 | mBeta 39 | hInf 40 | hTau 41 | hAlpha 42 | hBeta 43 | } 44 | 45 | STATE { 46 | m 47 | h 48 | } 49 | 50 | BREAKPOINT { 51 | SOLVE states METHOD cnexp 52 | g = gbar*m*m*m*h 53 | ina = g*(v-ena) 54 | } 55 | 56 | DERIVATIVE states { 57 | rates() 58 | m' = (mInf-m)/mTau 59 | h' = (hInf-h)/hTau 60 | } 61 | 62 | INITIAL{ 63 | rates() 64 | m = mInf 65 | h = hInf 66 | } 67 | 68 | PROCEDURE rates(){ 69 | LOCAL qt 70 | qt = 2.3^((celsius-23)/10) 71 | 72 | UNITSOFF 73 | mAlpha = malphaF * vtrap(-(v - mvhalf), mk) 74 | mBeta = mbetaF * vtrap((v - mvhalf), mk) 75 | 76 | mInf = mAlpha/(mAlpha + mBeta) 77 | mTau = (1/(mAlpha + mBeta))/qt 78 | 79 | hAlpha = halphaF * vtrap(v - hvhalf, hk) 80 | hBeta = hbetaF * vtrap(-(v - hvhalf), hk) 81 | 82 | hInf = hAlpha/(hAlpha + hBeta) 83 | hTau = (1/(hAlpha + hBeta))/qt 84 | UNITSON 85 | } 86 | 87 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 88 | UNITSOFF 89 | if (fabs(x / y) < 1e-6) { 90 | vtrap = y * (1 - x / y / 2) 91 | } else { 92 | vtrap = x / (exp(x / y) - 1) 93 | } 94 | UNITSON 95 | } -------------------------------------------------------------------------------- /biophys_optimize/modfiles/NaV.mod: -------------------------------------------------------------------------------- 1 | TITLE Mouse sodium current 2 | : Kinetics of Carter et al. (2012) 3 | : Based on 37 degC recordings from mouse hippocampal CA1 pyramids 4 | 5 | NEURON { 6 | SUFFIX NaV 7 | USEION na READ ena WRITE ina 8 | RANGE g, gbar 9 | } 10 | 11 | UNITS { 12 | (mV) = (millivolt) 13 | (S) = (siemens) 14 | } 15 | 16 | PARAMETER { 17 | gbar = .015 (S/cm2) 18 | 19 | : kinetic parameters 20 | Con = 0.01 (/ms) : closed -> inactivated transitions 21 | Coff = 40 (/ms) : inactivated -> closed transitions 22 | Oon = 8 (/ms) : open -> Ineg transition 23 | Ooff = 0.05 (/ms) : Ineg -> open transition 24 | alpha = 400 (/ms) 25 | beta = 12 (/ms) 26 | gamma = 250 (/ms) : opening 27 | delta = 60 (/ms) : closing 28 | 29 | alfac = 2.51 30 | btfac = 5.32 31 | 32 | : Vdep 33 | x1 = 24 (mV) : Vdep of activation (alpha) 34 | x2 = -24 (mV) : Vdep of deactivation (beta) 35 | } 36 | 37 | ASSIGNED { 38 | 39 | : rates 40 | f01 (/ms) 41 | f02 (/ms) 42 | f03 (/ms) 43 | f04 (/ms) 44 | f0O (/ms) 45 | f11 (/ms) 46 | f12 (/ms) 47 | f13 (/ms) 48 | f14 (/ms) 49 | f1n (/ms) 50 | fi1 (/ms) 51 | fi2 (/ms) 52 | fi3 (/ms) 53 | fi4 (/ms) 54 | fi5 (/ms) 55 | fin (/ms) 56 | 57 | b01 (/ms) 58 | b02 (/ms) 59 | b03 (/ms) 60 | b04 (/ms) 61 | b0O (/ms) 62 | b11 (/ms) 63 | b12 (/ms) 64 | b13 (/ms) 65 | b14 (/ms) 66 | b1n (/ms) 67 | bi1 (/ms) 68 | bi2 (/ms) 69 | bi3 (/ms) 70 | bi4 (/ms) 71 | bi5 (/ms) 72 | bin (/ms) 73 | 74 | v (mV) 75 | ena (mV) 76 | ina (milliamp/cm2) 77 | g (S/cm2) 78 | celsius (degC) 79 | } 80 | 81 | STATE { 82 | C1 FROM 0 TO 1 83 | C2 FROM 0 TO 1 84 | C3 FROM 0 TO 1 85 | C4 FROM 0 TO 1 86 | C5 FROM 0 TO 1 87 | I1 FROM 0 TO 1 88 | I2 FROM 0 TO 1 89 | I3 FROM 0 TO 1 90 | I4 FROM 0 TO 1 91 | I5 FROM 0 TO 1 92 | O FROM 0 TO 1 93 | I6 FROM 0 TO 1 94 | } 95 | 96 | BREAKPOINT { 97 | SOLVE activation METHOD sparse 98 | g = gbar * O 99 | ina = g * (v - ena) 100 | } 101 | 102 | INITIAL { 103 | rates(v) 104 | SOLVE seqinitial 105 | } 106 | 107 | KINETIC activation 108 | { 109 | rates(v) 110 | ~ C1 <-> C2 (f01,b01) 111 | ~ C2 <-> C3 (f02,b02) 112 | ~ C3 <-> C4 (f03,b03) 113 | ~ C4 <-> C5 (f04,b04) 114 | ~ C5 <-> O (f0O,b0O) 115 | ~ O <-> I6 (fin,bin) 116 | ~ I1 <-> I2 (f11,b11) 117 | ~ I2 <-> I3 (f12,b12) 118 | ~ I3 <-> I4 (f13,b13) 119 | ~ I4 <-> I5 (f14,b14) 120 | ~ I5 <-> I6 (f1n,b1n) 121 | ~ C1 <-> I1 (fi1,bi1) 122 | ~ C2 <-> I2 (fi2,bi2) 123 | ~ C3 <-> I3 (fi3,bi3) 124 | ~ C4 <-> I4 (fi4,bi4) 125 | ~ C5 <-> I5 (fi5,bi5) 126 | 127 | CONSERVE C1 + C2 + C3 + C4 + C5 + O + I1 + I2 + I3 + I4 + I5 + I6 = 1 128 | } 129 | 130 | LINEAR seqinitial { : sets initial equilibrium 131 | ~ I1*bi1 + C2*b01 - C1*( fi1+f01) = 0 132 | ~ C1*f01 + I2*bi2 + C3*b02 - C2*(b01+fi2+f02) = 0 133 | ~ C2*f02 + I3*bi3 + C4*b03 - C3*(b02+fi3+f03) = 0 134 | ~ C3*f03 + I4*bi4 + C5*b04 - C4*(b03+fi4+f04) = 0 135 | ~ C4*f04 + I5*bi5 + O*b0O - C5*(b04+fi5+f0O) = 0 136 | ~ C5*f0O + I6*bin - O*(b0O+fin) = 0 137 | 138 | ~ C1*fi1 + I2*b11 - I1*( bi1+f11) = 0 139 | ~ I1*f11 + C2*fi2 + I3*b12 - I2*(b11+bi2+f12) = 0 140 | ~ I2*f12 + C3*fi3 + I4*bi3 - I3*(b12+bi3+f13) = 0 141 | ~ I3*f13 + C4*fi4 + I5*b14 - I4*(b13+bi4+f14) = 0 142 | ~ I4*f14 + C5*fi5 + I6*b1n - I5*(b14+bi5+f1n) = 0 143 | 144 | ~ C1 + C2 + C3 + C4 + C5 + O + I1 + I2 + I3 + I4 + I5 + I6 = 1 145 | } 146 | 147 | PROCEDURE rates(v(mV) ) 148 | { 149 | LOCAL qt 150 | qt = 2.3^((celsius-37)/10) 151 | 152 | f01 = qt * 4 * alpha * exp(v/x1) 153 | f02 = qt * 3 * alpha * exp(v/x1) 154 | f03 = qt * 2 * alpha * exp(v/x1) 155 | f04 = qt * 1 * alpha * exp(v/x1) 156 | f0O = qt * gamma 157 | f11 = qt * 4 * alpha * alfac * exp(v/x1) 158 | f12 = qt * 3 * alpha * alfac * exp(v/x1) 159 | f13 = qt * 2 * alpha * alfac * exp(v/x1) 160 | f14 = qt * 1 * alpha * alfac * exp(v/x1) 161 | f1n = qt * gamma 162 | fi1 = qt * Con 163 | fi2 = qt * Con * alfac 164 | fi3 = qt * Con * alfac^2 165 | fi4 = qt * Con * alfac^3 166 | fi5 = qt * Con * alfac^4 167 | fin = qt * Oon 168 | 169 | b01 = qt * 1 * beta * exp(v/x2) 170 | b02 = qt * 2 * beta * exp(v/x2) 171 | b03 = qt * 3 * beta * exp(v/x2) 172 | b04 = qt * 4 * beta * exp(v/x2) 173 | b0O = qt * delta 174 | b11 = qt * 1 * beta * exp(v/x2) / btfac 175 | b12 = qt * 2 * beta * exp(v/x2) / btfac 176 | b13 = qt * 3 * beta * exp(v/x2) / btfac 177 | b14 = qt * 4 * beta * exp(v/x2) / btfac 178 | b1n = qt * delta 179 | bi1 = qt * Coff 180 | bi2 = qt * Coff / (btfac) 181 | bi3 = qt * Coff / (btfac^2) 182 | bi4 = qt * Coff / (btfac^3) 183 | bi5 = qt * Coff / (btfac^4) 184 | bin = qt * Ooff 185 | } 186 | 187 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/NaV2.mod: -------------------------------------------------------------------------------- 1 | TITLE Mouse sodium current 2 | : Kinetics of Carter et al. (2012) 3 | : Based on 37 degC recordings from mouse hippocampal CA1 pyramids 4 | 5 | NEURON { 6 | SUFFIX NaV2 7 | USEION na READ ena WRITE ina 8 | RANGE g, gbar 9 | } 10 | 11 | UNITS { 12 | (mV) = (millivolt) 13 | (S) = (siemens) 14 | } 15 | 16 | PARAMETER { 17 | gbar = .015 (S/cm2) 18 | 19 | : kinetic parameters 20 | Con = 0.01 (/ms) : closed -> inactivated transitions 21 | Coff = 2 (/ms) : inactivated -> closed transitions 22 | Oon = 8 (/ms) : open -> Ineg transition 23 | Ooff = 0.05 (/ms) : Ineg -> open transition 24 | alpha = 400 (/ms) 25 | beta = 12 (/ms) 26 | gamma = 250 (/ms) : opening 27 | delta = 60 (/ms) : closing 28 | 29 | alfac = 2.51 30 | btfac = 5.32 31 | 32 | : Vdep 33 | x1 = 24 (mV) : Vdep of activation (alpha) 34 | x2 = -24 (mV) : Vdep of deactivation (beta) 35 | rateadj = 1 36 | } 37 | 38 | ASSIGNED { 39 | 40 | : rates 41 | f01 (/ms) 42 | f02 (/ms) 43 | f03 (/ms) 44 | f04 (/ms) 45 | f0O (/ms) 46 | f11 (/ms) 47 | f12 (/ms) 48 | f13 (/ms) 49 | f14 (/ms) 50 | f1n (/ms) 51 | fi1 (/ms) 52 | fi2 (/ms) 53 | fi3 (/ms) 54 | fi4 (/ms) 55 | fi5 (/ms) 56 | fin (/ms) 57 | 58 | b01 (/ms) 59 | b02 (/ms) 60 | b03 (/ms) 61 | b04 (/ms) 62 | b0O (/ms) 63 | b11 (/ms) 64 | b12 (/ms) 65 | b13 (/ms) 66 | b14 (/ms) 67 | b1n (/ms) 68 | bi1 (/ms) 69 | bi2 (/ms) 70 | bi3 (/ms) 71 | bi4 (/ms) 72 | bi5 (/ms) 73 | bin (/ms) 74 | 75 | v (mV) 76 | ena (mV) 77 | ina (milliamp/cm2) 78 | g (S/cm2) 79 | celsius (degC) 80 | } 81 | 82 | STATE { 83 | C1 FROM 0 TO 1 84 | C2 FROM 0 TO 1 85 | C3 FROM 0 TO 1 86 | C4 FROM 0 TO 1 87 | C5 FROM 0 TO 1 88 | I1 FROM 0 TO 1 89 | I2 FROM 0 TO 1 90 | I3 FROM 0 TO 1 91 | I4 FROM 0 TO 1 92 | I5 FROM 0 TO 1 93 | O FROM 0 TO 1 94 | I6 FROM 0 TO 1 95 | } 96 | 97 | BREAKPOINT { 98 | SOLVE activation METHOD sparse 99 | g = gbar * O 100 | ina = g * (v - ena) 101 | } 102 | 103 | INITIAL { 104 | rates(v) 105 | SOLVE seqinitial 106 | } 107 | 108 | KINETIC activation 109 | { 110 | rates(v) 111 | ~ C1 <-> C2 (f01,b01) 112 | ~ C2 <-> C3 (f02,b02) 113 | ~ C3 <-> C4 (f03,b03) 114 | ~ C4 <-> C5 (f04,b04) 115 | ~ C5 <-> O (f0O,b0O) 116 | ~ O <-> I6 (fin,bin) 117 | ~ I1 <-> I2 (f11,b11) 118 | ~ I2 <-> I3 (f12,b12) 119 | ~ I3 <-> I4 (f13,b13) 120 | ~ I4 <-> I5 (f14,b14) 121 | ~ I5 <-> I6 (f1n,b1n) 122 | ~ C1 <-> I1 (fi1,bi1) 123 | ~ C2 <-> I2 (fi2,bi2) 124 | ~ C3 <-> I3 (fi3,bi3) 125 | ~ C4 <-> I4 (fi4,bi4) 126 | ~ C5 <-> I5 (fi5,bi5) 127 | 128 | CONSERVE C1 + C2 + C3 + C4 + C5 + O + I1 + I2 + I3 + I4 + I5 + I6 = 1 129 | } 130 | 131 | LINEAR seqinitial { : sets initial equilibrium 132 | ~ I1*bi1 + C2*b01 - C1*( fi1+f01) = 0 133 | ~ C1*f01 + I2*bi2 + C3*b02 - C2*(b01+fi2+f02) = 0 134 | ~ C2*f02 + I3*bi3 + C4*b03 - C3*(b02+fi3+f03) = 0 135 | ~ C3*f03 + I4*bi4 + C5*b04 - C4*(b03+fi4+f04) = 0 136 | ~ C4*f04 + I5*bi5 + O*b0O - C5*(b04+fi5+f0O) = 0 137 | ~ C5*f0O + I6*bin - O*(b0O+fin) = 0 138 | 139 | ~ C1*fi1 + I2*b11 - I1*( bi1+f11) = 0 140 | ~ I1*f11 + C2*fi2 + I3*b12 - I2*(b11+bi2+f12) = 0 141 | ~ I2*f12 + C3*fi3 + I4*bi3 - I3*(b12+bi3+f13) = 0 142 | ~ I3*f13 + C4*fi4 + I5*b14 - I4*(b13+bi4+f14) = 0 143 | ~ I4*f14 + C5*fi5 + I6*b1n - I5*(b14+bi5+f1n) = 0 144 | 145 | ~ C1 + C2 + C3 + C4 + C5 + O + I1 + I2 + I3 + I4 + I5 + I6 = 1 146 | } 147 | 148 | PROCEDURE rates(v(mV) ) 149 | { 150 | LOCAL qt 151 | qt = 2.3^((celsius-37)/10) * rateadj 152 | 153 | f01 = qt * 4 * alpha * exp(v/x1) 154 | f02 = qt * 3 * alpha * exp(v/x1) 155 | f03 = qt * 2 * alpha * exp(v/x1) 156 | f04 = qt * 1 * alpha * exp(v/x1) 157 | f0O = qt * gamma 158 | f11 = qt * 4 * alpha * alfac * exp(v/x1) 159 | f12 = qt * 3 * alpha * alfac * exp(v/x1) 160 | f13 = qt * 2 * alpha * alfac * exp(v/x1) 161 | f14 = qt * 1 * alpha * alfac * exp(v/x1) 162 | f1n = qt * gamma 163 | fi1 = qt * Con 164 | fi2 = qt * Con * alfac 165 | fi3 = qt * Con * alfac^2 166 | fi4 = qt * Con * alfac^3 167 | fi5 = qt * Con * alfac^4 168 | fin = qt * Oon 169 | 170 | b01 = qt * 1 * beta * exp(v/x2) 171 | b02 = qt * 2 * beta * exp(v/x2) 172 | b03 = qt * 3 * beta * exp(v/x2) 173 | b04 = qt * 4 * beta * exp(v/x2) 174 | b0O = qt * delta 175 | b11 = qt * 1 * beta * exp(v/x2) / btfac 176 | b12 = qt * 2 * beta * exp(v/x2) / btfac 177 | b13 = qt * 3 * beta * exp(v/x2) / btfac 178 | b14 = qt * 4 * beta * exp(v/x2) / btfac 179 | b1n = qt * delta 180 | bi1 = qt * Coff 181 | bi2 = qt * Coff / (btfac) 182 | bi3 = qt * Coff / (btfac^2) 183 | bi4 = qt * Coff / (btfac^3) 184 | bi5 = qt * Coff / (btfac^4) 185 | bin = qt * Ooff 186 | } 187 | 188 | -------------------------------------------------------------------------------- /biophys_optimize/modfiles/Nap.mod: -------------------------------------------------------------------------------- 1 | :Reference : Modeled according to kinetics derived from Magistretti & Alonso 1999 2 | :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 3 | 4 | NEURON { 5 | SUFFIX Nap 6 | USEION na READ ena WRITE ina 7 | RANGE gbar, g, ina 8 | } 9 | 10 | UNITS { 11 | (S) = (siemens) 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | } 15 | 16 | PARAMETER { 17 | gbar = 0.00001 (S/cm2) 18 | } 19 | 20 | ASSIGNED { 21 | v (mV) 22 | ena (mV) 23 | ina (mA/cm2) 24 | g (S/cm2) 25 | celsius (degC) 26 | mInf 27 | hInf 28 | hTau 29 | hAlpha 30 | hBeta 31 | } 32 | 33 | STATE { 34 | h 35 | } 36 | 37 | BREAKPOINT { 38 | SOLVE states METHOD cnexp 39 | rates() 40 | g = gbar*mInf*h 41 | ina = g*(v-ena) 42 | } 43 | 44 | DERIVATIVE states { 45 | rates() 46 | h' = (hInf-h)/hTau 47 | } 48 | 49 | INITIAL{ 50 | rates() 51 | h = hInf 52 | } 53 | 54 | PROCEDURE rates(){ 55 | LOCAL qt 56 | qt = 2.3^((celsius-21)/10) 57 | 58 | UNITSOFF 59 | mInf = 1.0/(1+exp((v- -52.6)/-4.6)) : assuming instantaneous activation as modeled by Magistretti and Alonso 60 | 61 | hInf = 1.0/(1+exp((v- -48.8)/10)) 62 | hAlpha = 2.88e-6 * vtrap(v + 17, 4.63) 63 | hBeta = 6.94e-6 * vtrap(-(v + 64.4), 2.63) 64 | 65 | hTau = (1/(hAlpha + hBeta))/qt 66 | UNITSON 67 | } 68 | 69 | FUNCTION vtrap(x, y) { : Traps for 0 in denominator of rate equations 70 | UNITSOFF 71 | if (fabs(x / y) < 1e-6) { 72 | vtrap = y * (1 - x / y / 2) 73 | } else { 74 | vtrap = x / (exp(x / y) - 1) 75 | } 76 | UNITSON 77 | } -------------------------------------------------------------------------------- /biophys_optimize/modfiles/SK.mod: -------------------------------------------------------------------------------- 1 | : SK-type calcium-activated potassium current 2 | : Reference : Kohler et al. 1996 3 | 4 | NEURON { 5 | SUFFIX SK 6 | USEION k READ ek WRITE ik 7 | USEION ca READ cai 8 | RANGE gbar, g, ik 9 | } 10 | 11 | UNITS { 12 | (mV) = (millivolt) 13 | (mA) = (milliamp) 14 | (mM) = (milli/liter) 15 | } 16 | 17 | PARAMETER { 18 | v (mV) 19 | gbar = .000001 (mho/cm2) 20 | zTau = 1 (ms) 21 | ek (mV) 22 | cai (mM) 23 | } 24 | 25 | ASSIGNED { 26 | zInf 27 | ik (mA/cm2) 28 | g (S/cm2) 29 | } 30 | 31 | STATE { 32 | z FROM 0 TO 1 33 | } 34 | 35 | BREAKPOINT { 36 | SOLVE states METHOD cnexp 37 | g = gbar * z 38 | ik = g * (v - ek) 39 | } 40 | 41 | DERIVATIVE states { 42 | rates(cai) 43 | z' = (zInf - z) / zTau 44 | } 45 | 46 | PROCEDURE rates(ca(mM)) { 47 | if(ca < 1e-7){ 48 | ca = ca + 1e-07 49 | } 50 | zInf = 1/(1 + (0.00043 / ca)^4.8) 51 | } 52 | 53 | INITIAL { 54 | rates(cai) 55 | z = zInf 56 | } 57 | -------------------------------------------------------------------------------- /biophys_optimize/neuron_parallel.py: -------------------------------------------------------------------------------- 1 | from builtins import zip 2 | from neuron import h 3 | import logging 4 | 5 | _pc = h.ParallelContext() 6 | 7 | def map(func, *iterables): 8 | """Submit function (`func`) and arguments (`iterables`) to NEURON parallel context""" 9 | start_time = pc_time() 10 | userids = [] 11 | userid = 200 # arbitrary, but needs to be a positive integer 12 | for args in zip(*iterables): 13 | args2 = (list(a) for a in args) 14 | _pc.submit(userid, func, *args2) 15 | userids.append(userid) 16 | userid += 1 17 | 18 | results = dict(_working()) 19 | 20 | end_time = _pc_time() 21 | logging.info("Map took {} seconds".format(end_time - start_time)) 22 | return [results[userid] for userid in userids] 23 | 24 | 25 | def _working(): 26 | while _pc.working(): 27 | userid = int(_pc.userid()) 28 | ret = _pc.pyret() 29 | yield userid, ret 30 | 31 | 32 | def _runworker(): 33 | _pc.runworker() 34 | 35 | 36 | def _done(): 37 | _pc.done() 38 | 39 | 40 | def _pc_time(): 41 | return _pc.time() -------------------------------------------------------------------------------- /biophys_optimize/neuron_passive_fit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from builtins import range 4 | from neuron import h 5 | import numpy as np 6 | import argparse 7 | import json 8 | import os.path 9 | from dataclasses import dataclass 10 | 11 | PASSIVE_FIT_1 = "passive_fit_1" 12 | PASSIVE_FIT_2 = "passive_fit_2" 13 | PASSIVE_FIT_ELEC = "passive_fit_elec" 14 | 15 | @dataclass 16 | class PassiveFitResult: 17 | """DataClass for passive fit results. 18 | 19 | Attributes 20 | ---------- 21 | ra : float 22 | Axial resistivity 23 | cm : float 24 | Specific membrane capacitance 25 | rm : float 26 | Specific membrane resistance 27 | a1 : float 28 | Surface area of the soma and axon compartments 29 | a2 : float 30 | Surface area of the dendrite compartments 31 | """ 32 | ra: float 33 | cm: float 34 | rm: float 35 | err: float 36 | a1: float 37 | a2: float 38 | 39 | 40 | 41 | def initialize_neuron(swc_path, file_paths): 42 | """ Initialize neuron with morphology and load hoc files 43 | 44 | Parameters 45 | ---------- 46 | swc_path : str 47 | Path to SWC file 48 | file_paths : list 49 | List of str file paths of files for NEURON to load 50 | 51 | """ 52 | h.load_file("stdgui.hoc") 53 | h.load_file("import3d.hoc") 54 | 55 | swc = h.Import3d_SWC_read() 56 | swc.input(swc_path) 57 | imprt = h.Import3d_GUI(swc, 0) 58 | h("objref this") 59 | imprt.instantiate(h.this) 60 | 61 | for sec in h.allsec(): 62 | if sec.name().startswith("axon"): 63 | h.delete_section(sec=sec) 64 | 65 | axon = h.Section() 66 | axon.L = 60 67 | axon.diam = 1 68 | axon.connect(h.soma[0], 0.5, 0) 69 | 70 | h.define_shape() 71 | 72 | for sec in h.allsec(): 73 | sec.insert('pas') 74 | for seg in sec: 75 | seg.pas.e = 0 76 | 77 | for file_path in file_paths: 78 | h.load_file(file_path.encode("ascii", "ignore")) 79 | 80 | 81 | def _common_config(fit_window_start, fit_window_end, up_data, down_data): 82 | h.v_init = 0 83 | h.tstop = 100 84 | h.cvode_active(1) 85 | 86 | v_rec = h.Vector() 87 | t_rec = h.Vector() 88 | v_rec.record(h.soma[0](0.5)._ref_v) 89 | t_rec.record(h._ref_t) 90 | 91 | mrf = h.MulRunFitter[0] 92 | gen0 = mrf.p.pf.generatorlist.object(0) 93 | gen0.toggle() 94 | fit0 = gen0.gen.fitnesslist.object(0) 95 | 96 | up_t = h.Vector(up_data[:, 0]) 97 | up_v = h.Vector(up_data[:, 1]) 98 | fit0.set_data(up_t, up_v) 99 | fit0.boundary.x[0] = fit_window_start 100 | fit0.boundary.x[1] = fit_window_end 101 | fit0.set_w() 102 | 103 | gen1 = mrf.p.pf.generatorlist.object(1) 104 | gen1.toggle() 105 | fit1 = gen1.gen.fitnesslist.object(0) 106 | 107 | down_t = h.Vector(down_data[:, 0]) 108 | down_v = h.Vector(down_data[:, 1]) 109 | fit1.set_data(down_t, down_v) 110 | fit1.boundary.x[0] = fit_window_start 111 | fit1.boundary.x[1] = fit_window_end 112 | fit1.set_w() 113 | 114 | return mrf 115 | 116 | 117 | def passive_fit_1(up_data, down_data, fit_window_start, fit_window_end, 118 | n_init=10): 119 | """ Fit passive properties (Ri, Cm, and Rm) 120 | 121 | Parameters 122 | ---------- 123 | up_data: (n_samples, 2) array 124 | Positive-going times and voltage responses 125 | down_data: (n_samples, 2) array 126 | Negative-going times and voltage responses 127 | fit_window_start: float 128 | Start of fit window (ms) 129 | fit_window_end: float 130 | End of fit window (ms) 131 | n_init: int, optional 132 | Number of random starts for passive fitting (default 10) 133 | 134 | Returns 135 | ------- 136 | :class:`PassiveFitResult` 137 | """ 138 | mrf = _common_config(fit_window_start, fit_window_end, up_data, down_data) 139 | 140 | minerr = 1e12 141 | for i in range(n_init): 142 | # Need to re-initialize the internal MRF variables, not top-level proxies 143 | # for randomize() to work 144 | mrf.p.pf.parmlist.object(0).val = 100 145 | mrf.p.pf.parmlist.object(1).val = 1 146 | mrf.p.pf.parmlist.object(2).val = 10000 147 | mrf.p.pf.putall() 148 | mrf.randomize() 149 | mrf.prun() 150 | if mrf.opt.minerr < minerr: 151 | fit_Ri = h.Ri 152 | fit_Cm = h.Cm 153 | fit_Rm = h.Rm 154 | minerr = mrf.opt.minerr 155 | 156 | return PassiveFitResult( 157 | fit_Ri, fit_Cm, fit_Rm, minerr, h.somaaxon_area(), h.alldend_area()) 158 | 159 | 160 | def passive_fit_2(up_data, down_data, fit_window_start, fit_window_end, 161 | n_init=10): 162 | """ Fit passive properties (Cm, and Rm) with Ri fixed at 100 Ohm-cm 163 | 164 | Parameters 165 | ---------- 166 | up_data: array, shape (n_samples, 2) 167 | Positive-going times and voltage responses 168 | down_data: array, shape (n_samples, 2) 169 | Negative-going times and voltage responses 170 | fit_window_start: float 171 | Start of fit window (ms) 172 | fit_window_end: float 173 | End of fit window (ms) 174 | n_init: int (optional, default 10) 175 | Number of random starts for passive fitting 176 | 177 | Returns 178 | ------- 179 | :class:`PassiveFitResult` 180 | """ 181 | mrf = _common_config(fit_window_start, fit_window_end, up_data, down_data) 182 | 183 | minerr = 1e12 184 | for i in range(n_init): 185 | # Need to re-initialize the internal MRF variables, not top-level proxies 186 | # for randomize() to work 187 | mrf.p.pf.parmlist.object(0).val = 1 188 | mrf.p.pf.parmlist.object(1).val = 10000 189 | mrf.p.pf.putall() 190 | mrf.randomize() 191 | mrf.prun() 192 | if mrf.opt.minerr < minerr: 193 | fit_Ri = h.Ri 194 | fit_Cm = h.Cm 195 | fit_Rm = h.Rm 196 | minerr = mrf.opt.minerr 197 | 198 | return PassiveFitResult( 199 | fit_Ri, fit_Cm, fit_Rm, minerr, h.somaaxon_area(), h.alldend_area()) 200 | 201 | 202 | def passive_fit_elec(up_data, down_data, fit_window_start, fit_window_end, 203 | bridge, electrode_cap, n_init=10): 204 | """ Fit passive properties (Ri, Cm, and Rm) with simulated recording electrode 205 | 206 | Parameters 207 | ---------- 208 | up_data: array, shape (n_samples, 2) 209 | Positive-going times and voltage responses 210 | down_data: array, shape (n_samples, 2) 211 | Negative-going times and voltage responses 212 | fit_window_start: float 213 | Start of fit window (ms) 214 | fit_window_end: float 215 | End of fit window (ms) 216 | bridge: float 217 | Value of bridge balance (estimated series resistance), MOhm 218 | electrode_cap: float 219 | Value of electrode capacitance (pF) 220 | n_init: int (optional, default 10) 221 | Number of random starts for passive fitting 222 | 223 | Returns 224 | ------- 225 | :class:`PassiveFitResult` 226 | """ 227 | mrf = _common_config(fit_window_start, fit_window_end, up_data, down_data) 228 | 229 | circuit = h.LinearCircuit[0] 230 | circuit.R2 = bridge / 2.0 231 | circuit.R3 = bridge / 2.0 232 | circuit.C4 = electrode_cap * 1e-3 233 | 234 | minerr = 1e12 235 | for i in range(n_init): 236 | # Need to re-initialize the internal MRF variables, not top-level proxies 237 | # for randomize() to work 238 | mrf.p.pf.parmlist.object(0).val = 100 239 | mrf.p.pf.parmlist.object(1).val = 1 240 | mrf.p.pf.parmlist.object(2).val = 10000 241 | mrf.p.pf.putall() 242 | mrf.randomize() 243 | mrf.prun() 244 | if mrf.opt.minerr < minerr: 245 | fit_Ri = h.Ri 246 | fit_Cm = h.Cm 247 | fit_Rm = h.Rm 248 | minerr = mrf.opt.minerr 249 | 250 | return PassiveFitResult( 251 | fit_Ri, fit_Cm, fit_Rm, minerr, h.somaaxon_area(), h.alldend_area()) 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /biophys_optimize/optimize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | from builtins import zip 5 | from builtins import str 6 | from builtins import map 7 | from builtins import range 8 | from mpi4py import MPI 9 | 10 | import argparse 11 | import numpy as np 12 | import random 13 | import json 14 | import os.path 15 | from dataclasses import dataclass 16 | from deap import algorithms, base, creator, tools 17 | from .utils import Utils 18 | from .environment import NeuronEnvironment 19 | from . import neuron_parallel 20 | 21 | 22 | # Constants 23 | BOUND_LOWER, BOUND_UPPER = 0.0, 1.0 24 | DEFAULT_NGEN = 500 25 | DEFAULT_MU = 1200 26 | 27 | # Globals - can't be used in partial functions with NEURON 28 | # so cannot be just passed into evaluation function 29 | utils = None 30 | t_vec = None 31 | v_vec = None 32 | i_vec = None 33 | 34 | 35 | @dataclass 36 | class StimParams: 37 | """ Dataclass for stimulation parameters 38 | 39 | Attributes 40 | ---------- 41 | amplitude : float 42 | Stimulus amplitude (nA) 43 | delay : float 44 | Delay before stimulus start (ms) 45 | duration : float 46 | Duration of stimulus (ms) 47 | """ 48 | amplitude: float 49 | delay: float 50 | duration: float 51 | 52 | 53 | def eval_param_set(params, do_block_check, max_stim_amp, stim_params, 54 | features, targets, t_vec): 55 | """Calculate a fitness score (lower is better) for a set of model parameters 56 | 57 | Parameters 58 | ---------- 59 | params : array 60 | Normalized (from 0 to 1) parameters for model 61 | do_block_check : bool 62 | Whether to check for depolarization block 63 | max_stim_amp : float 64 | Stimulation amplitude to use for depolarization block check 65 | stim_params : :class:`StimParams` 66 | Stimulation parameters 67 | features : list 68 | List of feature names (str) 69 | targets : dict 70 | Dictionary with feature names as keys and elements as dicts with "mean" and "stdev" key-value pairs 71 | t_vec : NEURON Vector 72 | time vector 73 | 74 | Returns 75 | ------- 76 | float 77 | Sum of feature errors for use as a fitness score 78 | """ 79 | utils.set_normalized_parameters(params) 80 | h = utils.h 81 | h.finitialize() 82 | h.run() 83 | 84 | try: 85 | feature_errors = utils.calculate_feature_errors(t_vec.as_numpy(), 86 | v_vec.as_numpy(), 87 | i_vec.as_numpy(), 88 | features, 89 | targets) 90 | except: 91 | print("Error with parameter set: %s" % str(params)) 92 | raise 93 | 94 | min_fail_penalty = 75.0 95 | if do_block_check and np.sum(feature_errors) < min_fail_penalty * len(feature_errors): 96 | if check_for_block(max_stim_amp, stim_params): 97 | feature_errors = min_fail_penalty * np.ones_like(feature_errors) 98 | # Reset the stimulus back 99 | utils.set_iclamp_params(stim_params.amplitude, stim_params.delay, 100 | stim_params.duration) 101 | 102 | return [np.sum(feature_errors)] 103 | 104 | 105 | def check_for_block(max_stim_amp, stim_params): 106 | """Check for presence of depolarization block at high stimulus amplitudes 107 | 108 | Parameters 109 | ---------- 110 | max_stim_amp : float 111 | Stimulus amplitude for depolarization block check (nA) 112 | stim_params : :class:`StimParams` 113 | Stimulus parameters (only delay and duration used) 114 | 115 | 116 | Returns 117 | ------- 118 | bool 119 | Whether the model exhibits depolarization block 120 | """ 121 | 122 | utils.set_iclamp_params(max_stim_amp, stim_params.delay, 123 | stim_params.duration) 124 | h = utils.h 125 | h.finitialize() 126 | h.run() 127 | 128 | v = v_vec.as_numpy() 129 | t = t_vec.as_numpy() 130 | stim_start_idx = np.flatnonzero(t >= utils.stim.delay)[0] 131 | stim_end_idx = np.flatnonzero(t >= utils.stim.delay + utils.stim.dur)[0] 132 | depol_block_threshold = -50.0 # mV 133 | block_min_duration = 50.0 # ms 134 | long_hyperpol_threshold = -75.0 # mV 135 | 136 | bool_v = np.array(v > depol_block_threshold, dtype=int) 137 | up_indexes = np.flatnonzero(np.diff(bool_v) == 1) 138 | down_indexes = np.flatnonzero(np.diff(bool_v) == -1) 139 | if len(up_indexes) > len(down_indexes): 140 | down_indexes = np.append(down_indexes, [stim_end_idx]) 141 | 142 | if len(up_indexes) == 0: 143 | # if it never gets high enough, that's not a good sign (meaning no spikes) 144 | return True 145 | else: 146 | max_depol_duration = np.max([t[down_indexes[k]] - t[up_idx] for k, up_idx in enumerate(up_indexes)]) 147 | if max_depol_duration > block_min_duration: 148 | return True 149 | 150 | bool_v = np.array(v > long_hyperpol_threshold, dtype=int) 151 | up_indexes = np.flatnonzero(np.diff(bool_v) == 1) 152 | down_indexes = np.flatnonzero(np.diff(bool_v) == -1) 153 | down_indexes = down_indexes[(down_indexes > stim_start_idx) & (down_indexes < stim_end_idx)] 154 | if len(down_indexes) != 0: 155 | up_indexes = up_indexes[(up_indexes > stim_start_idx) & (up_indexes < stim_end_idx) & (up_indexes > down_indexes[0])] 156 | if len(up_indexes) < len(down_indexes): 157 | up_indexes = np.append(up_indexes, [stim_end_idx]) 158 | max_hyperpol_duration = np.max([t[up_indexes[k]] - t[down_idx] for k, down_idx in enumerate(down_indexes)]) 159 | if max_hyperpol_duration > block_min_duration: 160 | return True 161 | return False 162 | 163 | 164 | def uniform(lower, upper, size=None): 165 | """Population generation with uniformly random variables 166 | 167 | Parameters 168 | ---------- 169 | lower : float 170 | Lower bound for parameter 171 | upper : float 172 | Upper bound for parameter 173 | size : int, optional 174 | Number of samples to generate. If None, generates one sample 175 | 176 | Returns 177 | ------- 178 | list 179 | Returns list with ``size`` samples uniformly distributed between ``lower`` and ``upper`` 180 | """ 181 | 182 | if size is None: 183 | return [random.uniform(a, b) for a, b in zip(lower, upper)] 184 | else: 185 | return [random.uniform(a, b) for a, b in zip([lower] * size, [upper] * size)] 186 | 187 | 188 | def best_sum(d): 189 | """ Return the lowest sum across columns 190 | 191 | Parameters 192 | ---------- 193 | d : (n, p) array 194 | Array with `n` samples each with `p` feature errors 195 | 196 | Returns 197 | ------- 198 | float 199 | Minimum feature error sum across samples in `d` 200 | """ 201 | return np.sum(d, axis=1).min() 202 | 203 | 204 | def initPopulation(pcls, ind_init, popfile): 205 | """ Load starting population from file 206 | 207 | Parameters 208 | ---------- 209 | pcls : function 210 | Population creation function (e.g. `list`) 211 | ind_init : function 212 | Individual initialization function 213 | popfile : str 214 | Path to population text file (with actual parameter values) 215 | 216 | Returns 217 | ------- 218 | any 219 | Result of `pcls` call 220 | """ 221 | popdata = np.loadtxt(popfile) 222 | return pcls(ind_init(utils.normalize_actual_parameters(line)) for line in popdata.tolist()) 223 | 224 | 225 | def optimize(hoc_files, compiled_mod_library, morphology_path, 226 | features, targets, stim_params, passive_results, 227 | fit_type, fit_style_data, 228 | ngen, seed, mu, 229 | storage_directory, 230 | starting_population=None): 231 | """ Perform embarrassingly parallel evolutionary optimization with NEURON 232 | 233 | Parameters 234 | ---------- 235 | hoc_files : list 236 | List of hoc files for NEURON to load 237 | compiled_mod_library : str 238 | Path to compiled .mod file library 239 | morphology_path : str 240 | Path to morphology SWC file 241 | features : list 242 | List of features to match 243 | targets : dict 244 | Dictionary with feature names as keys and elements as dicts with "mean" and "stdev" key-value pairs 245 | stim_params : :class:`StimParams` 246 | Stimulation parameters 247 | passive_results : dict 248 | Dictionary with passive parameters 249 | fit_type : str 250 | Code for fit type (for output filenames) 251 | fit_style_data : dict 252 | Dictionary of fit style parameters 253 | ngen : int 254 | Number of generations 255 | seed : int 256 | Seed for random number generator 257 | mu : int 258 | Size of each generation 259 | storage_directory : str 260 | Path to storage directory 261 | starting_population : str, optional 262 | Path to file with starting population. If `None`, a random starting population 263 | is generated. 264 | 265 | Returns 266 | ------- 267 | dict 268 | Dictionary with paths to output files 269 | """ 270 | # need to be global since cannot pass via partial functions to 271 | # parallel NEURON mapping function 272 | global utils 273 | global v_vec, i_vec, t_vec 274 | 275 | do_block_check = fit_style_data["check_depol_block"] 276 | if do_block_check: 277 | max_stim_amp = preprocess_results["max_stim_test_na"] 278 | if max_stim_amp <= stim_params["amplitude"]: 279 | print("Depol block check not necessary") 280 | do_block_check = False 281 | else: 282 | max_stim_amp = None 283 | 284 | environment = NeuronEnvironment(hoc_files, compiled_mod_library) 285 | utils = Utils() 286 | h = utils.h 287 | 288 | utils.generate_morphology(morphology_path) 289 | utils.load_cell_parameters(passive_results, 290 | fit_style_data["conditions"], 291 | fit_style_data["channels"], 292 | fit_style_data["addl_params"]) 293 | utils.insert_iclamp() 294 | utils.set_iclamp_params(stim_params["amplitude"], stim_params["delay"], 295 | stim_params["duration"]) 296 | 297 | h.tstop = stim_params["delay"] * 2.0 + stim_params["duration"] 298 | h.celsius = fit_style_data["conditions"]["celsius"] 299 | h.v_init = preprocess_results["v_baseline"] 300 | h.cvode_active(1) 301 | h.cvode.atolscale("cai", 1e-4) 302 | h.cvode.maxstep(10) 303 | 304 | v_vec, i_vec, t_vec = utils.record_values() 305 | 306 | try: 307 | neuron_parallel._runworker() 308 | 309 | print("Setting up GA") 310 | random.seed(seed) 311 | 312 | cxpb = 0.1 313 | mtpb = 0.35 314 | eta = 10.0 315 | 316 | ndim = len(fit_style_data["channels"]) + len(fit_style_data["addl_params"]) 317 | 318 | creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) 319 | creator.create("Individual", list, fitness=creator.FitnessMin) 320 | 321 | toolbox = base.Toolbox() 322 | 323 | toolbox.register("attr_float", uniform, BOUND_LOWER, BOUND_UPPER, ndim) 324 | toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.attr_float) 325 | toolbox.register("population", tools.initRepeat, list, toolbox.individual) 326 | 327 | toolbox.register("evaluate", eval_param_set, 328 | do_block_check=do_block_check, 329 | max_stim_amp=max_stim_amp, 330 | stim_params=stim_params, 331 | features=features, 332 | targets=targets 333 | ) 334 | toolbox.register("mate", tools.cxSimulatedBinaryBounded, low=BOUND_LOWER, up=BOUND_UPPER, 335 | eta=eta) 336 | toolbox.register("mutate", tools.mutPolynomialBounded, low=BOUND_LOWER, up=BOUND_UPPER, 337 | eta=eta, indpb=mtpb) 338 | toolbox.register("variate", algorithms.varAnd) 339 | toolbox.register("select", tools.selBest) 340 | toolbox.register("map", neuron_parallel.map) 341 | 342 | stats = tools.Statistics(lambda ind: ind.fitness.values) 343 | stats.register("min", np.min, axis=0) 344 | stats.register("max", np.max, axis=0) 345 | stats.register("best", best_sum) 346 | 347 | logbook = tools.Logbook() 348 | logbook.header = "gen", "nevals", "min", "max", "best" 349 | 350 | if starting_population is not None: 351 | print("Using a pre-defined starting population") 352 | toolbox.register("population_start", initPopulation, list, creator.Individual) 353 | pop = toolbox.population_start(starting_population) 354 | else: 355 | pop = toolbox.population(n=mu) 356 | 357 | invalid_ind = [ind for ind in pop if not ind.fitness.valid] 358 | fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) 359 | 360 | for ind, fit in zip(invalid_ind, fitnesses): 361 | ind.fitness.values = fit 362 | 363 | hof = tools.HallOfFame(mu) 364 | hof.update(pop) 365 | 366 | record = stats.compile(pop) 367 | logbook.record(gen=0, nevals=len(invalid_ind), **record) 368 | print(logbook.stream) 369 | print("Best so far:") 370 | print(utils.actual_parameters_from_normalized(hof[0])) 371 | 372 | for gen in range(1, ngen + 1): 373 | offspring = toolbox.variate(pop, toolbox, cxpb, 1.0) 374 | 375 | invalid_ind = [ind for ind in offspring if not ind.fitness.valid] 376 | fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) 377 | for ind, fit in zip(invalid_ind, fitnesses): 378 | ind.fitness.values = fit 379 | 380 | hof.update(offspring) 381 | 382 | pop[:] = toolbox.select(pop + offspring, mu) 383 | 384 | record = stats.compile(pop) 385 | logbook.record(gen=gen, nevals=len(invalid_ind), **record) 386 | print(logbook.stream) 387 | print("Best so far:") 388 | print(utils.actual_parameters_from_normalized(hof[0])) 389 | 390 | utils.set_normalized_parameters(hof[0]) 391 | h.finitialize() 392 | h.run() 393 | feature_errors = utils.calculate_feature_errors(t_vec.as_numpy(), 394 | v_vec.as_numpy(), 395 | i_vec.as_numpy(), 396 | features, 397 | targets) 398 | print("Error vector for best so far: " + str(feature_errors)) 399 | 400 | prefix = "{:s}_{:d}_".format(fit_type, seed) 401 | 402 | final_pop_path = os.path.join(storage_directory, prefix + "final_pop.txt") 403 | np.savetxt(final_pop_path, np.array(list(map(utils.actual_parameters_from_normalized, pop)), dtype=np.float64)) 404 | 405 | final_pop_fit_path = os.path.join(storage_directory, prefix + "final_pop_fit.txt") 406 | np.savetxt(final_pop_fit_path, np.array([ind.fitness.values for ind in pop])) 407 | 408 | final_hof_path = os.path.join(storage_directory, prefix + "final_hof.txt") 409 | np.savetxt(final_hof_path, np.array(list(map(utils.actual_parameters_from_normalized, hof)), dtype=np.float64)) 410 | 411 | final_hof_fit_path = os.path.join(storage_directory, prefix + "final_hof_fit.txt") 412 | np.savetxt(final_hof_fit_path, np.array([ind.fitness.values for ind in hof])) 413 | 414 | output = { 415 | "paths": { 416 | "final_pop": final_pop_path, 417 | "final_pop_fit": final_pop_fit_path, 418 | "final_hof": final_hof_path, 419 | "final_hof_fit_path": final_hof_fit_path, 420 | } 421 | } 422 | 423 | neuron_parallel._done() 424 | 425 | return output 426 | except: 427 | print("Exception encountered during parallel NEURON execution") 428 | MPI.COMM_WORLD.Abort() 429 | raise 430 | 431 | 432 | 433 | -------------------------------------------------------------------------------- /biophys_optimize/passive/circuit.ses: -------------------------------------------------------------------------------- 1 | objectvar save_window_, rvp_ 2 | objectvar scene_vector_[8] 3 | objectvar ocbox_, ocbox_list_, scene_, scene_list_ 4 | {ocbox_list_ = new List() scene_list_ = new List()} 5 | 6 | //Begin LinearCircuit[0] 7 | { 8 | load_file("lincir.hoc", "LinearCircuit") 9 | } 10 | { 11 | ocbox_ = new LinearCircuit(1) 12 | } 13 | {object_push(ocbox_)} 14 | {version(2)} 15 | {mkelm(8, 80, 70, 2, 0)} 16 | {mklabel(0, "soma(0.5)", 0, 0)} 17 | {sel.extra_info.set("soma", 0.5) sel.extra_info.name(sel)} 18 | {mkelm(1, 100, 90, 2, 0)} 19 | 10 20 | {mklabel(0, "R2", 15, 15)} 21 | {mkelm(1, 140, 90, 2, 0)} 22 | 10 23 | {mklabel(0, "R3", 15, 15)} 24 | {mklabel(2, "Ve", 15, 15)} 25 | {mkelm(2, 120, 70, 2, 1.5708)} 26 | 0.001 27 | {mklabel(0, "C4", 15, 15)} 28 | {mkelm(6, 120, 30, 2, 0)} 29 | {mkelm(5, 185, 90, 2.5, 3.14159)} 30 | {mklabel(0, "I6", 15, 15)} 31 | {sel.extra_info.restore()} 32 | 3 33 | 2 0 34 | 0.5 0.2 35 | 1e+09 0 36 | {mkelm(6, 210, 70, 2, 0)} 37 | {parasitic_ = 0 noconsist_ = 0} 38 | {g.exec_menu("Simulate") tool(2)} 39 | {sel = nil} 40 | {object_pop()} 41 | { 42 | { 43 | save_window_=ocbox_.g 44 | save_window_.size(0,300,0,200) 45 | scene_vector_[4] = save_window_ 46 | ocbox_.g = save_window_ 47 | save_window_.save_name("ocbox_.g") 48 | save_window_.label(80, 70, "soma(0.5)", 1, 1, 0.5, 0.5, 1) 49 | save_window_.label(115, 105, "R2", 1, 1, 0.5, 0.5, 1) 50 | save_window_.label(155, 105, "R3", 1, 1, 0.5, 0.5, 1) 51 | save_window_.label(175, 105, "Ve", 1, 1, 0.5, 0.5, 1) 52 | save_window_.label(135, 85, "C4", 1, 1, 0.5, 0.5, 1) 53 | save_window_.label(200, 105, "I6", 1, 1, 0.5, 0.5, 1) 54 | } 55 | ocbox_.map("LinearCircuit[0]", 190, 596, 519.36, 284.16) 56 | } 57 | objref ocbox_ 58 | //End LinearCircuit[0] 59 | 60 | objectvar scene_vector_[1] 61 | {doNotify()} 62 | -------------------------------------------------------------------------------- /biophys_optimize/passive/fixnseg.hoc: -------------------------------------------------------------------------------- 1 | /* Sets nseg in each section to an odd value 2 | so that its segments are no longer than 3 | d_lambda x the AC length constant 4 | at frequency freq in that section. 5 | 6 | Be sure to specify your own Ra and cm before calling geom_nseg() 7 | 8 | To understand why this works, 9 | and the advantages of using an odd value for nseg, 10 | see Hines, M.L. and Carnevale, N.T. 11 | NEURON: a tool for neuroscientists. 12 | The Neuroscientist 7:123-135, 2001. 13 | */ 14 | 15 | // these are reasonable values for most models 16 | freq = 100 // Hz, frequency at which AC length constant will be computed 17 | d_lambda = 0.1 18 | 19 | func lambda_f() { local i, x1, x2, d1, d2, lam 20 | if (n3d() < 2) { 21 | return 1e5*sqrt(diam/(4*PI*$1*Ra*cm)) 22 | } 23 | // above was too inaccurate with large variation in 3d diameter 24 | // so now we use all 3-d points to get a better approximate lambda 25 | x1 = arc3d(0) 26 | d1 = diam3d(0) 27 | lam = 0 28 | for i=1, n3d()-1 { 29 | x2 = arc3d(i) 30 | d2 = diam3d(i) 31 | lam += (x2 - x1)/sqrt(d1 + d2) 32 | x1 = x2 d1 = d2 33 | } 34 | // length of the section in units of lambda 35 | lam *= sqrt(2) * 1e-5*sqrt(4*PI*$1*Ra*cm) 36 | 37 | return L/lam 38 | } 39 | 40 | proc geom_nseg() { 41 | area(0.5) // make sure diam reflects 3d points 42 | forall { nseg = int((L/(d_lambda*lambda_f(freq))+0.9)/2)*2 + 1 } 43 | } -------------------------------------------------------------------------------- /biophys_optimize/passive/iclamp.ses: -------------------------------------------------------------------------------- 1 | objectvar save_window_, rvp_ 2 | objectvar scene_vector_[3] 3 | objectvar ocbox_, ocbox_list_, scene_, scene_list_ 4 | {ocbox_list_ = new List() scene_list_ = new List()} 5 | 6 | //Begin PointProcessManager 7 | { 8 | load_file("pointman.hoc") 9 | } 10 | { 11 | soma ocbox_ = new PointProcessManager(0) 12 | } 13 | {object_push(ocbox_)} 14 | { 15 | mt.select("IClamp") i = mt.selected() 16 | ms[i] = new MechanismStandard("IClamp") 17 | ms[i].set("del", 2, 0) 18 | ms[i].set("dur", 0.5, 0) 19 | ms[i].set("amp", 0.2, 0) 20 | mt.select("IClamp") i = mt.selected() maction(i) 21 | hoc_ac_ = 0.5 22 | sec.sec move() d1.flip_to(0) 23 | } 24 | {object_pop() doNotify()} 25 | { 26 | ocbox_ = ocbox_.v1 27 | ocbox_.map("PointProcessManager", 66, 307, 208.32, 326.4) 28 | } 29 | objref ocbox_ 30 | //End PointProcessManager 31 | 32 | objectvar scene_vector_[1] 33 | {doNotify()} 34 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf.ses: -------------------------------------------------------------------------------- 1 | objectvar save_window_, rvp_ 2 | objectvar scene_vector_[7] 3 | objectvar ocbox_, ocbox_list_, scene_, scene_list_ 4 | {ocbox_list_ = new List() scene_list_ = new List()} 5 | 6 | //Begin MulRunFitter[0] 7 | { 8 | load_file("mulfit.hoc", "MulRunFitter") 9 | } 10 | { 11 | ocbox_ = new MulRunFitter(1) 12 | } 13 | {object_push(ocbox_)} 14 | { 15 | version(6) 16 | ranfac = 2 17 | fspec = new File("mrf.ses.ft1") 18 | fdat = new File("mrf.ses.fd1") 19 | read_data() 20 | build() 21 | } 22 | opt.set_optimizer("MulfitPraxWrap") 23 | {object_push(opt.optimizer)} 24 | { 25 | nstep = 0 26 | } 27 | {object_pop()} 28 | {object_pop()} 29 | { 30 | ocbox_.map("MulRunFitter[0]", 729, 164, 360.96, 199.68) 31 | } 32 | objref ocbox_ 33 | //End MulRunFitter[0] 34 | 35 | objectvar scene_vector_[1] 36 | {doNotify()} 37 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf.ses.ft1: -------------------------------------------------------------------------------- 1 | ParmFitness: Unnamed multiple run protocol 2 | FitnessGenerator: iclamp_up 3 | RunStatement: 2, IClamp[0].amp = 0.2 4 | RegionFitness: soma.v(0.5) 5 | 6 | FitnessGenerator: iclamp_down 7 | RunStatement: 2, IClamp[0].amp = -0.2 8 | RegionFitness: soma.v(0.5) 9 | 10 | Parameters: 11 | "Ri", 100, 1e+01, 1e+03, 1, 1 12 | "Cm", 1, 1e-09, 1e+09, 1, 1 13 | "Rm", 10000, 1e-09, 1e+09, 1, 1 14 | End ParmFitness 15 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf2.ses: -------------------------------------------------------------------------------- 1 | objectvar save_window_, rvp_ 2 | objectvar scene_vector_[7] 3 | objectvar ocbox_, ocbox_list_, scene_, scene_list_ 4 | {ocbox_list_ = new List() scene_list_ = new List()} 5 | 6 | //Begin MulRunFitter[0] 7 | { 8 | load_file("mulfit.hoc", "MulRunFitter") 9 | } 10 | { 11 | ocbox_ = new MulRunFitter(1) 12 | } 13 | {object_push(ocbox_)} 14 | { 15 | version(6) 16 | ranfac = 2 17 | fspec = new File("mrf2.ses.ft1") 18 | fdat = new File("mrf2.ses.fd1") 19 | read_data() 20 | build() 21 | } 22 | opt.set_optimizer("MulfitPraxWrap") 23 | {object_push(opt.optimizer)} 24 | { 25 | nstep = 0 26 | } 27 | {object_pop()} 28 | {object_pop()} 29 | { 30 | ocbox_.map("MulRunFitter[0]", 729, 164, 360.96, 199.68) 31 | } 32 | objref ocbox_ 33 | //End MulRunFitter[0] 34 | 35 | objectvar scene_vector_[1] 36 | {doNotify()} 37 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf2.ses.ft1: -------------------------------------------------------------------------------- 1 | ParmFitness: Unnamed multiple run protocol 2 | FitnessGenerator: iclamp_up 3 | RunStatement: 2, IClamp[0].amp = 0.2 4 | RegionFitness: soma.v(0.5) 5 | 6 | FitnessGenerator: iclamp_down 7 | RunStatement: 2, IClamp[0].amp = -0.2 8 | RegionFitness: soma.v(0.5) 9 | 10 | Parameters: 11 | "Cm", 1, 1e-09, 1e+09, 1, 1 12 | "Rm", 10000, 1e-09, 1e+09, 1, 1 13 | End ParmFitness 14 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf3.ses: -------------------------------------------------------------------------------- 1 | objectvar save_window_, rvp_ 2 | objectvar scene_vector_[7] 3 | objectvar ocbox_, ocbox_list_, scene_, scene_list_ 4 | {ocbox_list_ = new List() scene_list_ = new List()} 5 | 6 | //Begin MulRunFitter[0] 7 | { 8 | load_file("mulfit.hoc", "MulRunFitter") 9 | } 10 | { 11 | ocbox_ = new MulRunFitter(1) 12 | } 13 | {object_push(ocbox_)} 14 | { 15 | version(6) 16 | ranfac = 2 17 | fspec = new File("mrf3.ses.ft1") 18 | fdat = new File("mrf3.ses.fd1") 19 | read_data() 20 | build() 21 | } 22 | opt.set_optimizer("MulfitPraxWrap") 23 | {object_push(opt.optimizer)} 24 | { 25 | nstep = 0 26 | } 27 | {object_pop()} 28 | {object_pop()} 29 | { 30 | ocbox_.map("MulRunFitter[0]", 729, 164, 360.96, 199.68) 31 | } 32 | objref ocbox_ 33 | //End MulRunFitter[0] 34 | 35 | objectvar scene_vector_[1] 36 | {doNotify()} 37 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf3.ses.ft1: -------------------------------------------------------------------------------- 1 | ParmFitness: Unnamed multiple run protocol 2 | FitnessGenerator: iclamp_up 3 | RunStatement: 2, LinearCircuit[0].I6_amp1 = 0.2 4 | RegionFitness: LinearCircuit[0].Ve 5 | 6 | FitnessGenerator: iclamp_down 7 | RunStatement: 2, LinearCircuit[0].I6_amp1 = -0.2 8 | RegionFitness: LinearCircuit[0].Ve 9 | 10 | Parameters: 11 | "Ri", 100, 1e+01, 1e+03, 1, 1 12 | "Cm", 1, 1e-09, 1e+09, 1, 1 13 | "Rm", 10000, 1e-09, 1e+09, 1, 1 14 | End ParmFitness 15 | -------------------------------------------------------------------------------- /biophys_optimize/passive/mrf_fixcm.ses.ft1: -------------------------------------------------------------------------------- 1 | ParmFitness: Unnamed multiple run protocol 2 | FitnessGenerator: iclamp_up 3 | RunStatement: 2, clamp.amp = 0.2 4 | RegionFitness: soma.v(0.5) 5 | 6 | FitnessGenerator: iclamp_down 7 | RunStatement: 2, clamp.amp = -0.2 8 | RegionFitness: soma.v(0.5) 9 | 10 | Parameters: 11 | "Ri", 100, 1e+01, 1e+03, 1, 1 12 | "Rm", 10000, 1e-09, 1e+09, 1, 1 13 | End ParmFitness 14 | -------------------------------------------------------------------------------- /biophys_optimize/passive/params.hoc: -------------------------------------------------------------------------------- 1 | Ri = 100 2 | Cm = 1 3 | Rm = 10000 4 | 5 | proc init() { 6 | forall { 7 | Ra = Ri 8 | cm = Cm 9 | g_pas = 1 / Rm 10 | } 11 | finitialize(v_init) 12 | if (cvode.active()) { 13 | cvode.re_init() 14 | } else { 15 | fcurrent() 16 | } 17 | frecord_init() 18 | } 19 | 20 | func somaaxon_area() { local _sum 21 | _sum = 0 22 | 23 | forsec "soma" for(x) { 24 | _sum += area(x) 25 | } 26 | 27 | forsec "axon" for(x) { 28 | _sum += area(x) 29 | } 30 | 31 | return _sum 32 | } 33 | 34 | func alldend_area() { local _sum 35 | _sum = 0 36 | 37 | forsec "dend" for(x) { 38 | _sum += area(x) 39 | } 40 | 41 | forsec "apic" for(x) { 42 | _sum += area(x) 43 | } 44 | 45 | return _sum 46 | } -------------------------------------------------------------------------------- /biophys_optimize/passive/pyr_params.hoc: -------------------------------------------------------------------------------- 1 | Ri = 100 2 | CmD = 2 3 | CmS = 1 4 | Rm = 10000 5 | 6 | proc init() { 7 | forall { 8 | Ra = Ri 9 | cm = CmS 10 | g_pas = 1 / Rm 11 | } 12 | 13 | forsec "dend" { 14 | cm = CmD 15 | } 16 | 17 | forsec "apic" { 18 | cm = CmD 19 | } 20 | 21 | finitialize(v_init) 22 | if (cvode.active()) { 23 | cvode.re_init() 24 | } else { 25 | fcurrent() 26 | } 27 | frecord_init() 28 | } 29 | -------------------------------------------------------------------------------- /biophys_optimize/passive/setup.hoc: -------------------------------------------------------------------------------- 1 | load_file("iclamp.ses") 2 | load_file("params.hoc") 3 | load_file("mrf.ses") 4 | -------------------------------------------------------------------------------- /biophys_optimize/population_selection.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def population_info(fits): 5 | """ Construct information about fit populations 6 | 7 | Parameters 8 | ---------- 9 | fits : list 10 | List of dictionaries with `fit_type`, hall-of-fame file path (`hof`), and 11 | hall-of-fame error values file path (`hof_fit`) 12 | 13 | Returns 14 | ------- 15 | info : list 16 | List of dictionaries summarizing the fit type (`fit_type`), best error encountered 17 | in hall-of-fame population (`best_err`), and file path of hall-of-fame population 18 | (`hof`). 19 | """ 20 | info = [] 21 | for fit in fits: 22 | fit_type = fit["fit_type"] 23 | hof_fit = np.loadtxt(fit["hof_fit"]) 24 | info.append({ 25 | "fit_type": fit_type, 26 | "best_err": hof_fit.min(), 27 | "hof": fit["hof"], 28 | }) 29 | return info 30 | 31 | 32 | def select_starting_population(populations): 33 | """ Choose starting population for next step from different populations 34 | 35 | Typically different populations come from different random seed initializations 36 | 37 | Parameters 38 | ---------- 39 | populations : list 40 | List of dictionaries summarizing the fit type (`fit_type`), best error encountered 41 | in hall-of-fame population (`best_err`), and file path of hall-of-fame population 42 | 43 | Returns 44 | ------- 45 | selection : dict 46 | Dictionary with different fit types as keys and best populations for fit types 47 | as values 48 | """ 49 | selection = {} 50 | for pop in populations: 51 | ft = pop["fit_type"] 52 | if ft not in selection or pop["best_err"] < selection[ft]["err"]: 53 | selection[ft] = { 54 | "err": pop["best_err"], 55 | "hof": pop["hof"], 56 | } 57 | return selection 58 | 59 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/biophys_optimize/b5db493d8c6c4d6bbeccdfdc055e0fca2d75011c/biophys_optimize/scripts/__init__.py -------------------------------------------------------------------------------- /biophys_optimize/scripts/hack_consolidate_passive_strategy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import os.path 5 | import allensdk.core.json_utilities as ju 6 | import biophys_optimize.neuron_passive_fit as npf 7 | 8 | parser = argparse.ArgumentParser(description='hack in paths that strategy will do - passive') 9 | parser.add_argument('preprocess_out', type=str) 10 | parser.add_argument('fit_1_out', type=str) 11 | parser.add_argument('fit_2_out', type=str) 12 | parser.add_argument('fit_elec_out', type=str) 13 | parser.add_argument('output', type=str) 14 | args = parser.parse_args() 15 | 16 | data = ju.read(args.preprocess_out) 17 | fit_1 = ju.read(args.fit_1_out) 18 | fit_2 = ju.read(args.fit_2_out) 19 | fit_3 = ju.read(args.fit_elec_out) 20 | 21 | out_data = { 22 | "paths": { 23 | "passive_info": data["paths"]["passive_info"], 24 | "preprocess_results": data["paths"]["preprocess_results"], 25 | "passive_fit_1": fit_1["paths"][npf.PASSIVE_FIT_1], 26 | "passive_fit_2": fit_2["paths"][npf.PASSIVE_FIT_2], 27 | "passive_fit_elec": fit_3["paths"][npf.PASSIVE_FIT_ELEC], 28 | "passive_results": os.path.join(data["paths"]["storage_directory"], "passive_results.json") 29 | } 30 | } 31 | 32 | ju.write(args.output, out_data) 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/hack_optimize_input.py: -------------------------------------------------------------------------------- 1 | import argparse, os 2 | import allensdk.core.json_utilities as ju 3 | from pkg_resources import resource_filename 4 | import biophys_optimize 5 | 6 | parser = argparse.ArgumentParser(description='hack in paths that strategy will do - passive') 7 | parser.add_argument('input', type=str) 8 | parser.add_argument('output', type=str) 9 | parser.add_argument('--fit_type_index', default=0) 10 | parser.add_argument("--stage_key", default="stage_1_task_list") 11 | parser.add_argument('--mu', default=10, type=int) 12 | parser.add_argument('--ngen', default=5, type=int) 13 | parser.add_argument('--sp', default=None, type=str) 14 | args = parser.parse_args() 15 | 16 | data = ju.read(args.input) 17 | fit_type_index = args.fit_type_index 18 | stage_key = args.stage_key 19 | fit_type = data[stage_key][fit_type_index]["fit_type"] 20 | seed = data[stage_key][fit_type_index]["seed"] 21 | 22 | boph_name = biophys_optimize.__name__ 23 | 24 | output = { 25 | "paths": { 26 | "swc": data["paths"]["swc"], 27 | "storage_directory": data["paths"]["storage_directory"], 28 | "preprocess_results": data["paths"]["preprocess_results"], 29 | "passive_results": os.path.join(data["paths"]["storage_directory"], "passive_results.json"), 30 | "fit_style": resource_filename(boph_name, "fit_styles/%s_fit_style.json" % fit_type), 31 | "compiled_mod_library": resource_filename(boph_name, "x86_64/.libs/libnrnmech.so"), 32 | "hoc_files": [ "stdgui.hoc", "import3d.hoc", resource_filename(boph_name, "cell.hoc") ] 33 | }, 34 | "fit_type": fit_type, 35 | "seed": seed, 36 | "mu": args.mu, 37 | "ngen": args.ngen, 38 | } 39 | 40 | if args.sp is not None: 41 | output["paths"]["starting_population"] = args.sp 42 | 43 | ju.write(args.output, output) 44 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/hack_population_selection_input.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | 3 | import allensdk.core.json_utilities as ju 4 | 5 | storage_dir = "./test_storage" 6 | fit_types = sys.argv[1:-1] 7 | seed = 1234 8 | 9 | data = { 10 | 'paths': { 11 | 'fits': [ { 12 | "fit_type": ft, 13 | "hof_fit": os.path.join(storage_dir, "%s_%d_final_hof_fit.txt" % (ft, seed)), 14 | "hof": os.path.join(storage_dir, "%s_%d_final_hof.txt" % (ft, seed)) 15 | } for ft in fit_types ] } } 16 | 17 | 18 | ju.write(sys.argv[-1], data) 19 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/hack_preprocess_input.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | import argparse 5 | import numpy as np 6 | import psycopg2 7 | import json 8 | 9 | CONNECTION_STRING = 'host=limsdb2 dbname=lims2 user=limsreader password=limsro' 10 | 11 | 12 | def preprocess_info_from_lims(specimen_id): 13 | sql = """ 14 | with dendrite_type as 15 | ( 16 | select sts.specimen_id, st.name 17 | from specimen_tags_specimens sts 18 | join specimen_tags st on sts.specimen_tag_id = st.id 19 | where st.name like 'dendrite type%%' 20 | ) 21 | select swc.storage_directory || swc.filename, 22 | nwb.storage_directory || nwb.filename, 23 | dt.name 24 | from specimens sp 25 | join dendrite_type dt on sp.id = dt.specimen_id 26 | join ephys_roi_results err on sp.ephys_roi_result_id = err.id 27 | join well_known_files nwb on nwb.attachable_id = err.id 28 | join neuron_reconstructions n on n.specimen_id = sp.id 29 | join well_known_files swc on swc.attachable_id = n.id 30 | where sp.id = %s 31 | and nwb.well_known_file_type_id = 475137571 32 | and nwb.attachable_type = 'EphysRoiResult' 33 | and n.manual and not n.superseded 34 | and swc.well_known_file_type_id = 303941301 35 | """ 36 | 37 | conn = psycopg2.connect(CONNECTION_STRING) 38 | cur = conn.cursor() 39 | cur.execute(sql, (specimen_id,)) 40 | result = cur.fetchone() 41 | cur.close() 42 | conn.close() 43 | 44 | if not result: 45 | print("Could not find info for specimen ", specimen_id) 46 | return None 47 | 48 | return result 49 | 50 | 51 | def get_sweeps_of_type(sweep_type, specimen_id, passed_only=False): 52 | conn = psycopg2.connect(CONNECTION_STRING) 53 | cur = conn.cursor() 54 | sql = "SELECT sw.sweep_number FROM ephys_sweeps sw JOIN ephys_stimuli stim \ 55 | ON stim.id = sw.ephys_stimulus_id \ 56 | WHERE sw.specimen_id = %s AND stim.description LIKE %s" 57 | 58 | if passed_only: 59 | sql += "\nAND sw.workflow_state LIKE '%%passed'" 60 | 61 | cur.execute(sql, (specimen_id, '%' + sweep_type + '%')) 62 | sweeps = [s[0] for s in cur.fetchall()] 63 | cur.close() 64 | conn.close() 65 | 66 | return sweeps 67 | 68 | 69 | def bridge_average(specimen_id, cap_check_sweeps): 70 | conn = psycopg2.connect(CONNECTION_STRING) 71 | cur = conn.cursor() 72 | 73 | sql = """select sw.bridge_balance_mohm from ephys_sweeps sw 74 | join ephys_stimuli stim on stim.id = sw.ephys_stimulus_id 75 | where sw.specimen_id = %s 76 | and sw.sweep_number in %s""" 77 | 78 | cur.execute(sql, (specimen_id, tuple(cap_check_sweeps))) 79 | 80 | sweeps_data = cur.fetchall() 81 | cur.close() 82 | conn.close() 83 | 84 | bridge_balances = [s[0] for s in sweeps_data] 85 | bridge_avg = np.mean(bridge_balances) 86 | 87 | return bridge_avg 88 | 89 | 90 | def main(): 91 | parser = argparse.ArgumentParser(description='Make a preprocess input json file') 92 | parser.add_argument('specimen_id') 93 | parser.add_argument('storage_directory') 94 | parser.add_argument('output_json') 95 | args = parser.parse_args() 96 | 97 | specimen_id = args.specimen_id 98 | storage_directory = args.storage_directory 99 | output_json = args.output_json 100 | 101 | result = preprocess_info_from_lims(specimen_id) 102 | if not result: 103 | return 104 | swc_path, nwb_path, dendrite_type = result 105 | 106 | sweep_types = { 107 | "core_1_long_squares": "C1LSCOARSE", 108 | "core_2_long_squares": "C2SQRHELNG", 109 | "seed_1_noise": "C1NSSEED_1", 110 | "seed_2_noise": "C1NSSEED_2", 111 | "cap_checks": "C1SQCAPCHK", 112 | } 113 | 114 | sweeps = {k: get_sweeps_of_type(v, specimen_id, passed_only=True) 115 | for k, v in list(sweep_types.items())} 116 | 117 | if len(sweeps["cap_checks"]) > 0: 118 | bridge_avg = bridge_average(specimen_id, sweeps["cap_checks"]) 119 | else: 120 | bridge_avg = 0 121 | 122 | output = { 123 | "paths": { 124 | "nwb": nwb_path, 125 | "swc": swc_path, 126 | "storage_directory": storage_directory, 127 | }, 128 | "dendrite_type_tag": dendrite_type, 129 | "sweeps": sweeps, 130 | "bridge_avg": bridge_avg, 131 | } 132 | 133 | with open(output_json, "w") as f: 134 | json.dump(output, f, indent=2) 135 | 136 | if __name__ == "__main__": main() 137 | 138 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/hack_preprocess_to_passive_strategy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import argparse 5 | import os.path 6 | from pkg_resources import resource_filename 7 | import biophys_optimize.neuron_passive_fit as npf 8 | 9 | parser = argparse.ArgumentParser(description='hack in paths that strategy will do - passive') 10 | parser.add_argument('input', type=str) 11 | parser.add_argument('output', type=str) 12 | parser.add_argument('passive_fit_type', type=str) 13 | args = parser.parse_args() 14 | 15 | fit1_handles = [ 16 | "passive/fixnseg.hoc", 17 | "passive/iclamp.ses", 18 | "passive/params.hoc", 19 | "passive/mrf.ses", 20 | ] 21 | 22 | fit2_handles = [ 23 | "passive/fixnseg.hoc", 24 | "passive/iclamp.ses", 25 | "passive/params.hoc", 26 | "passive/mrf2.ses", 27 | ] 28 | 29 | fit3_handles = [ 30 | "passive/fixnseg.hoc", 31 | "passive/circuit.ses", 32 | "passive/params.hoc", 33 | "passive/mrf3.ses", 34 | ] 35 | 36 | if args.passive_fit_type == npf.PASSIVE_FIT_1: 37 | fit_handles = fit1_handles 38 | elif args.passive_fit_type == npf.PASSIVE_FIT_2: 39 | fit_handles = fit2_handles 40 | elif args.passive_fit_type == npf.PASSIVE_FIT_ELEC: 41 | fit_handles = fit3_handles 42 | 43 | with open(args.input, "r") as f: 44 | data = json.load(f) 45 | 46 | import biophys_optimize 47 | bo_name = biophys_optimize.__name__ 48 | 49 | new_path_info = { 50 | "fit": [resource_filename(bo_name, f) for f in fit_handles], 51 | "passive_fit_results_file": os.path.join(data["paths"]["storage_directory"], "%s_results.json" % args.passive_fit_type) 52 | } 53 | 54 | data["paths"].update(new_path_info) 55 | data["passive_fit_type"] = args.passive_fit_type 56 | 57 | with open(args.output, "w") as f: 58 | json.dump(data, f, indent=2) 59 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_consolidate_passive_fitting.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to compare the results of the passive fitting variants and select the best one. 3 | 4 | .. autoclass:: ConsolidateParameters 5 | .. autoclass:: ConsolidatePaths 6 | 7 | """ 8 | 9 | import argparse 10 | 11 | import allensdk.core.json_utilities as ju 12 | 13 | import biophys_optimize.consolidate_passive_fits as cpf 14 | from biophys_optimize.neuron_passive_fit import PassiveFitResult 15 | 16 | import argschema as ags 17 | 18 | class ConsolidatePaths(ags.schemas.DefaultSchema): 19 | preprocess_results = ags.fields.InputFile(description="path to preprocess results file") 20 | passive_info = ags.fields.InputFile(description="path to passive info file") 21 | passive_fit_1 = ags.fields.InputFile(description="path to passive fit 1 results file") 22 | passive_fit_2 = ags.fields.InputFile(description="path to passive fit 2 results file") 23 | passive_fit_elec = ags.fields.InputFile(description="path to passive fit elec results file") 24 | passive_results = ags.fields.OutputFile(description="path to store consolidated results") 25 | 26 | class ConsolidateParameters(ags.ArgSchema): 27 | paths = ags.fields.Nested(ConsolidatePaths) 28 | 29 | def main(): 30 | module = ags.ArgSchemaParser(schema_type=ConsolidateParameters) 31 | 32 | preprocess_results = ju.read(module.args["paths"]["preprocess_results"]) 33 | is_spiny = preprocess_results["is_spiny"] 34 | info = ju.read(module.args["paths"]["passive_info"]) 35 | 36 | if info["should_run"]: 37 | fit_1_path = module.args["paths"]["passive_fit_1"] 38 | fit_1 = PassiveFitResult(**ju.read(fit_1_path)) 39 | 40 | fit_2_path = module.args["paths"]["passive_fit_2"] 41 | fit_2 = PassiveFitResult(**ju.read(fit_2_path)) 42 | 43 | fit_3_path = module.args["paths"]["passive_fit_elec"] 44 | fit_3 = PassiveFitResult(ju.read(fit_3_path)) 45 | 46 | ra, cm1, cm2 = cpf.compare_runs(fit_1, fit_2, fit_3, is_spiny) 47 | else: 48 | ra = 100. 49 | cm1 = 1. 50 | if is_spiny: 51 | cm2 = 2. 52 | else: 53 | cm2 = 1. 54 | 55 | passive = { 56 | "ra": ra, 57 | "cm": {"soma": cm1, "axon": cm1, "dend": cm2 }, 58 | "e_pas": preprocess_results["v_baseline"] 59 | } 60 | 61 | passive["e_pas"] = preprocess_results["v_baseline"] 62 | if preprocess_results["has_apical"]: 63 | passive["cm"]["apic"] = cm2 64 | 65 | passive_results_path = module.args["paths"]["passive_results"] 66 | ju.write(passive_results_path, passive) 67 | 68 | output = { 69 | "paths": { 70 | "passive_results": passive_results_path, 71 | } 72 | } 73 | 74 | ju.write(module.args["output_json"], output) 75 | 76 | 77 | if __name__ == "__main__": main() 78 | 79 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_model_selection.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to select the best model from the population 3 | 4 | .. autoclass:: ModelSelectionParameters 5 | .. autoclass:: ModelSelectionPaths 6 | .. autoclass:: ModelFitStyles 7 | .. autoclass:: ModelFit 8 | 9 | """ 10 | 11 | import logging 12 | import argparse 13 | import allensdk.core.json_utilities as ju 14 | 15 | import biophys_optimize.model_selection as ms 16 | 17 | import argschema as ags 18 | 19 | class ModelFitStyles(ags.schemas.DefaultSchema): 20 | f6 = ags.fields.InputFile(description="") 21 | f6_noapic = ags.fields.InputFile(description="") 22 | f9 = ags.fields.InputFile(description="") 23 | f9_noapic = ags.fields.InputFile(description="") 24 | f12 = ags.fields.InputFile(description="") 25 | f12_noapic = ags.fields.InputFile(description="") 26 | f13 = ags.fields.InputFile(description="") 27 | f13_noapic = ags.fields.InputFile(description="") 28 | 29 | class ModelFit(ags.schemas.DefaultSchema): 30 | fit_type = ags.fields.Str(description="") 31 | hof_fit = ags.fields.InputFile(description="") 32 | hof = ags.InputFile(description="") 33 | 34 | class ModelSelectionPaths(ags.schemas.DefaultSchema): 35 | swc = ags.fields.InputFile(description="path to swc file") 36 | nwb = ags.fields.InputFile(description="path to nwb file") 37 | fit_styles = ags.fields.Nested(ModelFitStyles, description="") 38 | 39 | fits = ags.fields.Nested(ModelFit, description="", many=True) 40 | 41 | best_fit_json_path = ags.fields.OutputFile(description="where to store best fit") 42 | passive_results = ags.fields.InputFile(description="passive results file") 43 | preprocess_results = ags.fields.InputFile(description="preprocess results file") 44 | hoc_files = ags.fields.List(ags.fields.Str, description="list of hoc files") 45 | compiled_mod_library = ags.fields.InputFile(description="path to compiled mod library file") 46 | 47 | class ModelSelectionParameters(ags.ArgSchema): 48 | paths = ags.fields.Nested(ModelSelectionPaths) 49 | noise_1_sweeps = ags.fields.List(ags.fields.Int, description="list of noise 1 sweep numbers") 50 | noise_2_sweeps = ags.fields.List(ags.fields.Int, description="list of noise 2 sweep numbers") 51 | 52 | 53 | def main(): 54 | module = ags.ArgSchemaParser(schema_type=ModelSelectionParameters) 55 | 56 | swc_path = module.args["paths"]["swc"] 57 | fit_style_paths = module.args["paths"]["fit_styles"] 58 | best_fit_json_path = module.args["paths"]["best_fit_json_path"] 59 | passive = ju.read(module.args["paths"]["passive_results"]) 60 | preprocess = ju.read(module.args["paths"]["preprocess_results"]) 61 | 62 | 63 | fits = module.args["paths"]["fits"] 64 | fit_results = ms.fit_info(fits) 65 | best_fit = ms.select_model(fit_results, module.args["paths"], passive, preprocess["v_baseline"], 66 | module.args["noise_1_sweeps"], module.args["noise_2_sweeps"]) 67 | if best_fit is None: 68 | raise Exception("Failed to find acceptable optimized model") 69 | 70 | logging.info("building fit data") 71 | fit_style_data = ju.read(module.args["paths"]["fit_styles"][best_fit["fit_type"]]) 72 | fit_data = ms.build_fit_data(best_fit["params"], passive, preprocess, fit_style_data) 73 | 74 | logging.info("writing fit data: %s", best_fit_json_path) 75 | ju.write(best_fit_json_path, fit_data) 76 | 77 | output = { 78 | "paths": { 79 | "fit_json": best_fit_json_path, 80 | } 81 | } 82 | 83 | logging.info("writing output json: %s", module.args["output_json"]) 84 | ju.write(module.args["output_json"], output) 85 | 86 | if __name__ == "__main__": main() 87 | 88 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_optimize.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to run the optimization using an evolutionary algorithm. 3 | 4 | .. autoclass:: OptimizeParameters 5 | .. autoclass:: OptimizePaths 6 | 7 | """ 8 | 9 | import argparse 10 | from biophys_optimize.optimize import optimize, StimParams 11 | import allensdk.core.json_utilities as ju 12 | import logging 13 | 14 | import argschema as ags 15 | 16 | class OptimizePaths(ags.schemas.DefaultSchema): 17 | preprocess_results = ags.fields.InputFile(description="path to preprocess results file") 18 | passive_results = ags.fields.InputFile(description="path to passive results file") 19 | fit_style = ags.fields.InputFile(description="path to fit style file") 20 | hoc_files = ags.fields.List(ags.fields.Str, description="list of hoc files") 21 | compiled_mod_library = ags.fields.InputFile(description="path to compiled mod library file") 22 | swc = ags.fields.InputFile(description="path to SWC file") 23 | storage_directory = ags.fields.Str(description="where to store outputs") 24 | starting_population = ags.fields.Str(description="starting population") 25 | 26 | class OptimizeParameters(ags.ArgSchema): 27 | paths = ags.fields.Nested(OptimizePaths) 28 | fit_type = ags.fields.Str(description="fit type") 29 | seed = ags.fields.Int(description="seed") 30 | mu = ags.fields.Int(description="mu") 31 | ngen = ags.fields.Int(description="ngen") 32 | 33 | def main(): 34 | module = ags.ArgSchemaParser(schema_type=OptimizeParameters) 35 | 36 | preprocess_results = ju.read(module.args["paths"]["preprocess_results"]) 37 | passive_results = ju.read(module.args["paths"]["passive_results"]) 38 | fit_style_data = ju.read(module.args["paths"]["fit_style"]) 39 | 40 | results = optimize(hoc_files=module.args["paths"]["hoc_files"], 41 | compiled_mod_library=module.args["paths"]["compiled_mod_library"], 42 | morphology_path=module.args["paths"]["swc"], 43 | features=preprocess_results["features"], 44 | targets=preprocess_results["target_features"], 45 | stim_params=StimParams(preprocess_results["stimulus"]), 46 | passive_results=passive_results, 47 | fit_type=module.args["fit_type"], 48 | fit_style_data=fit_style_data, 49 | seed=module.args["seed"], 50 | ngen=module.args["ngen"], 51 | mu=module.args["mu"], 52 | storage_directory = module.args["paths"]["storage_directory"], 53 | starting_population = module.args["paths"].get("starting_population",None)) 54 | 55 | logging.info("Writing optimization output") 56 | ju.write(module.args["output_json"], results) 57 | 58 | if __name__ == "__main__": main() 59 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_passive_fitting.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to run passive fit variants. 3 | 4 | .. autoclass:: PassiveFittingParameters 5 | .. autoclass:: PassiveFittingPaths 6 | 7 | """ 8 | import argparse 9 | import allensdk.core.json_utilities as ju 10 | import numpy as np 11 | import biophys_optimize.neuron_passive_fit as npf 12 | from dataclasses import asdict 13 | 14 | import argschema as ags 15 | 16 | class PassiveFittingPaths(ags.schemas.DefaultSchema): 17 | swc = ags.fields.InputFile(description="path to SWC file") 18 | up = ags.fields.InputFile(descritpion="up data path") 19 | down = ags.fields.InputFile(descritpion="down data path") 20 | passive_info = ags.fields.InputFile(description="passive info file") 21 | fit = ags.fields.List(ags.InputFile, 22 | description="list of passive fitting files", 23 | cli_as_single_argument=True) 24 | passive_fit_results_file = ags.fields.OutputFile(description="passive fit results file") 25 | 26 | 27 | class PassiveFittingParameters(ags.ArgSchema): 28 | paths = ags.fields.Nested(PassiveFittingPaths) 29 | passive_fit_type = ags.fields.Str(description="passive fit type") 30 | 31 | 32 | def main(paths, passive_fit_type, output_json, **kwargs): 33 | info = ju.read(paths["passive_info"]) 34 | if not info["should_run"]: 35 | ju.write(output_json, { "paths": {} }) 36 | return 37 | 38 | swc_path = paths["swc"].encode('ascii', 'ignore') 39 | up_data = np.loadtxt(paths["up"]) 40 | down_data = np.loadtxt(paths["down"]) 41 | results_file = paths["passive_fit_results_file"] 42 | 43 | npf.initialize_neuron(swc_path, paths["fit"]) 44 | 45 | if passive_fit_type == npf.PASSIVE_FIT_1: 46 | results = npf.passive_fit_1(up_data, down_data, 47 | info["fit_window_start"], info["fit_window_end"]) 48 | elif passive_fit_type == npf.PASSIVE_FIT_2: 49 | results = npf.passive_fit_2(up_data, down_data, 50 | info["fit_window_start"], info["fit_window_end"]) 51 | elif passive_fit_type == npf.PASSIVE_FIT_ELEC: 52 | results = npf.passive_fit_elec(up_data, down_data, 53 | info["fit_window_start"], info["fit_window_end"], 54 | info["bridge"], info["electrode_cap"]) 55 | else: 56 | raise Exception("unknown passive fit type: %s" % passive_fit_type) 57 | 58 | ju.write(results_file, asdict(results)) 59 | ju.write(output_json, { "paths": { passive_fit_type: results_file } }) 60 | 61 | 62 | if __name__ == "__main__": 63 | module = ags.ArgSchemaParser(schema_type=PassiveFittingParameters) 64 | main(**module.args) 65 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_population_selection.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to select the starting population 3 | 4 | .. autoclass:: PopulationSelectionParameters 5 | .. autoclass:: PopulationSelectionPaths 6 | .. autoclass:: ModelFit 7 | """ 8 | 9 | from __future__ import print_function 10 | import argparse 11 | import allensdk.core.json_utilities as ju 12 | 13 | import biophys_optimize.population_selection as ps 14 | 15 | import argschema as ags 16 | 17 | class ModelFit(ags.schemas.DefaultSchema): 18 | fit_type = ags.fields.Str(description="") 19 | hof_fit = ags.fields.InputFile(description="") 20 | hof = ags.fields.InputFile(description="") 21 | 22 | 23 | class PopulationSelectionPaths(ags.schemas.DefaultSchema): 24 | fits = ags.fields.Nested(ModelFit, description="", many=True) 25 | 26 | 27 | class PopulationSelectionParameters(ags.ArgSchema): 28 | paths = ags.fields.Nested(PopulationSelectionPaths) 29 | 30 | 31 | def main(): 32 | module = ags.ArgSchemaParser(schema_type=PopulationSelectionParameters) 33 | print(module.args) 34 | 35 | fits = module.args["paths"]["fits"] 36 | populations = ps.population_info(fits) 37 | starting_populations = ps.select_starting_population(populations) 38 | 39 | output = { 40 | "paths": { 41 | "starting_populations": starting_populations, 42 | } 43 | } 44 | 45 | ju.write(module.args["output_json"], output) 46 | 47 | 48 | if __name__ == "__main__": main() 49 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_preprocessing.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to preprocess sweeps and morphologies before optimization. 3 | 4 | .. autoclass:: PreprocessorParameters 5 | .. autoclass:: PreprocessorSweeps 6 | .. autoclass:: PreprocessorPaths 7 | 8 | 9 | """ 10 | import argparse 11 | import pandas as pd 12 | import os 13 | import argschema as ags 14 | 15 | import allensdk.core.json_utilities as ju 16 | from ipfx.nwb_reader import create_nwb_reader 17 | import biophys_optimize.preprocess as preprocess 18 | from biophys_optimize.step_analysis import StepAnalysis 19 | from biophys_optimize.sweep_functions import sweeps_from_nwb 20 | 21 | 22 | class PreprocessorPaths(ags.schemas.DefaultSchema): 23 | nwb = ags.fields.InputFile(description="path to input NWB (Neurodata Without Borders) file") 24 | swc = ags.fields.InputFile(description="path to input SWC (morphology) file") 25 | storage_directory = ags.fields.OutputDir(description="path to storage directory") 26 | 27 | 28 | class PreprocessorSweeps(ags.schemas.DefaultSchema): 29 | core_1_long_squares = ags.fields.List(ags.fields.Int, 30 | description="list of core 1 long square sweep numbers", 31 | cli_as_single_argument=True) 32 | core_2_long_squares = ags.fields.List(ags.fields.Int, 33 | description="list of core 2 long square sweep numbers", 34 | cli_as_single_argument=True) 35 | seed_1_noise = ags.fields.List(ags.fields.Int, 36 | description="list of seed 1 noise sweep numbers", 37 | cli_as_single_argument=True) 38 | seed_2_noise = ags.fields.List(ags.fields.Int, 39 | description="list of seed 2 noise sweep numbers", 40 | cli_as_single_argument=True) 41 | cap_checks = ags.fields.List(ags.fields.Int, 42 | description="list of capacitance check sweep numbers", 43 | cli_as_single_argument=True) 44 | 45 | 46 | class PreprocessorParameters(ags.ArgSchema): 47 | paths = ags.fields.Nested(PreprocessorPaths) 48 | dendrite_type = ags.fields.Str(description="dendrite type (spiny or aspiny)", 49 | validation=lambda x: x in ["spiny", "aspiny"]) 50 | sweeps = ags.fields.Nested(PreprocessorSweeps) 51 | bridge_avg = ags.fields.Float(description="average bridge balance") 52 | passive_fit_start_time = ags.fields.Float(description="start time of passive fit window (ms)", default=4.0) 53 | electrode_capacitance = ags.fields.Float(description="Capacitance of electrode for passive fitting (pF)", default=1.0) 54 | junction_potential = ags.fields.Float(description="Liquid junction potential (mV)", default=-14.0) 55 | random_seeds = ags.fields.List(ags.fields.Integer, description="list of random seeds", 56 | default=[1234, 1001, 4321, 1024, 2048], 57 | cli_as_single_argument=True) 58 | 59 | 60 | def main(paths, sweeps, dendrite_type, bridge_avg, passive_fit_start_time, 61 | electrode_capacitance, junction_potential, random_seeds, 62 | output_json, **kwargs): 63 | """Main sequence of pre-processing and passive fitting""" 64 | 65 | # Extract Sweep objects (from IPFX package) from NWB file 66 | nwb_path = paths["nwb"] # nwb - neurodata without borders (ephys data) 67 | nwb_data = create_nwb_reader(nwb_path) 68 | core_1_lsq, c1_start, c1_end = sweeps_from_nwb( 69 | nwb_data, sweeps["core_1_long_squares"]) 70 | core_2_lsq, c2_start, c2_end = sweeps_from_nwb( 71 | nwb_data, sweeps["core_2_long_squares"]) 72 | 73 | # Choose sweeps to train the model 74 | sweep_set_to_fit, start, end = preprocess.select_core_1_or_core_2_sweeps( 75 | core_1_lsq, c1_start, c1_end, 76 | core_2_lsq, c2_start, c2_end) 77 | if len(sweep_set_to_fit.sweeps) == 0: 78 | ju.write(output_json, { 'error': "No usable sweeps found" }) 79 | return 80 | 81 | 82 | # Calculate the target features from the training sweeps 83 | step_analysis = StepAnalysis(start, end) 84 | step_analysis.analyze(sweep_set_to_fit) 85 | target_info = preprocess.target_features( 86 | step_analysis.sweep_features(), 87 | step_analysis.spikes_data()) 88 | 89 | stim_amp = step_analysis.sweep_features()["stim_amp"].values[0] 90 | stim_dur = end - start 91 | v_baseline = target_info.at["v_baseline", "mean"] 92 | 93 | # Determine maximum current used for depolarization block checks 94 | # during optimization 95 | 96 | # Load noise sweeps to check highest current used 97 | noise_1, _, _ = sweeps_from_nwb( 98 | nwb_data, sweeps["seed_1_noise"]) 99 | noise_2, _, _ = sweeps_from_nwb( 100 | nwb_data, sweeps["seed_2_noise"]) 101 | 102 | max_i = preprocess.max_i_for_depol_block_check( 103 | core_1_lsq, core_2_lsq, noise_1, noise_2) 104 | 105 | # Prepare inputs for passive fitting 106 | is_spiny = dendrite_type == "spiny" 107 | 108 | cap_checks, _, _ = sweeps_from_nwb( 109 | nwb_data, sweeps["cap_checks"]) 110 | if len(cap_checks.sweeps) == 0: 111 | logging.info("No cap check traces found") 112 | should_run_passive_fit = False 113 | passive_info = { 114 | "should_run": False, 115 | } 116 | else: 117 | grand_up, grand_down, t = preprocess.cap_check_grand_averages(cap_checks) 118 | up_file, down_file = preprocess.save_grand_averages( 119 | grand_up, grand_down, t, paths["storage_directory"]) 120 | escape_time = preprocess.passive_fit_window(grand_up, grand_down, t, 121 | start_time=passive_fit_start_time) 122 | passive_info = { 123 | "should_run": True, 124 | "bridge": bridge_avg, 125 | "fit_window_start": passive_fit_start_time, 126 | "fit_window_end": escape_time, 127 | "electrode_cap": electrode_capacitance, 128 | "is_spiny": is_spiny, 129 | } 130 | paths["up"] = up_file 131 | paths["down"] = down_file 132 | 133 | passive_info_path = os.path.join( 134 | paths["storage_directory"], "passive_info.json") 135 | ju.write(passive_info_path, passive_info) 136 | 137 | # Determine whether morphology has an apical dendrite 138 | has_apical = preprocess.swc_has_apical_compartments(paths["swc"]) 139 | 140 | # Decide which fits to run based on morphology and AP width 141 | fit_types = preprocess.FitStyle.get_fit_types( 142 | has_apical=has_apical, 143 | is_spiny=is_spiny, 144 | width=target_info.at["width", "mean"]) 145 | 146 | stage_1_tasks = [{"fit_type": fit_type, "seed": seed} 147 | for seed in random_seeds 148 | for fit_type in fit_types] 149 | 150 | stage_2_tasks = [{"fit_type": preprocess.FitStyle.map_stage_2(fit_type), "seed": seed} 151 | for seed in random_seeds 152 | for fit_type in fit_types] 153 | 154 | preprocess_results_path = os.path.join( 155 | paths["storage_directory"], "preprocess_results.json") 156 | ju.write(preprocess_results_path, { 157 | "is_spiny": is_spiny, 158 | "has_apical": has_apical, 159 | "junction_potential": junction_potential, 160 | "max_stim_test_na": max_i, 161 | "v_baseline": v_baseline, 162 | "stimulus": { 163 | "amplitude": 1e-3 * stim_amp, # to nA 164 | "delay": 1e3, 165 | "duration": 1e3 * stim_dur, # to ms 166 | }, 167 | "target_features": target_info.to_dict(orient="index"), 168 | "sweeps": sweeps, 169 | "sweeps_to_fit": [s.sweep_number for s in sweep_set_to_fit.sweeps], 170 | }) 171 | 172 | paths.update({ 173 | "preprocess_results": preprocess_results_path, 174 | "passive_info": passive_info_path, 175 | }) 176 | 177 | output = { 178 | "paths": paths, 179 | "stage_1_task_list": stage_1_tasks, 180 | "stage_2_task_list": stage_2_tasks, 181 | } 182 | 183 | ju.write(module.args["output_json"], output) 184 | 185 | 186 | if __name__ == "__main__": 187 | # argschema reads arguments from a JSON file or command line arguments 188 | module = ags.ArgSchemaParser(schema_type=PreprocessorParameters, logger_name=None) 189 | main(**module.args) 190 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_python_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export ALLENSDK_PATH=/data/informatics/mousecelltypes/biophys_optimize/allensdk/ 4 | export ARGSCHEMA_PATH=/data/informatics/mousecelltypes/biophys_optimize/argschema/ 5 | export MM_PATH=/data/informatics/mousecelltypes/biophys_optimize/marshmallow/ 6 | export BPO_PATH=/data/informatics/mousecelltypes/biophys_optimize/biophys_optimize/ 7 | 8 | NEURON_HOME=/shared/utils.x86_64/nrn-7.4-1370 9 | export PYTHONPATH=${NEURON_HOME}/lib/python:${ALLENSDK_PATH}:${ARGSCHEMA_PATH}:${MM_PATH}:${BPO_PATH}:${PYTHONPATH} 10 | export PYTHON_HOME=/shared/utils.x86_64/python-2.7 11 | export PYTHON=${PYTHON_HOME}/bin/python 12 | export PATH=${PYTHON_HOME}/bin:${NEURON_HOME}/x86_64/bin:${PATH} 13 | 14 | $PYTHON $@ 15 | -------------------------------------------------------------------------------- /biophys_optimize/scripts/run_python_mpi_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export ALLENSDK_PATH=/data/informatics/mousecelltypes/biophys_optimize/allensdk/ 4 | export ARGSCHEMA_PATH=/data/informatics/mousecelltypes/biophys_optimize/argschema/ 5 | export MM_PATH=/data/informatics/mousecelltypes/biophys_optimize/marshmallow/ 6 | export BPO_PATH=/data/informatics/mousecelltypes/biophys_optimize/biophys_optimize/ 7 | 8 | NEURON_HOME=/shared/utils.x86_64/nrn-7.4-1370 9 | export PYTHONPATH=${NEURON_HOME}/lib/python:${ALLENSDK_PATH}:${ARGSCHEMA_PATH}:${MM_PATH}:${BPO_PATH}:${PYTHONPATH} 10 | export PYTHON_HOME=/shared/utils.x86_64/python-2.7 11 | export PYTHON=${PYTHON_HOME}/bin/python 12 | export PATH=${PYTHON_HOME}/bin:${NEURON_HOME}/x86_64/bin:${PATH} 13 | NUM_PROCS=240 14 | 15 | mpiexec -np $NUM_PROCS $PYTHON $@ 16 | -------------------------------------------------------------------------------- /biophys_optimize/step_analysis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from ipfx import stim_features as stf 3 | from ipfx import feature_extractor as fx 4 | from ipfx.stimulus_protocol_analysis import StimulusProtocolAnalysis 5 | 6 | class StepAnalysis(StimulusProtocolAnalysis): 7 | """ Analysis of responses to step current stimulation 8 | 9 | Parameters 10 | ---------- 11 | start: float 12 | Start time of stimulus interval (seconds) 13 | 14 | end: float 15 | End time of stimulus interval (seconds) 16 | """ 17 | def __init__(self, start, end): 18 | spx = fx.SpikeFeatureExtractor(start=start, end=end) 19 | sptx = fx.SpikeTrainFeatureExtractor(start, end, 20 | stim_amp_fn=stf._step_stim_amp) 21 | super(StepAnalysis, self).__init__(spx, sptx) 22 | 23 | def analyze(self, sweep_set, exclude_clipped=False): 24 | """ Analyze spike and sweep features 25 | 26 | Parameters 27 | ---------- 28 | sweep_set: SweepSet 29 | 30 | exclude_clipped: bool, optional 31 | Whether to exclude clipped spikes from sweep-level features (default False) 32 | """ 33 | extra_sweep_features = ["stim_amp", "v_baseline"] 34 | self.analyze_basic_features(sweep_set, 35 | extra_sweep_features=extra_sweep_features, 36 | exclude_clipped=exclude_clipped) 37 | 38 | # Analyze additional spike-level features 39 | for sd in self._spikes_set: 40 | if sd.shape[0] >= 2: 41 | sd["slow_trough_delta_v"] = _slow_trough_delta_v( 42 | sd["fast_trough_v"].values, sd["slow_trough_v"].values) 43 | sd["slow_trough_norm_time"] = _slow_trough_norm_t( 44 | sd["threshold_t"].values, 45 | sd["slow_trough_t"].values, 46 | sd["trough_t"].values) 47 | 48 | def spikes_data(self): 49 | """ Return a list of spike feature dataframes""" 50 | return self._spikes_set 51 | 52 | def sweep_features(self): 53 | """ Return a sweep feature dataframe""" 54 | return self._sweep_features 55 | 56 | 57 | def _slow_trough_delta_v(fast_trough_v, slow_trough_v): 58 | delta = fast_trough_v - slow_trough_v 59 | delta[np.isnan(delta)] = 0 60 | return delta 61 | 62 | 63 | def _slow_trough_norm_t(threshold_t, slow_trough_t, trough_t): 64 | trough_values = slow_trough_t 65 | mask = np.isnan(trough_values) 66 | trough_values[mask] = trough_t[mask] 67 | 68 | isis = np.diff(threshold_t) 69 | slow_trough_norm_t = np.zeros_like(threshold_t) * np.nan 70 | slow_trough_norm_t[:-1] = (trough_values[:-1] - threshold_t[:-1]) / isis 71 | return slow_trough_norm_t 72 | 73 | -------------------------------------------------------------------------------- /biophys_optimize/sweep_functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from ipfx.sweep import Sweep, SweepSet 3 | import ipfx.stim_features as stf 4 | 5 | 6 | def sweeps_from_nwb(nwb_data, sweep_number_list): 7 | """ Generate a SweepSet object from an NWB reader and list of sweep numbers 8 | 9 | Sweeps should be in current-clamp mode. 10 | 11 | Parameters 12 | ---------- 13 | nwb_data: NwbReader 14 | sweep_number_list: list 15 | List of sweep numbers 16 | 17 | Returns 18 | ------- 19 | sweeps: SweepSet 20 | stim_start: float 21 | Start time of stimulus (seconds) 22 | stim_end: float 23 | End time of stimulus (seconds) 24 | """ 25 | 26 | sweep_list = [] 27 | start = None 28 | dur = None 29 | for sweep_number in sweep_number_list: 30 | sweep_data = nwb_data.get_sweep_data(sweep_number) 31 | sampling_rate = sweep_data["sampling_rate"] 32 | dt = 1.0 / sampling_rate 33 | t = np.arange(0, len(sweep_data["stimulus"])) * dt 34 | v = sweep_data["response"] * 1e3 # data from NWB now comes in Volts 35 | i = sweep_data["stimulus"] * 1e12 # data from NWB now comes in Amps 36 | sweep = Sweep(t=t, 37 | v=v, 38 | i=i, 39 | sampling_rate=sampling_rate, 40 | sweep_number=sweep_number, 41 | clamp_mode="CurrentClamp", 42 | epochs=None, 43 | ) 44 | sweep_list.append(sweep) 45 | start, dur, _, _, _ = stf.get_stim_characteristics(i, t) 46 | if start is None or dur is None: 47 | return SweepSet(sweep_list), None, None 48 | else: 49 | return SweepSet(sweep_list), start, start + dur 50 | 51 | 52 | def sweep_set_for_model(t, v, i): 53 | """Generate a SweepSet object based on a single model sweep 54 | 55 | Parameters 56 | ---------- 57 | t: array 58 | Time data (sec) 59 | v: array 60 | Voltage data (mV) 61 | i: array 62 | Current stimulus data (nA) 63 | 64 | Returns 65 | ------- 66 | SweepSet 67 | Contains one Sweep object 68 | """ 69 | sampling_rate = 1 / (t[1] - t[0]) 70 | sweep = Sweep(t=t, 71 | v=v, 72 | i=i, 73 | sampling_rate=sampling_rate, 74 | sweep_number=None, 75 | clamp_mode="CurrentClamp", 76 | epochs=None, 77 | ) 78 | return SweepSet([sweep]) 79 | 80 | 81 | -------------------------------------------------------------------------------- /biophys_optimize/tests/test_preprocess.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import biophys_optimize.preprocess as preprocess 3 | import numpy as np 4 | 5 | 6 | def test_passive_fit_window_inputs(): 7 | grand_up = np.zeros(3) 8 | grand_down_1 = np.zeros(4) 9 | grand_down_2 = np.zeros(3) 10 | t = np.zeros(5) 11 | 12 | pytest.raises(ValueError, preprocess.passive_fit_window,grand_up, grand_down_1, t) 13 | pytest.raises(ValueError, preprocess.passive_fit_window, grand_up, grand_down_2, t) 14 | 15 | 16 | def test_passive_fit_window_zero_window(): 17 | n_points = 500 18 | grand_up = np.ones(n_points) 19 | grand_down = np.ones(n_points) * 5 20 | t = np.arange(n_points) 21 | pytest.raises(RuntimeError, preprocess.passive_fit_window, 22 | grand_up, grand_down, t) 23 | 24 | 25 | def test_passive_fit_window_full_window(): 26 | n_points = 500 27 | grand_up = np.ones(n_points) 28 | grand_down = -grand_up 29 | t = np.arange(n_points) 30 | assert preprocess.passive_fit_window(grand_up, grand_down, t) == t[-1] 31 | 32 | 33 | def test_passive_fit_window_escape(): 34 | n_points = 500 35 | grand_up = np.ones(n_points) 36 | grand_down = -grand_up 37 | escape = 300 38 | grand_down[escape:] = grand_down[escape:] * 2 39 | t = np.arange(n_points) 40 | assert preprocess.passive_fit_window(grand_up, grand_down, t) >= escape 41 | assert preprocess.passive_fit_window(grand_up, grand_down, t) < t[-1] 42 | 43 | 44 | def test_passive_fit_window_transient_before_start(): 45 | n_points = 500 46 | grand_up = np.ones(n_points) 47 | grand_down = -grand_up 48 | escape = 300 49 | grand_down[95] = grand_down[95] * 100 50 | t = np.arange(n_points) 51 | assert preprocess.passive_fit_window(grand_up, grand_down, t, start_time=100) == t[-1] 52 | 53 | 54 | def test_passive_fit_window_transient_after_start(): 55 | n_points = 500 56 | grand_up = np.ones(n_points) 57 | grand_down = -grand_up 58 | escape = 300 59 | grand_down[110] = grand_down[110] * 100 60 | t = np.arange(n_points) 61 | assert preprocess.passive_fit_window(grand_up, grand_down, t, start_time=100) < t[-1] 62 | -------------------------------------------------------------------------------- /biophys_optimize/utils.py: -------------------------------------------------------------------------------- 1 | from builtins import object 2 | import numpy as np 3 | import logging 4 | from ipfx import feature_extractor as fx 5 | from .step_analysis import StepAnalysis 6 | from . import sweep_functions as sf 7 | from neuron import h 8 | 9 | 10 | class Utils(object): 11 | """ Class to implement and manipulate models in NEURON 12 | 13 | Attributes 14 | ---------- 15 | h : NEURON simulation object 16 | stim : NEURON IClamp object 17 | cell : NEURON object 18 | Cell object in NEURON 19 | channels : dict 20 | Dictionary of channel mechanism names and maximum conductances 21 | addl_params : dict 22 | Dictionary of additional (non-channel) mechanism names and values 23 | """ 24 | 25 | def __init__(self): 26 | self.h = h 27 | self.stim = None 28 | self.cell = self.h.cell() 29 | 30 | def generate_morphology(self, morph_filename): 31 | """Instantiate a morphology from an SWC file at `morph_filename` 32 | 33 | Also deletes the axonal compartments from the SWC file and inserts an axonal 34 | "stub" in its place. 35 | """ 36 | 37 | cell = self.cell 38 | 39 | swc = self.h.Import3d_SWC_read() 40 | swc.quiet = 1 41 | swc.input(morph_filename.encode('ascii', 'ignore')) 42 | imprt = self.h.Import3d_GUI(swc, 0) 43 | imprt.instantiate(cell) 44 | 45 | for seg in cell.soma[0]: 46 | seg.area() 47 | 48 | for sec in cell.all: 49 | sec.nseg = 1 + 2 * int(sec.L / 40) 50 | 51 | cell.simplify_axon() 52 | for sec in cell.axonal: 53 | sec.L = 30 54 | sec.diam = 1 55 | sec.nseg = 1 + 2 * int(sec.L / 40) 56 | cell.axon[0].connect(cell.soma[0], 0.5, 0) 57 | cell.axon[1].connect(cell.axon[0], 1, 0) 58 | h.define_shape() 59 | 60 | def load_cell_parameters(self, passive, conditions, channels, addl_params): 61 | """Set passive and active cell parameters 62 | 63 | Parameters 64 | ---------- 65 | passive : dict 66 | Dictionary of passive parameters 67 | conditions : dict 68 | Dictionary of experimental conditions (specifically reversal potentials) 69 | channels : dict 70 | Dictionary of channel mechanism names and maximum conductances 71 | addl_params : dict 72 | Dictionary of additional (non-channel) mechanism names and values 73 | """ 74 | cell = self.cell 75 | self.channels = channels 76 | self.addl_params = addl_params 77 | 78 | # Set passive properties 79 | for sec in cell.all: 80 | sec.Ra = passive['ra'] 81 | sec.cm = passive['cm'][sec.name().split(".")[1][:4]] 82 | sec.insert('pas') 83 | for seg in sec: 84 | seg.pas.e = passive["e_pas"] 85 | self.h.v_init = passive["e_pas"] 86 | 87 | # Insert channels and set parameters 88 | for c in channels: 89 | if c["mechanism"] != "": 90 | sections = [s for s in cell.all if s.name().split(".")[1][:4] == c["section"]] 91 | for sec in sections: 92 | sec.insert(c["mechanism"]) 93 | 94 | for ap in addl_params: 95 | if ap["mechanism"] != "": 96 | sections = [s for s in cell.all if s.name().split(".")[1][:4] == ap["section"]] 97 | for sec in sections: 98 | sec.insert(ap["mechanism"]) 99 | 100 | # Set reversal potentials 101 | for erev in conditions['erev']: 102 | sections = [s for s in cell.all if s.name().split(".")[1][:4] == erev["section"]] 103 | for sec in sections: 104 | sec.ena = erev["ena"] 105 | sec.ek = erev["ek"] 106 | 107 | def set_normalized_parameters(self, params): 108 | """ Set model parameters to normalized list of parameters 109 | 110 | Normalization is between 0 and 1. 111 | """ 112 | channels_and_others = self.channels + self.addl_params 113 | for i, p in enumerate(params): 114 | c = channels_and_others[i] 115 | if p > 1.0 or p < 0.0: 116 | logging.warning("WARNING: Setting a normalized parameter with a value outside [0, 1] ({:s} set to {:f})".format(c, p)) 117 | value = p * (c["max"] - c["min"]) + c["min"] 118 | sections = [s for s in self.cell.all if s.name().split(".")[1][:4] == c["section"]] 119 | for sec in sections: 120 | param_name = c["parameter"] 121 | if c["mechanism"] != "": 122 | param_name += "_" + c["mechanism"] 123 | setattr(sec, param_name, value) 124 | 125 | def set_actual_parameters(self, params): 126 | """ Set model parameters to actual-valued list of parameters 127 | 128 | Values are on scale used by NEURON 129 | """ 130 | channels_and_others = self.channels + self.addl_params 131 | for i, p in enumerate(params): 132 | c = channels_and_others[i] 133 | sections = [s for s in self.cell.all if s.name().split(".")[1][:4] == c["section"]] 134 | for sec in sections: 135 | param_name = c["parameter"] 136 | if c["mechanism"] != "": 137 | param_name += "_" + c["mechanism"] 138 | setattr(sec, param_name, p) 139 | 140 | def normalize_actual_parameters(self, params): 141 | """ Normalize parameters to 0 and 1 using information in `self.channels` and `self.addl_params`""" 142 | params_array = np.array(params) 143 | channels_and_others = self.channels + self.addl_params 144 | max_vals = np.array([c["max"] for c in channels_and_others]) 145 | min_vals = np.array([c["min"] for c in channels_and_others]) 146 | 147 | normalized_params = (params_array - min_vals) / (max_vals - min_vals) 148 | return normalized_params.tolist() 149 | 150 | def actual_parameters_from_normalized(self, params): 151 | """ Calculate actual values of parameters that have been normalized """ 152 | channels_and_others = self.channels + self.addl_params 153 | actual_params = [(p * 154 | (channels_and_others[i]["max"] - 155 | channels_and_others[i]["min"]) + 156 | channels_and_others[i]["min"]) 157 | for i, p in enumerate(params)] 158 | return actual_params 159 | 160 | def insert_iclamp(self): 161 | """ Create an IClamp object at the soma """ 162 | self.stim = self.h.IClamp(self.cell.soma[0](0.5)) 163 | 164 | def set_iclamp_params(self, amp, delay, dur): 165 | """ Set IClamp object parameters 166 | 167 | Parameters 168 | ---------- 169 | amp : float 170 | Stimulus amplitude (nA) 171 | delay : float 172 | Delay to start of stimulus (ms) 173 | dur : float 174 | Duration of stimulus (ms) 175 | """ 176 | self.stim.amp = amp 177 | self.stim.delay = delay 178 | self.stim.dur = dur 179 | 180 | def calculate_feature_errors(self, t_ms, v, i, feature_names, targets): 181 | """ Calculate feature errors (z-scored difference) 182 | 183 | Apply penalties for particular situations (no spikes, etc.) 184 | 185 | Parameters 186 | ---------- 187 | t_ms : array-like 188 | time vector in ms 189 | v : array-like 190 | voltage vector in mV 191 | i : array-like 192 | current vector 193 | feature_names : list 194 | list of feature names for error calculation 195 | targets : dict 196 | dictionary of feature target values (means and stdevs) 197 | 198 | Returns 199 | ------- 200 | array 201 | array of per-feature errors 202 | """ 203 | # Special case checks and penalty values 204 | minimum_num_spikes = 2 205 | missing_penalty_value = 20.0 206 | max_fail_penalty = 250.0 207 | min_fail_penalty = 75.0 208 | overkill_reduction = 0.75 209 | variance_factor = 0.1 210 | 211 | fail_trace = False 212 | 213 | delay = self.stim.delay * 1e-3 214 | duration = self.stim.dur * 1e-3 215 | t = t_ms * 1e-3 216 | 217 | # penalize for failing to return to rest 218 | start_index = np.flatnonzero(t >= delay)[0] 219 | if np.abs(v[-1] - v[:start_index].mean()) > 2.0: 220 | fail_trace = True 221 | else: 222 | pre_swp = fx.SpikeFeatureExtractor(start=0, end=delay) 223 | pre_spike_df = pre_swp.process(t, v, i) 224 | 225 | if pre_spike_df.shape[0] > 0: 226 | fail_trace = True 227 | 228 | if not fail_trace: 229 | model_sweep_set = sf.sweep_set_for_model(t, v, i) 230 | step_analysis = StepAnalysis(start=delay, end=delay + duration) 231 | step_analysis.analyze(model_sweep_set) 232 | 233 | spike_data = step_analysis.spikes_data()[0] 234 | sweep_data = step_analysis.sweep_features() 235 | 236 | if spike_data.shape[0] < minimum_num_spikes: # Enough spikes? 237 | fail_trace = True 238 | else: 239 | avg_per_spike_peak_error = np.abs( 240 | spike_data["peak_v"].values - 241 | targets["peak_v"]["mean"]).mean() 242 | avg_overall_error = abs(targets["peak_v"]["mean"] - 243 | spike_data["peak_v"].mean()) 244 | if avg_per_spike_peak_error > 3. * avg_overall_error: # Weird bi-modality of spikes; 3.0 is arbitrary 245 | fail_trace = True 246 | 247 | if fail_trace: 248 | variance_start = np.flatnonzero(t >= delay - 0.1)[0] 249 | variance_end = np.flatnonzero(t >= (delay + duration) / 2.0)[0] 250 | trace_variance = v[variance_start:variance_end].var() 251 | error_value = max(max_fail_penalty - trace_variance * variance_factor, min_fail_penalty) 252 | errs = np.ones(len(feature_names)) * error_value 253 | else: 254 | errs = [] 255 | for k in feature_names: 256 | if k in sweep_data: 257 | model_mean = sweep_data[k].values[0] 258 | elif k in spike_data: 259 | model_mean = spike_data[k].mean(skipna=True) 260 | else: 261 | logging.debug("Could not find feature %s", k) 262 | errs.append(missing_penalty_value) 263 | continue 264 | if np.isnan(model_mean): 265 | errs.append(missing_penalty_value) 266 | else: 267 | target_mean = targets[k]['mean'] 268 | target_stdev = targets[k]['stdev'] 269 | errs.append(np.abs((model_mean - target_mean) / target_stdev)) 270 | errs = np.array(errs) 271 | return errs 272 | 273 | def calculate_features(self, t_ms, v, i, feature_names): 274 | """Calculate sweep features 275 | 276 | Parameters 277 | ---------- 278 | t_ms : array-like 279 | time vector in ms 280 | v : array-like 281 | voltage vector in mV 282 | i : array-like 283 | current vector 284 | 285 | Returns 286 | ------- 287 | array 288 | Array of sweep features 289 | """ 290 | delay = self.stim.delay * 1e-3 291 | duration = self.stim.dur * 1e-3 292 | t = t_ms * 1e-3 293 | 294 | model_sweep_set = sf.sweep_set_for_model(t, v, i) 295 | step_analysis = StepAnalysis(start=delay, end=delay + duration) 296 | step_analysis.analyze(model_sweep_set) 297 | 298 | spike_data = step_analysis.spikes_data()[0] 299 | sweep_data = step_analysis.sweep_features() 300 | 301 | out_features = [] 302 | for k in feature_names: 303 | if k in sweep_data: 304 | out_features.append(sweep_data[k].values[0]) 305 | elif k in spike_data: 306 | out_features.append(spike_data[k].mean(skipna=True)) 307 | else: 308 | out_features.append(np.nan) 309 | return np.array(out_features) 310 | 311 | def record_values(self): 312 | """Create and return NEURON Vectors to record voltage, current, and time""" 313 | v_vec = self.h.Vector() 314 | t_vec = self.h.Vector() 315 | i_vec = self.h.Vector() 316 | 317 | v_vec.record(self.cell.soma[0](0.5)._ref_v) 318 | i_vec.record(self.stim._ref_amp) 319 | t_vec.record(self.h._ref_t) 320 | 321 | return v_vec, i_vec, t_vec 322 | 323 | -------------------------------------------------------------------------------- /config/minimum_feature_standard_deviations.yaml.example: -------------------------------------------------------------------------------- 1 | avg_rate: 0.5 # spikes/s 2 | adapt: 0.001 3 | peak_v: 2.0 # mV 4 | trough_v: 2.0 # mV 5 | fast_trough_v: 2.0 # mV 6 | slow_trough_delta_v: 0.5 # mV 7 | slow_trough_norm_time: 0.05 8 | latency: 0.005 # s 9 | isi_cv: 0.1 10 | mean_isi: 0.005 # s 11 | first_isi: 0.001 # s 12 | v_baseline: 2.0 # mV 13 | width: 0.0001 # s 14 | upstroke: 5.0 # V/s 15 | downstroke: 5.0 # V/s 16 | upstroke_v: 2.0 # mV 17 | downstroke_v: 2.0 # mV 18 | threshold_v: 2.0 # mV 19 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # http://www.sphinx-doc.org/en/master/config 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | sys.path.insert(0, os.path.abspath('..')) 16 | from argschema.autodoc import process_schemas 17 | 18 | 19 | # -- Project information ----------------------------------------------------- 20 | 21 | project = 'biophys_optimize' 22 | copyright = '2020, Allen Institute for Brain Science' 23 | author = 'Allen Institute for Brain Science' 24 | 25 | # The full version, including alpha/beta/rc tags 26 | release = '0.1' 27 | 28 | 29 | # -- General configuration --------------------------------------------------- 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | 'sphinx.ext.autodoc', 36 | 'sphinx.ext.viewcode', 37 | 'sphinx.ext.autosummary', 38 | 'sphinx.ext.napoleon', 39 | ] 40 | 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # generate autosummary pages 46 | autosummary_generate=True 47 | 48 | # List of patterns, relative to source directory, that match files and 49 | # directories to ignore when looking for source files. 50 | # This pattern also affects html_static_path and html_extra_path. 51 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 52 | 53 | 54 | # -- Options for HTML output ------------------------------------------------- 55 | 56 | # The theme to use for HTML and HTML Help pages. See the documentation for 57 | # a list of builtin themes. 58 | # 59 | html_theme = 'sphinx_rtd_theme' 60 | 61 | # Add any paths that contain custom static files (such as style sheets) here, 62 | # relative to this directory. They are copied after the builtin static files, 63 | # so a file named "default.css" will overwrite the builtin "default.css". 64 | html_static_path = ['_static'] 65 | 66 | def setup(app): 67 | app.connect('autodoc-process-docstring',process_schemas) 68 | 69 | -------------------------------------------------------------------------------- /docs/getting_started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | The `biophys_optimize` package enables the systematic generation of biophysical models based on a standard stimulus set. It has been built to expect data in the form of `NWB files `_, but it could be customized to use other data formats. 5 | 6 | Model generation is broken into several stages to allow for easier workflow management. These are executed by different `scripts ` that draw upon library functions. The scripts use JSON files as inputs and outputs to pass information from one stage to another. Individual scripts could be customized or replaced depending on your needs. This guide will cover the typical stages of fitting a model. 7 | 8 | Preprocessing 9 | ------------- 10 | 11 | The preprocessing stage performs several tasks before model fitting begins. Its tasks include: 12 | 13 | * Comparing "Core 1" to "Core 2" sweeps and selecting one as a training sweep 14 | * Calculating target features from the training sweep 15 | * Identifying the maximum current used to perform depolarization block checks during optimization 16 | * Averaging and saving the traces for passive parameter fitting 17 | * Selecting the "fit style" to use for optimization 18 | 19 | To do this, the :mod:`~biophys_optimize.scripts.run_passive_fitting` script expects a number of parameters in its input JSON file. An example of that input file looks like: 20 | 21 | { 22 | "paths": { 23 | "nwb": "/path/to/nwb/file.nwb", 24 | "swc": "/path/to/swc/file.swc", 25 | "storage_directory": "/path/to/fitting_storage_directory" 26 | }, 27 | "dendrite_type": "spiny", 28 | "sweeps": { 29 | "core_1_long_squares": [31, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45], 30 | "core_2_long_squares": [63, 64, 65, 67, 68, 69, 71, 73, 75, 76, 77], 31 | "seed_1_noise": [52, 56, 58], 32 | "seed_2_noise": [53, 55, 57, 59], 33 | "cap_checks": [61, 62] 34 | }, 35 | "bridge_avg": , 36 | "junction_potential": -14.0, 37 | } -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to biophys_optimize's documentation! 2 | ============================================ 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | - Getting Started 9 | - Reference 10 | 11 | 12 | Indices and tables 13 | ================== 14 | 15 | * :ref:`genindex` 16 | * :ref:`modindex` 17 | * :ref:`search` 18 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/reference/index.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | :Release: |release| 5 | :Date: |today| 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | scripts 11 | preprocess 12 | passive 13 | optimize -------------------------------------------------------------------------------- /docs/source/reference/optimize.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Optimization 3 | ============ 4 | 5 | 6 | Evolutionary algorithm optimization 7 | =================================== 8 | 9 | .. autosummary:: 10 | :toctree: generated/ 11 | 12 | ~biophys_optimize.optimize.optimize 13 | ~biophys_optimize.optimize.initPopulation 14 | ~biophys_optimize.optimize.eval_param_set 15 | ~biophys_optimize.optimize.uniform 16 | ~biophys_optimize.optimize.best_sum 17 | ~biophys_optimize.optimize.check_for_block 18 | 19 | 20 | Post-optimization model selection 21 | ================================= 22 | 23 | .. autosummary:: 24 | :toctree: generated/ 25 | 26 | ~biophys_optimize.model_selection.select_model 27 | ~biophys_optimize.model_selection.build_fit_data 28 | ~biophys_optimize.model_selection.has_noise_block 29 | ~biophys_optimize.model_selection.fit_info 30 | 31 | 32 | Starting optimization from existing population 33 | ============================================== 34 | 35 | .. autosummary:: 36 | :toctree: generated/ 37 | 38 | ~biophys_optimize.population_selection.population_info 39 | ~biophys_optimize.population_selection.select_starting_population 40 | 41 | 42 | Configuration 43 | ============= 44 | 45 | .. autosummary:: 46 | :toctree: generated/ 47 | 48 | ~biophys_optimize.utils.Utils 49 | ~biophys_optimize.environment.NeuronEnvironment 50 | ~biophys_optimize.optimize.StimParams 51 | 52 | 53 | NEURON parallel execution 54 | ========================= 55 | 56 | .. autosummary:: 57 | :toctree: generated/ 58 | 59 | ~biophys_optimize.neuron_parallel.map 60 | 61 | -------------------------------------------------------------------------------- /docs/source/reference/passive.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | Passive Fitting 3 | =============== 4 | 5 | .. automodule:: biophys_optimize.neuron_passive_fit 6 | 7 | Passive fitting functions 8 | ========================= 9 | 10 | .. autosummary:: 11 | :toctree: generated/ 12 | 13 | passive_fit_1 14 | passive_fit_2 15 | passive_fit_elec 16 | 17 | 18 | Data structure for passive fit results 19 | ====================================== 20 | 21 | .. autosummary:: 22 | :toctree: generated/ 23 | 24 | PassiveFitResult 25 | 26 | 27 | Setup functions 28 | ================ 29 | .. autosummary:: 30 | :toctree: generated/ 31 | 32 | initialize_neuron 33 | 34 | 35 | Selection from different passive fitting runs 36 | ============================================== 37 | 38 | .. automodule:: biophys_optimize.consolidate_passive_fits 39 | .. autosummary:: 40 | :toctree: generated/ 41 | 42 | compare_runs -------------------------------------------------------------------------------- /docs/source/reference/preprocess.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | Preprocessing 3 | ============= 4 | 5 | Sweep selection 6 | =============== 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | ~biophys_optimize.preprocess.select_core_1_or_core_2_sweeps 11 | ~biophys_optimize.preprocess.select_core1_trace 12 | ~biophys_optimize.preprocess.is_sweep_good_quality 13 | ~biophys_optimize.preprocess.has_pause 14 | ~biophys_optimize.check_fi_shift.estimate_fi_shift 15 | ~biophys_optimize.check_fi_shift.fi_shift 16 | ~biophys_optimize.check_fi_shift.fi_curve 17 | 18 | 19 | Feature analysis 20 | ================ 21 | .. autosummary:: 22 | :toctree: generated/ 23 | 24 | ~biophys_optimize.preprocess.target_features 25 | ~biophys_optimize.step_analysis.StepAnalysis 26 | 27 | 28 | Passive fit preparation 29 | ======================= 30 | .. autosummary:: 31 | :toctree: generated/ 32 | 33 | ~biophys_optimize.preprocess.cap_check_grand_averages 34 | ~biophys_optimize.preprocess.save_grand_averages 35 | ~biophys_optimize.preprocess.passive_fit_window 36 | 37 | Additional characteristics 38 | ========================== 39 | .. autosummary:: 40 | :toctree: generated/ 41 | 42 | ~biophys_optimize.preprocess.max_i_for_depol_block_check 43 | ~biophys_optimize.preprocess.swc_has_apical_compartments 44 | -------------------------------------------------------------------------------- /docs/source/reference/scripts.rst: -------------------------------------------------------------------------------- 1 | Scripts 2 | ======= 3 | 4 | These scripts execute the main steps of fitting a biophysically detailed model. 5 | 6 | .. autosummary:: 7 | :toctree: generated/ 8 | 9 | ~biophys_optimize.scripts.run_preprocessing 10 | ~biophys_optimize.scripts.run_passive_fitting 11 | ~biophys_optimize.scripts.run_consolidate_passive_fitting 12 | ~biophys_optimize.scripts.run_optimize 13 | ~biophys_optimize.scripts.run_population_selection 14 | ~biophys_optimize.scripts.run_model_selection -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | deap 2 | neuron 3 | numpy 4 | pandas 5 | allensdk 6 | ipfx 7 | argschema <2.0 8 | marshmallow <3.0 9 | pyyaml 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import biophys_optimize 3 | 4 | with open('requirements.txt', 'r') as f: 5 | required = f.read().splitlines() 6 | 7 | setup( 8 | version = biophys_optimize.__version__, 9 | name = 'biophys_optimize', 10 | author = 'Nathan Gouwens', 11 | author_email = 'nathang@alleninstitute.org', 12 | packages = find_packages(), 13 | package_data = { 14 | 'biophys_optimize': [ 'passive/*', 15 | 'fit_styles/*.json', 16 | 'modfiles/*.mod', 17 | '*.hoc' ], 18 | 19 | }, 20 | include_package_data = True, 21 | install_requires=required 22 | ) 23 | -------------------------------------------------------------------------------- /test_input_files/test_compare_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_types": ["f6"], 3 | "paths": { 4 | "f6": [ 5 | { 6 | "seed": 1234, 7 | "hof": "test_storage/f6_1234_final_hof.txt", 8 | "hof_fit": "test_storage/f6_1234_final_hof_fit.txt" 9 | } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test_input_files/test_consolidate_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "passive_fit_2": "./test_storage/passive_fit_2_results.json", 4 | "passive_fit_1": "./test_storage/passive_fit_1_results.json", 5 | "passive_fit_elec": "./test_storage/passive_fit_elec_results.json", 6 | "passive_info": "./test_storage/passive_info.json", 7 | "preprocess_results": "./test_storage/preprocess_results.json", 8 | "passive_results": "./test_storage/passive_results.json" 9 | } 10 | } -------------------------------------------------------------------------------- /test_input_files/test_optimize_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "fit_type": "f13", 3 | "paths": { 4 | "hoc_files": [ 5 | "stdgui.hoc", 6 | "import3d.hoc", 7 | "/local1/stash/biophys_optimize/biophys_optimize/cell.hoc" 8 | ], 9 | "compiled_mod_library": "/local1/stash/biophys_optimize/biophys_optimize/x86_64/.libs/libnrnmech.so", 10 | "swc": "/projects/mousecelltypes/vol1/prod506/specimen_485835055/Rbp4-Cre_KL100_Ai14-204744.04.01.01_496123897_m.swc", 11 | "starting_population": "./test_storage/f13_1234_final_hof.txt", 12 | "storage_directory": "./test_storage", 13 | "preprocess_results": "./test_storage/preprocess_results.json", 14 | "passive_results": "./test_storage/consolidated_passive_info.json", 15 | "fit_style": "/local1/stash/biophys_optimize/biophys_optimize/fit_styles/f13_fit_style.json" 16 | }, 17 | "seed": 1234, 18 | "ngen": 5, 19 | "mu": 10 20 | } -------------------------------------------------------------------------------- /test_input_files/test_passive_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "passive_info": "./test_storage/passive_info.json", 4 | "swc": "../GeneralTutorials/AllenSDK/cell_types/specimen_313862022/reconstruction.swc", 5 | "up": "./test_storage/upbase.dat", 6 | "down": "./test_storage/downbase.dat", 7 | "storage_directory": "./test_storage", 8 | "preprocess_results": "./test_storage/preprocess_results.json", 9 | "nwb": "../GeneralTutorials/AllenSDK/cell_types/specimen_313862022/ephys.nwb", 10 | "fit3": [ 11 | "./biophys_optimize/passive/fixnseg.hoc", 12 | "./biophys_optimize/passive/circuit.ses", 13 | "./biophys_optimize/passive/params.hoc", 14 | "./biophys_optimize/passive/mrf3.ses" 15 | ], 16 | "fit2": [ 17 | "./biophys_optimize/passive/fixnseg.hoc", 18 | "./biophys_optimize/passive/iclamp.ses", 19 | "./biophys_optimize/passive/params.hoc", 20 | "./biophys_optimize/passive/mrf2.ses" 21 | ], 22 | "fit1": [ 23 | "./biophys_optimize/passive/fixnseg.hoc", 24 | "./biophys_optimize/passive/iclamp.ses", 25 | "./biophys_optimize/passive/params.hoc", 26 | "./biophys_optimize/passive/mrf.ses" 27 | ] 28 | }, 29 | "task_list": [ 30 | { 31 | "fit_type": "f6", 32 | "seed": 1234 33 | }, 34 | { 35 | "fit_type": "f12", 36 | "seed": 1234 37 | }, 38 | { 39 | "fit_type": "f6", 40 | "seed": 1001 41 | }, 42 | { 43 | "fit_type": "f12", 44 | "seed": 1001 45 | }, 46 | { 47 | "fit_type": "f6", 48 | "seed": 4321 49 | }, 50 | { 51 | "fit_type": "f12", 52 | "seed": 4321 53 | }, 54 | { 55 | "fit_type": "f6", 56 | "seed": 1024 57 | }, 58 | { 59 | "fit_type": "f12", 60 | "seed": 1024 61 | }, 62 | { 63 | "fit_type": "f6", 64 | "seed": 2048 65 | }, 66 | { 67 | "fit_type": "f12", 68 | "seed": 2048 69 | } 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /test_input_files/test_passive_input_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "swc": "../GeneralTutorials/AllenSDK/cell_types/specimen_313862022/reconstruction.swc", 4 | "up": "./test_storage/upbase.dat", 5 | "down": "./test_storage/downbase.dat", 6 | "passive_fit_results_file": "./test_storage/passive_fit_1_results.json", 7 | "passive_info": "./test_storage/passive_info.json", 8 | "fit": [ 9 | "/home/ben/biophys_optimize/biophys_optimize/passive/fixnseg.hoc", 10 | "/home/ben/biophys_optimize/biophys_optimize/passive/iclamp.ses", 11 | "/home/ben/biophys_optimize/biophys_optimize/passive/params.hoc", 12 | "/home/ben/biophys_optimize/biophys_optimize/passive/mrf.ses" 13 | ] 14 | }, 15 | "passive_fit_type": "passive_fit_1", 16 | "output_json": "passive1_out.json" 17 | } 18 | -------------------------------------------------------------------------------- /test_input_files/test_passive_input_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "fit": [ 4 | "/local1/stash/biophys_optimize/biophys_optimize/passive/fixnseg.hoc", 5 | "/local1/stash/biophys_optimize/biophys_optimize/passive/iclamp.ses", 6 | "/local1/stash/biophys_optimize/biophys_optimize/passive/params.hoc", 7 | "/local1/stash/biophys_optimize/biophys_optimize/passive/mrf2.ses" 8 | ], 9 | "passive_info": "./test_storage/passive_info.json", 10 | "swc": "/projects/mousecelltypes/vol1/prod506/specimen_485835055/Rbp4-Cre_KL100_Ai14-204744.04.01.01_496123897_m.swc", 11 | "up": "./test_storage/upbase.dat", 12 | "passive_fit_results_file": "./test_storage/passive_fit_2_results.json", 13 | "down": "./test_storage/downbase.dat", 14 | "storage_directory": "./test_storage", 15 | "preprocess_results": "./test_storage/preprocess_results.json", 16 | "nwb": "/projects/mousecelltypes/vol1/prod485/Ephys_Roi_Result_485835053/485835053.nwb" 17 | }, 18 | "passive_fit_type": "passive_fit_2", 19 | "task_list": [ 20 | { 21 | "fit_type": "f6", 22 | "seed": 1234 23 | }, 24 | { 25 | "fit_type": "f12", 26 | "seed": 1234 27 | }, 28 | { 29 | "fit_type": "f6", 30 | "seed": 1001 31 | }, 32 | { 33 | "fit_type": "f12", 34 | "seed": 1001 35 | }, 36 | { 37 | "fit_type": "f6", 38 | "seed": 4321 39 | }, 40 | { 41 | "fit_type": "f12", 42 | "seed": 4321 43 | }, 44 | { 45 | "fit_type": "f6", 46 | "seed": 1024 47 | }, 48 | { 49 | "fit_type": "f12", 50 | "seed": 1024 51 | }, 52 | { 53 | "fit_type": "f6", 54 | "seed": 2048 55 | }, 56 | { 57 | "fit_type": "f12", 58 | "seed": 2048 59 | } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /test_input_files/test_passive_input_elec.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "fit": [ 4 | "/local1/stash/biophys_optimize/biophys_optimize/passive/fixnseg.hoc", 5 | "/local1/stash/biophys_optimize/biophys_optimize/passive/circuit.ses", 6 | "/local1/stash/biophys_optimize/biophys_optimize/passive/params.hoc", 7 | "/local1/stash/biophys_optimize/biophys_optimize/passive/mrf3.ses" 8 | ], 9 | "passive_info": "./test_storage/passive_info.json", 10 | "swc": "/projects/mousecelltypes/vol1/prod506/specimen_485835055/Rbp4-Cre_KL100_Ai14-204744.04.01.01_496123897_m.swc", 11 | "up": "./test_storage/upbase.dat", 12 | "passive_fit_results_file": "./test_storage/passive_fit_elec_results.json", 13 | "down": "./test_storage/downbase.dat", 14 | "storage_directory": "./test_storage", 15 | "preprocess_results": "./test_storage/preprocess_results.json", 16 | "nwb": "/projects/mousecelltypes/vol1/prod485/Ephys_Roi_Result_485835053/485835053.nwb" 17 | }, 18 | "passive_fit_type": "passive_fit_elec", 19 | "task_list": [ 20 | { 21 | "fit_type": "f6", 22 | "seed": 1234 23 | }, 24 | { 25 | "fit_type": "f12", 26 | "seed": 1234 27 | }, 28 | { 29 | "fit_type": "f6", 30 | "seed": 1001 31 | }, 32 | { 33 | "fit_type": "f12", 34 | "seed": 1001 35 | }, 36 | { 37 | "fit_type": "f6", 38 | "seed": 4321 39 | }, 40 | { 41 | "fit_type": "f12", 42 | "seed": 4321 43 | }, 44 | { 45 | "fit_type": "f6", 46 | "seed": 1024 47 | }, 48 | { 49 | "fit_type": "f12", 50 | "seed": 1024 51 | }, 52 | { 53 | "fit_type": "f6", 54 | "seed": 2048 55 | }, 56 | { 57 | "fit_type": "f12", 58 | "seed": 2048 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /test_input_files/test_population_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "fits": [ 4 | { 5 | "fit_type": "f6", 6 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1234/final_hof_fit.txt", 7 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1234/final_hof.txt" 8 | }, 9 | { 10 | "fit_type": "f6", 11 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1001/final_hof_fit.txt", 12 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1001/final_hof.txt" 13 | }, 14 | { 15 | "fit_type": "f6", 16 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s4321/final_hof_fit.txt", 17 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s4321/final_hof.txt" 18 | }, 19 | { 20 | "fit_type": "f6", 21 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1024/final_hof_fit.txt", 22 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s1024/final_hof.txt" 23 | }, 24 | { 25 | "fit_type": "f6", 26 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s2048/final_hof_fit.txt", 27 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f6/s2048/final_hof.txt" 28 | }, 29 | { 30 | "fit_type": "f12", 31 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1234/final_hof_fit.txt", 32 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1234/final_hof.txt" 33 | }, 34 | { 35 | "fit_type": "f12", 36 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1001/final_hof_fit.txt", 37 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1001/final_hof.txt" 38 | }, 39 | { 40 | "fit_type": "f12", 41 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s4321/final_hof_fit.txt", 42 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s4321/final_hof.txt" 43 | }, 44 | { 45 | "fit_type": "f12", 46 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1024/final_hof_fit.txt", 47 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s1024/final_hof.txt" 48 | }, 49 | { 50 | "fit_type": "f12", 51 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s2048/final_hof_fit.txt", 52 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f12/s2048/final_hof.txt" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /test_input_files/test_population_selection_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "fits": [ 4 | { 5 | "fit_type": "f9", 6 | "hof": "./test_storage/f9_1234_final_hof.txt", 7 | "hof_fit": "./test_storage/f9_1234_final_hof_fit.txt" 8 | }, 9 | { 10 | "fit_type": "f13", 11 | "hof": "./test_storage/f13_1234_final_hof.txt", 12 | "hof_fit": "./test_storage/f13_1234_final_hof_fit.txt" 13 | } 14 | ] 15 | } 16 | } -------------------------------------------------------------------------------- /test_input_files/test_preprocess_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "bridge_avg": 10.1953601837158, 3 | "paths": { 4 | "swc": "../GeneralTutorials/AllenSDK/cell_types/specimen_313862022/reconstruction.swc", 5 | "storage_directory": "test_storage/", 6 | "nwb": "../GeneralTutorials/AllenSDK/cell_types/specimen_313862022/ephys.nwb" 7 | }, 8 | "dendrite_type_tag": "dendrite type - spiny", 9 | "sweeps": { 10 | "core_1_long_squares": [ 11 | 37, 12 | 50, 13 | 49, 14 | 48, 15 | 47, 16 | 45, 17 | 44, 18 | 43, 19 | 41, 20 | 39, 21 | 38, 22 | 36, 23 | 46, 24 | 52, 25 | 51, 26 | 54, 27 | 55, 28 | 56, 29 | 58 30 | ], 31 | "seed_2_noise": [], 32 | "seed_1_noise": [ 33 | 64, 34 | 66 35 | ], 36 | "core_2_long_squares": [], 37 | "cap_checks": [ 38 | 69 39 | ] 40 | }, 41 | "output_json": "output.json" 42 | } 43 | -------------------------------------------------------------------------------- /test_input_files/test_select_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "nwb": "/projects/mousecelltypes/vol1/prod485/Ephys_Roi_Result_485835053/485835053.nwb", 4 | "swc": "/projects/mousecelltypes/vol1/prod506/specimen_485835055/Rbp4-Cre_KL100_Ai14-204744.04.01.01_496123897_m.swc", 5 | "fit_styles": { 6 | "f9": "/local1/stash/biophys_optimize/biophys_optimize/fit_styles/f9_fit_style.json", 7 | "f13": "/local1/stash/biophys_optimize/biophys_optimize/fit_styles/f13_fit_style.json" 8 | }, 9 | "passive_results": "test_storage/passive_results.json", 10 | "preprocess_results": "test_storage/preprocess_results.json", 11 | "best_fit_json_path": "test_storage/best_fit.json", 12 | "fits": [ 13 | { 14 | "fit_type": "f9", 15 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1234/final_hof_fit.txt", 16 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1234/final_hof.txt" 17 | }, 18 | { 19 | "fit_type": "f9", 20 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1001/final_hof_fit.txt", 21 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1001/final_hof.txt" 22 | }, 23 | { 24 | "fit_type": "f9", 25 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s4321/final_hof_fit.txt", 26 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s4321/final_hof.txt" 27 | }, 28 | { 29 | "fit_type": "f9", 30 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1024/final_hof_fit.txt", 31 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s1024/final_hof.txt" 32 | }, 33 | { 34 | "fit_type": "f9", 35 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s2048/final_hof_fit.txt", 36 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f9/s2048/final_hof.txt" 37 | }, 38 | { 39 | "fit_type": "f13", 40 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1234/final_hof_fit.txt", 41 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1234/final_hof.txt" 42 | }, 43 | { 44 | "fit_type": "f13", 45 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1001/final_hof_fit.txt", 46 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1001/final_hof.txt" 47 | }, 48 | { 49 | "fit_type": "f13", 50 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s4321/final_hof_fit.txt", 51 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s4321/final_hof.txt" 52 | }, 53 | { 54 | "fit_type": "f13", 55 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1024/final_hof_fit.txt", 56 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s1024/final_hof.txt" 57 | }, 58 | { 59 | "fit_type": "f13", 60 | "hof_fit": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s2048/final_hof_fit.txt", 61 | "hof": "/data/mat/nathang/deap_optimize/fits/eaf_485835055/f13/s2048/final_hof.txt" 62 | } 63 | ], 64 | "compiled_mod_library": "/local1/stash/biophys_optimize/biophys_optimize/x86_64/.libs/libnrnmech.so", 65 | "hoc_files": [ "stdgui.hoc", "import3d.hoc", "/local1/stash/biophys_optimize/biophys_optimize/cell.hoc" ] 66 | }, 67 | "noise_1_sweeps": [57], 68 | "noise_2_sweeps": [58, 52] 69 | } -------------------------------------------------------------------------------- /test_storage/passive_fit_1_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "cm": 2.224849978163392, 3 | "err": 0.0007596079829486633, 4 | "a1": 657.6357573816457, 5 | "a2": 5516.1983795364795, 6 | "ra": 195.97272035917572, 7 | "rm": 2892.3445577440775 8 | } -------------------------------------------------------------------------------- /test_storage/passive_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "is_spiny": true, 3 | "should_run": true, 4 | "limit": 10.375, 5 | "electrode_cap": 1.0, 6 | "bridge": 10.1953601837158 7 | } -------------------------------------------------------------------------------- /test_storage/preprocess_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "sweeps_to_fit": [ 3 | 58 4 | ], 5 | "has_apical": true, 6 | "v_baseline": -76.31674194335938, 7 | "target_features": [ 8 | { 9 | "stdev": 0.05, 10 | "name": "slow_trough_norm_t", 11 | "mean": 0.3146276230417891 12 | }, 13 | { 14 | "stdev": 2.0, 15 | "name": "v_baseline", 16 | "mean": -76.31674194335938 17 | }, 18 | { 19 | "stdev": 2.0, 20 | "name": "downstroke_v", 21 | "mean": -1.8958330154418945 22 | }, 23 | { 24 | "stdev": 0.5, 25 | "name": "avg_rate", 26 | "mean": 24.0 27 | }, 28 | { 29 | "stdev": 0.005, 30 | "name": "latency", 31 | "mean": 0.0046800000000000175 32 | }, 33 | { 34 | "stdev": 2.0, 35 | "name": "fast_trough_v", 36 | "mean": -57.82551956176758 37 | }, 38 | { 39 | "stdev": 0.5, 40 | "name": "slow_trough_delta_v", 41 | "mean": 1.1328121821085613 42 | }, 43 | { 44 | "stdev": 5.0, 45 | "name": "upstroke", 46 | "mean": 154.73884017976465 47 | }, 48 | { 49 | "stdev": 2.0, 50 | "name": "trough_v", 51 | "mean": -59.05208206176758 52 | }, 53 | { 54 | "stdev": 0.0005, 55 | "name": "mean_isi", 56 | "mean": 0.04134652173913044 57 | }, 58 | { 59 | "stdev": 0.0001, 60 | "name": "width", 61 | "mean": 0.0020412500000000036 62 | }, 63 | { 64 | "stdev": 2.0, 65 | "name": "peak_v", 66 | "mean": 12.588541984558105 67 | }, 68 | { 69 | "stdev": 0.001, 70 | "name": "adapt", 71 | "mean": 0.046961055283351906 72 | }, 73 | { 74 | "stdev": 0.001, 75 | "name": "first_isi", 76 | "mean": 0.017055000000000042 77 | }, 78 | { 79 | "stdev": 2.0, 80 | "name": "threshold_v", 81 | "mean": -47.38411331176758 82 | }, 83 | { 84 | "stdev": 5.0, 85 | "name": "downstroke", 86 | "mean": -29.432389250379696 87 | }, 88 | { 89 | "stdev": 2.0, 90 | "name": "upstroke_v", 91 | "mean": -14.876301765441895 92 | }, 93 | { 94 | "stdev": 0.1, 95 | "name": "isi_cv", 96 | "mean": 0.7327438036937474 97 | } 98 | ], 99 | "junction_potential": -14.0, 100 | "is_spiny": true, 101 | "stimulus": { 102 | "delay": 1000.0, 103 | "duration": 1000.0, 104 | "amplitude": 0.35000000000000003 105 | }, 106 | "max_stim_test_na": 0.4503749694824219, 107 | "sweeps": { 108 | "core_1_long_squares": [ 109 | 37, 110 | 50, 111 | 49, 112 | 48, 113 | 47, 114 | 45, 115 | 44, 116 | 43, 117 | 41, 118 | 39, 119 | 38, 120 | 36, 121 | 46, 122 | 52, 123 | 51, 124 | 54, 125 | 55, 126 | 56, 127 | 58 128 | ], 129 | "seed_2_noise": [], 130 | "seed_1_noise": [ 131 | 64, 132 | 66 133 | ], 134 | "core_2_long_squares": [], 135 | "cap_checks": [ 136 | 69 137 | ] 138 | } 139 | } --------------------------------------------------------------------------------