1 package com.github.celldynamics.quimp;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.io.PrintWriter;
9 import java.util.Arrays;
10 import java.util.List;
11
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import com.github.celldynamics.quimp.BOA_.CustomStackWindow;
16 import com.github.celldynamics.quimp.filesystem.FileExtensions;
17 import com.github.celldynamics.quimp.filesystem.IQuimpSerialize;
18 import com.github.celldynamics.quimp.geom.SegmentedShapeRoi;
19 import com.github.celldynamics.quimp.plugin.utils.QuimpDataConverter;
20 import com.github.celldynamics.quimp.utils.QuimpToolsCollection;
21
22 import ij.IJ;
23 import ij.gui.PolygonRoi;
24 import ij.gui.Roi;
25
26
27
28
29
30
31
32
33
34
35
36 public class SnakeHandler extends ShapeHandler<Snake> implements IQuimpSerialize {
37
38
39
40
41 static final Logger LOGGER = LoggerFactory.getLogger(SnakeHandler.class.getName());
42
43
44
45 private transient Roi roi;
46
47
48
49
50
51 private Snake liveSnake;
52
53
54
55
56
57 private Snake[] finalSnakes;
58
59
60
61 private Snake[] segSnakes;
62
63
64
65 private int ID;
66
67
68
69
70
71
72
73
74 private boolean snakeHandlerFrozen = false;
75
76
77
78
79 public SnakeHandler() {
80 }
81
82
83
84
85
86
87
88
89
90 public SnakeHandler(final Roi r, int frame, int id) throws BoaException {
91 this();
92 startFrame = frame;
93 endFrame = BOA_.qState.boap.getFrames();
94 roi = r;
95
96
97 finalSnakes = new Snake[BOA_.qState.boap.getFrames() - startFrame + 1];
98 segSnakes = new Snake[BOA_.qState.boap.getFrames() - startFrame + 1];
99 ID = id;
100 liveSnake = new Snake(r, ID, false);
101 backupLiveSnake(frame);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public SnakeHandler(List<SegmentedShapeRoi> snakes, int id) throws BoaException {
117 this();
118 startFrame = snakes.get(0).getFrame();
119 finalSnakes = new Snake[BOA_.qState.boap.getFrames() - startFrame + 1];
120 segSnakes = new Snake[BOA_.qState.boap.getFrames() - startFrame + 1];
121 ID = id;
122 roi = snakes.get(0);
123 for (SegmentedShapeRoi ss : snakes) {
124 liveSnake = new Snake(ss.getOutlineasPoints(), ID);
125 backupLiveSnake(ss.getFrame());
126 storeLiveSnake(ss.getFrame());
127 }
128 endFrame = snakes.get(snakes.size() - 1).getFrame();
129 liveSnake = new Snake(snakes.get(0).getOutlineasPoints(), ID);
130
131
132 endFrame = snakes.get(snakes.size() - 1).getFrame();
133 LOGGER.debug("Added" + this.toString());
134 }
135
136
137
138
139
140
141 public void storeLiveSnake(int frame) {
142 finalSnakes[frame - startFrame] = null;
143 finalSnakes[frame - startFrame] = new Snake(liveSnake, ID);
144 }
145
146
147
148
149
150
151
152
153
154
155
156 public void backupLiveSnake(int frame) {
157 LOGGER.trace("Stored live snake in frame " + frame + " ID " + ID);
158 segSnakes[frame - startFrame] = null;
159 segSnakes[frame - startFrame] = new Snake(liveSnake, ID);
160 }
161
162
163
164
165
166
167
168 public void storeThisSnake(final Snake snake, int frame) {
169 finalSnakes[frame - startFrame] = null;
170 finalSnakes[frame - startFrame] = new Snake(snake, ID);
171 }
172
173
174
175
176
177
178
179 public void backupThisSnake(final Snake snake, int frame) {
180 segSnakes[frame - startFrame] = null;
181 segSnakes[frame - startFrame] = new Snake(snake, ID);
182 }
183
184
185
186
187 public void copyFromSegToFinal() {
188 for (int i = 0; i < segSnakes.length; i++) {
189 if (segSnakes[i] == null) {
190 finalSnakes[i] = null;
191 } else {
192 finalSnakes[i] = new Snake(segSnakes[i]);
193 }
194 }
195 }
196
197
198
199
200 public void copyFromFinalToSeg() {
201 for (int i = 0; i < finalSnakes.length; i++) {
202 if (finalSnakes[i] == null) {
203 segSnakes[i] = null;
204 } else {
205 segSnakes[i] = new Snake(finalSnakes[i]);
206 }
207 }
208 }
209
210
211
212
213
214
215 public void copyFromFinalToLive(int frame) {
216 if (finalSnakes[frame - startFrame] == null) {
217 return;
218 }
219 liveSnake = new Snake(finalSnakes[frame - startFrame]);
220
221 }
222
223
224
225
226
227
228
229
230 public boolean writeSnakes() throws IOException {
231 String snakeOutFile = BOA_.qState.boap.deductSnakeFileName(ID);
232 LOGGER.debug("Write " + FileExtensions.snakeFileExt + " at: " + snakeOutFile);
233 PrintWriter pw = new PrintWriter(new FileWriter(snakeOutFile), true);
234 pw.write("#QuimP11 Node data");
235 pw.write("\n#Node Position\tX-coord\tY-coord\tOrigin\tG-Origin\tSpeed");
236 pw.write("\tFluor_Ch1\tCh1_x\tCh1_y\tFluor_Ch2\tCh2_x\tCh2_y\tFluor_CH3\tCH3_x\tCh3_y\n#");
237
238 Snake s;
239 for (int i = startFrame; i <= endFrame; i++) {
240 s = getStoredSnake(i);
241 s.setPositions();
242 pw.write("\n#Frame " + i);
243 write(pw, i + 1, s.getNumPoints(), s.getHead());
244 }
245 pw.close();
246 BOA_.qState.writeParams(ID, startFrame, endFrame);
247
248 if (BOA_.qState.boap.oldFormat) {
249 writeOldFormats();
250 }
251 return true;
252 }
253
254
255
256
257
258
259
260
261
262 private void write(final PrintWriter pw, int frame, int nodes, Node n) {
263 pw.print("\n" + nodes);
264
265 do {
266
267 pw.print("\n" + IJ.d2s(n.position, 6) + "\t" + IJ.d2s(n.getX(), 2) + "\t"
268 + IJ.d2s(n.getY(), 2) + "\t0\t0\t0" + "\t-2\t-2\t-2\t-2\t-2\t-2\t-2\t-2\t-2");
269 n = n.getNext();
270 } while (!n.isHead());
271
272 }
273
274
275
276
277
278
279 private void writeOldFormats() throws IOException {
280
281 File old = new File(BOA_.qState.boap.getOutputFileCore().getParent(),
282 BOA_.qState.boap.getFileName() + ".dat");
283 PrintWriter pw = new PrintWriter(new FileWriter(old), true);
284
285 for (int i = 0; i < finalSnakes.length; i++) {
286 if (finalSnakes[i] == null) {
287 break;
288 }
289 if (i != 0) {
290 pw.print("\n");
291 }
292 pw.print(finalSnakes[i].getNumPoints());
293
294 Node n = finalSnakes[i].getHead();
295 do {
296 pw.print("\n" + IJ.d2s(n.getX(), 6));
297 pw.print("\n" + IJ.d2s(n.getY(), 6));
298 n = n.getNext();
299 } while (!n.isHead());
300 }
301 pw.close();
302
303 old = new File(BOA_.qState.boap.getOutputFileCore().getParent(),
304 BOA_.qState.boap.getFileName() + ".dat_tn");
305 pw = new PrintWriter(new FileWriter(old), true);
306
307 for (int i = 0; i < finalSnakes.length; i++) {
308 if (finalSnakes[i] == null) {
309 break;
310 }
311 if (i != 0) {
312 pw.print("\n");
313 }
314 pw.print(finalSnakes[i].getNumPoints());
315
316 Node n = finalSnakes[i].getHead();
317 do {
318 pw.print("\n" + IJ.d2s(n.getX(), 6));
319 pw.print("\n" + IJ.d2s(n.getY(), 6));
320 pw.print("\n" + n.getTrackNum());
321 n = n.getNext();
322 } while (!n.isHead());
323 }
324 pw.close();
325
326 old = new File(BOA_.qState.boap.getOutputFileCore().getParent(),
327 BOA_.qState.boap.getFileName() + ".dat1");
328 pw = new PrintWriter(new FileWriter(old), true);
329
330 pw.print(IJ.d2s(BOA_.qState.boap.NMAX, 6) + "\n");
331 pw.print(IJ.d2s(BOA_.qState.boap.delta_t, 6) + "\n");
332 pw.print(IJ.d2s(BOA_.qState.segParam.max_iterations, 6) + "\n");
333 pw.print(IJ.d2s(BOA_.qState.segParam.getMin_dist(), 6) + "\n");
334 pw.print(IJ.d2s(BOA_.qState.segParam.getMax_dist(), 6) + "\n");
335 pw.print(IJ.d2s(BOA_.qState.segParam.blowup, 6) + "\n");
336 pw.print(IJ.d2s(BOA_.qState.segParam.sample_tan, 6) + "\n");
337 pw.print(IJ.d2s(BOA_.qState.segParam.sample_norm, 6) + "\n");
338 pw.print(IJ.d2s(BOA_.qState.segParam.vel_crit, 6) + "\n");
339 pw.print(IJ.d2s(BOA_.qState.segParam.f_central, 6) + "\n");
340 pw.print(IJ.d2s(BOA_.qState.segParam.f_contract, 6) + "\n");
341 pw.print(IJ.d2s(BOA_.qState.boap.f_friction, 6) + "\n");
342 pw.print(IJ.d2s(BOA_.qState.segParam.f_image, 6) + "\n");
343 pw.print(IJ.d2s(1.0, 6) + "\n");
344 pw.print(IJ.d2s(BOA_.qState.boap.sensitivity, 6) + "\n");
345 pw.print(IJ.d2s(BOA_.qState.boap.cut_every, 6) + "\n");
346 pw.print("100");
347
348 pw.close();
349 }
350
351
352
353
354
355
356 public Snake getLiveSnake() {
357 return liveSnake;
358 }
359
360
361
362
363
364
365
366 public Snake getBackupSnake(int f) {
367 LOGGER.trace("Asked for backup snake at frame " + f + " ID " + ID);
368 if (f - startFrame < 0) {
369 LOGGER.info("Tried to access negative frame store: frame: " + f + ", snakeID: " + ID);
370 return null;
371 }
372 return segSnakes[f - startFrame];
373 }
374
375
376
377
378
379
380
381 public Snake getStoredSnake(int f) {
382 if (f - startFrame < 0) {
383 LOGGER.info("Tried to access negative frame store: frame: " + f + ", snakeID: " + ID);
384 return null;
385 }
386 return finalSnakes[f - startFrame];
387 }
388
389
390
391
392
393
394
395 boolean isStoredAt(int f) {
396 if (f - startFrame < 0) {
397 return false;
398 } else if (f - startFrame >= finalSnakes.length) {
399 return false;
400 } else if (finalSnakes[f - startFrame] == null) {
401 return false;
402 } else {
403 return true;
404 }
405
406 }
407
408
409
410
411
412
413
414
415
416
417
418 @Deprecated
419 public int snakeReader(final File inFile) throws Exception {
420 String thisLine;
421 int nn;
422 int index;
423 double x;
424 double y;
425 Node head;
426 Node n;
427 Node prevn;
428 int s = 0;
429 BufferedReader br = null;
430
431 try {
432 br = new BufferedReader(new FileReader(inFile));
433
434 while ((thisLine = br.readLine()) != null) {
435 index = 0;
436 head = new Node(index);
437 head.setHead(true);
438 prevn = head;
439 index++;
440
441 nn = (int) QuimpToolsCollection.s2d(thisLine);
442
443 for (int i = 0; i < nn; i++) {
444 x = QuimpToolsCollection.s2d(br.readLine());
445 y = QuimpToolsCollection.s2d(br.readLine());
446
447 n = new Node(index);
448 n.setX(x);
449 n.setY(y);
450 index++;
451
452 prevn.setNext(n);
453 n.setPrev(prevn);
454
455 prevn = n;
456
457 }
458
459 prevn.setNext(head);
460 head.setPrev(prevn);
461
462 finalSnakes[s] = new Snake(head, nn + 1, ID);
463
464
465
466 finalSnakes[s].removeNode(head);
467 s++;
468 }
469 } catch (IOException e) {
470 System.err.println("Error: " + e);
471 } finally {
472 if (br != null) {
473 try {
474 br.close();
475 } catch (Exception e) {
476 e.printStackTrace();
477 }
478 }
479 }
480
481 return 1;
482 }
483
484
485
486
487 public void revive() {
488 liveSnake.alive = true;
489 }
490
491
492
493
494 public void kill() {
495 liveSnake.alive = false;
496 }
497
498
499
500
501
502
503 public void reset() throws BoaException {
504 liveSnake = new Snake(roi, ID, false);
505 }
506
507
508
509
510
511
512 public int getID() {
513 return ID;
514 }
515
516
517
518
519
520
521 public boolean isLive() {
522 return liveSnake.alive;
523 }
524
525
526
527
528
529
530 void deleteStoreAt(int frame) {
531 if (frame - startFrame < 0) {
532 BOA_.log("Tried to delete negative frame store\n\tframe:" + frame + "\n\tsnakeID:" + ID);
533 } else {
534 finalSnakes[frame - startFrame] = null;
535 segSnakes[frame - startFrame] = null;
536 }
537 }
538
539
540
541
542
543
544 void deleteStoreFrom(int frame) {
545 for (int i = frame; i <= BOA_.qState.boap.getFrames(); i++) {
546 deleteStoreAt(i);
547 }
548 endFrame = frame;
549 }
550
551
552
553
554
555
556
557
558
559 void resetForFrame(int f) {
560 try {
561 if (BOA_.qState.segParam.use_previous_snake) {
562
563 liveSnake = new Snake((PolygonRoi) this.getStoredSnake(f - 1).asFloatRoi(), ID);
564 } else {
565 liveSnake = new Snake(roi, ID, false);
566 }
567 } catch (Exception e) {
568 BOA_.log("Could not reset live snake form frame" + f);
569 LOGGER.debug(e.getMessage(), e);
570 }
571 }
572
573
574
575
576
577
578
579 void storeRoi(final PolygonRoi r, int frame) {
580 try {
581 Snakeimp/Snake.html#Snake">Snake snake = new Snake(r, ID);
582 snake.calcCentroid();
583 this.deleteStoreAt(frame);
584 storeThisSnake(snake, frame);
585 backupThisSnake(snake, frame);
586
587 } catch (Exception e) {
588 BOA_.log("Could not store ROI");
589 LOGGER.debug(e.getMessage(), e);
590 }
591 }
592
593
594
595
596 void findLastFrame() {
597 for (int i = startFrame; i <= BOA_.qState.boap.getFrames(); i++) {
598 if (!isStoredAt(i)) {
599 endFrame = i - 1;
600 return;
601 }
602 }
603 endFrame = BOA_.qState.boap.getFrames();
604 }
605
606
607
608
609
610
611
612
613
614
615 public boolean isSnakeHandlerFrozen() {
616 return snakeHandlerFrozen;
617 }
618
619
620
621
622
623
624
625
626 public void freezeHandler() {
627 snakeHandlerFrozen = true;
628 }
629
630
631
632
633
634
635
636
637 public void unfreezeHandler() {
638 snakeHandlerFrozen = false;
639 }
640
641
642
643
644
645
646 @Override
647 public String toString() {
648 return "SnakeHandler [liveSnake=" + liveSnake + ", finalSnakes=" + Arrays.toString(finalSnakes)
649 + ", ID=" + ID + ", startFrame=" + startFrame + ", endFrame=" + endFrame + "]";
650 }
651
652
653
654
655 @Override
656 public void beforeSerialize() {
657 if (liveSnake != null) {
658 liveSnake.beforeSerialize();
659 }
660 for (Snake s : finalSnakes) {
661 if (s != null) {
662 s.beforeSerialize();
663 }
664 }
665 for (Snake s : segSnakes) {
666 if (s != null) {
667 s.beforeSerialize();
668 }
669 }
670 findLastFrame();
671 }
672
673
674
675
676 @Override
677 public void afterSerialize() throws Exception {
678 if (liveSnake != null) {
679 liveSnake.afterSerialize();
680 }
681 for (Snake s : finalSnakes) {
682 if (s != null) {
683 s.afterSerialize();
684 }
685 }
686 for (Snake s : segSnakes) {
687 if (s != null) {
688 s.afterSerialize();
689 }
690 }
691
692 if (segSnakes.length > 0) {
693 int i = 0;
694 while (i < segSnakes.length && segSnakes[i++] == null) {
695 ;
696 }
697 QuimpDataConverter/utils/QuimpDataConverter.html#QuimpDataConverter">QuimpDataConverter dc = new QuimpDataConverter(segSnakes[--i]);
698
699 roi = new PolygonRoi(dc.getFloatX(), dc.getFloatY(), Roi.FREEROI);
700 }
701 }
702 }