bmtool 0.7.6__py3-none-any.whl → 0.7.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bmtool/synapses.py CHANGED
@@ -38,6 +38,7 @@ DEFAULT_GAP_JUNCTION_GENERAL_SETTINGS = {
38
38
  "tdur": 500.0,
39
39
  "dt": 0.025,
40
40
  "celsius": 20,
41
+ "iclamp_amp": -0.01, # nA
41
42
  }
42
43
 
43
44
 
@@ -1325,7 +1326,7 @@ class SynapseTuner:
1325
1326
  vlamp_status = self.vclamp
1326
1327
 
1327
1328
  # Connection dropdown
1328
- connection_options = list(self.conn_type_settings.keys())
1329
+ connection_options = sorted(list(self.conn_type_settings.keys()))
1329
1330
  w_connection = widgets.Dropdown(
1330
1331
  options=connection_options,
1331
1332
  value=self.current_connection,
@@ -1762,42 +1763,356 @@ class GapJunctionTuner:
1762
1763
  self.general_settings = {**DEFAULT_GAP_JUNCTION_GENERAL_SETTINGS, **general_settings}
1763
1764
  self.conn_type_settings = conn_type_settings
1764
1765
 
1766
+ self._syn_params_cache = {}
1767
+ self.config = config
1768
+ self.available_networks = []
1769
+ self.current_network = None
1770
+ if self.conn_type_settings is None and self.config is not None:
1771
+ self.conn_type_settings = self._build_conn_type_settings_from_config(self.config)
1772
+ if self.conn_type_settings is None or len(self.conn_type_settings) == 0:
1773
+ raise ValueError("conn_type_settings must be provided or config must be given to load gap junction connections from")
1774
+ self.current_connection = list(self.conn_type_settings.keys())[0]
1775
+ self.conn = self.conn_type_settings[self.current_connection]
1776
+
1765
1777
  h.tstop = self.general_settings["tstart"] + self.general_settings["tdur"] + 100.0
1766
1778
  h.dt = self.general_settings["dt"] # Time step (resolution) of the simulation in ms
1767
1779
  h.steps_per_ms = 1 / h.dt
1768
1780
  h.celsius = self.general_settings["celsius"]
1769
1781
 
1782
+ # Clean up any existing parallel context before setting up gap junctions
1783
+ try:
1784
+ pc_temp = h.ParallelContext()
1785
+ pc_temp.done() # Clean up any existing parallel context
1786
+ except:
1787
+ pass # Ignore errors if no existing context
1788
+
1789
+ # Force cleanup
1790
+ import gc
1791
+ gc.collect()
1792
+
1770
1793
  # set up gap junctions
1771
- pc = h.ParallelContext()
1794
+ self.pc = h.ParallelContext()
1772
1795
 
1773
1796
  # Use provided hoc_cell or create new cells
1774
1797
  if self.hoc_cell is not None:
1775
1798
  self.cell1 = self.hoc_cell
1776
1799
  # For gap junctions, we need two cells, so create a second one if using hoc_cell
1777
- self.cell_name = conn_type_settings["cell"]
1800
+ self.cell_name = self.conn['cell']
1778
1801
  self.cell2 = getattr(h, self.cell_name)()
1779
1802
  else:
1780
- self.cell_name = conn_type_settings["cell"]
1803
+ print(self.conn)
1804
+ self.cell_name = self.conn['cell']
1781
1805
  self.cell1 = getattr(h, self.cell_name)()
1782
1806
  self.cell2 = getattr(h, self.cell_name)()
1783
1807
 
1784
1808
  self.icl = h.IClamp(self.cell1.soma[0](0.5))
1785
1809
  self.icl.delay = self.general_settings["tstart"]
1786
1810
  self.icl.dur = self.general_settings["tdur"]
1787
- self.icl.amp = self.conn_type_settings["iclamp_amp"] # nA
1811
+ self.icl.amp = self.general_settings["iclamp_amp"] # nA
1788
1812
 
1789
- sec1 = list(self.cell1.all)[conn_type_settings["sec_id"]]
1790
- sec2 = list(self.cell2.all)[conn_type_settings["sec_id"]]
1813
+ sec1 = list(self.cell1.all)[self.conn["sec_id"]]
1814
+ sec2 = list(self.cell2.all)[self.conn["sec_id"]]
1791
1815
 
1792
- pc.source_var(sec1(conn_type_settings["sec_x"])._ref_v, 0, sec=sec1)
1816
+ # Use unique IDs to avoid conflicts with existing parallel context setups
1817
+ import time
1818
+ unique_id = int(time.time() * 1000) % 10000 # Use timestamp as unique base ID
1819
+
1820
+ self.pc.source_var(sec1(self.conn["sec_x"])._ref_v, unique_id, sec=sec1)
1793
1821
  self.gap_junc_1 = h.Gap(sec1(0.5))
1794
- pc.target_var(self.gap_junc_1._ref_vgap, 1)
1822
+ self.pc.target_var(self.gap_junc_1._ref_vgap, unique_id + 1)
1795
1823
 
1796
- pc.source_var(sec2(conn_type_settings["sec_x"])._ref_v, 1, sec=sec2)
1824
+ self.pc.source_var(sec2(self.conn["sec_x"])._ref_v, unique_id + 1, sec=sec2)
1797
1825
  self.gap_junc_2 = h.Gap(sec2(0.5))
1798
- pc.target_var(self.gap_junc_2._ref_vgap, 0)
1826
+ self.pc.target_var(self.gap_junc_2._ref_vgap, unique_id)
1827
+
1828
+ self.pc.setup_transfer()
1829
+
1830
+ # Now it's safe to initialize NEURON
1831
+ h.finitialize()
1832
+
1833
+ def _load_synaptic_params_from_config(self, config: dict, dynamics_params: str) -> dict:
1834
+ try:
1835
+ # Get the synaptic models directory from config
1836
+ synaptic_models_dir = config.get('components', {}).get('synaptic_models_dir', '')
1837
+ if synaptic_models_dir:
1838
+ # Handle path variables
1839
+ if synaptic_models_dir.startswith('$'):
1840
+ # This is a placeholder, try to resolve it
1841
+ config_dir = os.path.dirname(config.get('config_path', ''))
1842
+ synaptic_models_dir = synaptic_models_dir.replace('$COMPONENTS_DIR',
1843
+ os.path.join(config_dir, 'components'))
1844
+ synaptic_models_dir = synaptic_models_dir.replace('$BASE_DIR', config_dir)
1845
+
1846
+ dynamics_file = os.path.join(synaptic_models_dir, dynamics_params)
1847
+
1848
+ if os.path.exists(dynamics_file):
1849
+ with open(dynamics_file, 'r') as f:
1850
+ return json.load(f)
1851
+ else:
1852
+ print(f"Warning: Dynamics params file not found: {dynamics_file}")
1853
+ except Exception as e:
1854
+ print(f"Warning: Error loading synaptic parameters: {e}")
1855
+
1856
+ return {}
1857
+
1858
+ def _load_available_networks(self) -> None:
1859
+ """
1860
+ Load available network names from the config file for the network dropdown feature.
1861
+
1862
+ This method is automatically called during initialization when a config file is provided.
1863
+ It populates the available_networks list which enables the network dropdown in
1864
+ InteractiveTuner when multiple networks are available.
1865
+
1866
+ Network Dropdown Behavior:
1867
+ -------------------------
1868
+ - If only one network exists: No network dropdown is shown
1869
+ - If multiple networks exist: Network dropdown appears next to connection dropdown
1870
+ - Networks are loaded from the edges data in the config file
1871
+ - Current network defaults to the first available if not specified during init
1872
+ """
1873
+ if self.config is None:
1874
+ self.available_networks = []
1875
+ return
1876
+
1877
+ try:
1878
+ edges = load_edges_from_config(self.config)
1879
+ self.available_networks = list(edges.keys())
1880
+
1881
+ # Set current network to first available if not specified
1882
+ if self.current_network is None and self.available_networks:
1883
+ self.current_network = self.available_networks[0]
1884
+ except Exception as e:
1885
+ print(f"Warning: Could not load networks from config: {e}")
1886
+ self.available_networks = []
1887
+
1888
+ def _build_conn_type_settings_from_config(self, config_path: str) -> Dict[str, dict]:
1889
+ # Load configuration and get nodes and edges using util.py methods
1890
+ config = load_config(config_path)
1891
+ # Ensure the config dict knows its source path so path substitutions can be resolved
1892
+ try:
1893
+ config['config_path'] = config_path
1894
+ except Exception:
1895
+ pass
1896
+ nodes = load_nodes_from_config(config_path)
1897
+ edges = load_edges_from_config(config_path)
1898
+
1899
+ conn_type_settings = {}
1900
+
1901
+ # Process all edge datasets
1902
+ for edge_dataset_name, edge_df in edges.items():
1903
+ if edge_df.empty:
1904
+ continue
1905
+
1906
+ # Merging with node data to get model templates
1907
+ source_node_df = None
1908
+ target_node_df = None
1909
+
1910
+ # First, try to deterministically parse the edge_dataset_name for patterns like '<src>_to_<tgt>'
1911
+ if '_to_' in edge_dataset_name:
1912
+ parts = edge_dataset_name.split('_to_')
1913
+ if len(parts) == 2:
1914
+ src_name, tgt_name = parts
1915
+ if src_name in nodes:
1916
+ source_node_df = nodes[src_name].add_prefix('source_')
1917
+ if tgt_name in nodes:
1918
+ target_node_df = nodes[tgt_name].add_prefix('target_')
1919
+
1920
+ # If not found by parsing name, fall back to inspecting a sample edge row
1921
+ if source_node_df is None or target_node_df is None:
1922
+ sample_edge = edge_df.iloc[0] if len(edge_df) > 0 else None
1923
+ if sample_edge is not None:
1924
+ source_pop_name = sample_edge.get('source_population', '')
1925
+ target_pop_name = sample_edge.get('target_population', '')
1926
+ if source_pop_name in nodes:
1927
+ source_node_df = nodes[source_pop_name].add_prefix('source_')
1928
+ if target_pop_name in nodes:
1929
+ target_node_df = nodes[target_pop_name].add_prefix('target_')
1930
+
1931
+ # As a last resort, attempt to heuristically match
1932
+ if source_node_df is None or target_node_df is None:
1933
+ for pop_name, node_df in nodes.items():
1934
+ if source_node_df is None and (edge_dataset_name.startswith(pop_name) or edge_dataset_name.endswith(pop_name)):
1935
+ source_node_df = node_df.add_prefix('source_')
1936
+ if target_node_df is None and (edge_dataset_name.startswith(pop_name) or edge_dataset_name.endswith(pop_name)):
1937
+ target_node_df = node_df.add_prefix('target_')
1938
+
1939
+ if source_node_df is None or target_node_df is None:
1940
+ print(f"Warning: Could not find node data for edge dataset {edge_dataset_name}")
1941
+ continue
1942
+
1943
+ # Merge edge data with source node info
1944
+ edges_with_source = pd.merge(
1945
+ edge_df.reset_index(),
1946
+ source_node_df,
1947
+ how='left',
1948
+ left_on='source_node_id',
1949
+ right_index=True
1950
+ )
1951
+
1952
+ # Merge with target node info
1953
+ edges_with_nodes = pd.merge(
1954
+ edges_with_source,
1955
+ target_node_df,
1956
+ how='left',
1957
+ left_on='target_node_id',
1958
+ right_index=True
1959
+ )
1960
+
1961
+ # Skip edge datasets that don't have gap junction information
1962
+ if 'is_gap_junction' not in edges_with_nodes.columns:
1963
+ continue
1964
+
1965
+ # Filter to only gap junction edges
1966
+ # Handle NaN values in is_gap_junction column
1967
+ gap_junction_mask = edges_with_nodes['is_gap_junction'].fillna(False) == True
1968
+ gap_junction_edges = edges_with_nodes[gap_junction_mask]
1969
+ if gap_junction_edges.empty:
1970
+ continue
1971
+
1972
+ # Get unique edge types from the gap junction edges
1973
+ if 'edge_type_id' in gap_junction_edges.columns:
1974
+ edge_types = gap_junction_edges['edge_type_id'].unique()
1975
+ else:
1976
+ edge_types = [None] # Single edge type
1977
+
1978
+ # Process each edge type
1979
+ for edge_type_id in edge_types:
1980
+ # Filter edges for this type
1981
+ if edge_type_id is not None:
1982
+ edge_type_data = gap_junction_edges[gap_junction_edges['edge_type_id'] == edge_type_id]
1983
+ else:
1984
+ edge_type_data = gap_junction_edges
1985
+
1986
+ if len(edge_type_data) == 0:
1987
+ continue
1988
+
1989
+ # Get representative edge for this type
1990
+ edge_info = edge_type_data.iloc[0]
1991
+
1992
+ # Process gap junction
1993
+ source_model_template = edge_info.get('source_model_template', '')
1994
+ target_model_template = edge_info.get('target_model_template', '')
1995
+
1996
+ source_cell_type = source_model_template.replace('hoc:', '') if source_model_template.startswith('hoc:') else source_model_template
1997
+ target_cell_type = target_model_template.replace('hoc:', '') if target_model_template.startswith('hoc:') else target_model_template
1998
+
1999
+ if source_cell_type != target_cell_type:
2000
+ continue # Only process gap junctions between same cell types
2001
+
2002
+ source_pop = edge_info.get('source_pop_name', '')
2003
+ target_pop = edge_info.get('target_pop_name', '')
2004
+
2005
+ conn_name = f"{source_pop}2{target_pop}_gj"
2006
+ if edge_type_id is not None:
2007
+ conn_name += f"_type_{edge_type_id}"
2008
+
2009
+ conn_settings = {
2010
+ 'cell': source_cell_type,
2011
+ 'sec_id': 0,
2012
+ 'sec_x': 0.5,
2013
+ 'iclamp_amp': -0.01,
2014
+ 'spec_syn_param': {}
2015
+ }
2016
+
2017
+ # Load dynamics params
2018
+ dynamics_file_name = edge_info.get('dynamics_params', '')
2019
+ if dynamics_file_name and dynamics_file_name.upper() != 'NULL':
2020
+ try:
2021
+ syn_params = self._load_synaptic_params_from_config(config, dynamics_file_name)
2022
+ conn_settings['spec_syn_param'] = syn_params
2023
+ except Exception as e:
2024
+ print(f"Warning: could not load dynamics_params file '{dynamics_file_name}': {e}")
2025
+
2026
+ conn_type_settings[conn_name] = conn_settings
2027
+
2028
+ return conn_type_settings
1799
2029
 
1800
- pc.setup_transfer()
2030
+ def _switch_connection(self, new_connection: str) -> None:
2031
+ """
2032
+ Switch to a different gap junction connection and update all related properties.
2033
+
2034
+ Parameters:
2035
+ -----------
2036
+ new_connection : str
2037
+ Name of the new connection type to switch to.
2038
+ """
2039
+ if new_connection not in self.conn_type_settings:
2040
+ raise ValueError(f"Connection '{new_connection}' not found in conn_type_settings")
2041
+
2042
+ # Update current connection
2043
+ self.current_connection = new_connection
2044
+ self.conn = self.conn_type_settings[new_connection]
2045
+
2046
+ # Check if cell type changed
2047
+ new_cell_name = self.conn['cell']
2048
+ if self.cell_name != new_cell_name:
2049
+ self.cell_name = new_cell_name
2050
+
2051
+ # Recreate cells
2052
+ if self.hoc_cell is None:
2053
+ self.cell1 = getattr(h, self.cell_name)()
2054
+ self.cell2 = getattr(h, self.cell_name)()
2055
+ else:
2056
+ # For hoc_cell, recreate the second cell
2057
+ self.cell2 = getattr(h, self.cell_name)()
2058
+
2059
+ # Recreate IClamp
2060
+ self.icl = h.IClamp(self.cell1.soma[0](0.5))
2061
+ self.icl.delay = self.general_settings["tstart"]
2062
+ self.icl.dur = self.general_settings["tdur"]
2063
+ self.icl.amp = self.general_settings["iclamp_amp"]
2064
+ else:
2065
+ # Update IClamp parameters even if same cell type
2066
+ self.icl.amp = self.general_settings["iclamp_amp"]
2067
+
2068
+ # Always recreate gap junctions when switching connections
2069
+ # (even for same cell type, sec_id or sec_x might differ)
2070
+
2071
+ # Clean up previous gap junctions and parallel context
2072
+ if hasattr(self, 'gap_junc_1'):
2073
+ del self.gap_junc_1
2074
+ if hasattr(self, 'gap_junc_2'):
2075
+ del self.gap_junc_2
2076
+
2077
+ # Properly clean up the existing parallel context
2078
+ if hasattr(self, 'pc'):
2079
+ self.pc.done() # Clean up existing parallel context
2080
+
2081
+ # Force garbage collection and reset NEURON state
2082
+ import gc
2083
+ gc.collect()
2084
+ h.finitialize()
2085
+
2086
+ # Create a fresh parallel context after cleanup
2087
+ self.pc = h.ParallelContext()
2088
+
2089
+ try:
2090
+ sec1 = list(self.cell1.all)[self.conn["sec_id"]]
2091
+ sec2 = list(self.cell2.all)[self.conn["sec_id"]]
2092
+
2093
+ # Use unique IDs to avoid conflicts with existing parallel context setups
2094
+ import time
2095
+ unique_id = int(time.time() * 1000) % 10000 # Use timestamp as unique base ID
2096
+
2097
+ self.pc.source_var(sec1(self.conn["sec_x"])._ref_v, unique_id, sec=sec1)
2098
+ self.gap_junc_1 = h.Gap(sec1(0.5))
2099
+ self.pc.target_var(self.gap_junc_1._ref_vgap, unique_id + 1)
2100
+
2101
+ self.pc.source_var(sec2(self.conn["sec_x"])._ref_v, unique_id + 1, sec=sec2)
2102
+ self.gap_junc_2 = h.Gap(sec2(0.5))
2103
+ self.pc.target_var(self.gap_junc_2._ref_vgap, unique_id)
2104
+
2105
+ self.pc.setup_transfer()
2106
+ except Exception as e:
2107
+ print(f"Error setting up gap junctions: {e}")
2108
+ # Try to continue with basic setup
2109
+ self.gap_junc_1 = h.Gap(list(self.cell1.all)[self.conn["sec_id"]](0.5))
2110
+ self.gap_junc_2 = h.Gap(list(self.cell2.all)[self.conn["sec_id"]](0.5))
2111
+
2112
+ # Reset NEURON state after complete setup
2113
+ h.finitialize()
2114
+
2115
+ print(f"Successfully switched to connection: {new_connection}")
1801
2116
 
1802
2117
  def model(self, resistance):
1803
2118
  """
@@ -1901,13 +2216,9 @@ class GapJunctionTuner:
1901
2216
  continuous_update=True,
1902
2217
  )
1903
2218
 
1904
- ui = VBox([w_run, resistance])
1905
-
1906
- # Create an output widget to control what gets cleared
1907
2219
  output = widgets.Output()
1908
2220
 
1909
- display(ui)
1910
- display(output)
2221
+ ui_widgets = [w_run, resistance]
1911
2222
 
1912
2223
  def on_button(*args):
1913
2224
  with output:
@@ -1915,7 +2226,7 @@ class GapJunctionTuner:
1915
2226
  output.clear_output(wait=True)
1916
2227
 
1917
2228
  resistance_for_gap = resistance.value
1918
- print(f"Running simulation with resistance: {resistance_for_gap}")
2229
+ print(f"Running simulation with resistance: {resistance_for_gap:0.6f} and {self.general_settings['iclamp_amp']*1000}pA current clamps")
1919
2230
 
1920
2231
  try:
1921
2232
  self.model(resistance_for_gap)
@@ -1936,6 +2247,25 @@ class GapJunctionTuner:
1936
2247
 
1937
2248
  traceback.print_exc()
1938
2249
 
2250
+ # Add connection dropdown if multiple connections exist
2251
+ if len(self.conn_type_settings) > 1:
2252
+ connection_dropdown = widgets.Dropdown(
2253
+ options=list(self.conn_type_settings.keys()),
2254
+ value=self.current_connection,
2255
+ description='Connection:',
2256
+ )
2257
+ def on_connection_change(change):
2258
+ if change['type'] == 'change' and change['name'] == 'value':
2259
+ self._switch_connection(change['new'])
2260
+ on_button() # Automatically rerun the simulation after switching
2261
+ connection_dropdown.observe(on_connection_change)
2262
+ ui_widgets.insert(0, connection_dropdown)
2263
+
2264
+ ui = VBox(ui_widgets)
2265
+
2266
+ display(ui)
2267
+ display(output)
2268
+
1939
2269
  # Run once initially
1940
2270
  on_button()
1941
2271
  w_run.on_click(on_button)
@@ -2316,7 +2646,6 @@ class SynapseOptimizer:
2316
2646
  self.tuner.ispk = None
2317
2647
  self.tuner.SingleEvent(plot_and_print=True)
2318
2648
 
2319
-
2320
2649
  # dataclass means just init the typehints as self.typehint. looks a bit cleaner
2321
2650
  @dataclass
2322
2651
  class GapOptimizationResult:
@@ -2531,4 +2860,4 @@ class GapJunctionOptimizer:
2531
2860
  results["resistance"].append(resistance)
2532
2861
  results["coupling_coefficient"].append(cc)
2533
2862
 
2534
- return results
2863
+ return results
bmtool/util/util.py CHANGED
@@ -1163,9 +1163,43 @@ def percent_connections(
1163
1163
  num_sources = s_list[source_id_type].value_counts().sort_index().loc[source_id]
1164
1164
  num_targets = t_list[target_id_type].value_counts().sort_index().loc[target_id]
1165
1165
 
1166
- total = round(total_cons / (num_sources * num_targets) * 100, 2)
1167
- uni = round(num_uni / (num_sources * num_targets) * 100, 2)
1168
- bi = round(num_bi / (num_sources * num_targets) * 100, 2)
1166
+ # Check if this is a recurrent network (same source and target population)
1167
+ # For recurrent networks (e.g., FSI->FSI), we need special handling because:
1168
+ # - Each pair can have at most 2 directed connections (bidirectional)
1169
+ # - We want to count unique pairs, not directed connections
1170
+ # - The denominator should be n*(n-1)/2, not n*n
1171
+ is_recurrent = source_id == target_id
1172
+
1173
+ if is_recurrent:
1174
+ # For recurrent networks, calculate connectivity based on unique undirected pairs
1175
+ # This avoids double-counting reciprocal connections and uses correct denominator
1176
+ pair_counts = {}
1177
+ for _, row in cons.iterrows():
1178
+ sid = row['source_node_id']
1179
+ tid = row['target_node_id']
1180
+ if sid != tid: # Exclude self-connections
1181
+ # Use symmetric pair key to count connections per unique pair
1182
+ pair_key = (min(sid, tid), max(sid, tid))
1183
+ if pair_key not in pair_counts:
1184
+ pair_counts[pair_key] = 0
1185
+ pair_counts[pair_key] += 1
1186
+
1187
+ # Count pairs with exactly 1 connection (unidirectional) vs 2 connections (bidirectional)
1188
+ num_uni = sum(1 for count in pair_counts.values() if count == 1)
1189
+ num_bi = sum(1 for count in pair_counts.values() if count == 2)
1190
+
1191
+ # Total possible unique pairs (excluding self-connections)
1192
+ total_possible = num_sources * (num_sources - 1) / 2
1193
+ total = round((num_uni + num_bi) / total_possible * 100, 2)
1194
+ uni = round(num_uni / total_possible * 100, 2)
1195
+ bi = round(num_bi / total_possible * 100, 2)
1196
+ else:
1197
+ # For non-recurrent networks, use the original calculation
1198
+ # Each connection is unique (no double-counting issues)
1199
+ total = round(total_cons / (num_sources * num_targets) * 100, 2)
1200
+ uni = round(num_uni / (num_sources * num_targets) * 100, 2)
1201
+ bi = round(num_bi / (num_sources * num_targets) * 100, 2)
1202
+
1169
1203
  if method == "total":
1170
1204
  return total
1171
1205
  if method == "uni":
@@ -1309,9 +1343,10 @@ def gap_junction_connections(
1309
1343
  s_list = kwargs["source_nodes"]
1310
1344
 
1311
1345
  cons = edges[(edges[source_id_type] == source_id) & (edges[target_id_type] == target_id)]
1312
- # add functionality that shows only the one's with gap_junctions
1346
+ # print(cons)
1347
+
1313
1348
  try:
1314
- cons = cons[cons["is_gap_junction"]]
1349
+ cons = cons[cons["is_gap_junction"]==True]
1315
1350
  except:
1316
1351
  raise Exception("no gap junctions found to drop from connections")
1317
1352
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.7.6
3
+ Version: 0.7.7
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -1,19 +1,19 @@
1
1
  bmtool/SLURM.py,sha256=UBfITY1MtYo95nyKglgGSqAC9Ds8PBvlHczsiNMFxvc,20573
2
2
  bmtool/__init__.py,sha256=r_8fXc-2uj1DndCdhB4jME51r1pn6ESTD5zRc355BrU,134
3
3
  bmtool/__main__.py,sha256=uCEqPwRxIuNRUASKhsvh4S8Nkp4dqnvfXTMUv-wWWRU,665
4
- bmtool/connectors.py,sha256=4SJRqBXM145_-nFycGrnlfjSyaoarOr0QkHl00jWq4I,74384
4
+ bmtool/connectors.py,sha256=tkCh9oVsIgaV5zzBzTFTG2Y6YVAoIHv2Pm-qxZAbca8,93124
5
5
  bmtool/graphs.py,sha256=gBTzI6c2BBK49dWGcfWh9c56TAooyn-KaiEy0Im1HcI,6717
6
6
  bmtool/manage.py,sha256=lsgRejp02P-x6QpA7SXcyXdalPhRmypoviIA2uAitQs,608
7
7
  bmtool/plot_commands.py,sha256=Dxm_RaT4CtHnfsltTtUopJ4KVbfhxtktEB_b7bFEXII,12716
8
- bmtool/singlecell.py,sha256=xqdLM2TjjnL8YyTy-c3WR6mElTv3E4zkZgkfUh4S5X0,47161
9
- bmtool/synapses.py,sha256=GbnPPdXotl7MTeju_QTBwZfFxYFNCq0fJijntzfttds,106071
8
+ bmtool/singlecell.py,sha256=qcciWdn8RjJCp7z8G2dCdPTLS9Brho3lPFSIsYMw8Ls,65348
9
+ bmtool/synapses.py,sha256=2M0dUBXfdYrJA3FWLbqsZGqAkO0sS2gQ-zq6GHYaVE4,121393
10
10
  bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  bmtool/analysis/entrainment.py,sha256=NQloQtVpEWjDzmkZwMWVcm3hSjErHBZfQl1mrBVoIE8,25321
12
12
  bmtool/analysis/lfp.py,sha256=S2JvxkjcK3-EH93wCrhqNSFY6cX7fOq74pz64ibHKrc,26556
13
13
  bmtool/analysis/netcon_reports.py,sha256=VnPZNKPaQA7oh1q9cIatsqQudm4cOtzNtbGPXoiDCD0,2909
14
14
  bmtool/analysis/spikes.py,sha256=3n-xmyEZ7w6CKEND7-aKOAvdDg0lwDuPI5sMdOuPwa0,24637
15
15
  bmtool/bmplot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- bmtool/bmplot/connections.py,sha256=xACgnkLAZrEBpaxa9Ob9MX-B1DO782UAeMvih9DleDk,59400
16
+ bmtool/bmplot/connections.py,sha256=xn9QaNN7fTTVNaalS8QHIp2TVo7nXgiT-nO4nKXOo6w,59612
17
17
  bmtool/bmplot/entrainment.py,sha256=BrBMerqyiG2YWAO_OEFv7OJf3yeFz3l9jUt4NamluLc,32837
18
18
  bmtool/bmplot/lfp.py,sha256=7JLozQQJ19ty0ZNyfhkuJAr_K8_pVP9C0flVJd_YXaY,2027
19
19
  bmtool/bmplot/netcon_reports.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -23,12 +23,12 @@ bmtool/debug/commands.py,sha256=VV00f6q5gzZI503vUPeG40ABLLen0bw_k4-EX-H5WZE,580
23
23
  bmtool/debug/debug.py,sha256=9yUFvA4_Bl-x9s29quIEG3pY-S8hNJF3RKBfRBHCl28,208
24
24
  bmtool/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  bmtool/util/commands.py,sha256=Nn-R-4e9g8ZhSPZvTkr38xeKRPfEMANB9Lugppj82UI,68564
26
- bmtool/util/util.py,sha256=HbVgPpvDBSkvXv5gAz7ad1V5GKL26q_LyJGt6ehpGQE,75929
26
+ bmtool/util/util.py,sha256=oXrY-Cc4wxPvgJVg2TqaAPua_gAl1Kj1nqrLgsqsXS8,77815
27
27
  bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  bmtool/util/neuron/celltuner.py,sha256=lokRLUM1rsdSYBYrNbLBBo39j14mm8TBNVNRnSlhHCk,94868
29
- bmtool-0.7.6.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
30
- bmtool-0.7.6.dist-info/METADATA,sha256=iSIT7erBJsvbZ6vJE1LKOlQPF1ne1BiluVL-81Z8l4U,3595
31
- bmtool-0.7.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- bmtool-0.7.6.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
33
- bmtool-0.7.6.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
34
- bmtool-0.7.6.dist-info/RECORD,,
29
+ bmtool-0.7.7.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
30
+ bmtool-0.7.7.dist-info/METADATA,sha256=uHViQaXG-O6O_GqENKn1vOkXp6g_yN94M9jSRilSnJU,3595
31
+ bmtool-0.7.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ bmtool-0.7.7.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
33
+ bmtool-0.7.7.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
34
+ bmtool-0.7.7.dist-info/RECORD,,
File without changes