Skip to content

Commit 795ff14

Browse files
committed
working on connect() spine
1 parent e35ffe2 commit 795ff14

1 file changed

Lines changed: 253 additions & 0 deletions

File tree

sandbox/connectSpines.py

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import numpy as np
2+
import pandas as pd
3+
4+
from mapmanagercore import MapAnnotations, MMapLoader
5+
from mapmanagercore.annotations.single_time_point import SingleTimePointAnnotations
6+
7+
from mapmanagercore.logger import logger
8+
9+
def connectSpines(map :MapAnnotations, tp1, tp2, segment1, segment2, thesholdDist : float = 10):
10+
"""Connect spines between tp1 and tp2.
11+
12+
Parameters
13+
---------
14+
tp1,tp2 : int
15+
The timepoint (e.g. time or t) to connect between
16+
17+
18+
Returns
19+
-------
20+
pd.DataFrame with columns
21+
spineID
22+
position
23+
toSpineID
24+
toPosition
25+
dist
26+
"""
27+
spineID = 0
28+
position = 1
29+
isLeft = 2
30+
toSpineID = 3
31+
toDistance = 4
32+
toPosition = 5
33+
# spineLength = 6
34+
# toSpineLength = 7
35+
36+
# thesholdDist = 10
37+
# print('thesholdDist:', thesholdDist)
38+
39+
def makeNp(tp : SingleTimePointAnnotations, segmentID): # , isFrom : bool):
40+
points = tp.points[:]
41+
points = points[points['segmentID']==segmentID]
42+
43+
points['isLeft'] = (points['spineSide']=='Left')
44+
45+
# print(points['spineLength'].max()) # about 25
46+
47+
m = len(points)
48+
49+
_np = np.zeros(shape=(m,6))
50+
_np[:,spineID] = points.index.to_list()
51+
_np[:,position] = points['spinePosition']
52+
_np[:,isLeft] = points['isLeft'] # left -> 1, right -> 0
53+
54+
_np[:,toSpineID] = np.nan
55+
_np[:,toDistance] = np.nan
56+
_np[:,toPosition] = np.nan
57+
58+
# _np[:,spineLength] = points['spineLength']
59+
# _np[:,toSpineLength] = np.nan
60+
61+
# print('xxx')
62+
# print(_np[:,spineID])
63+
64+
return _np
65+
66+
def connect(i, j):
67+
dist = abs(fromNp[i,position] - toNp[j,position])
68+
fromNp[i,toSpineID] = toNp[j, spineID] # int(j)
69+
fromNp[i,toDistance] = dist
70+
fromNp[i, toPosition] = toNp[j,position]
71+
72+
toNp[j, toSpineID] = fromNp[i, spineID] # int(i)
73+
toNp[j, toDistance] = dist
74+
toNp[j, toPosition] = fromNp[i,position] # not used
75+
76+
def disconnect(i, j):
77+
fromNp[i,toSpineID] = np.nan
78+
fromNp[i,toDistance] = np.nan
79+
fromNp[i,toPosition] = np.nan
80+
81+
toNp[j, toSpineID] = np.nan
82+
toNp[j, toDistance] = np.nan
83+
toNp[j, toPosition] = np.nan
84+
85+
_fromTp : SingleTimePointAnnotations = map.getTimePoint(tp1)
86+
_toTp : SingleTimePointAnnotations = map.getTimePoint(tp2)
87+
88+
fromNp = makeNp(_fromTp, segment1)
89+
toNp = makeNp(_toTp, segment2)
90+
91+
m = len(fromNp)
92+
n = len(toNp)
93+
94+
numTieBreakers = -1
95+
numIteration = 0
96+
while numTieBreakers != 0:
97+
logger.info(f'iteration:{numIteration} tie breakers:{numTieBreakers}')
98+
99+
numTieBreakers = 0
100+
for i in range(m):
101+
iLeft = fromNp[i,isLeft]
102+
iIsTaken = ~np.isnan(fromNp[i, toSpineID])
103+
for j in range(n):
104+
jLeft = toNp[j,isLeft]
105+
if iLeft != jLeft:
106+
continue
107+
108+
jIsTaken = ~np.isnan(toNp[j, toSpineID])
109+
dist = abs(fromNp[i,position] - toNp[j,position])
110+
111+
if dist < thesholdDist:
112+
if jIsTaken:
113+
existingDist = toNp[j,toDistance]
114+
if dist < existingDist:
115+
numTieBreakers += 1
116+
_toSpineID = int(toNp[j,toSpineID])
117+
disconnect(_toSpineID, j)
118+
# print(f'jIsTaken broke tie {i} {j} existingDist:{existingDist} new dist:{dist}')
119+
else:
120+
# j is taken but current (i,j) dist does not beat it
121+
continue
122+
123+
elif iIsTaken:
124+
# check if we are closer, e.g. break a tie
125+
existingDist = fromNp[i,toDistance]
126+
if dist < existingDist:
127+
numTieBreakers += 1
128+
disconnect(i, j)
129+
# print(f'iIsTaken broke tie {i} {j} existingDist:{existingDist} new dist:{dist}')
130+
else:
131+
# i is taken but current (i,j) dist does not beat it
132+
continue
133+
134+
connect(i, j)
135+
iIsTaken = True
136+
#
137+
numIteration += 1
138+
139+
logger.info(f'numIteration:{numIteration}')
140+
141+
dfRet = pd.DataFrame()
142+
dfRet['spineID'] = fromNp[:, spineID]
143+
dfRet['position'] = fromNp[:, position]
144+
145+
dfRet['toSpineID'] = fromNp[:, toSpineID]
146+
dfRet['toPosition'] = fromNp[:, toPosition]
147+
148+
dfRet['dist'] = dfRet['toPosition'] - dfRet['position']
149+
150+
dfRet['spineLength'] = _fromTp.points[:].loc[dfRet['spineID']]['spineLength']
151+
152+
# toSpineID will have nan
153+
_df = dfRet['toSpineID'].dropna().to_list()
154+
# print(_df)
155+
# _tmp = _toTp.points[:]['spineLength'].loc[_df].to_list()
156+
# print(_tmp)
157+
158+
# dfRet['toSpineLength'] = _toTp.points[:]['spineLength'].loc[_df]
159+
# print(dfRet['toSpineLength'])
160+
161+
# print('dfRet:', len(dfRet))
162+
163+
# print('connecting spines')
164+
# for idx, row in dfRet.iterrows():
165+
# fromSpineID = row['spineID']
166+
# toSpineID = row['toSpineID']
167+
# if ~np.isnan(fromSpineID) and ~np.isnan(toSpineID):
168+
# fromSpineID = int(fromSpineID)
169+
# toSpineID = int(toSpineID)
170+
# # print(f'connect spine {fromSpineID} to {toSpineID}')
171+
# map.connect((fromSpineID, tp1), (toSpineID, tp2))
172+
173+
return dfRet
174+
175+
def debugConnectSpines(map :MapAnnotations):
176+
_tmp = map.points[ map.points['segmentID'] == 0 ]
177+
178+
_indexSlice = pd.IndexSlice[5,:] # all spines with id 5
179+
# _indexSlice = pd.IndexSlice[:,0] # does not work
180+
# print(_tmp[_indexSlice])
181+
182+
#print(_tmp.index)
183+
184+
# tp1 starts with spine id 139
185+
# tp = map.getTimePoint(1)
186+
187+
# df1.rename(index={1: 'a'})
188+
map.points.index.rename({(140,1): (2,1)}, inplace=True)
189+
190+
_indexSlice = pd.IndexSlice[140,:] # all spines with id 5
191+
print('_indexSlice:', _indexSlice)
192+
print(map.points[_indexSlice])
193+
194+
_indexSlice = pd.IndexSlice[2,:] # all spines with id 5
195+
print('_indexSlice:', _indexSlice)
196+
print(map.points[_indexSlice])
197+
198+
def debugMultiIndex():
199+
200+
_index = [
201+
(0,0),
202+
(2,0),
203+
204+
(2,1),
205+
(5,1)
206+
]
207+
df = pd.DataFrame(index=_index)
208+
df['a'] = [
209+
'a', 'b', 'c', 'd']
210+
print(df)
211+
212+
_indexSlice = pd.IndexSlice[2,:] # all spines with id 5
213+
print('xxx:')
214+
print(df.loc[_indexSlice])
215+
216+
def _plotNp(dfRet):
217+
fromPosition = dfRet['position']
218+
toPosition = dfRet['toPosition']
219+
220+
xPlot = []
221+
yPlot = []
222+
for idx, position in enumerate(fromPosition):
223+
yPlot.append(position)
224+
yPlot.append(toPosition[idx])
225+
yPlot.append(np.nan)
226+
227+
xPlot.append(0)
228+
xPlot.append(1)
229+
xPlot.append(np.nan)
230+
231+
import matplotlib.pyplot as plt
232+
plt.plot(xPlot, yPlot, 'o-')
233+
plt.show()
234+
235+
if __name__ == '__main__':
236+
237+
# a 2 session map
238+
path = 'sandbox/data/rr30a_2tp.mmap'
239+
map = MapAnnotations(MMapLoader('/Users/cudmore/Sites/MapManagerCore/sandbox/data/rr30a_2tp.mmap'))
240+
241+
tp1 = 0
242+
tp2 = 1
243+
segment1 = 0
244+
segment2 = 0
245+
thesholdDist = 10
246+
df = connectSpines(map, tp1, tp2, segment1, segment2, thesholdDist=thesholdDist)
247+
248+
# debugConnectSpines(map)
249+
250+
# debugMultiIndex()
251+
252+
# a plot for debugging
253+
_plotNp(df)

0 commit comments

Comments
 (0)