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.nio.file.Path;
10 import java.nio.file.Paths;
11 import java.util.ArrayList;
12 import java.util.Random;
13
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import com.github.celldynamics.quimp.BOAState.BOAp;
18 import com.github.celldynamics.quimp.filesystem.FileExtensions;
19 import com.github.celldynamics.quimp.utils.QuimpToolsCollection;
20
21 import ij.IJ;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class QParams {
48
49
50
51
52 static final Logger LOGGER = LoggerFactory.getLogger(QParams.class.getName());
53
54
55
56
57 public static final int OLD_QUIMP = 1;
58
59
60
61
62 public static final int QUIMP_11 = 2;
63
64
65
66
67 public static final int NEW_QUIMP = 3;
68
69
70
71 private File paramFile;
72
73
74
75 protected int paramFormat;
76
77
78
79
80
81
82 private String fileName;
83
84
85
86
87
88 private String path;
89 private File segImageFile;
90 private File snakeQP;
91
92
93
94
95 protected File statsQP;
96
97
98
99
100 public File[] fluTiffs;
101
102 private File convexFile;
103 private File coordFile;
104 private File motilityFile;
105 private File originFile;
106 private File xmapFile;
107 private File ymapFile;
108 private File[] fluFiles;
109
110 private double imageScale;
111 private double frameInterval;
112 private int startFrame;
113 private int endFrame;
114
115 private int blowup;
116 private double nodeRes;
117
118 int nmax;
119 int maxIterations;
120 int sampleTan;
121 int sampleNorm;
122
123 double deltaT;
124 double velCrit;
125 double centralForce;
126 double contractForce;
127 double imageForce;
128 double frictionForce;
129
130
131
132
133 public double finalShrink;
134
135
136
137 public double cortexWidth;
138
139
140
141
142 long key;
143
144
145
146
147 double sensitivity;
148
149
150
151 private boolean ecmmHasRun = false;
152
153
154
155
156
157
158 public boolean isEcmmHasRun() {
159 return ecmmHasRun;
160 }
161
162
163
164
165 public QParams() {
166
167 }
168
169
170
171
172
173
174 public QParams(File p) {
175 setParamFile(p);
176
177 paramFormat = QParams.QUIMP_11;
178
179 segImageFile = new File("/");
180 snakeQP = new File("/");
181 statsQP = new File("/");
182
183 fluTiffs = new File[3];
184 fluTiffs[0] = new File("/");
185 fluTiffs[1] = new File("/");
186 fluTiffs[2] = new File("/");
187
188 imageScale = -1;
189 frameInterval = -1;
190 startFrame = -1;
191 endFrame = -1;
192 nmax = -1;
193 blowup = -1;
194 maxIterations = -1;
195 sampleTan = -1;
196 sampleNorm = -1;
197 deltaT = -1;
198 nodeRes = -1;
199 velCrit = -1;
200 centralForce = -1;
201 contractForce = -1;
202 imageForce = -1;
203 frictionForce = -1;
204 finalShrink = -1;
205 cortexWidth = 0.7;
206 key = -1;
207 sensitivity = -1;
208 }
209
210
211
212
213
214
215
216 public File getParamFile() {
217 return paramFile;
218 }
219
220
221
222
223
224
225 public void setParamFile(File paramFile) {
226 fileName = QuimpToolsCollection.removeExtension(paramFile.getName());
227 this.paramFile = paramFile;
228 path = paramFile.getParent();
229
230
231 if (path == null) {
232 throw new IllegalArgumentException("Input file: " + paramFile
233 + " must contain path as other files will be created in its folder");
234 }
235 }
236
237
238
239
240
241
242
243
244 public String getFileName() {
245 return fileName;
246 }
247
248
249
250
251
252
253 public String getPath() {
254 return path;
255 }
256
257
258
259
260
261
262
263 public Path getPathasPath() {
264 return Paths.get(this.getPath());
265 }
266
267
268
269
270
271
272 public double getNodeRes() {
273 return nodeRes;
274 }
275
276
277
278
279
280
281 public void setNodeRes(double nodeRes) {
282 this.nodeRes = nodeRes;
283 }
284
285
286
287
288
289
290 public int getBlowup() {
291 return blowup;
292 }
293
294
295
296
297
298
299 public void setBlowup(int blowup) {
300 this.blowup = blowup;
301 }
302
303
304
305
306
307
308 public double getImageScale() {
309 return imageScale;
310 }
311
312
313
314
315
316
317 public void setImageScale(double imageScale) {
318 this.imageScale = imageScale;
319 }
320
321
322
323
324
325
326 public double getFrameInterval() {
327 return frameInterval;
328 }
329
330
331
332
333
334
335 public void setFrameInterval(double frameInterval) {
336 this.frameInterval = frameInterval;
337 }
338
339
340
341
342
343
344 public int getStartFrame() {
345 return startFrame;
346 }
347
348
349
350
351
352
353 public void setStartFrame(int startFrame) {
354 this.startFrame = startFrame;
355 }
356
357
358
359
360
361
362 public int getEndFrame() {
363 return endFrame;
364 }
365
366
367
368
369
370
371 public void setEndFrame(int endFrame) {
372 this.endFrame = endFrame;
373 }
374
375
376
377
378
379
380 public File getSnakeQP() {
381 return snakeQP;
382 }
383
384
385
386
387
388
389 public void setSnakeQP(File snakeQP) {
390 this.snakeQP = snakeQP;
391 }
392
393
394
395
396
397
398 public File getStatsQP() {
399 return statsQP;
400 }
401
402
403
404
405
406
407 public File[] getFluFiles() {
408 return fluFiles;
409 }
410
411
412
413
414
415
416 public void setStatsQP(File statsQP) {
417 this.statsQP = statsQP;
418 }
419
420
421
422
423
424
425 public File getSegImageFile() {
426 return segImageFile;
427 }
428
429
430
431
432
433
434 public void setSegImageFile(File segImageFile) {
435 this.segImageFile = segImageFile;
436 }
437
438
439
440
441
442
443 public File getConvexFile() {
444 return convexFile;
445 }
446
447
448
449
450
451
452 public void setConvexFile(File convexFile) {
453 this.convexFile = convexFile;
454 }
455
456
457
458
459
460
461 public File getCoordFile() {
462 return coordFile;
463 }
464
465
466
467
468
469
470 public void setCoordFile(File coordFile) {
471 this.coordFile = coordFile;
472 }
473
474
475
476
477
478
479 public File getMotilityFile() {
480 return motilityFile;
481 }
482
483
484
485
486
487
488 public void setMotilityFile(File motilityFile) {
489 this.motilityFile = motilityFile;
490 }
491
492
493
494
495
496
497 public File getOriginFile() {
498 return originFile;
499 }
500
501
502
503
504
505
506 public void setOriginFile(File originFile) {
507 this.originFile = originFile;
508 }
509
510
511
512
513
514
515 public File getxmapFile() {
516 return xmapFile;
517 }
518
519
520
521
522
523
524 public void setxmapFile(File xmapFile) {
525 this.xmapFile = xmapFile;
526 }
527
528
529
530
531
532
533 public File getymapFile() {
534 return ymapFile;
535 }
536
537
538
539
540
541
542 public void setymapFile(File ymapFile) {
543 this.ymapFile = ymapFile;
544 }
545
546
547
548
549
550
551 public int getParamFormat() {
552 return paramFormat;
553 }
554
555
556
557
558
559
560
561
562
563
564 public void readParams() throws QuimpException {
565 paramFormat = QParams.OLD_QUIMP;
566 BufferedReader d = null;
567 try {
568 d = new BufferedReader(new FileReader(paramFile));
569
570 String l = d.readLine();
571 if (l == null) {
572 throw new IllegalStateException(
573 "File " + paramFile.getAbsolutePath() + " seems to be empty");
574 }
575 if (!(l.length() < 2)) {
576 String fileID = l.substring(0, 2);
577 if (!fileID.equals("#p")) {
578 throw new QuimpException("Not compatible paramater file");
579 }
580 } else {
581 throw new QuimpException("Not compatible paramater file");
582 }
583 key = (long) QuimpToolsCollection.s2d(d.readLine());
584 segImageFile = new File(d.readLine());
585
586 String sn = d.readLine();
587
588 if (!l.substring(0, 3).equals("#p2")) {
589 sn = sn.substring(1);
590
591
592 int lastDot = sn.lastIndexOf(".");
593
594 String tempS = sn.substring(0, lastDot);
595 statsQP = new File(paramFile.getParent() + tempS + FileExtensions.statsFileExt);
596 }
597 snakeQP = new File(paramFile.getParent() + "" + sn);
598 LOGGER.debug("snake file: " + snakeQP.getAbsolutePath());
599
600 d.readLine();
601 imageScale = QuimpToolsCollection.s2d(d.readLine());
602 if (imageScale == 0) {
603 IJ.log("Warning. Image scale was zero. Set to 1");
604 imageScale = 1;
605 }
606 frameInterval = QuimpToolsCollection.s2d(d.readLine());
607
608 d.readLine();
609 nmax = (int) QuimpToolsCollection.s2d(d.readLine());
610 deltaT = QuimpToolsCollection.s2d(d.readLine());
611 maxIterations = (int) QuimpToolsCollection.s2d(d.readLine());
612 nodeRes = QuimpToolsCollection.s2d(d.readLine());
613 blowup = (int) QuimpToolsCollection.s2d(d.readLine());
614 sampleTan = (int) QuimpToolsCollection.s2d(d.readLine());
615 sampleNorm = (int) QuimpToolsCollection.s2d(d.readLine());
616 velCrit = QuimpToolsCollection.s2d(d.readLine());
617
618 centralForce = QuimpToolsCollection.s2d(d.readLine());
619 contractForce = QuimpToolsCollection.s2d(d.readLine());
620 frictionForce = QuimpToolsCollection.s2d(d.readLine());
621 imageForce = QuimpToolsCollection.s2d(d.readLine());
622 sensitivity = QuimpToolsCollection.s2d(d.readLine());
623
624 if (l.substring(0, 3).equals("#p2")) {
625 paramFormat = QParams.QUIMP_11;
626
627
628
629 d.readLine();
630 cortexWidth = QuimpToolsCollection.s2d(d.readLine());
631 startFrame = (int) QuimpToolsCollection.s2d(d.readLine());
632 endFrame = (int) QuimpToolsCollection.s2d(d.readLine());
633 finalShrink = QuimpToolsCollection.s2d(d.readLine());
634 statsQP = new File(paramFile.getParent() + "" + d.readLine());
635
636 d.readLine();
637 fluTiffs[0] = new File(d.readLine());
638 fluTiffs[1] = new File(d.readLine());
639 fluTiffs[2] = new File(d.readLine());
640 }
641 this.guessOtherFileNames();
642
643 ecmmHasRun = verifyEcmminpsnQP();
644 if (ecmmHasRun) {
645 LOGGER.info("ECMM has been run on this paFile data");
646 }
647 } catch (IOException e) {
648 throw new QuimpException(e);
649 } finally {
650 try {
651 if (d != null) {
652 d.close();
653 }
654 } catch (IOException e) {
655 LOGGER.error("Can not close file " + e);
656 }
657 }
658 }
659
660
661
662
663
664
665 public void writeParams() throws IOException {
666 LOGGER.debug("Write " + FileExtensions.configFileExt + " at: " + paramFile);
667 if (paramFile.exists()) {
668 paramFile.delete();
669 }
670
671 Random generator = new Random();
672 double d = generator.nextDouble() * 1000000;
673 key = Math.round(d);
674
675 PrintWriter ppW = new PrintWriter(new FileWriter(paramFile), true);
676
677 ppW.print("#p2 - QuimP parameter file (QuimP11). Created " + QuimpToolsCollection.dateAsString()
678 + "\n");
679 ppW.print(IJ.d2s(key, 0) + "\n");
680 ppW.print(segImageFile.getAbsolutePath() + "\n");
681 ppW.print(File.separator + snakeQP.getName() + "\n");
682
683
684 ppW.print("#Image calibration (scale, frame interval)\n");
685 ppW.print(IJ.d2s(imageScale, 6) + "\n");
686 ppW.print(IJ.d2s(frameInterval, 3) + "\n");
687
688
689 ppW.print("#segmentation parameters (" + "Maximum number of nodes, " + "ND, "
690 + "Max iterations, " + "Node spacing, " + "Blowup, " + "Sample tan, " + "Sample norm, "
691 + "Crit velocity, " + "Central F, " + "Contract F, " + "ND, " + "Image force, "
692 + "ND)\n");
693 ppW.print(IJ.d2s(nmax, 0) + "\n");
694 ppW.print(IJ.d2s(deltaT, 6) + "\n");
695 ppW.print(IJ.d2s(maxIterations, 6) + "\n");
696 ppW.print(IJ.d2s(nodeRes, 6) + "\n");
697 ppW.print(IJ.d2s(blowup, 6) + "\n");
698 ppW.print(IJ.d2s(sampleTan, 0) + "\n");
699 ppW.print(IJ.d2s(sampleNorm, 0) + "\n");
700 ppW.print(IJ.d2s(velCrit, 6) + "\n");
701 ppW.print(IJ.d2s(centralForce, 6) + "\n");
702 ppW.print(IJ.d2s(contractForce, 6) + "\n");
703 ppW.print(IJ.d2s(frictionForce, 6) + "\n");
704 ppW.print(IJ.d2s(imageForce, 6) + "\n");
705 ppW.print(IJ.d2s(sensitivity, 6) + "\n");
706
707 ppW.print("# - new parameters (cortex width, start frame, end frame,"
708 + " final shrink, statsQP, fluImage)\n");
709 ppW.print(IJ.d2s(cortexWidth, 2) + "\n");
710 ppW.print(IJ.d2s(startFrame, 0) + "\n");
711 ppW.print(IJ.d2s(endFrame, 0) + "\n");
712 ppW.print(IJ.d2s(finalShrink, 2) + "\n");
713 ppW.print(File.separator + statsQP.getName() + "\n");
714
715 ppW.print("# - Fluorescence channel tiff's\n");
716 ppW.print(fluTiffs[0].getAbsolutePath() + "\n");
717 ppW.print(fluTiffs[1].getAbsolutePath() + "\n");
718 ppW.print(fluTiffs[2].getAbsolutePath() + "\n");
719
720 ppW.print("#END");
721
722 ppW.close();
723 }
724
725
726
727
728
729
730
731
732
733
734
735 public File[] findParamFiles() {
736 File[] otherPaFiles;
737 File directory = new File(path);
738 ArrayList<String> paFiles = new ArrayList<String>();
739
740 if (directory.isDirectory()) {
741 String[] filenames = directory.list();
742 if (filenames == null) {
743 otherPaFiles = new File[0];
744 return otherPaFiles;
745 }
746 String extension;
747
748 for (int i = 0; i < filenames.length; i++) {
749 if (filenames[i].matches("\\.") || filenames[i].matches("\\.\\.")
750 || filenames[i].matches(paramFile.getName())) {
751 continue;
752 }
753 extension = QuimpToolsCollection.getFileExtension(filenames[i]);
754 if (extension.matches(FileExtensions.configFileExt.substring(1))) {
755 paFiles.add(filenames[i]);
756 LOGGER.info("paFile: " + filenames[i]);
757 }
758 }
759 }
760 if (paFiles.isEmpty()) {
761 otherPaFiles = new File[0];
762 return otherPaFiles;
763 } else {
764 otherPaFiles = new File[paFiles.size()];
765 for (int j = 0; j < otherPaFiles.length; j++) {
766 otherPaFiles[j] =
767 new File(directory.getAbsolutePath() + File.separator + (String) paFiles.get(j));
768 }
769 return otherPaFiles;
770 }
771 }
772
773
774
775
776
777 protected void guessOtherFileNames() {
778 LOGGER.debug("prefix: " + fileName);
779
780 convexFile = new File(path + File.separator + fileName + FileExtensions.convmapFileExt);
781
782 coordFile = new File(path + File.separator + fileName + FileExtensions.coordmapFileExt);
783 motilityFile = new File(path + File.separator + fileName + FileExtensions.motmapFileExt);
784 originFile = new File(path + File.separator + fileName + FileExtensions.originmapFileExt);
785 xmapFile = new File(path + File.separator + fileName + FileExtensions.xmapFileExt);
786 ymapFile = new File(path + File.separator + fileName + FileExtensions.ymapFileExt);
787
788 fluFiles = new File[3];
789 fluFiles[0] = new File(
790 path + File.separator + fileName + FileExtensions.fluomapFileExt.replace('%', '1'));
791 fluFiles[1] = new File(
792 path + File.separator + fileName + FileExtensions.fluomapFileExt.replace('%', '2'));
793 fluFiles[2] = new File(
794 path + File.separator + fileName + FileExtensions.fluomapFileExt.replace('%', '3'));
795
796 }
797
798
799
800
801
802
803
804
805
806 public boolean verifyEcmminpsnQP() throws IOException {
807 BufferedReader br = new BufferedReader(new FileReader(snakeQP));
808 String line = br.readLine();
809 if (line == null) {
810 br.close();
811 throw new IllegalStateException("File " + snakeQP + " seems to be empty");
812 }
813 br.close();
814 return line.contains("-ECMM");
815 }
816
817 }