bmtool 0.6.7.1__py3-none-any.whl → 0.6.8__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/analysis/spikes.py CHANGED
@@ -5,7 +5,7 @@ Module for processing BMTK spikes output.
5
5
  import h5py
6
6
  import pandas as pd
7
7
  from bmtool.util.util import load_nodes_from_config
8
- from typing import Dict, Optional,Tuple, Union
8
+ from typing import Dict, Optional,Tuple, Union, List
9
9
  import numpy as np
10
10
  import os
11
11
 
@@ -40,16 +40,89 @@ def load_spikes_to_df(spike_file: str, network_name: str, sort: bool = True, con
40
40
  nodes = load_nodes_from_config(config)
41
41
  nodes = nodes[network_name]
42
42
 
43
- # Check if 'groupby' is a string or a list of strings and handle accordingly
43
+ # Convert single string to a list for uniform handling
44
44
  if isinstance(groupby, str):
45
- spikes_df = spikes_df.merge(nodes[groupby], left_on='node_ids', right_index=True, how='left')
46
- elif isinstance(groupby, list):
47
- for group in groupby:
48
- spikes_df = spikes_df.merge(nodes[group], left_on='node_ids', right_index=True, how='left')
45
+ groupby = [groupby]
46
+
47
+ # Ensure all requested columns exist
48
+ missing_cols = [col for col in groupby if col not in nodes.columns]
49
+ if missing_cols:
50
+ raise KeyError(f"Columns {missing_cols} not found in nodes DataFrame.")
51
+
52
+ spikes_df = spikes_df.merge(nodes[groupby], left_on='node_ids', right_index=True, how='left')
49
53
 
50
54
  return spikes_df
51
55
 
52
56
 
57
+ def compute_firing_rate_stats(df: pd.DataFrame, groupby: Union[str, List[str]] = "pop_name", start_time: float = None, stop_time: float = None) -> Tuple[pd.DataFrame, pd.DataFrame]:
58
+ """
59
+ Computes the firing rates of individual nodes and the mean and standard deviation of firing rates per group.
60
+
61
+ Args:
62
+ df (pd.DataFrame): Dataframe containing spike timestamps and node IDs.
63
+ groupby (str or list of str, optional): Column(s) to group by (e.g., 'pop_name' or ['pop_name', 'layer']).
64
+ start_time (float, optional): Start time for the analysis window. Defaults to the minimum timestamp in the data.
65
+ stop_time (float, optional): Stop time for the analysis window. Defaults to the maximum timestamp in the data.
66
+
67
+ Returns:
68
+ Tuple[pd.DataFrame, pd.DataFrame]:
69
+ - The first DataFrame (`pop_stats`) contains the mean and standard deviation of firing rates per group.
70
+ - The second DataFrame (`individual_stats`) contains the firing rate of each individual node.
71
+ """
72
+
73
+ # Ensure groupby is a list
74
+ if isinstance(groupby, str):
75
+ groupby = [groupby]
76
+
77
+ # Ensure all columns exist in the dataframe
78
+ for col in groupby:
79
+ if col not in df.columns:
80
+ raise ValueError(f"Column '{col}' not found in dataframe.")
81
+
82
+ # Filter dataframe based on start/stop time
83
+ if start_time is not None:
84
+ df = df[df["timestamps"] >= start_time]
85
+ if stop_time is not None:
86
+ df = df[df["timestamps"] <= stop_time]
87
+
88
+ # Compute total duration for firing rate calculation
89
+ if start_time is None:
90
+ min_time = df["timestamps"].min()
91
+ else:
92
+ min_time = start_time
93
+
94
+ if stop_time is None:
95
+ max_time = df["timestamps"].max()
96
+ else:
97
+ max_time = stop_time
98
+
99
+ duration = max_time - min_time # Avoid division by zero
100
+
101
+ if duration <= 0:
102
+ raise ValueError("Invalid time window: Stop time must be greater than start time.")
103
+
104
+ # Compute firing rate for each node
105
+ import pandas as pd
106
+
107
+ # Compute spike counts per node
108
+ spike_counts = df["node_ids"].value_counts().reset_index()
109
+ spike_counts.columns = ["node_ids", "spike_count"] # Rename columns
110
+
111
+ # Merge with original dataframe to get corresponding labels (e.g., 'pop_name')
112
+ spike_counts = spike_counts.merge(df[["node_ids"] + groupby].drop_duplicates(), on="node_ids", how="left")
113
+
114
+ # Compute firing rate
115
+ spike_counts["firing_rate"] = spike_counts["spike_count"] / duration * 1000 # scale to Hz
116
+ indivdual_stats = spike_counts
117
+
118
+ # Compute mean and standard deviation per group
119
+ pop_stats = spike_counts.groupby(groupby)["firing_rate"].agg(["mean", "std"]).reset_index()
120
+
121
+ # Rename columns
122
+ pop_stats.rename(columns={"mean": "firing_rate_mean", "std": "firing_rate_std"}, inplace=True)
123
+
124
+ return pop_stats,indivdual_stats
125
+
53
126
 
54
127
  def _pop_spike_rate(spike_times: Union[np.ndarray, list], time: Optional[Tuple[float, float, float]] = None,
55
128
  time_points: Optional[Union[np.ndarray, list]] = None, frequeny: bool = False) -> np.ndarray:
bmtool/bmplot.py CHANGED
@@ -13,6 +13,7 @@ import matplotlib.colors as colors
13
13
  import matplotlib.gridspec as gridspec
14
14
  from mpl_toolkits.mplot3d import Axes3D
15
15
  from matplotlib.axes import Axes
16
+ import seaborn as sns
16
17
  from IPython import get_ipython
17
18
  from IPython.display import display, HTML
18
19
  import statistics
@@ -20,7 +21,7 @@ import pandas as pd
20
21
  import os
21
22
  import sys
22
23
  import re
23
- from typing import Optional, Dict
24
+ from typing import Optional, Dict, Union, List
24
25
 
25
26
  from .util.util import CellVarsFile,load_nodes_from_config #, missing_units
26
27
  from bmtk.analyzer.utils import listify
@@ -849,6 +850,169 @@ def raster(spikes_df: Optional[pd.DataFrame] = None, config: Optional[str] = Non
849
850
 
850
851
  return ax
851
852
 
853
+ # uses df from bmtool.analysis.spikes compute_firing_rate_stats
854
+ def plot_firing_rate_pop_stats(firing_stats: pd.DataFrame, groupby: Union[str, List[str]], ax: Optional[Axes] = None,
855
+ color_map: Optional[Dict[str, str]] = None) -> Axes:
856
+ """
857
+ Plots a bar graph of mean firing rates with error bars (standard deviation).
858
+
859
+ Parameters:
860
+ ----------
861
+ firing_stats : pd.DataFrame
862
+ Dataframe containing 'firing_rate_mean' and 'firing_rate_std'.
863
+ groupby : str or list of str
864
+ Column(s) used for grouping.
865
+ ax : matplotlib.axes.Axes, optional
866
+ Axes on which to plot the bar chart; if None, a new figure and axes are created.
867
+ color_map : dict, optional
868
+ Dictionary specifying colors for each group. Keys should be group names, and values should be color values.
869
+
870
+ Returns:
871
+ -------
872
+ matplotlib.axes.Axes
873
+ Axes with the bar plot.
874
+ """
875
+ # Ensure groupby is a list for consistent handling
876
+ if isinstance(groupby, str):
877
+ groupby = [groupby]
878
+
879
+ # Create a categorical column for grouping
880
+ firing_stats["group"] = firing_stats[groupby].astype(str).agg("_".join, axis=1)
881
+
882
+ # Get unique group names
883
+ unique_groups = firing_stats["group"].unique()
884
+
885
+ # Generate colors if no color_map is provided
886
+ if color_map is None:
887
+ cmap = plt.get_cmap('viridis')
888
+ color_map = {group: cmap(i / len(unique_groups)) for i, group in enumerate(unique_groups)}
889
+ else:
890
+ # Ensure color_map contains all groups
891
+ missing_colors = [group for group in unique_groups if group not in color_map]
892
+ if missing_colors:
893
+ raise ValueError(f"color_map is missing colors for groups: {missing_colors}")
894
+
895
+ # Create new figure and axes if ax is not provided
896
+ if ax is None:
897
+ fig, ax = plt.subplots(figsize=(10, 6))
898
+
899
+ # Sort data for consistent plotting
900
+ firing_stats = firing_stats.sort_values(by="group")
901
+
902
+ # Extract values for plotting
903
+ x_labels = firing_stats["group"]
904
+ means = firing_stats["firing_rate_mean"]
905
+ std_devs = firing_stats["firing_rate_std"]
906
+
907
+ # Get colors for each group
908
+ colors = [color_map[group] for group in x_labels]
909
+
910
+ # Create bar plot
911
+ bars = ax.bar(x_labels, means, yerr=std_devs, capsize=5, color=colors, edgecolor="black")
912
+
913
+ # Add error bars manually with caps
914
+ _, caps, _ = ax.errorbar(
915
+ x=np.arange(len(x_labels)),
916
+ y=means,
917
+ yerr=std_devs,
918
+ fmt='none',
919
+ capsize=5,
920
+ capthick=2,
921
+ color="black"
922
+ )
923
+
924
+ # Formatting
925
+ ax.set_xticks(np.arange(len(x_labels)))
926
+ ax.set_xticklabels(x_labels, rotation=45, ha="right")
927
+ ax.set_xlabel("Population Group")
928
+ ax.set_ylabel("Mean Firing Rate (spikes/s)")
929
+ ax.set_title("Firing Rate Statistics by Population")
930
+ ax.grid(axis='y', linestyle='--', alpha=0.7)
931
+
932
+ return ax
933
+
934
+ # uses df from bmtool.analysis.spikes compute_firing_rate_stats
935
+ def plot_firing_rate_distribution(individual_stats: pd.DataFrame, groupby: Union[str, list], ax: Optional[Axes] = None,
936
+ color_map: Optional[Dict[str, str]] = None,
937
+ plot_type: Union[str, list] = "box", swarm_alpha: float = 0.6) -> Axes:
938
+ """
939
+ Plots a distribution of individual firing rates using one or more plot types
940
+ (box plot, violin plot, or swarm plot), overlaying them on top of each other.
941
+
942
+ Parameters:
943
+ ----------
944
+ individual_stats : pd.DataFrame
945
+ Dataframe containing individual firing rates and corresponding group labels.
946
+ groupby : str or list of str
947
+ Column(s) used for grouping.
948
+ ax : matplotlib.axes.Axes, optional
949
+ Axes on which to plot the graph; if None, a new figure and axes are created.
950
+ color_map : dict, optional
951
+ Dictionary specifying colors for each group. Keys should be group names, and values should be color values.
952
+ plot_type : str or list of str, optional
953
+ List of plot types to generate. Options: "box", "violin", "swarm". Default is "box".
954
+ swarm_alpha : float, optional
955
+ Transparency of swarm plot points. Default is 0.6.
956
+
957
+ Returns:
958
+ -------
959
+ matplotlib.axes.Axes
960
+ Axes with the selected plot type(s) overlayed.
961
+ """
962
+ # Ensure groupby is a list for consistent handling
963
+ if isinstance(groupby, str):
964
+ groupby = [groupby]
965
+
966
+ # Create a categorical column for grouping
967
+ individual_stats["group"] = individual_stats[groupby].astype(str).agg("_".join, axis=1)
968
+
969
+ # Validate plot_type (it can be a list or a single type)
970
+ if isinstance(plot_type, str):
971
+ plot_type = [plot_type]
972
+
973
+ for pt in plot_type:
974
+ if pt not in ["box", "violin", "swarm"]:
975
+ raise ValueError("plot_type must be one of: 'box', 'violin', 'swarm'.")
976
+
977
+ # Get unique groups for coloring
978
+ unique_groups = individual_stats["group"].unique()
979
+
980
+ # Generate colors if no color_map is provided
981
+ if color_map is None:
982
+ cmap = plt.get_cmap('viridis')
983
+ color_map = {group: cmap(i / len(unique_groups)) for i, group in enumerate(unique_groups)}
984
+
985
+ # Ensure color_map contains all groups
986
+ missing_colors = [group for group in unique_groups if group not in color_map]
987
+ if missing_colors:
988
+ raise ValueError(f"color_map is missing colors for groups: {missing_colors}")
989
+
990
+ # Create new figure and axes if ax is not provided
991
+ if ax is None:
992
+ fig, ax = plt.subplots(figsize=(10, 6))
993
+
994
+ # Sort data for consistent plotting
995
+ individual_stats = individual_stats.sort_values(by="group")
996
+
997
+ # Loop over each plot type and overlay them
998
+ for pt in plot_type:
999
+ if pt == "box":
1000
+ sns.boxplot(data=individual_stats, x="group", y="firing_rate", ax=ax, palette=color_map, width=0.5)
1001
+ elif pt == "violin":
1002
+ sns.violinplot(data=individual_stats, x="group", y="firing_rate", ax=ax, palette=color_map, inner="quartile", alpha=0.4)
1003
+ elif pt == "swarm":
1004
+ sns.swarmplot(data=individual_stats, x="group", y="firing_rate", ax=ax, palette=color_map, alpha=swarm_alpha)
1005
+
1006
+ # Formatting
1007
+ ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha="right")
1008
+ ax.set_xlabel("Population Group")
1009
+ ax.set_ylabel("Firing Rate (spikes/s)")
1010
+ ax.set_title("Firing Rate Distribution by Population")
1011
+ ax.grid(axis='y', linestyle='--', alpha=0.7)
1012
+
1013
+ return ax
1014
+
1015
+
852
1016
  def plot_3d_positions(config=None, populations_list=None, group_by=None, title=None, save_file=None, subset=None):
853
1017
  """
854
1018
  Plots a 3D graph of all cells with x, y, z location.
@@ -1154,164 +1318,3 @@ def plot_report_default(config, report_name, variables, gids):
1154
1318
  plot_report(config_file=config, report_file=report_file, report_name=report_name, variables=variables, gids=gids);
1155
1319
 
1156
1320
  return
1157
-
1158
- # The following code was developed by Matthew Stroud 7/15/21 neural engineering supervisor: Satish Nair
1159
- # This is an extension of bmtool: a development of Tyler Banks.
1160
- # The goal of the sim_setup() function is to output relevant simulation information that can be gathered by providing only the main configuration file.
1161
-
1162
-
1163
- def sim_setup(config_file='simulation_config.json',network=None):
1164
- if "JPY_PARENT_PID" in os.environ:
1165
- print("Inside a notebook:")
1166
- get_ipython().run_line_magic('matplotlib', 'tk')
1167
-
1168
-
1169
- # Output tables that contain the cells involved in the configuration file given. Also returns the first biophysical network found
1170
- bio=plot_basic_cell_info(config_file)
1171
- if network == None:
1172
- network=bio
1173
-
1174
- print("Please wait. This may take a while depending on your network size...")
1175
- # Plot connection probabilities
1176
- plt.close(1)
1177
- probability_connection_matrix(config=config_file,sources=network,targets=network, no_prepend_pop=True,sids= 'pop_name', tids= 'pop_name', bins=10,line_plot=True,verbose=False)
1178
- # Gives current clamp information
1179
- plot_I_clamps(config_file)
1180
- # Plot spike train info
1181
- plot_inspikes(config_file)
1182
- # Using bmtool, print total number of connections between cell groups
1183
- total_connection_matrix(config=config_file,sources='all',targets='all',sids='pop_name',tids='pop_name',title='All Connections found', size_scalar=2, no_prepend_pop=True, synaptic_info='0')
1184
- # Plot 3d positions of the network
1185
- plot_3d_positions(populations='all',config=config_file,group_by='pop_name',title='3D Positions',save_file=None)
1186
-
1187
- def plot_I_clamps(fp):
1188
- print("Plotting current clamp info...")
1189
- clamps = util.load_I_clamp_from_config(fp)
1190
- if not clamps:
1191
- print(" No current clamps were found.")
1192
- return
1193
- time=[]
1194
- num_clamps=0
1195
- fig, ax = plt.subplots()
1196
- ax = plt.gca()
1197
- for clinfo in clamps:
1198
- simtime=len(clinfo[0])*clinfo[1]
1199
- time.append(np.arange(0,simtime,clinfo[1]).tolist())
1200
-
1201
- line,=ax.plot(time[num_clamps],clinfo[0],drawstyle='steps')
1202
- line.set_label('I Clamp to: '+str(clinfo[2]))
1203
- plt.legend()
1204
- num_clamps=num_clamps+1
1205
-
1206
- def plot_basic_cell_info(config_file):
1207
- print("Network and node info:")
1208
- nodes=util.load_nodes_from_config(config_file)
1209
- if not nodes:
1210
- print("No nodes were found.")
1211
- return
1212
- pd.set_option("display.max_rows", None, "display.max_columns", None)
1213
- bio=[]
1214
- i=0
1215
- j=0
1216
- for j in nodes:
1217
- node=nodes[j]
1218
- node_type_id=node['node_type_id']
1219
- num_cells=len(node['node_type_id'])
1220
- if node['model_type'][0]=='virtual':
1221
- CELLS=[]
1222
- count=1
1223
- for i in range(num_cells-1):
1224
- if(node_type_id[i]==node_type_id[i+1]):
1225
- count+=1
1226
- else:
1227
- node_type=node_type_id[i]
1228
- pop_name=node['pop_name'][i]
1229
- model_type=node['model_type'][i]
1230
- CELLS.append([node_type,pop_name,model_type,count])
1231
- count=1
1232
- else:
1233
- node_type=node_type_id[i]
1234
- pop_name=node['pop_name'][i]
1235
- model_type=node['model_type'][i]
1236
- CELLS.append([node_type,pop_name,model_type,count])
1237
- count=1
1238
- df1 = pd.DataFrame(CELLS, columns = ["node_type","pop_name","model_type","count"])
1239
- print(j+':')
1240
- notebook = is_notebook()
1241
- if notebook == True:
1242
- display(HTML(df1.to_html()))
1243
- else:
1244
- print(df1)
1245
- elif node['model_type'][0]=='biophysical':
1246
- CELLS=[]
1247
- count=1
1248
- node_type_id=node['node_type_id']
1249
- num_cells=len(node['node_type_id'])
1250
- for i in range(num_cells-1):
1251
- if(node_type_id[i]==node_type_id[i+1]):
1252
- count+=1
1253
- else:
1254
- node_type=node_type_id[i]
1255
- pop_name=node['pop_name'][i]
1256
- model_type=node['model_type'][i]
1257
- model_template=node['model_template'][i]
1258
- morphology=node['morphology'][i] if node['morphology'][i] else ''
1259
- CELLS.append([node_type,pop_name,model_type,model_template,morphology,count])
1260
- count=1
1261
- else:
1262
- node_type=node_type_id[i]
1263
- pop_name=node['pop_name'][i]
1264
- model_type=node['model_type'][i]
1265
- model_template=node['model_template'][i]
1266
- morphology=node['morphology'][i] if node['morphology'][i] else ''
1267
- CELLS.append([node_type,pop_name,model_type,model_template,morphology,count])
1268
- count=1
1269
- df2 = pd.DataFrame(CELLS, columns = ["node_type","pop_name","model_type","model_template","morphology","count"])
1270
- print(j+':')
1271
- bio.append(j)
1272
- notebook = is_notebook()
1273
- if notebook == True:
1274
- display(HTML(df2.to_html()))
1275
- else:
1276
- print(df2)
1277
- if len(bio)>0:
1278
- return bio[0]
1279
-
1280
- def plot_inspikes(fp):
1281
-
1282
- print("Plotting spike Train info...")
1283
- trains = util.load_inspikes_from_config(fp)
1284
- if not trains:
1285
- print("No spike trains were found.")
1286
- num_trains=len(trains)
1287
-
1288
- time=[]
1289
- node=[]
1290
- fig, ax = plt.subplots(num_trains, figsize=(12,12),squeeze=False)
1291
- fig.subplots_adjust(hspace=0.5, wspace=0.5)
1292
-
1293
- pos=0
1294
- for tr in trains:
1295
- node_group=tr[0][2]
1296
- if node_group=='':
1297
- node_group='Defined by gids (y-axis)'
1298
- time=[]
1299
- node=[]
1300
- for sp in tr:
1301
- node.append(sp[1])
1302
- time.append(sp[0])
1303
-
1304
- #plotting spike train
1305
-
1306
- ax[pos,0].scatter(time,node,s=1)
1307
- ax[pos,0].title.set_text('Input Spike Train to: '+node_group)
1308
- plt.xticks(rotation = 45)
1309
- if num_trains <=4:
1310
- ax[pos,0].xaxis.set_major_locator(plt.MaxNLocator(20))
1311
- if num_trains <=9 and num_trains >4:
1312
- ax[pos,0].xaxis.set_major_locator(plt.MaxNLocator(4))
1313
- elif num_trains <9:
1314
- ax[pos,0].xaxis.set_major_locator(plt.MaxNLocator(2))
1315
- #fig.suptitle('Input Spike Train to: '+node_group, fontsize=14)
1316
- fig.show()
1317
- pos+=1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bmtool
3
- Version: 0.6.7.1
3
+ Version: 0.6.8
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -53,6 +53,7 @@ A collection of modules to make developing [Neuron](https://www.neuron.yale.edu/
53
53
  - [Synapses](#synapses-module)
54
54
  - [Connectors](#connectors-module)
55
55
  - [Bmplot](#bmplot-module)
56
+ - [Analysis](#analysis-module)
56
57
  - [SLURM](#slurm-module)
57
58
  - [Graphs](#graphs-module)
58
59
 
@@ -471,7 +472,11 @@ bmplot.plot_network_graph(config='config.json',sources='LA',targets='LA',tids='p
471
472
 
472
473
 
473
474
  ![png](readme_figures/output_35_0.png)
474
-
475
+
476
+
477
+ ## Analysis Module
478
+ ### A notebook example of how to use the spikes module can be found [here](examples/analysis/using_spikes.ipynb)
479
+
475
480
  ## SLURM Module
476
481
  ### This is an extremely helpful module that can simplify using SLURM too submit your models. There is also features to enable doing a seedSweep. This will vary the parameters of the simulation and make tuning the model easier. An example can be found [here](examples/SLURM/using_BlockRunner.ipynb)
477
482
 
@@ -1,7 +1,7 @@
1
1
  bmtool/SLURM.py,sha256=AKxu_Ln9wuCBVLdOJP4yAN59jYt222DM-iUlsQojNvY,18145
2
2
  bmtool/__init__.py,sha256=ZStTNkAJHJxG7Pwiy5UgCzC4KlhMS5pUNPtUJZVwL_Y,136
3
3
  bmtool/__main__.py,sha256=TmFkmDxjZ6250nYD4cgGhn-tbJeEm0u-EMz2ajAN9vE,650
4
- bmtool/bmplot.py,sha256=iTK6q8XEqc8QEAKR152ut_1qdtnMoEe1Uq-4dCrkCA0,53992
4
+ bmtool/bmplot.py,sha256=PJeciKP89o9dOCB3prTTeI7ZDNwUBYtbUSvAmjn1uOo,54059
5
5
  bmtool/connectors.py,sha256=hWkUUcJ4tmas8NDOFPPjQT-TgTlPcpjuZsYyAW2WkPA,72242
6
6
  bmtool/graphs.py,sha256=K8BiughRUeXFVvAgo8UzrwpSClIVg7UfmIcvtEsEsk0,6020
7
7
  bmtool/manage.py,sha256=_lCU0qBQZ4jSxjzAJUd09JEetb--cud7KZgxQFbLGSY,657
@@ -10,7 +10,7 @@ bmtool/singlecell.py,sha256=XZAT_2n44EhwqVLnk3qur9aO7oJ-10axJZfwPBslM88,27219
10
10
  bmtool/synapses.py,sha256=gIkfLhKDG2dHHCVJJoKuQrFn_Qut843bfk_-s97wu6c,54553
11
11
  bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  bmtool/analysis/lfp.py,sha256=Zp-aJ8x2KmsI3h_mqvq4u9ixFYu4n0CxQpgdbYnrtYE,14909
13
- bmtool/analysis/spikes.py,sha256=23k_wFOC9pKQgetxMp1V2z6cZaW2eoIZAZyjFiTfrrM,8560
13
+ bmtool/analysis/spikes.py,sha256=qqJ4zD8xfvSwltlWm_Bhicdngzl6uBqH6Kn5wOMKRc8,11507
14
14
  bmtool/debug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  bmtool/debug/commands.py,sha256=AwtcR7BUUheM0NxvU1Nu234zCdpobhJv5noX8x5K2vY,583
16
16
  bmtool/debug/debug.py,sha256=xqnkzLiH3s-tS26Y5lZZL62qR2evJdi46Gud-HzxEN4,207
@@ -19,9 +19,9 @@ bmtool/util/commands.py,sha256=zJF-fiLk0b8LyzHDfvewUyS7iumOxVnj33IkJDzux4M,64396
19
19
  bmtool/util/util.py,sha256=00vOAwTVIifCqouBoFoT0lBashl4fCalrk8fhg_Uq4c,56654
20
20
  bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  bmtool/util/neuron/celltuner.py,sha256=xSRpRN6DhPFz4q5buq_W8UmsD7BbUrkzYBEbKVloYss,87194
22
- bmtool-0.6.7.1.dist-info/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
23
- bmtool-0.6.7.1.dist-info/METADATA,sha256=qlkGt9KNUlVP7C3J1xgvj23YUHaPD7SlVFzhVhSUceg,20226
24
- bmtool-0.6.7.1.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
25
- bmtool-0.6.7.1.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
26
- bmtool-0.6.7.1.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
27
- bmtool-0.6.7.1.dist-info/RECORD,,
22
+ bmtool-0.6.8.dist-info/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
23
+ bmtool-0.6.8.dist-info/METADATA,sha256=KuVWM0W-zZpBGO8JF3y6etJw_bfyvG-F8-78fi-ORJ4,20385
24
+ bmtool-0.6.8.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
25
+ bmtool-0.6.8.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
26
+ bmtool-0.6.8.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
27
+ bmtool-0.6.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.1)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5