bmtool 0.7.5.1__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/util/util.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import argparse
2
+ from logging import raiseExceptions
2
3
  import math
3
4
  import os
4
5
  import smtplib
@@ -1081,7 +1082,9 @@ def connection_totals(
1081
1082
  total = edges[(edges[source_id_type] == source_id) & (edges[target_id_type] == target_id)]
1082
1083
  if not include_gap:
1083
1084
  try:
1084
- total = total[~total["is_gap_junction"]]
1085
+ # Handle mixed types and NaN values in is_gap_junction column
1086
+ gap_col = total["is_gap_junction"].fillna(False).astype(bool)
1087
+ total = total[~gap_col]
1085
1088
  except:
1086
1089
  # If there are no gap junctions, just continue
1087
1090
  pass
@@ -1129,7 +1132,8 @@ def percent_connections(
1129
1132
  cons = edges[(edges[source_id_type] == source_id) & (edges[target_id_type] == target_id)]
1130
1133
  if not include_gap:
1131
1134
  try:
1132
- gaps = cons["is_gap_junction"]==True
1135
+ # Handle mixed types and NaN values in is_gap_junction column
1136
+ gaps = cons["is_gap_junction"].fillna(False).astype(bool)
1133
1137
  cons = cons[~gaps]
1134
1138
  except:
1135
1139
  raise Exception("no gap junctions found to drop from connections")
@@ -1159,9 +1163,43 @@ def percent_connections(
1159
1163
  num_sources = s_list[source_id_type].value_counts().sort_index().loc[source_id]
1160
1164
  num_targets = t_list[target_id_type].value_counts().sort_index().loc[target_id]
1161
1165
 
1162
- total = round(total_cons / (num_sources * num_targets) * 100, 2)
1163
- uni = round(num_uni / (num_sources * num_targets) * 100, 2)
1164
- 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
+
1165
1203
  if method == "total":
1166
1204
  return total
1167
1205
  if method == "uni":
@@ -1200,9 +1238,17 @@ def connection_divergence(
1200
1238
  cons = edges[(edges[source_id_type] == source_id) & (edges[target_id_type] == target_id)]
1201
1239
  if not include_gap:
1202
1240
  try:
1203
- cons = cons[~cons["is_gap_junction"]]
1241
+ # Handle mixed types and NaN values in is_gap_junction column
1242
+ gap_col = cons["is_gap_junction"].fillna(False).astype(bool)
1243
+ cons = cons[~gap_col]
1204
1244
  except:
1205
- raise Exception("no gap junctions found to drop from connections")
1245
+ raise Exception("error")
1246
+
1247
+ if cons.empty:
1248
+ if method == "mean+std":
1249
+ return (0, 0)
1250
+ else:
1251
+ return 0
1206
1252
 
1207
1253
  if convergence:
1208
1254
  if method == "min":
@@ -1213,15 +1259,16 @@ def connection_divergence(
1213
1259
  return round(count, 2)
1214
1260
  elif method == "std":
1215
1261
  std = cons["target_node_id"].value_counts().std()
1216
- return round(std, 2)
1262
+ return round(std, 2) if not np.isnan(std) else 0
1217
1263
  elif method == "mean":
1218
1264
  mean = cons["target_node_id"].value_counts().mean()
1219
- return round(mean, 2)
1265
+ return round(mean, 2) if not np.isnan(mean) else 0
1220
1266
  elif method == "mean+std": # default is mean + std
1221
1267
  mean = cons["target_node_id"].value_counts().mean()
1222
1268
  std = cons["target_node_id"].value_counts().std()
1223
- # std = cons.apply(pd.Series.value_counts).target_node_id.dropna().std() no longer a valid way
1224
- return (round(mean, 2)), (round(std, 2))
1269
+ mean = round(mean, 2) if not np.isnan(mean) else 0
1270
+ std = round(std, 2) if not np.isnan(std) else 0
1271
+ return (mean, std)
1225
1272
  else: # divergence
1226
1273
  if method == "min":
1227
1274
  count = cons["source_node_id"].value_counts().min()
@@ -1231,14 +1278,16 @@ def connection_divergence(
1231
1278
  return round(count, 2)
1232
1279
  elif method == "std":
1233
1280
  std = cons["source_node_id"].value_counts().std()
1234
- return round(std, 2)
1281
+ return round(std, 2) if not np.isnan(std) else 0
1235
1282
  elif method == "mean":
1236
1283
  mean = cons["source_node_id"].value_counts().mean()
1237
- return round(mean, 2)
1284
+ return round(mean, 2) if not np.isnan(mean) else 0
1238
1285
  elif method == "mean+std": # default is mean + std
1239
1286
  mean = cons["source_node_id"].value_counts().mean()
1240
1287
  std = cons["source_node_id"].value_counts().std()
1241
- return (round(mean, 2)), (round(std, 2))
1288
+ mean = round(mean, 2) if not np.isnan(mean) else 0
1289
+ std = round(std, 2) if not np.isnan(std) else 0
1290
+ return (mean, std)
1242
1291
 
1243
1292
  return relation_matrix(
1244
1293
  config,
@@ -1294,9 +1343,10 @@ def gap_junction_connections(
1294
1343
  s_list = kwargs["source_nodes"]
1295
1344
 
1296
1345
  cons = edges[(edges[source_id_type] == source_id) & (edges[target_id_type] == target_id)]
1297
- # add functionality that shows only the one's with gap_junctions
1346
+ # print(cons)
1347
+
1298
1348
  try:
1299
- cons = cons[cons["is_gap_junction"]]
1349
+ cons = cons[cons["is_gap_junction"]==True]
1300
1350
  except:
1301
1351
  raise Exception("no gap junctions found to drop from connections")
1302
1352
 
@@ -1442,7 +1492,9 @@ def connection_probabilities(
1442
1492
  ]
1443
1493
  if not include_gap:
1444
1494
  try:
1445
- relevant_edges = relevant_edges[~relevant_edges["is_gap_junction"]]
1495
+ # Handle mixed types and NaN values in is_gap_junction column
1496
+ gap_col = relevant_edges["is_gap_junction"].fillna(False).astype(bool)
1497
+ relevant_edges = relevant_edges[~gap_col]
1446
1498
  except:
1447
1499
  raise Exception("no gap junctions found to drop from connections")
1448
1500
  connected_distances = eudist(relevant_edges, dist_X, dist_Y, dist_Z).values.tolist()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.7.5.1
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=k-xyZjElz2CHM2oGXqBnFOCd0NusoA6JASzPXHPCj5c,106068
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=DwnnMp5cUwZC3OqsJqvgTPr4lBzc0sNWYRPmwij0WRk,59337
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=TAWdGd0tDuouS-JiusMs8WwP7kQpWHPr1nu0XG01TBQ,75056
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.5.1.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
30
- bmtool-0.7.5.1.dist-info/METADATA,sha256=H1XxiaHJuU-Bq_HTck5_z1fm08rTmSNxZYBA7hVcmNk,3597
31
- bmtool-0.7.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- bmtool-0.7.5.1.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
33
- bmtool-0.7.5.1.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
34
- bmtool-0.7.5.1.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,,