1 package com.github.celldynamics.quimp;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Iterator;
8 import java.util.List;
9
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import com.github.celldynamics.quimp.filesystem.IQuimpSerialize;
14 import com.github.celldynamics.quimp.geom.ExtendedVector2d;
15 import com.github.celldynamics.quimp.geom.SegmentedShapeRoi;
16 import com.github.celldynamics.quimp.utils.QuimPArrayUtils;
17
18 import ij.IJ;
19 import ij.ImagePlus;
20 import ij.gui.PolygonRoi;
21 import ij.gui.Roi;
22
23
24
25
26
27
28
29 public class Nest implements IQuimpSerialize {
30
31 private static final Logger LOGGER = LoggerFactory.getLogger(Nest.class.getName());
32
33
34
35
36
37
38
39
40
41
42
43
44
45 private ArrayList<SnakeHandler> sHs;
46
47
48
49 private int NSNAKES;
50
51
52
53 private int ALIVE;
54
55
56
57 private int nextID;
58
59
60
61
62 public Nest() {
63 NSNAKES = 0;
64 ALIVE = 0;
65 nextID = 0;
66 sHs = new ArrayList<SnakeHandler>();
67 }
68
69
70
71
72
73
74
75
76
77 public void addHandlers(ArrayList<ArrayList<SegmentedShapeRoi>> roiArray) {
78 LOGGER.trace("Adding " + roiArray.size() + " SnakeHandlers");
79 for (List<SegmentedShapeRoi> lsS : roiArray) {
80 try {
81 sHs.add(new SnakeHandler(lsS, nextID));
82 nextID++;
83 NSNAKES++;
84 ALIVE++;
85 } catch (Exception e) {
86 LOGGER.error("A snake on frame " + lsS.get(0).getFrame() + " failed to initilise "
87 + e.getMessage());
88 }
89 }
90 }
91
92
93
94
95
96
97
98 public void addHandlers(Roi[] roiArray, int startFrame) {
99 int i = 0;
100 for (; i < roiArray.length; i++) {
101 try {
102 sHs.add(new SnakeHandler(roiArray[i], startFrame, nextID));
103 nextID++;
104 NSNAKES++;
105 ALIVE++;
106 } catch (Exception e) {
107 BOA_.log("A snake failed to initilise: " + e.getMessage());
108 }
109 }
110 BOA_.log("Added " + roiArray.length + " cells at frame " + startFrame);
111 BOA_.log("Cells being tracked: " + NSNAKES);
112 }
113
114
115
116
117
118
119
120
121 public SnakeHandler addHandler(final Roi r, int startFrame) {
122 SnakeHandler sh;
123 try {
124 sh = new SnakeHandler(r, startFrame, nextID);
125 sHs.add(sh);
126 nextID++;
127 NSNAKES++;
128 ALIVE++;
129 BOA_.log("Added one cell, begining frame " + startFrame);
130 } catch (Exception e) {
131 BOA_.log("Added cell failed to initilise");
132 LOGGER.debug(e.getMessage(), e);
133 return null;
134 }
135 BOA_.log("Cells being tracked: " + NSNAKES);
136 return sh;
137 }
138
139
140
141
142
143
144
145
146
147 public SnakeHandler getHandler(int s) {
148 return sHs.get(s);
149 }
150
151
152
153
154
155
156 public List<SnakeHandler> getHandlers() {
157 return Collections.unmodifiableList(sHs);
158 }
159
160
161
162
163
164
165
166
167 public SnakeHandler getHandlerofId(int id) {
168 int ret = -1;
169 for (int i = 0; i < sHs.size(); i++) {
170 if (sHs.get(i) != null && sHs.get(i).getID() == id) {
171 ret = i;
172 break;
173 }
174 }
175 if (ret < 0) {
176 throw new IllegalArgumentException("SnakeHandler of index " + id + " not found in nest");
177 } else {
178 return getHandler(ret);
179 }
180 }
181
182
183
184
185
186
187
188
189
190
191 public boolean writeSnakes() throws IOException {
192 Iterator<SnakeHandler> shitr = sHs.iterator();
193 ArrayList<SnakeHandler> toRemove = new ArrayList<>();
194 SnakeHandler sh;
195 while (shitr.hasNext()) {
196 sh = (SnakeHandler) shitr.next();
197 sh.findLastFrame();
198 if (sh.getStartFrame() > sh.getEndFrame()) {
199 IJ.error("Snake " + sh.getID() + " not written as its empty. Deleting it.");
200 toRemove.add(sh);
201 continue;
202 }
203 if (!sh.writeSnakes()) {
204 return false;
205 }
206 }
207
208 for (int i = 0; i < toRemove.size(); i++) {
209 removeHandler(toRemove.get(i));
210 }
211 return true;
212 }
213
214
215
216
217
218
219 public void kill(final SnakeHandler sh) {
220 sh.kill();
221 ALIVE--;
222 }
223
224
225
226
227 public void reviveNest() {
228 Iterator<SnakeHandler> shitr = sHs.iterator();
229 while (shitr.hasNext()) {
230 SnakeHandler/../../../com/github/celldynamics/quimp/SnakeHandler.html#SnakeHandler">SnakeHandler sh = (SnakeHandler) shitr.next();
231 sh.revive();
232 }
233 ALIVE = NSNAKES;
234 }
235
236
237
238
239
240
241 public boolean isVacant() {
242 if (NSNAKES == 0) {
243 return true;
244 }
245 return false;
246 }
247
248
249
250
251
252
253 public boolean allDead() {
254 if (ALIVE == 0 || NSNAKES == 0) {
255 return true;
256 }
257 return false;
258 }
259
260
261
262
263
264
265 public boolean allFrozen() {
266 boolean ret = true;
267 for (SnakeHandler s : sHs) {
268 ret = ret && s.isSnakeHandlerFrozen();
269 }
270 return ret;
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 public List<CellStatsEval> analyse(final ImagePlus oi, boolean saveStats) {
287 OutlineHandler outputH;
288 SnakeHandler sh;
289 ArrayList<CellStatsEval> ret = new ArrayList<>();
290 Iterator<SnakeHandler> shitr = sHs.iterator();
291 while (shitr.hasNext()) {
292 sh = (SnakeHandler) shitr.next();
293
294 File statsFile;
295 outputH = new OutlineHandler(sh);
296 if (saveStats == true) {
297 statsFile = new File(BOA_.qState.boap.deductStatsFileName(sh.getID()));
298 } else {
299 statsFile = null;
300 }
301 CellStatsEvalllStatsEval.html#CellStatsEval">CellStatsEval tmp = new CellStatsEval(outputH, oi, statsFile,
302 BOA_.qState.boap.getImageScale(), BOA_.qState.boap.getImageFrameInterval());
303 ret.add(tmp);
304 }
305 return ret;
306 }
307
308
309
310
311 public void resetNest() {
312 reviveNest();
313 Iterator<SnakeHandler> shitr = sHs.iterator();
314 ArrayList<SnakeHandler> toRemove = new ArrayList<>();
315 while (shitr.hasNext()) {
316 SnakeHandler/../../../com/github/celldynamics/quimp/SnakeHandler.html#SnakeHandler">SnakeHandler sh = (SnakeHandler) shitr.next();
317 try {
318 sh.reset();
319 } catch (Exception e) {
320 LOGGER.error("Could not reset snake " + e.getMessage(), e);
321 BOA_.log("Could not reset snake " + sh.getID());
322 BOA_.log("Removing snake " + sh.getID());
323
324
325 toRemove.add(sh);
326 }
327 }
328
329 for (int i = 0; i < toRemove.size(); i++) {
330 removeHandler(toRemove.get(i));
331 }
332 }
333
334
335
336
337
338
339 public void removeHandler(final SnakeHandler sh) {
340 if (sh.isLive()) {
341 ALIVE--;
342 }
343 sHs.remove(sh);
344 NSNAKES--;
345 }
346
347
348
349
350 public void cleanNest() {
351 sHs.clear();
352 NSNAKES = 0;
353 ALIVE = 0;
354 nextID = 0;
355 }
356
357
358
359
360
361
362 public int size() {
363 return NSNAKES;
364 }
365
366
367
368
369
370
371 void resetForFrame(int f) {
372 reviveNest();
373 Iterator<SnakeHandler> shitr = sHs.iterator();
374 ArrayList<SnakeHandler> toRemove = new ArrayList<>();
375 while (shitr.hasNext()) {
376 SnakeHandler/../../../com/github/celldynamics/quimp/SnakeHandler.html#SnakeHandler">SnakeHandler sh = (SnakeHandler) shitr.next();
377 if (sh.isSnakeHandlerFrozen()) {
378 continue;
379 }
380 try {
381 if (f <= sh.getStartFrame()) {
382
383 sh.reset();
384 } else {
385
386 sh.resetForFrame(f);
387 }
388 } catch (Exception e) {
389 LOGGER.debug("Could not reset snake " + e.getMessage(), e);
390 BOA_.log("Could not reset snake " + sh.getID());
391 BOA_.log("Removing snake " + sh.getID());
392
393
394 toRemove.add(sh);
395 }
396 }
397
398 for (int i = 0; i < toRemove.size(); i++) {
399 removeHandler(toRemove.get(i));
400 }
401 }
402
403
404
405
406
407
408
409 public List<Integer> getSnakesforFrame(int frame) {
410 ArrayList<Integer> ret = new ArrayList<Integer>();
411 Iterator<SnakeHandler> shiter = sHs.iterator();
412 while (shiter.hasNext()) {
413 SnakeHandler sh = shiter.next();
414 if (sh.getStartFrame() > frame || sh.getEndFrame() < frame) {
415 continue;
416 }
417 if (sh.isStoredAt(frame)) {
418
419
420 Snake s = sh.getStoredSnake(frame);
421 ret.add(s.getSnakeID());
422 }
423 }
424 return ret;
425 }
426
427
428
429
430
431
432
433 int nbSnakesAt(int frame) {
434 int n = 0;
435 for (int i = 0; i < NSNAKES; i++) {
436 if (sHs.get(i).getStartFrame() >= frame) {
437 n++;
438 }
439 }
440 return n;
441 }
442
443
444
445
446
447
448
449
450
451
452
453 public void addOutlinehandler(final OutlineHandler oh) {
454 SnakeHandler sh = addHandler(oh.indexGetOutline(0).asFloatRoi(), oh.getStartFrame());
455 if (sh == null) {
456 LOGGER.error("Outline handler could not be added");
457 return;
458 }
459 Outline o;
460 for (int i = oh.getStartFrame(); i <= oh.getEndFrame(); i++) {
461 o = oh.getStoredOutline(i);
462 sh.storeRoi((PolygonRoi) o.asFloatRoi(), i);
463 }
464 sh.copyFromFinalToSeg();
465 }
466
467
468
469
470
471
472
473
474
475
476 public SnakeHandler findClosestTo(int offScreenX, int offScreenY, int frame, double dist) {
477 SnakeHandler snakeH;
478 Snake snake;
479 ExtendedVector2d snakeV;
480 ExtendedVector2dExtendedVector2d.html#ExtendedVector2d">ExtendedVector2d mdV = new ExtendedVector2d(offScreenX, offScreenY);
481 List<Double> distance = new ArrayList<Double>();
482
483 for (int i = 0; i < size(); i++) {
484 snakeH = getHandler(i);
485 if (snakeH.isStoredAt(frame)) {
486 snake = snakeH.getStoredSnake(frame);
487 snakeV = snake.getCentroid();
488 distance.add(ExtendedVector2d.lengthP2P(mdV, snakeV));
489 }
490 }
491 int minIndex = QuimPArrayUtils.minListIndex(distance);
492 double minDistance = distance.get(minIndex);
493 if (minDistance < dist) {
494 return getHandler(minIndex);
495 } else {
496 return null;
497 }
498 }
499
500
501
502
503
504
505 @Override
506 public void beforeSerialize() {
507 Iterator<SnakeHandler> shitr = sHs.iterator();
508 ArrayList<SnakeHandler> toRemove = new ArrayList<>();
509 SnakeHandler sh;
510
511 while (shitr.hasNext()) {
512 sh = (SnakeHandler) shitr.next();
513 sh.findLastFrame();
514 if (sh.getStartFrame() > sh.getEndFrame()) {
515 IJ.error("Snake " + sh.getID() + " not written as its empty. Deleting it.");
516 toRemove.add(sh);
517 continue;
518 }
519 sh.beforeSerialize();
520 }
521
522 for (int i = 0; i < toRemove.size(); i++) {
523 removeHandler(toRemove.get(i));
524 }
525 }
526
527
528
529
530
531
532 @Override
533 public void afterSerialize() throws Exception {
534 Iterator<SnakeHandler> shitr = sHs.iterator();
535 SnakeHandler sh;
536 while (shitr.hasNext()) {
537 sh = (SnakeHandler) shitr.next();
538 sh.afterSerialize();
539 }
540
541 }
542
543
544
545
546
547
548 @Override
549 public String toString() {
550 return "Nest [sHs=" + sHs + ", NSNAKES=" + NSNAKES + ", ALIVE=" + ALIVE + ", nextID=" + nextID
551 + "]";
552 }
553 }