1 package com.github.celldynamics.quimp.plugin.protanalysis;
2
3 import java.awt.Point;
4 import java.awt.Polygon;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.ListIterator;
12
13 import org.apache.commons.lang3.tuple.ImmutablePair;
14 import org.apache.commons.lang3.tuple.Pair;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 import com.github.celldynamics.quimp.geom.MapTracker;
19 import com.github.celldynamics.quimp.plugin.qanalysis.STmap;
20 import com.github.celldynamics.quimp.utils.QuimPArrayUtils;
21
22
23
24
25
26
27
28
29
30
31
32
33 public class TrackMapAnalyser {
34
35
36
37
38 static final Logger LOGGER = LoggerFactory.getLogger(TrackMapAnalyser.class.getName());
39
40
41
42
43
44
45 public static final int WITH_SELFCROSSING = 2;
46
47
48
49
50
51
52 public static final int WITHOUT_SELFCROSSING = 4;
53
54
55
56
57
58
59 private static boolean INCLUDE_INITIAL = true;
60
61
62
63
64 private TrackCollection trackCollection;
65
66
67
68
69
70
71 public TrackCollection getTrackCollection() {
72 return trackCollection;
73 }
74
75
76
77
78
79
80
81 public TrackMapAnalyser() {
82 trackCollection = new TrackCollection(INCLUDE_INITIAL);
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public void trackMaxima(final STmap mapCell, double drop, final MaximaFinder maximaFinder) {
105 int numFrames = mapCell.getMotMap().length;
106
107 Polygon maxi = maximaFinder.getMaxima();
108 double[] maxValues = maximaFinder.getMaxValues();
109
110 MapTrackerp/geom/MapTracker.html#MapTracker">MapTracker trackMap = new MapTracker(mapCell.getOriginMap(), mapCell.getCoordMap());
111 trackMap.includeFirst = INCLUDE_INITIAL;
112 ArrayList<Point> trackForward = null;
113 ArrayList<Point> trackBackward = null;
114
115 int nb = 0;
116 int nf = 0;
117
118 for (int i = 0; i < maxi.npoints; i++) {
119 int index = maxi.ypoints[i];
120 int frame = maxi.xpoints[i];
121 LOGGER.trace("Max = [" + frame + "," + index + "]");
122
123 trackForward = (ArrayList<Point>) trackMap.trackForwardValid(frame, index, numFrames - frame);
124
125 trackBackward = (ArrayList<Point>) trackMap.trackBackwardValid(frame, index, frame);
126 Collections.reverse(trackBackward);
127
128 double dropValue;
129 dropValue = maxValues[i] - maxValues[i] * drop;
130 for (nb = 0; nb < trackBackward.size() && trackBackward.get(nb).y >= 0; nb++) {
131 double val = (mapCell.getMotMap()[trackBackward.get(nb).x][trackBackward.get(nb).y]);
132 if (drop >= 0 && val < dropValue) {
133 break;
134 }
135 }
136 LOGGER.trace("tBackward: " + trackBackward);
137 LOGGER.trace("Accepted:" + nb);
138
139 for (nf = 0; nf < trackForward.size() && trackForward.get(nf).y >= 0; nf++) {
140 double val = (mapCell.getMotMap()[trackForward.get(nf).x][trackForward.get(nf).y]);
141 if (drop >= 0 && val < dropValue) {
142 break;
143 }
144 }
145 LOGGER.trace("tForward: " + trackForward);
146 LOGGER.trace("Accepted:" + nf);
147
148
149 trackCollection.addPair(trackBackward.subList(0, nb), trackForward.subList(0, nf));
150 }
151 }
152
153
154
155
156
157
158
159 public Polygon getCommonPoints() {
160 ArrayList<Point> tmpRet = new ArrayList<>();
161 List<Pair<Track, Track>> tracks = trackCollection.getBf();
162 for (int i = 0; i < tracks.size() - 1; i++) {
163 for (int j = i + 1; j < tracks.size(); j++) {
164 Track b1 = tracks.get(i).getLeft();
165 Track b2 = tracks.get(j).getLeft();
166 Track f1 = tracks.get(i).getRight();
167 Track f2 = tracks.get(j).getRight();
168
169
170 {
171 Trackmics/quimp/plugin/protanalysis/Track.html#Track">Track copy = new Track(b1);
172 copy.retainAll(b2);
173 tmpRet.addAll(copy);
174 }
175
176 {
177 Trackmics/quimp/plugin/protanalysis/Track.html#Track">Track copy = new Track(b1);
178 copy.retainAll(f2);
179 tmpRet.addAll(copy);
180 }
181
182 {
183 Trackmics/quimp/plugin/protanalysis/Track.html#Track">Track copy = new Track(b2);
184 copy.retainAll(f1);
185 tmpRet.addAll(copy);
186 }
187
188 {
189 Trackmics/quimp/plugin/protanalysis/Track.html#Track">Track copy = new Track(f1);
190 copy.retainAll(f2);
191 tmpRet.addAll(copy);
192 }
193 }
194 }
195 LOGGER.debug("Common points found:" + tmpRet.size());
196 return point2i2Polygon(QuimPArrayUtils.removeDuplicates(tmpRet));
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 public Polygon getIntersectionPoints(List<Polygon> tracks) {
214 List<Polygon> tmpRet = new ArrayList<>();
215 for (int i = 0; i < tracks.size() - 1; i++) {
216 for (int j = i + 1; j < tracks.size(); j++) {
217 Polygon retPol = getIntersectionPoints(tracks.get(i), tracks.get(j));
218 if (retPol.npoints != 0) {
219 tmpRet.add(retPol);
220 }
221 }
222 }
223
224 List<Point> retP2i = QuimPArrayUtils.removeDuplicates(polygon2Point2i(tmpRet));
225
226 return point2i2Polygon(retP2i);
227 }
228
229
230
231
232
233
234
235
236 public Polygon getIntersectionPoints(Polygon p1, Polygon p2) {
237 Polygon ret = new Polygon();
238 List<Point> tmpRet = new ArrayList<>();
239 List<Point> p1p = polygon2Point2i(Arrays.asList(p1));
240 List<Point> p2p = polygon2Point2i(Arrays.asList(p2));
241
242 p1p.retainAll(p2p);
243 tmpRet.addAll(p1p);
244
245 ret = point2i2Polygon(tmpRet);
246 return ret;
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260 public List<Pair<Point, Point>> getIntersectionParents(List<Polygon> tracks, int mode) {
261 ArrayList<Pair<Point, Point>> retTmp = new ArrayList<>();
262 List<Pair<Point, Point>> ret;
263 for (int i = 0; i < tracks.size() - 1; i++) {
264 for (int j = i + 1; j < tracks.size(); j++) {
265 Polygon retPol = getIntersectionPoints(tracks.get(i), tracks.get(j));
266 for (int n = 0; n < retPol.npoints; n++) {
267 Pair<Point, Point> pairTmp = new ImmutablePair<Point, Point>(new Point(i, j),
268 new Point(retPol.xpoints[n], retPol.ypoints[n]));
269 retTmp.add(pairTmp);
270 }
271 }
272 }
273 ret = retTmp;
274 if ((mode & WITHOUT_SELFCROSSING) == WITHOUT_SELFCROSSING) {
275 ret = removeSelfCrossings(ret);
276 }
277 return ret;
278 }
279
280
281
282
283
284
285
286
287 public List<Pair<Point, Point>> removeSelfRepeatings(List<Pair<Point, Point>> intersections,
288 List<Polygon> tracks) {
289 HashMap<Integer, List<Pair<Point, Point>>> map = new HashMap<>();
290 List<Pair<Point, Point>> ret = new ArrayList<>();
291
292 for (Pair<Point, Point> p : intersections) {
293 Integer parentleft = p.getLeft().x;
294 if (map.get(parentleft) == null) {
295 map.put(parentleft, new ArrayList<>());
296 }
297 map.get(parentleft).add(p);
298 }
299
300
301 Iterator<Integer> it = map.keySet().iterator();
302 int minInd = Integer.MAX_VALUE;
303 while (it.hasNext()) {
304 Integer key = it.next();
305 List<Pair<Point, Point>> values = map.get(key);
306 Pair<Point, Point> minPoint = null;
307
308 for (Pair<Point, Point> p : values) {
309
310
311 int back;
312 int forw;
313 if (p.getLeft().x % 2 == 0) {
314 back = p.getLeft().x;
315 forw = back + 1;
316 } else {
317 forw = p.getLeft().x;
318 back = forw - 1;
319 }
320 int ind = enumeratePoint(tracks.get(back), tracks.get(forw), p.getRight());
321 if (ind < 0) {
322 throw new IllegalArgumentException("Point does not exist in track");
323 }
324 if (ind < minInd) {
325 minInd = ind;
326 minPoint = p;
327 }
328 }
329 ret.add(minPoint);
330 }
331 return ret;
332
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 private List<Pair<Point, Point>> removeSelfCrossings(List<Pair<Point, Point>> input) {
353 ArrayList<Pair<Point, Point>> ret = new ArrayList<>(input);
354 ListIterator<Pair<Point, Point>> it = ret.listIterator();
355 while (it.hasNext()) {
356 Pair<Point, Point> element = it.next();
357
358
359 if (element.getLeft().x % 2 == 0 && element.getLeft().x + 1 == element.getLeft().y) {
360 it.remove();
361 }
362 }
363 return ret;
364 }
365
366
367
368
369
370
371
372
373
374
375 public static List<Point> polygon2Point2i(List<Polygon> list) {
376 List<Point> ret = new ArrayList<>();
377 for (Polygon pl : list) {
378 for (int i = 0; i < pl.npoints; i++) {
379 ret.add(new Point(pl.xpoints[i], pl.ypoints[i]));
380 }
381 }
382 return ret;
383 }
384
385
386
387
388
389
390
391
392
393
394 public static Polygon point2i2Polygon(List<Point> list) {
395 int[] x = new int[list.size()];
396 int[] y = new int[list.size()];
397 int l = 0;
398 for (Point p : list) {
399 x[l] = p.x;
400 y[l] = p.y;
401 l++;
402 }
403 return new Polygon(x, y, list.size());
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421 static int enumeratePoint(Polygon backwardMap, Polygon forwardMap, Point point) {
422 int i = 0;
423 int delta = 0;
424
425
426 if (INCLUDE_INITIAL && forwardMap.npoints > 0 && backwardMap.npoints > 0) {
427 delta = 1;
428 }
429
430 for (i = 0; i < backwardMap.npoints - delta; i++) {
431 if (backwardMap.xpoints[i] == point.x && backwardMap.ypoints[i] == point.y) {
432 return i;
433 }
434 }
435 for (; i < forwardMap.npoints + backwardMap.npoints - delta; i++) {
436 if (forwardMap.xpoints[i - backwardMap.npoints + delta] == point.x
437 && forwardMap.ypoints[i - backwardMap.npoints + delta] == point.y) {
438 return i;
439 }
440 }
441 return -1;
442 }
443
444 }