nettracer3d 0.7.4__py3-none-any.whl → 0.7.5__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.
@@ -8,7 +8,6 @@ from networkx.algorithms import community
8
8
  from scipy import ndimage
9
9
  from scipy.ndimage import zoom
10
10
  from networkx.algorithms import community
11
- from community import community_louvain
12
11
  import random
13
12
  from . import node_draw
14
13
 
@@ -229,38 +228,11 @@ def _isolate_connected(G, key = None):
229
228
  return G0
230
229
 
231
230
 
232
- def extract_mothers(nodes, excel_file_path, centroid_dic = None, directory = None, louvain = True, ret_nodes = False, called = False):
233
-
234
- if type(nodes) == str:
235
- nodes = tifffile.imread(nodes)
236
-
237
- if np.unique(nodes) < 3:
238
- structure_3d = np.ones((3, 3, 3), dtype=int)
239
- nodes, num_nodes = ndimage.label(nodes, structure=structure_3d)
240
-
241
- if type(excel_file_path) == str:
242
- G, edge_weights = weighted_network(excel_file_path)
243
- else:
244
- G = excel_file_path
245
-
246
- if not called:
247
-
248
- if louvain:
249
- # Apply the Louvain algorithm for community detection
250
- partition = community_louvain.best_partition(G)
251
- some_communities = set(partition.values())
252
- else:
253
- some_communities = list(nx.community.label_propagation_communities(G))
254
- partition = {}
255
- for i, community in enumerate(some_communities):
256
- for node in community:
257
- partition[node] = i + 1
258
- else:
259
- partition = louvain
260
- some_communities = (partition.keys())
231
+ def extract_mothers(nodes, G, partition, centroid_dic = None, directory = None, ret_nodes = False, called = False):
261
232
 
262
233
 
263
234
  my_nodes, intercom_connections, connected_coms = get_border_nodes(partition, G)
235
+ some_communities = partition.keys()
264
236
 
265
237
  print(f"Number of intercommunity connections: {intercom_connections}")
266
238
  print(f"{len(connected_coms)} communities with any connectivity of {len(some_communities)} communities")
@@ -390,10 +362,14 @@ def find_hub_nodes(G: nx.Graph, proportion: float = 0.1) -> List:
390
362
  # Dictionary to store average path lengths for all nodes
391
363
  avg_path_lengths: Dict[int, float] = {}
392
364
 
365
+ output = []
366
+
393
367
  # Process each component separately
394
368
  for component in components:
395
369
  # Create subgraph for this component
396
370
  subgraph = G.subgraph(component)
371
+ if not (len(subgraph.nodes()) * proportion >= 0.75): #Skip components that are too small
372
+ continue
397
373
 
398
374
  # Calculate average shortest path length for each node in this component
399
375
  for node in subgraph.nodes():
@@ -403,16 +379,18 @@ def find_hub_nodes(G: nx.Graph, proportion: float = 0.1) -> List:
403
379
  avg_length = sum(path_lengths.values()) / (len(subgraph.nodes()) - 1)
404
380
  avg_path_lengths[node] = avg_length
405
381
 
406
- # Sort nodes by average path length (ascending)
407
- sorted_nodes = sorted(avg_path_lengths.items(), key=lambda x: x[1])
408
-
409
- # Calculate number of nodes to return
410
- num_nodes = int(np.ceil(len(G.nodes()) * proportion))
411
-
412
- # Return the top nodes (those with lowest average path lengths)
413
- hub_nodes = [node for node, _ in sorted_nodes[:num_nodes]]
382
+ # Sort nodes by average path length (ascending)
383
+ sorted_nodes = sorted(avg_path_lengths.items(), key=lambda x: x[1])
384
+
385
+ # Calculate number of nodes to return
386
+ num_nodes = int(np.ceil(len(G.nodes()) * proportion))
387
+
388
+ # Return the top nodes (those with lowest average path lengths)
389
+ hub_nodes = [node for node, _ in sorted_nodes[:num_nodes]]
390
+ output.extend(hub_nodes)
391
+ avg_path_lengths: Dict[int, float] = {}
414
392
 
415
- return hub_nodes
393
+ return output
416
394
 
417
395
  def get_color_name_mapping():
418
396
  """Return a dictionary of common colors and their RGB values."""
nettracer3d/modularity.py CHANGED
@@ -1,5 +1,4 @@
1
1
  from networkx.algorithms import community
2
- from community import community_louvain
3
2
  import pandas as pd
4
3
  import networkx as nx
5
4
  import matplotlib.pyplot as plt
@@ -104,77 +103,8 @@ def read_excel_to_lists(file_path, sheet_name=0):
104
103
 
105
104
 
106
105
 
107
-
108
- def louvain_mod_solo(G, edge_weights = None, identifier = None, directory_path = None):
109
-
110
- if type(G) == str:
111
- G, edge_weights = weighted_network(G)
112
-
113
- if edge_weights is None:
114
- edge_weights = get_edge_weights(G)
115
-
116
- # Assuming G is your NetworkX graph
117
- # Louvain community detection
118
- partition = community_louvain.best_partition(G)
119
-
120
- # Print modularity
121
- modularity = community_louvain.modularity(partition, G)
122
- number_of_nodes = G.number_of_nodes()
123
- print("Modularity:", modularity)
124
- num_components = nx.number_connected_components(G)
125
-
126
- if directory_path:
127
- with open(f'{directory_path}/{identifier} network stats.txt', 'a') as f:
128
- f.write(f'\nlouvain full graph modularity: {modularity} constructed from {num_components} components containing {number_of_nodes} nodes')
129
- f.close()
130
-
131
- louvain_graph(edge_weights, identifier, directory_path)
132
-
133
- def louvain_mod(G, edge_weights=None, identifier=None, geometric = False, geo_info = None, directory = None):
134
-
135
- if type(G) == list:
136
- num_edge = len(G[0])
137
- else:
138
- num_edge = None
139
-
140
-
141
- if type(G) == str or type(G) == list:
142
- G, edge_weights = network_analysis.weighted_network(G)
143
-
144
- if edge_weights is None:
145
- edge_weights = get_edge_weights(G)
146
-
147
- connected_components = list(nx.connected_components(G))
148
- num_nodes = float(G.number_of_nodes())
149
-
150
- print("Number of nodes:", num_nodes)
151
- print("Number of edges:", num_edge)
152
-
153
- # Calculate the average degree connectivity
154
- average_degree_connectivity = nx.average_degree_connectivity(G)
155
- print("Average degree connectivity:", average_degree_connectivity)
156
-
157
- # Calculate the average number of edges attached to a node
158
- average_edges_per_node = num_nodes/num_edge
159
- print("Average edges per node:", average_edges_per_node)
160
-
161
- for i, component in enumerate(connected_components):
162
- # Apply the Louvain community detection on the subgraph
163
- partition = community_louvain.best_partition(G.subgraph(component))
164
-
165
- # Calculate modularity
166
- modularity = community_louvain.modularity(partition, G.subgraph(component))
167
- num_nodes = len(component)
168
-
169
- print(f"Louvain modularity for component with {num_nodes} nodes: {modularity}")
170
-
171
-
172
- louvain_graph(edge_weights, identifier, directory, geometric, geo_info)
173
-
174
106
  def show_communities_flex(G, master_list, normalized_weights, geo_info = None, geometric=False, directory=None, weighted=True, partition=None, style=0):
175
- if partition is None:
176
- partition, normalized_weights, _ = community_partition(master_list, weighted=weighted, style=style)
177
- print(partition)
107
+
178
108
  if normalized_weights is None:
179
109
  G, edge_weights = network_analysis.weighted_network(master_list)
180
110
 
@@ -276,13 +206,7 @@ def show_communities_flex(G, master_list, normalized_weights, geo_info = None, g
276
206
 
277
207
 
278
208
 
279
-
280
-
281
-
282
-
283
-
284
-
285
- def community_partition(master_list, weighted = False, style = 0, dostats = True):
209
+ def community_partition(master_list, weighted = False, style = 0, dostats = True, seed = None):
286
210
 
287
211
  def calculate_network_stats(G, communities):
288
212
  """
@@ -392,7 +316,7 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
392
316
 
393
317
  return stats
394
318
 
395
- def calculate_louvain_network_stats(G, partition):
319
+ def calculate_louvain_network_stats(G, partition, seed):
396
320
  """
397
321
  Calculate comprehensive network statistics for the graph using Louvain community detection.
398
322
 
@@ -410,17 +334,10 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
410
334
  """
411
335
  stats = {}
412
336
 
413
- # Convert partition dict to communities list format
414
- communities = []
415
- max_community = max(partition.values())
416
- for com_id in range(max_community + 1):
417
- community_nodes = {node for node, com in partition.items() if com == com_id}
418
- if community_nodes: # Only add non-empty communities
419
- communities.append(community_nodes)
420
337
 
421
338
  try:
422
339
  # Overall network modularity using Louvain
423
- stats['Modularity Entire Network'] = community_louvain.modularity(partition, G)
340
+ stats['Modularity Entire Network'] = community.modularity(partition, G)
424
341
  except:
425
342
  pass
426
343
 
@@ -430,8 +347,8 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
430
347
  if len(connected_components) > 1:
431
348
  for i, component in enumerate(connected_components):
432
349
  subgraph = G.subgraph(component)
433
- subgraph_partition = community_louvain.best_partition(subgraph)
434
- modularity = community_louvain.modularity(subgraph_partition, subgraph)
350
+ subgraph_partition = nx.community.louvain_communities(G, weight='weight', seed = seed)
351
+ modularity = community.modularity(subgraph_partition, subgraph)
435
352
  num_nodes = len(component)
436
353
  stats[f'Modularity of component with {num_nodes} nodes'] = modularity
437
354
  except:
@@ -523,7 +440,6 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
523
440
  edge_weights = get_edge_weights(G)
524
441
 
525
442
  if style == 1 and weighted:
526
-
527
443
  G = nx.Graph()
528
444
 
529
445
  # Find the maximum and minimum edge weights
@@ -540,33 +456,38 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
540
456
  for edge, normalized_weight in normalized_weights.items():
541
457
  G.add_edge(edge[0], edge[1], weight=normalized_weight)
542
458
 
543
- # Perform Louvain community detection
544
- partition = community_louvain.best_partition(G)
459
+ # Replace Louvain with NetworkX's implementation
460
+ communities = list(nx.community.louvain_communities(G, weight='weight', seed = seed))
461
+
462
+ # Convert to the same format as community_louvain.best_partition
463
+ output = {}
464
+ for i, com in enumerate(communities):
465
+ for node in com:
466
+ output[node] = i + 1
545
467
 
546
468
  if dostats:
469
+ stats = calculate_louvain_network_stats(G, communities, seed)
547
470
 
548
- stats = calculate_louvain_network_stats(G, partition)
549
-
550
-
551
- return partition, normalized_weights, stats
471
+ return output, normalized_weights, stats
552
472
 
553
473
  elif style == 1:
554
-
555
474
  edges = list(zip(master_list[0], master_list[1]))
556
-
557
475
  G = nx.Graph()
558
-
559
476
  G.add_edges_from(edges)
560
477
 
478
+ # Replace Louvain with NetworkX's implementation
479
+ communities = list(nx.community.louvain_communities(G, seed = seed))
561
480
 
562
- # Perform Louvain community detection
563
- partition = community_louvain.best_partition(G)
481
+ # Convert to the same format as community_louvain.best_partition
482
+ output = {}
483
+ for i, com in enumerate(communities):
484
+ for node in com:
485
+ output[node] = i + 1
564
486
 
565
487
  if dostats:
488
+ stats = calculate_louvain_network_stats(G, communities, seed)
566
489
 
567
- stats = calculate_louvain_network_stats(G, partition)
568
-
569
- return partition, None, stats
490
+ return output, None, stats
570
491
 
571
492
  elif style == 0 and weighted:
572
493
 
@@ -586,6 +507,13 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
586
507
  for edge, normalized_weight in normalized_weights.items():
587
508
  G.add_edge(edge[0], edge[1], weight=normalized_weight)
588
509
 
510
+ if seed is not None:
511
+ import random
512
+ import numpy as np
513
+ # Set seeds
514
+ random.seed(seed)
515
+ np.random.seed(seed)
516
+
589
517
  # Detect communities using label propagation
590
518
  communities = list(community.label_propagation_communities(G))
591
519
  output = {}
@@ -614,6 +542,14 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
614
542
 
615
543
 
616
544
  # Detect communities using label propagation
545
+
546
+ if seed is not None:
547
+ import random
548
+ import numpy as np
549
+ # Set seeds
550
+ random.seed(seed)
551
+ np.random.seed(seed)
552
+
617
553
  communities = list(community.label_propagation_communities(G))
618
554
  output = {}
619
555
  for i, com in enumerate(communities):
@@ -627,127 +563,6 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
627
563
  return output, None, stats
628
564
 
629
565
 
630
-
631
- def _louvain_mod_solo(G, edge_weights = None):
632
-
633
-
634
- if type(G) == str:
635
- G, edge_weights = weighted_network(G)
636
-
637
- # Louvain community detection
638
- partition = community_louvain.best_partition(G)
639
-
640
- # modularity
641
- modularity = community_louvain.modularity(partition, G)
642
-
643
- print(f"Modularity is {modularity}")
644
-
645
- return modularity
646
-
647
- def _louvain_mod(G, edge_weights = None):
648
-
649
- if type(G) == str:
650
- G, edge_weights = weighted_network(G)
651
-
652
- connected_components = list(nx.connected_components(G))
653
- return_dict = {}
654
-
655
- for i, component in enumerate(connected_components):
656
- # Apply the Louvain community detection on the subgraph
657
- partition = community_louvain.best_partition(G.subgraph(component))
658
-
659
- # Calculate modularity
660
- modularity = community_louvain.modularity(partition, G.subgraph(component))
661
- num_nodes = len(component)
662
- return_dict[num_nodes] = modularity
663
-
664
- print(f"Louvain modularity for component with {num_nodes} nodes: {modularity}")
665
-
666
- return return_dict
667
-
668
- def louvain_graph(edge_weights, identifier, directory_path, geometric, geo_info):
669
- G = nx.Graph()
670
-
671
- # Find the maximum and minimum edge weights
672
- max_weight = max(weight for edge, weight in edge_weights.items())
673
- min_weight = min(weight for edge, weight in edge_weights.items())
674
-
675
- if max_weight > 1:
676
- # Normalize edge weights to the range [0.1, 1.0]
677
- normalized_weights = {edge: 0.1 + 0.9 * ((weight - min_weight) / (max_weight - min_weight)) for edge, weight in edge_weights.items()}
678
- else:
679
- normalized_weights = {edge: 0.1 for edge, weight in edge_weights.items()}
680
-
681
- # Add edges to the graph with normalized weights
682
- for edge, normalized_weight in normalized_weights.items():
683
- G.add_edge(edge[0], edge[1], weight=normalized_weight)
684
-
685
- if geometric:
686
- for node in list(G.nodes()):
687
- if node not in geo_info[0]:
688
- G.remove_node(node)
689
- print(f"Removing node {node} from network visualization (no centroid - likely due to downsampling when finding centroids)")
690
-
691
- # Perform Louvain community detection
692
- partition = community_louvain.best_partition(G)
693
-
694
- # Invert the partition dictionary to group nodes by their community
695
- print(f"louvain_communities_initial: {partition}")
696
- communities = {}
697
- for node, community_id in partition.items():
698
- communities.setdefault(community_id, []).append(node)
699
-
700
- print(f"louvain_communities_after: {partition}")
701
-
702
- # Prepare colors for each community
703
- unique_communities = set(partition.values())
704
- colors = [plt.cm.jet(i / len(unique_communities)) for i in range(len(unique_communities))]
705
-
706
- if geometric:
707
-
708
- pos, z_pos = simple_network.geometric_positions(geo_info[0], geo_info[1])
709
- #nx.draw(G, pos, with_labels=True, font_color='black', font_weight='bold', node_size = node_sizes_list, node_color = node_color_list, alpha=0.8, font_size = 12)
710
-
711
- # Draw the nodes, coloring them according to their community
712
- for community_id, nodes in communities.items():
713
- node_sizes_list = [z_pos[node] for node in nodes]
714
- nx.draw_networkx_nodes(G, pos, nodelist=nodes, node_color=[colors[community_id]], node_size=node_sizes_list, alpha=0.8)
715
-
716
- # Modify edge drawing to consider normalized weights
717
- for edge in G.edges():
718
- normalized_weight = G[edge[0]][edge[1]]['weight']
719
-
720
- # Scale the width based on a constant factor (e.g., 5)
721
- nx.draw_networkx_edges(G, pos, edgelist=[edge], width=5 * normalized_weight, edge_color='black')
722
-
723
- # Optionally, draw node labels
724
- nx.draw_networkx_labels(G, pos)
725
-
726
-
727
- else:
728
- # Position nodes using the spring layout
729
- pos = nx.spring_layout(G)
730
-
731
- # Draw the nodes, coloring them according to their community
732
- for community_id, nodes in communities.items():
733
- nx.draw_networkx_nodes(G, pos, nodelist=nodes, node_color=[colors[community_id]], node_size=100, alpha=0.8)
734
-
735
- # Modify edge drawing to consider normalized weights
736
- for edge in G.edges():
737
- normalized_weight = G[edge[0]][edge[1]]['weight']
738
-
739
- # Scale the width based on a constant factor (e.g., 5)
740
- nx.draw_networkx_edges(G, pos, edgelist=[edge], width=5 * normalized_weight, edge_color='black')
741
-
742
- # Optionally, draw node labels
743
- nx.draw_networkx_labels(G, pos)
744
-
745
- plt.axis('off')
746
- if directory_path is not None:
747
- plt.savefig(f'{directory_path}/community_louvain_network_plot.png')
748
-
749
- plt.show()
750
-
751
566
  def create_directory(directory_name):
752
567
  try:
753
568
  os.mkdir(directory_name)
@@ -782,43 +597,5 @@ def remove_small_components(G, threshold):
782
597
  return G
783
598
 
784
599
 
785
- def louvain_analysis_5x(G, excel_file, identifier, directory_path):
786
- print("Performing Louvain Community Detection...")
787
- df = pd.read_excel(excel_file)
788
- G, edge_weights = weighted_network(excel_file)
789
- threshold = find_threshold(G)
790
- G = remove_small_components(G, threshold)
791
- louvain_mod(G, identifier, directory_path)
792
- louvain_graph(edge_weights, identifier, directory_path)
793
- print("Done")
794
-
795
- def louvain_analysis_20x(G, excel_file, identifier, directory_path):
796
- print("Performing Louvain Community Detection...")
797
- df = pd.read_excel(excel_file)
798
- G, edge_weights = weighted_network(excel_file)
799
- louvain_mod_20x(G, identifier, directory_path)
800
- louvain_graph(edge_weights, identifier, directory_path)
801
- print("Done")
802
-
803
-
804
600
  if __name__ == "__main__":
805
- excel_name = input("excel file?: ")
806
- is_5x = input("Is 5x? (Type Y for 5x): ")
807
- if is_5x == 'Y':
808
-
809
- df = pd.read_excel(excel_name)
810
- identifier = "output"
811
- directory_path = 'output'
812
- create_directory(directory_path)
813
- G, edge_weights = weighted_network(excel_name)
814
- #threshold = find_threshold(G)
815
- #G = remove_small_components(G, threshold)
816
- louvain_mod_solo(G, edge_weights, identifier, directory_path)
817
-
818
- else:
819
- df = pd.read_excel(excel_name)
820
- identifier = "output"
821
- directory_path = 'output'
822
- create_directory(directory_path)
823
- G, edge_weights = weighted_network(excel_name)
824
- louvain_mod(G, edge_weights, identifier, directory_path)
601
+ pass
nettracer3d/nettracer.py CHANGED
@@ -3564,12 +3564,12 @@ class Network_3D:
3564
3564
 
3565
3565
  #Some methods that may be useful:
3566
3566
 
3567
- def community_partition(self, weighted = False, style = 0, dostats = True):
3567
+ def community_partition(self, weighted = False, style = 0, dostats = True, seed = None):
3568
3568
  """
3569
3569
  Sets the communities attribute by splitting the network into communities
3570
3570
  """
3571
3571
 
3572
- self._communities, self.normalized_weights, stats = modularity.community_partition(self._network_lists, weighted = weighted, style = style, dostats = dostats)
3572
+ self._communities, self.normalized_weights, stats = modularity.community_partition(self._network_lists, weighted = weighted, style = style, dostats = dostats, seed = seed)
3573
3573
 
3574
3574
  return stats
3575
3575
 
@@ -4027,66 +4027,6 @@ class Network_3D:
4027
4027
  self._communities, self.normalized_weights = modularity.show_communities_flex(self._network, self._network_lists, self.normalized_weights, geo_info = [self._node_centroids, self._nodes.shape], geometric = geometric, directory = directory, weighted = weighted, partition = partition, style = style)
4028
4028
 
4029
4029
 
4030
- def show_communities(self, geometric = False, directory = None):
4031
- """
4032
- Shows the network property, and some basic stats, as a graph where nodes are labelled by colors representing the community they belong to as determined by a label propogation algorithm. Does not support viewing edge weights.
4033
- :param geoemtric: (Optional - Val = False; boolean). If False, node placement in the graph will be random. If True, nodes
4034
- will be placed in their actual spatial location (from the original node segmentation) along the XY plane, using node_centroids.
4035
- The node size will then represent the nodes Z location, with smaller nodes representing a larger Z value. If False, nodes will be placed randomly.
4036
- :param directory: (Optional – Val = None; string). An optional string path to a directory to save the network plot image to. If not set, nothing will be saved.
4037
- """
4038
-
4039
- if not geometric:
4040
-
4041
- simple_network.show_community_network(self._network_lists, directory = directory)
4042
-
4043
- else:
4044
- simple_network.show_community_network(self._network_lists, geometric = True, geo_info = [self._node_centroids, self._nodes.shape], directory = directory)
4045
-
4046
-
4047
- def show_communities_louvain(self, geometric = False, directory = None):
4048
- """
4049
- Shows the network property as a graph, and some basic stats, where nodes are labelled by colors representing the community they belong to as determined by a louvain algorithm. Supports viewing edge weights.
4050
- :param geoemtric: (Optional - Val = False; boolean). If False, node placement in the graph will be random. If True, nodes
4051
- will be placed in their actual spatial location (from the original node segmentation) along the XY plane, using node_centroids.
4052
- The node size will then represent the nodes Z location, with smaller nodes representing a larger Z value. If False, nodes will be placed randomly.
4053
- """
4054
-
4055
- if not geometric:
4056
-
4057
- modularity.louvain_mod(self._network_lists, directory = directory)
4058
- else:
4059
- modularity.louvain_mod(self._network_lists, geometric = True, geo_info = [self._node_centroids, self._nodes.shape], directory = directory)
4060
-
4061
- def louvain_modularity(self, solo_mod = False):
4062
- """
4063
- Shows some basic stats of the network, including modularity (essentially strength of community structure), using a louvain algorithm that accounts for edge weights.
4064
- :param solo_mod: (Optional - Val = False; boolean). If True, will return a singular modularity for the network, taking into
4065
- account all disconnected components as pieces of a network. If False, will return the modularity of each singular disconnected component of the network with the number of nodes in the component as a key
4066
- and the modularity of the component as a value.
4067
- :returns: A dictionary containing the modularity for each disconnected component in the network, key-indexed by that component's node count, or a single modularity value accounting for all disconnected components of the network if the solo_mod param is True.
4068
- """
4069
-
4070
- if not solo_mod:
4071
- mod = modularity._louvain_mod(self._network)
4072
- else:
4073
- mod = modularity._louvain_mod_solo(self._network)
4074
-
4075
- return mod
4076
-
4077
- def modularity(self, solo_mod = False):
4078
- """
4079
- Shows some basic stats of the network, including modularity (essentially strength of community structure), using a label propogation algorithm that does not consider edge weights.
4080
- :param solo_mod: (Optional - Val = False; boolean). If True, will return a singular modularity for the network, taking into
4081
- account all disconnected components as pieces of a network. If False, will return the modularity of each singular disconnected component of the network with the number of nodes in the component as a key
4082
- and the modularity of the component as a value.
4083
- :returns: A dictionary containing the modularity for each disconnected component in the network, key-indexed by that component's node count, or a single modularity value accounting for all disconnected components of the network if the solo_mod param is True.
4084
- """
4085
-
4086
- modularity = simple_network.modularity(self._network, solo_mod = solo_mod)
4087
-
4088
- return modularity
4089
-
4090
4030
 
4091
4031
  def show_identity_network(self, geometric = False, directory = None):
4092
4032
  """
@@ -4149,7 +4089,7 @@ class Network_3D:
4149
4089
  return G
4150
4090
 
4151
4091
 
4152
- def isolate_mothers(self, directory = None, down_factor = 1, louvain = True, ret_nodes = False, called = False):
4092
+ def isolate_mothers(self, directory = None, down_factor = 1, ret_nodes = False, called = False):
4153
4093
 
4154
4094
  """
4155
4095
  Method to isolate 'mother' nodes of a network (in this case, this means nodes that exist betwixt communities), also generating overlays that relate this information to the 3D structure.
@@ -4163,7 +4103,7 @@ class Network_3D:
4163
4103
  """
4164
4104
 
4165
4105
  if ret_nodes:
4166
- mothers = community_extractor.extract_mothers(None, self._network, louvain = louvain, ret_nodes = True, called = called)
4106
+ mothers = community_extractor.extract_mothers(None, self._network, self._communities, ret_nodes = True, called = called)
4167
4107
  return mothers
4168
4108
  else:
4169
4109
 
@@ -4172,9 +4112,9 @@ class Network_3D:
4172
4112
  for item in self._node_centroids:
4173
4113
  centroids[item] = np.round((self._node_centroids[item]) / down_factor)
4174
4114
  nodes = downsample(self._nodes, down_factor)
4175
- mothers, overlay = community_extractor.extract_mothers(nodes, self._network, directory = directory, centroid_dic = centroids, louvain = louvain, called = called)
4115
+ mothers, overlay = community_extractor.extract_mothers(nodes, self._network, self._communities, directory = directory, centroid_dic = centroids, called = called)
4176
4116
  else:
4177
- mothers, overlay = community_extractor.extract_mothers(self._nodes, self._network, centroid_dic = self._node_centroids, directory = directory, louvain = louvain, called = called)
4117
+ mothers, overlay = community_extractor.extract_mothers(self._nodes, self._network, self._communities, centroid_dic = self._node_centroids, directory = directory, called = called)
4178
4118
  return mothers, overlay
4179
4119
 
4180
4120
 
@@ -4186,7 +4126,7 @@ class Network_3D:
4186
4126
 
4187
4127
  hub_img = np.isin(self._nodes, hubs) * self._nodes
4188
4128
  else:
4189
- hub_iimg = None
4129
+ hub_img = None
4190
4130
 
4191
4131
  return hubs, hub_img
4192
4132
 
@@ -4248,33 +4188,6 @@ class Network_3D:
4248
4188
 
4249
4189
 
4250
4190
 
4251
-
4252
-
4253
- def extract_communities_louvain(self, directory = None, down_factor = 1, color_code = True):
4254
- """
4255
- Method to generate overlays that relate community detection in a network to the 3D structure.
4256
- Overlays include a grayscale image where nodes are assigned a grayscale value corresponding to their community, a numerical index where numbers are drawn at nodes corresponding to their community, and a
4257
- color coded overlay where a nodes color corresponds to its community. Community detection will be done with louvain algorithm.
4258
- These will be saved to the active directory if none is specified.
4259
- :param directory: (Optional - Val = None; string). A path to a directory to save outputs.
4260
- :param down_factor: (Optional - Val = 1; int). A factor to downsample nodes by while drawing overlays. Note this option REQUIRES node_centroids to already be set.
4261
- :param color code: (Optional - Val = True; boolean). If set to False, the color-coded overlay will not be drawn.
4262
- :returns: A dictionary where nodes are grouped by community.
4263
- """
4264
-
4265
- if down_factor > 1:
4266
- centroids = self._node_centroids.copy()
4267
- for item in self._node_centroids:
4268
- centroids[item] = np.round((self._node_centroids[item]) / down_factor)
4269
- nodes = downsample(self._nodes, down_factor)
4270
- partition = network_analysis.community_partition(nodes, self._network_lists, directory = directory, centroids = centroids, color_code = color_code)
4271
-
4272
- else:
4273
- partition = network_analysis.community_partition(self._nodes, self._network_lists, directory = directory, centroids = self._node_centroids, color_code = color_code)
4274
-
4275
- return partition
4276
-
4277
-
4278
4191
  #Methods related to analysis:
4279
4192
 
4280
4193
  def radial_distribution(self, radial_distance, directory = None):