bmtool 0.5.9.9__py3-none-any.whl → 0.6.1__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/SLURM.py +77 -16
- bmtool/bmplot.py +120 -63
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/METADATA +1 -1
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/RECORD +8 -8
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/LICENSE +0 -0
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/WHEEL +0 -0
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/entry_points.txt +0 -0
- {bmtool-0.5.9.9.dist-info → bmtool-0.6.1.dist-info}/top_level.txt +0 -0
bmtool/SLURM.py
CHANGED
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
import subprocess
|
4
4
|
import json
|
5
5
|
import requests
|
6
|
+
import shutil
|
6
7
|
|
7
8
|
|
8
9
|
def check_job_status(job_id):
|
@@ -106,7 +107,6 @@ class seedSweep:
|
|
106
107
|
|
107
108
|
print(f"JSON file '{self.json_file_path}' modified successfully with {self.param_name}={new_value}.", flush=True)
|
108
109
|
|
109
|
-
|
110
110
|
def change_json_file_path(self,new_json_file_path):
|
111
111
|
self.json_file_path = new_json_file_path
|
112
112
|
|
@@ -156,8 +156,7 @@ class multiSeedSweep(seedSweep):
|
|
156
156
|
|
157
157
|
|
158
158
|
class SimulationBlock:
|
159
|
-
def __init__(self, block_name, time, partition, nodes, ntasks, mem, simulation_cases, output_base_dir,account=None,additional_commands=None,
|
160
|
-
status_list = ['COMPLETED', 'FAILED', 'CANCELLED']):
|
159
|
+
def __init__(self, block_name, time, partition, nodes, ntasks, mem, simulation_cases, output_base_dir,account=None,additional_commands=None,status_list = ['COMPLETED', 'FAILED', 'CANCELLED'],component_path=None):
|
161
160
|
"""
|
162
161
|
Initializes the SimulationBlock instance.
|
163
162
|
|
@@ -187,6 +186,7 @@ class SimulationBlock:
|
|
187
186
|
self.additional_commands = additional_commands if additional_commands is not None else []
|
188
187
|
self.status_list = status_list
|
189
188
|
self.job_ids = []
|
189
|
+
self.component_path = component_path
|
190
190
|
|
191
191
|
def create_batch_script(self, case_name, command):
|
192
192
|
"""
|
@@ -207,6 +207,8 @@ class SimulationBlock:
|
|
207
207
|
additional_commands_str = "\n".join(self.additional_commands)
|
208
208
|
# Conditional account linegit
|
209
209
|
account_line = f"#SBATCH --account={self.account}\n" if self.account else ""
|
210
|
+
env_var_component_path = f"export COMPONENT_PATH={self.component_path}" if self.component_path else ""
|
211
|
+
|
210
212
|
|
211
213
|
# Write the batch script to the file
|
212
214
|
with open(batch_script_path, 'w') as script_file:
|
@@ -224,6 +226,9 @@ class SimulationBlock:
|
|
224
226
|
# Additional user-defined commands
|
225
227
|
{additional_commands_str}
|
226
228
|
|
229
|
+
#enviroment vars
|
230
|
+
{env_var_component_path}
|
231
|
+
|
227
232
|
export OUTPUT_DIR={case_output_dir}
|
228
233
|
|
229
234
|
{command}
|
@@ -272,7 +277,6 @@ export OUTPUT_DIR={case_output_dir}
|
|
272
277
|
return False
|
273
278
|
return True
|
274
279
|
|
275
|
-
|
276
280
|
def check_block_running(self):
|
277
281
|
"""checks if a job is running
|
278
282
|
|
@@ -284,9 +288,21 @@ export OUTPUT_DIR={case_output_dir}
|
|
284
288
|
if status != 'RUNNING': #
|
285
289
|
return False
|
286
290
|
return True
|
291
|
+
|
292
|
+
def check_block_submited(self):
|
293
|
+
"""checks if a job is running
|
287
294
|
|
295
|
+
Returns:
|
296
|
+
bool: True if jobs are RUNNING false if anything else
|
297
|
+
"""
|
298
|
+
for job_id in self.job_ids:
|
299
|
+
status = check_job_status(job_id)
|
300
|
+
if status != 'PENDING': #
|
301
|
+
return False
|
302
|
+
return True
|
288
303
|
|
289
|
-
|
304
|
+
|
305
|
+
class BlockRunner:
|
290
306
|
"""
|
291
307
|
Class to handle submitting multiple blocks sequentially.
|
292
308
|
|
@@ -297,17 +313,23 @@ class SequentialBlockRunner:
|
|
297
313
|
webhook (str): a microsoft webhook for teams. When used will send teams messages to the hook!
|
298
314
|
"""
|
299
315
|
|
300
|
-
def __init__(self, blocks, json_editor=None,
|
316
|
+
def __init__(self, blocks, json_editor=None,json_file_path=None, param_name=None,
|
317
|
+
param_values=None, check_interval=60,syn_dict_list = None,
|
318
|
+
webhook=None):
|
301
319
|
self.blocks = blocks
|
302
320
|
self.json_editor = json_editor
|
303
321
|
self.param_values = param_values
|
304
322
|
self.check_interval = check_interval
|
305
323
|
self.webhook = webhook
|
324
|
+
self.param_name = param_name
|
325
|
+
self.json_file_path = json_file_path
|
326
|
+
self.syn_dict_list = syn_dict_list
|
306
327
|
|
307
328
|
def submit_blocks_sequentially(self):
|
308
329
|
"""
|
309
|
-
Submits all blocks sequentially, ensuring each block starts only after the previous block has completed.
|
330
|
+
Submits all blocks sequentially, ensuring each block starts only after the previous block has completed or is running.
|
310
331
|
Updates the JSON file with new parameters before each block run.
|
332
|
+
json file path should be the path WITH the components folder
|
311
333
|
"""
|
312
334
|
for i, block in enumerate(self.blocks):
|
313
335
|
# Update JSON file with new parameter value
|
@@ -317,15 +339,14 @@ class SequentialBlockRunner:
|
|
317
339
|
if len(self.blocks) != len(self.param_values):
|
318
340
|
raise Exception("Number of blocks needs to each number of params given")
|
319
341
|
new_value = self.param_values[i]
|
320
|
-
# NGL didnt test the multi but should work
|
321
|
-
if isinstance(self.json_editor, multiSeedSweep):
|
322
|
-
self.json_editor.edit_all_jsons(new_value)
|
323
|
-
elif isinstance(self.json_editor,seedSweep):
|
324
|
-
print(f"Updating JSON file with parameter value for block: {block.block_name}", flush=True)
|
325
|
-
self.json_editor.edit_json(new_value)
|
326
|
-
else:
|
327
|
-
raise Exception("json editor provided but not a seedSweep class not sure what your doing?!?")
|
328
342
|
|
343
|
+
if self.syn_dict_list == None:
|
344
|
+
json_editor = seedSweep(self.json_file_path, self.param_name)
|
345
|
+
json_editor.edit_json(new_value)
|
346
|
+
else:
|
347
|
+
json_editor = multiSeedSweep(self.json_file_path,self.param_name,
|
348
|
+
self.syn_dict_list,base_ratio=1)
|
349
|
+
json_editor.edit_all_jsons(new_value)
|
329
350
|
|
330
351
|
# Submit the block
|
331
352
|
print(f"Submitting block: {block.block_name}", flush=True)
|
@@ -335,7 +356,7 @@ class SequentialBlockRunner:
|
|
335
356
|
send_teams_message(self.webhook,message)
|
336
357
|
|
337
358
|
# Wait for the block to complete
|
338
|
-
if i == len(self.blocks) - 1:
|
359
|
+
if i == len(self.blocks) - 1:
|
339
360
|
while not block.check_block_completed():
|
340
361
|
print(f"Waiting for the last block {i} to complete...")
|
341
362
|
time.sleep(self.check_interval)
|
@@ -350,3 +371,43 @@ class SequentialBlockRunner:
|
|
350
371
|
message = "SIMULATION UPDATE: Simulation are Done!"
|
351
372
|
send_teams_message(self.webhook,message)
|
352
373
|
|
374
|
+
def submit_blocks_parallel(self):
|
375
|
+
"""
|
376
|
+
submits all the blocks at once onto the queue. To do this the components dir will be cloned and each block will have its own.
|
377
|
+
Also the json_file_path should be the path after the components dir
|
378
|
+
"""
|
379
|
+
if self.webhook:
|
380
|
+
message = "SIMULATION UPDATE: Simulations have been submited in parallel!"
|
381
|
+
send_teams_message(self.webhook,message)
|
382
|
+
for i, block in enumerate(self.blocks):
|
383
|
+
if block.component_path == None:
|
384
|
+
raise Exception("Unable to use parallel submitter without defining the component path")
|
385
|
+
new_value = self.param_values[i]
|
386
|
+
|
387
|
+
source_dir = block.component_path
|
388
|
+
destination_dir = f"{source_dir}{i+1}"
|
389
|
+
block.component_path = destination_dir
|
390
|
+
|
391
|
+
shutil.copytree(source_dir, destination_dir) # create new components folder
|
392
|
+
json_file_path = os.path.join(destination_dir,self.json_file_path)
|
393
|
+
if self.syn_dict_list == None:
|
394
|
+
json_editor = seedSweep(json_file_path, self.param_name)
|
395
|
+
json_editor.edit_json(new_value)
|
396
|
+
else:
|
397
|
+
json_editor = multiSeedSweep(json_file_path,self.param_name,
|
398
|
+
self.syn_dict_list,base_ratio=1)
|
399
|
+
json_editor.edit_all_jsons(new_value)
|
400
|
+
|
401
|
+
# submit block with new component path
|
402
|
+
print(f"Submitting block: {block.block_name}", flush=True)
|
403
|
+
block.submit_block()
|
404
|
+
if i == len(self.blocks) - 1:
|
405
|
+
while not block.check_block_completed():
|
406
|
+
print(f"Waiting for the last block {i} to complete...")
|
407
|
+
time.sleep(self.check_interval)
|
408
|
+
|
409
|
+
if self.webhook:
|
410
|
+
message = "SIMULATION UPDATE: Simulations are Done!"
|
411
|
+
send_teams_message(self.webhook,message)
|
412
|
+
|
413
|
+
|
bmtool/bmplot.py
CHANGED
@@ -306,46 +306,47 @@ def gap_junction_matrix(config=None,title=None,sources=None, targets=None, sids=
|
|
306
306
|
|
307
307
|
|
308
308
|
def filter_rows(syn_info, data, source_labels, target_labels):
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
if(all(x==0 for x in row)): #checks if all of a row is zeroes
|
322
|
-
row_index = np.where(new_data==row)[0][0]
|
323
|
-
if row_index!=-1: #deletes corresponding row accordingly in all relevant variables.
|
324
|
-
new_syn_info = np.delete(new_syn_info,row_index,0)
|
325
|
-
new_data = np.delete(new_data,row_index,0)
|
326
|
-
new_source_labels = np.delete(new_source_labels,row_index)
|
327
|
-
return new_syn_info, new_data,new_source_labels,new_target_labels
|
328
|
-
|
329
|
-
def filter_rows_and_columns(syn_info,data,source_labels,target_labels):
|
309
|
+
# Identify rows with all NaN or all zeros
|
310
|
+
valid_rows = ~np.all(np.isnan(data), axis=1) & ~np.all(data == 0, axis=1)
|
311
|
+
|
312
|
+
# Filter rows based on valid_rows mask
|
313
|
+
new_syn_info = syn_info[valid_rows]
|
314
|
+
new_data = data[valid_rows]
|
315
|
+
new_source_labels = np.array(source_labels)[valid_rows]
|
316
|
+
|
317
|
+
return new_syn_info, new_data, new_source_labels, target_labels
|
318
|
+
|
319
|
+
def filter_rows_and_columns(syn_info, data, source_labels, target_labels):
|
320
|
+
# Filter rows first
|
330
321
|
syn_info, data, source_labels, target_labels = filter_rows(syn_info, data, source_labels, target_labels)
|
331
|
-
|
322
|
+
|
323
|
+
# Transpose data to filter columns
|
324
|
+
transposed_syn_info = np.transpose(syn_info)
|
332
325
|
transposed_data = np.transpose(data)
|
333
326
|
transposed_source_labels = target_labels
|
334
327
|
transposed_target_labels = source_labels
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
328
|
+
|
329
|
+
# Filter columns (by treating them as rows in transposed data)
|
330
|
+
transposed_syn_info, transposed_data, transposed_source_labels, transposed_target_labels = filter_rows(
|
331
|
+
transposed_syn_info, transposed_data, transposed_source_labels, transposed_target_labels
|
332
|
+
)
|
333
|
+
|
334
|
+
# Transpose back to original orientation
|
335
|
+
filtered_syn_info = np.transpose(transposed_syn_info)
|
336
|
+
filtered_data = np.transpose(transposed_data)
|
337
|
+
filtered_source_labels = transposed_target_labels # Back to original source_labels
|
338
|
+
filtered_target_labels = transposed_source_labels # Back to original target_labels
|
339
|
+
|
340
|
+
return filtered_syn_info, filtered_data, filtered_source_labels, filtered_target_labels
|
341
|
+
|
341
342
|
|
342
343
|
syn_info, data, source_labels, target_labels = filter_rows_and_columns(syn_info, data, source_labels, target_labels)
|
343
344
|
|
344
345
|
if title == None or title=="":
|
345
346
|
title = 'Gap Junction'
|
346
|
-
if
|
347
|
+
if method == 'convergence':
|
347
348
|
title+=' Syn Convergence'
|
348
|
-
elif
|
349
|
+
elif method == 'percent':
|
349
350
|
title+=' Percent Connectivity'
|
350
351
|
plot_connection_info(syn_info,data,source_labels,target_labels,title, save_file=save_file)
|
351
352
|
return
|
@@ -535,35 +536,42 @@ def edge_histogram_matrix(config=None,sources = None,targets=None,sids=None,tids
|
|
535
536
|
fig.text(0.04, 0.5, 'Source', va='center', rotation='vertical')
|
536
537
|
plt.draw()
|
537
538
|
|
538
|
-
def plot_connection_info(text, num, source_labels,target_labels, title, syn_info='0', save_file=None,return_dict=None):
|
539
|
+
def plot_connection_info(text, num, source_labels, target_labels, title, syn_info='0', save_file=None, return_dict=None):
|
539
540
|
"""
|
540
|
-
|
541
|
+
Function to plot connection information as a heatmap, including handling missing source and target values.
|
542
|
+
If there is no source or target, set the value to 0.
|
541
543
|
"""
|
542
544
|
|
543
|
-
#
|
545
|
+
# Ensure text dimensions match num dimensions
|
546
|
+
num_source = len(source_labels)
|
547
|
+
num_target = len(target_labels)
|
544
548
|
|
545
|
-
|
546
|
-
num_target=len(target_labels)
|
549
|
+
# Set color map
|
547
550
|
matplotlib.rc('image', cmap='viridis')
|
548
551
|
|
549
|
-
|
552
|
+
# Create figure and axis for the plot
|
553
|
+
fig1, ax1 = plt.subplots(figsize=(num_source, num_target))
|
554
|
+
num = np.nan_to_num(num, nan=0) # replace NaN with 0
|
550
555
|
im1 = ax1.imshow(num)
|
551
|
-
|
552
|
-
#
|
556
|
+
|
557
|
+
# Set ticks and labels for source and target
|
553
558
|
ax1.set_xticks(list(np.arange(len(target_labels))))
|
554
559
|
ax1.set_yticks(list(np.arange(len(source_labels))))
|
555
|
-
# ... and label them with the respective list entries
|
556
560
|
ax1.set_xticklabels(target_labels)
|
557
|
-
ax1.set_yticklabels(source_labels,size=12, weight
|
558
|
-
|
561
|
+
ax1.set_yticklabels(source_labels, size=12, weight='semibold')
|
562
|
+
|
563
|
+
# Rotate the tick labels for better visibility
|
559
564
|
plt.setp(ax1.get_xticklabels(), rotation=45, ha="right",
|
560
|
-
|
565
|
+
rotation_mode="anchor", size=12, weight='semibold')
|
561
566
|
|
567
|
+
# Dictionary to store connection information
|
562
568
|
graph_dict = {}
|
563
|
-
|
569
|
+
|
570
|
+
# Loop over data dimensions and create text annotations
|
564
571
|
for i in range(num_source):
|
565
572
|
for j in range(num_target):
|
566
|
-
|
573
|
+
# Get the edge info, or set it to '0' if it's missing
|
574
|
+
edge_info = text[i, j] if text[i, j] is not None else 0
|
567
575
|
|
568
576
|
# Initialize the dictionary for the source node if not already done
|
569
577
|
if source_labels[i] not in graph_dict:
|
@@ -571,35 +579,41 @@ def plot_connection_info(text, num, source_labels,target_labels, title, syn_info
|
|
571
579
|
|
572
580
|
# Add edge info for the target node
|
573
581
|
graph_dict[source_labels[i]][target_labels[j]] = edge_info
|
574
|
-
|
575
|
-
|
582
|
+
|
583
|
+
# Set text annotations based on syn_info type
|
584
|
+
if syn_info == '2' or syn_info == '3':
|
585
|
+
if num_source > 8 and num_source < 20:
|
576
586
|
fig_text = ax1.text(j, i, edge_info,
|
577
|
-
|
587
|
+
ha="center", va="center", color="w", rotation=37.5, size=8, weight='semibold')
|
578
588
|
elif num_source > 20:
|
579
589
|
fig_text = ax1.text(j, i, edge_info,
|
580
|
-
|
590
|
+
ha="center", va="center", color="w", rotation=37.5, size=7, weight='semibold')
|
581
591
|
else:
|
582
592
|
fig_text = ax1.text(j, i, edge_info,
|
583
|
-
|
593
|
+
ha="center", va="center", color="w", rotation=37.5, size=11, weight='semibold')
|
584
594
|
else:
|
585
595
|
fig_text = ax1.text(j, i, edge_info,
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
ax1.
|
590
|
-
ax1.
|
591
|
-
|
592
|
-
|
596
|
+
ha="center", va="center", color="w", size=11, weight='semibold')
|
597
|
+
|
598
|
+
# Set labels and title for the plot
|
599
|
+
ax1.set_ylabel('Source', size=11, weight='semibold')
|
600
|
+
ax1.set_xlabel('Target', size=11, weight='semibold')
|
601
|
+
ax1.set_title(title, size=20, weight='semibold')
|
602
|
+
|
603
|
+
# Display the plot or save it based on the environment and arguments
|
604
|
+
notebook = is_notebook() # Check if running in a Jupyter notebook
|
593
605
|
if notebook == False:
|
594
606
|
fig1.show()
|
607
|
+
|
595
608
|
if save_file:
|
596
609
|
plt.savefig(save_file)
|
610
|
+
|
597
611
|
if return_dict:
|
598
612
|
return graph_dict
|
599
613
|
else:
|
600
614
|
return
|
601
615
|
|
602
|
-
def connector_percent_matrix(csv_path: str = None, exclude_strings=None, title: str = 'Percent connection matrix', pop_order=None) -> None:
|
616
|
+
def connector_percent_matrix(csv_path: str = None, exclude_strings=None, assemb_key=None, title: str = 'Percent connection matrix', pop_order=None) -> None:
|
603
617
|
"""
|
604
618
|
Generates and plots a connection matrix based on connection probabilities from a CSV file produced by bmtool.connector.
|
605
619
|
|
@@ -633,6 +647,7 @@ def connector_percent_matrix(csv_path: str = None, exclude_strings=None, title:
|
|
633
647
|
# Filter the DataFrame based on exclude_strings
|
634
648
|
def filter_dataframe(df, column_name, exclude_strings):
|
635
649
|
def process_string(string):
|
650
|
+
|
636
651
|
match = re.search(r"\[\'(.*?)\'\]", string)
|
637
652
|
if exclude_strings and any(ex_string in string for ex_string in exclude_strings):
|
638
653
|
return None
|
@@ -640,17 +655,55 @@ def connector_percent_matrix(csv_path: str = None, exclude_strings=None, title:
|
|
640
655
|
filtered_string = match.group(1)
|
641
656
|
if 'Gap' in string:
|
642
657
|
filtered_string = filtered_string + "-Gap"
|
658
|
+
if assemb_key in string:
|
659
|
+
filtered_string = filtered_string + assemb_key
|
643
660
|
return filtered_string # Return matched string
|
644
661
|
|
645
662
|
return string # If no match, return the original string
|
646
|
-
|
663
|
+
|
647
664
|
df[column_name] = df[column_name].apply(process_string)
|
648
665
|
df = df.dropna(subset=[column_name])
|
666
|
+
|
649
667
|
return df
|
650
668
|
|
651
669
|
df = filter_dataframe(df, 'Source', exclude_strings)
|
652
670
|
df = filter_dataframe(df, 'Target', exclude_strings)
|
671
|
+
|
672
|
+
#process assem rows and combine them into one prob per assem type
|
673
|
+
assems = df[df['Source'].str.contains(assemb_key)]
|
674
|
+
unique_sources = assems['Source'].unique()
|
653
675
|
|
676
|
+
for source in unique_sources:
|
677
|
+
source_assems = assems[assems['Source'] == source]
|
678
|
+
unique_targets = source_assems['Target'].unique() # Filter targets for the current source
|
679
|
+
|
680
|
+
for target in unique_targets:
|
681
|
+
# Filter the assemblies with the current source and target
|
682
|
+
unique_assems = source_assems[source_assems['Target'] == target]
|
683
|
+
|
684
|
+
# find the prob of a conn
|
685
|
+
forward_probs = []
|
686
|
+
for _,row in unique_assems.iterrows():
|
687
|
+
selected_percentage = row[selected_column]
|
688
|
+
selected_percentage = [float(p) for p in selected_percentage.strip('[]').split()]
|
689
|
+
if len(selected_percentage) == 1 or len(selected_percentage) == 2:
|
690
|
+
forward_probs.append(selected_percentage[0])
|
691
|
+
if len(selected_percentage) == 3:
|
692
|
+
forward_probs.append(selected_percentage[0])
|
693
|
+
forward_probs.append(selected_percentage[1])
|
694
|
+
|
695
|
+
mean_probs = np.mean(forward_probs)
|
696
|
+
source = source.replace(assemb_key, "")
|
697
|
+
target = target.replace(assemb_key, "")
|
698
|
+
new_row = pd.DataFrame({
|
699
|
+
'Source': [source],
|
700
|
+
'Target': [target],
|
701
|
+
'Percent connectionivity within possible connections': [mean_probs],
|
702
|
+
'Percent connectionivity within all connections': [0]
|
703
|
+
})
|
704
|
+
|
705
|
+
df = pd.concat([df, new_row], ignore_index=False)
|
706
|
+
|
654
707
|
# Prepare connection data
|
655
708
|
connection_data = {}
|
656
709
|
for _, row in df.iterrows():
|
@@ -671,14 +724,18 @@ def connector_percent_matrix(csv_path: str = None, exclude_strings=None, title:
|
|
671
724
|
if source in populations and target in populations:
|
672
725
|
source_idx = populations.index(source)
|
673
726
|
target_idx = populations.index(target)
|
674
|
-
|
675
|
-
if
|
727
|
+
|
728
|
+
if type(probabilities) == float:
|
729
|
+
connection_matrix[source_idx][target_idx] = probabilities
|
730
|
+
elif len(probabilities) == 1:
|
676
731
|
connection_matrix[source_idx][target_idx] = probabilities[0]
|
677
|
-
|
732
|
+
elif len(probabilities) == 2:
|
678
733
|
connection_matrix[source_idx][target_idx] = probabilities[0]
|
679
|
-
|
734
|
+
elif len(probabilities) == 3:
|
680
735
|
connection_matrix[source_idx][target_idx] = probabilities[0]
|
681
736
|
connection_matrix[target_idx][source_idx] = probabilities[1]
|
737
|
+
else:
|
738
|
+
raise Exception("unsupported format")
|
682
739
|
|
683
740
|
# Plotting
|
684
741
|
fig, ax = plt.subplots(figsize=(10, 8))
|
@@ -890,7 +947,7 @@ def plot_3d_positions(config=None, populations_list=None, group_by=None, title=N
|
|
890
947
|
if not is_notebook:
|
891
948
|
plt.show()
|
892
949
|
|
893
|
-
return
|
950
|
+
return ax
|
894
951
|
|
895
952
|
def plot_3d_cell_rotation(config=None, populations_list=None, group_by=None, title=None, save_file=None, quiver_length=None, arrow_length_ratio=None, group=None, subset=None):
|
896
953
|
from scipy.spatial.transform import Rotation as R
|
@@ -1,7 +1,7 @@
|
|
1
|
-
bmtool/SLURM.py,sha256=
|
1
|
+
bmtool/SLURM.py,sha256=woANwh6ToP5nsEkVX1qlINvkfGMp3P7Roq4O8X611M8,16371
|
2
2
|
bmtool/__init__.py,sha256=ZStTNkAJHJxG7Pwiy5UgCzC4KlhMS5pUNPtUJZVwL_Y,136
|
3
3
|
bmtool/__main__.py,sha256=TmFkmDxjZ6250nYD4cgGhn-tbJeEm0u-EMz2ajAN9vE,650
|
4
|
-
bmtool/bmplot.py,sha256=
|
4
|
+
bmtool/bmplot.py,sha256=HuzBRrVsD6xFM-siWdT_t6XqffFhK6LFcGF7RttR6pQ,54013
|
5
5
|
bmtool/connectors.py,sha256=2vVUsqYMaCuWZ-4C5eUzqwsFItFM9vm0ytZdRQdWgoc,72243
|
6
6
|
bmtool/graphs.py,sha256=K8BiughRUeXFVvAgo8UzrwpSClIVg7UfmIcvtEsEsk0,6020
|
7
7
|
bmtool/manage.py,sha256=_lCU0qBQZ4jSxjzAJUd09JEetb--cud7KZgxQFbLGSY,657
|
@@ -16,9 +16,9 @@ bmtool/util/commands.py,sha256=zJF-fiLk0b8LyzHDfvewUyS7iumOxVnj33IkJDzux4M,64396
|
|
16
16
|
bmtool/util/util.py,sha256=00vOAwTVIifCqouBoFoT0lBashl4fCalrk8fhg_Uq4c,56654
|
17
17
|
bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
18
|
bmtool/util/neuron/celltuner.py,sha256=xSRpRN6DhPFz4q5buq_W8UmsD7BbUrkzYBEbKVloYss,87194
|
19
|
-
bmtool-0.
|
20
|
-
bmtool-0.
|
21
|
-
bmtool-0.
|
22
|
-
bmtool-0.
|
23
|
-
bmtool-0.
|
24
|
-
bmtool-0.
|
19
|
+
bmtool-0.6.1.dist-info/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
|
20
|
+
bmtool-0.6.1.dist-info/METADATA,sha256=Ir2-vUb_0qfRxIJlj5iDuKVbnp5gFe6SOsqgCBWRdU4,19113
|
21
|
+
bmtool-0.6.1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
22
|
+
bmtool-0.6.1.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
|
23
|
+
bmtool-0.6.1.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
|
24
|
+
bmtool-0.6.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|