connections.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import pickle
  2. import graph_tool as gt
  3. import itertools
  4. import numpy as np
  5. from interneuron_polarity.model.morphology.volume import get_distance_from_to
  6. class RecurrentInhibition:
  7. INTERNEURON_IDENTITY = "interneuron_idx"
  8. POSITION = "position"
  9. def __init__(self, in_ex_connectivity, ex_somata_positions):
  10. n_in, n_ex = tuple(in_ex_connectivity.shape)
  11. g = gt.Graph(directed=False)
  12. interneuron_identity = g.new_edge_property("int")
  13. positions = g.new_vertex_property("vector<float>")
  14. exs = g.add_vertex(n_ex)
  15. for ex in exs:
  16. positions[ex] = ex_somata_positions[:, g.vertex_index[ex]]
  17. for interneuron_idx in range(n_in):
  18. connected_exs_indices = np.where(in_ex_connectivity[interneuron_idx, :] == 1)[0]
  19. for comb in itertools.combinations(set(connected_exs_indices), 2):
  20. ex1, ex2 = comb
  21. new_edge = g.add_edge(ex1, ex2)
  22. interneuron_identity[new_edge] = interneuron_idx
  23. g.edge_properties[RecurrentInhibition.INTERNEURON_IDENTITY] = interneuron_identity
  24. g.vertex_properties[RecurrentInhibition.POSITION] = positions
  25. self.n_in = n_in
  26. self.n_ex = n_ex
  27. self.positions = ex_somata_positions
  28. self.g = g
  29. def get_distance_to_neighbors(self, excitatory_neuron_index):
  30. neighbors = self.g.get_out_neighbors(excitatory_neuron_index)
  31. distances = self.get_distance(excitatory_neuron_index, neighbors)
  32. return distances[0,:]
  33. def get_distances_to_neighbors(self):
  34. distances = [self.get_distance_to_neighbors(idx) for idx in np.arange(0, self.n_ex)]
  35. return np.concatenate(tuple(distances))
  36. def get_number_of_neighbors(self):
  37. return np.array([len(self.g.get_out_neighbors(v)) for v in self.g.vertices()])
  38. def get_second_order_neighbors(self, tested_vertex):
  39. first_order_neighbors = self.g.get_out_neighbors(tested_vertex)
  40. excluded_neighbors = set(first_order_neighbors).union([tested_vertex])
  41. second_order_neighbors = []
  42. for first_order_neighbor in first_order_neighbors:
  43. potential_second_order_neighbors = set(self.g.get_out_neighbors(first_order_neighbor))
  44. second_order_neighbors.extend(potential_second_order_neighbors.difference(excluded_neighbors))
  45. return second_order_neighbors
  46. def get_distance_to_second_order_neighbors(self, excitatory_idx):
  47. second_order_neighbors = self.get_second_order_neighbors(excitatory_idx)
  48. distances = self.get_distance(excitatory_idx, second_order_neighbors)
  49. return distances[0,:]
  50. def get_distances_to_second_order_neighbors(self):
  51. distances = [self.get_distance_to_second_order_neighbors(idx) for idx in np.arange(0, self.n_ex)]
  52. return np.concatenate(tuple(distances))
  53. def get_connected_interneuron_indices(self, excitatory_neuron_index):
  54. edges = self.g.get_out_edges(excitatory_neuron_index)
  55. return np.array([self.g.edge_properties[RecurrentInhibition.INTERNEURON_IDENTITY][edge] for edge in edges])
  56. def get_numbers_of_containing_axonal_clouds(self):
  57. number_of_containing_axonal_clouds = [len(np.unique(self.get_connected_interneuron_indices(idx))) for idx in range(self.n_ex)]
  58. return number_of_containing_axonal_clouds
  59. def get_distance(self, from_idx, to):
  60. this_position = self.positions[:, from_idx]
  61. neighbor_positions = self.positions[:, to]
  62. distances = get_distance_from_to(this_position, neighbor_positions)
  63. return distances
  64. def save(self, filename):
  65. with open(filename, 'wb') as file:
  66. pickle.dump(self, file)
  67. @staticmethod
  68. def load(filename):
  69. with open(filename, 'rb') as file:
  70. recurrent_inhibition_graph = pickle.load(file)
  71. return recurrent_inhibition_graph
  72. class OverlapMatrix:
  73. def __init__(self, excitatory_neurons, inhibitory_neurons, overlaps):
  74. self.excitatory_neurons = excitatory_neurons
  75. self.inhibitory_neurons = inhibitory_neurons
  76. self.overlaps = overlaps
  77. def ex_on_ex(self):
  78. return self.overlaps[:self.excitatory_neurons.number, :self.excitatory_neurons.number]
  79. def ex_on_in(self):
  80. return self.overlaps[:self.excitatory_neurons.number, self.excitatory_neurons.number:-1]
  81. def in_on_in(self):
  82. return self.overlaps[self.excitatory_neurons.number:-1, self.excitatory_neurons.number:-1]
  83. def in_on_ex(self):
  84. return self.overlaps[self.excitatory_neurons.number:-1, :self.excitatory_neurons.number]
  85. def get_submatrices(self):
  86. return self.ex_on_ex(), self.ex_on_in(), self.in_on_in(), self.in_on_ex()
  87. def save_overlap(filename, overlap_matrix):
  88. with open(filename, 'wb') as file:
  89. pickle.dump(overlap_matrix,file)
  90. def load_overlap(filename):
  91. with open(filename, 'rb') as file:
  92. overlap_matrix = pickle.load(file)
  93. return overlap_matrix