1 package com.github.celldynamics.quimp.plugin.ana;
2
3 import java.awt.AWTEvent;
4 import java.awt.Checkbox;
5 import java.awt.Choice;
6 import java.awt.Color;
7 import java.awt.Polygon;
8 import java.io.File;
9 import java.io.IOException;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import com.github.celldynamics.quimp.CellStats;
17 import com.github.celldynamics.quimp.FrameStatistics;
18 import com.github.celldynamics.quimp.Outline;
19 import com.github.celldynamics.quimp.OutlineHandler;
20 import com.github.celldynamics.quimp.QParams;
21 import com.github.celldynamics.quimp.QParamsQconf;
22 import com.github.celldynamics.quimp.QuimP;
23 import com.github.celldynamics.quimp.QuimpException;
24 import com.github.celldynamics.quimp.QuimpException.MessageSinkTypes;
25 import com.github.celldynamics.quimp.Vert;
26 import com.github.celldynamics.quimp.filesystem.ANAParamCollection;
27 import com.github.celldynamics.quimp.filesystem.DataContainer;
28 import com.github.celldynamics.quimp.filesystem.OutlinesCollection;
29 import com.github.celldynamics.quimp.filesystem.converter.FormatConverter;
30 import com.github.celldynamics.quimp.geom.ExtendedVector2d;
31 import com.github.celldynamics.quimp.plugin.AbstractPluginQconf;
32 import com.github.celldynamics.quimp.plugin.QuimpPluginException;
33 import com.github.celldynamics.quimp.plugin.ecmm.ECMM_Mapping;
34 import com.github.celldynamics.quimp.plugin.ecmm.ECMp;
35 import com.github.celldynamics.quimp.plugin.ecmm.ODEsolver;
36 import com.github.celldynamics.quimp.utils.QuimPArrayUtils;
37 import com.github.celldynamics.quimp.utils.QuimpToolsCollection;
38
39 import ij.IJ;
40 import ij.ImagePlus;
41 import ij.Prefs;
42 import ij.WindowManager;
43 import ij.gui.DialogListener;
44 import ij.gui.GenericDialog;
45 import ij.gui.Overlay;
46 import ij.gui.PointRoi;
47 import ij.gui.PolygonRoi;
48 import ij.gui.Roi;
49 import ij.gui.YesNoCancelDialog;
50 import ij.measure.Measurements;
51 import ij.measure.ResultsTable;
52 import ij.plugin.Converter;
53 import ij.plugin.filter.Analyzer;
54 import ij.process.ImageProcessor;
55 import ij.process.ImageStatistics;
56
57
58
59
60
61
62 public class ANA_ extends AbstractPluginQconf implements DialogListener {
63
64 private static String thisPluginName = "ANA";
65
66
67
68
69 static final Logger LOGGER = LoggerFactory.getLogger(ANA_.class.getName());
70
71 private OutlineHandler oh;
72 private OutlineHandler outputH;
73 private OutlineHandler ecmH;
74 private OutlinesCollection outputOutlineHandlers;
75 private Outline frameOneClone;
76 private ECMM_Mapping ecmMapping;
77 private Overlay overlay;
78
79 private ArrayList<Roi> storedOuterROI;
80 private ArrayList<Roi> storedInnerROI;
81
82 private ImagePlus setupImage;
83 private ImageProcessor orgIpr;
84
85
86
87
88
89
90 private FrameStatistics[] fluoStats;
91 private ANAp anap;
92 private static final int m =
93 Measurements.AREA + Measurements.INTEGRATED_DENSITY + Measurements.MEAN;
94
95
96
97
98 public ANA_() {
99 super(new AnaOptions(), thisPluginName);
100 storedOuterROI = new ArrayList<>();
101 storedInnerROI = new ArrayList<>();
102 anap = new ANAp();
103 ECMp.plot = false;
104 ecmMapping = new ECMM_Mapping(1);
105 }
106
107
108
109
110
111
112 @Override
113 public void run(String arg) {
114
115
116 setupImage = WindowManager.getCurrentImage();
117 if (setupImage == null) {
118 IJ.error("Image required to take fluoresence measurments.");
119 return;
120 }
121 if (setupImage.getOriginalFileInfo() == null
122 || setupImage.getOriginalFileInfo().directory.matches("")) {
123 IJ.log("Error: Fluorescence file needs to be saved to disk");
124 IJ.error("Please save your fluorescence image to file.");
125 return;
126 }
127 Prefs.interpolateScaledImages = false;
128
129 overlay = new Overlay();
130 setupImage.setOverlay(overlay);
131 orgIpr = setupImage.getProcessor();
132 super.run(arg);
133 }
134
135
136
137
138
139
140 @Override
141 protected void executer() throws QuimpException {
142 super.executer();
143
144 if (qconfLoader.getQp() == null) {
145 return;
146 }
147
148 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
149
150 overlay = new Overlay();
151 setupImage.setOverlay(overlay);
152 for (int f = 1; f < setupImage.getStackSize(); f++) {
153 setupImage.setSlice(f);
154 for (OutlineHandler ohTmp : outputOutlineHandlers.oHs) {
155 if (f >= ohTmp.getStartFrame() && f <= ohTmp.getEndFrame()) {
156 Outline o = ohTmp.getStoredOutline(f);
157 if (o == null) {
158 continue;
159 }
160 drawSamplePointsFloat(o, f);
161 setupImage.draw();
162 }
163 }
164 }
165
166 if (opts.plotOutlines) {
167 ImagePlus orgIplclone = setupImage.duplicate();
168 orgIplclone.show();
169 new Converter().run("RGB Color");
170 Overlay overlay = new Overlay();
171 orgIplclone.setOverlay(overlay);
172 for (Roi r : storedOuterROI) {
173 overlay.add(r);
174 }
175 for (Roi r : storedInnerROI) {
176 overlay.add(r);
177 }
178 orgIplclone.draw();
179 }
180
181
182 if (opts.fluoResultTable || opts.fluoResultTableAppend) {
183 if (qconfLoader.isFileLoaded() == QParams.NEW_QUIMP) {
184 ResultsTable rt;
185 if (opts.fluoResultTableAppend) {
186 rt = Analyzer.getResultsTable();
187 } else {
188 rt = new ResultsTable();
189 Analyzer.setResultsTable(rt);
190 }
191
192 for (CellStats cs : qconfLoader.getStats().getStatCollection()) {
193 cs.addFluosToResultTable(rt, opts.channel);
194 }
195 rt.show("Results");
196 } else {
197 LOGGER.warn(
198 "Results can be shown in IJ table only if ANA is started with QCONF file format");
199 }
200 }
201 ecmMapping = null;
202 }
203
204
205
206
207
208
209 @Override
210 protected void validate() throws QuimpException {
211 qconfLoader.getBOA();
212 qconfLoader.getEcmm();
213 qconfLoader.getStats();
214 }
215
216
217
218
219
220
221 @Override
222 public String about() {
223 return "ANA plugin.\n" + "Authors: Piotr Baniukiewicz\n"
224 + "mail: p.baniukiewicz@warwick.ac.uk\n" + "Richard Tyson";
225 }
226
227
228
229
230
231
232 @Override
233 protected void runFromQconf() throws QuimpException {
234 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
235 LOGGER.debug("Processing from new file format");
236 if (apiCall == false && errorSink == MessageSinkTypes.GUI && qconfLoader.isANAPresent()) {
237 YesNoCancelDialog ync;
238 ync = new YesNoCancelDialog(IJ.getInstance(), "Overwrite",
239 "You are about to override previous ANA results. Is it ok?");
240 if (!ync.yesPressed()) {
241 throw new QuimpPluginException("Cancelled - no changes made in input file",
242 MessageSinkTypes.MESSAGE, true);
243 }
244 }
245
246 QParamsQconf/../../../../../com/github/celldynamics/quimp/QParamsQconf.html#QParamsQconf">QParamsQconf qp = (QParamsQconf) qconfLoader.getQp();
247 ANAParamCollection anaStates;
248 OutlinesCollection ecmmState = qp.getLoadedDataContainer().ECMMState;
249 outputOutlineHandlers = new OutlinesCollection(ecmmState.oHs.size());
250 if (qp.getLoadedDataContainer().getANAState() == null) {
251
252 anaStates = new ANAParamCollection(ecmmState.oHs.size());
253 } else {
254 anaStates = qp.getLoadedDataContainer().getANAState();
255 }
256 try {
257
258
259
260 if (qconfLoader.getStats().sHs.isEmpty()) {
261 throw new QuimpPluginException("Stats not found in QCONF file.");
262 }
263 for (int i = 0; i < ecmmState.oHs.size(); i++) {
264
265
266 qp.setActiveHandler(i);
267 oh = ecmmState.oHs.get(i);
268 anap = anaStates.aS.get(i);
269 anap.setup(qconfLoader.getQp());
270
271
272 fluoStats = qconfLoader.getStats().sHs.get(i).framestat.toArray(new FrameStatistics[0]);
273
274 investigateChannels(oh.indexGetOutline(0));
275 if (anap.noData && oh.getSize() == 1) {
276
277 System.out.println("Only one frame. set marker res to 2");
278 oh.indexGetOutline(0).setResolution(anap.oneFrameRes);
279 }
280 setImageScale();
281 setupImage.setSlice(qconfLoader.getQp().getStartFrame());
282
283
284 if (apiCall == false && errorSink != MessageSinkTypes.IJERROR && !anaDialog()) {
285 IJ.log("ANA cancelled");
286 return;
287 } else {
288 frameOneClone = (Outline) oh.indexGetOutline(0).clone();
289 anap.setCortextWidthScale(opts.userScale);
290 if (opts.clearFlu && !anap.cleared) {
291 resetFluo();
292 }
293 }
294 anap.fluTiffs[opts.channel] = new File(setupImage.getOriginalFileInfo().directory,
295 setupImage.getOriginalFileInfo().fileName);
296 outputH = new OutlineHandler(oh);
297 runPlugin();
298
299 if (QuimP.newFileFormat.get() == false || QuimP.newFileFormat.get() == true) {
300 FrameStatistics.write(fluoStats, anap.statFile, anap.scale, anap.frameInterval);
301 }
302 CellStats statH = qconfLoader.getStats().sHs.get(i);
303 statH.framestat = new ArrayList<FrameStatistics>(Arrays.asList(fluoStats));
304 outputOutlineHandlers.oHs.add(i, new OutlineHandler(outputH));
305 }
306
307 DataContainer dc = qp.getLoadedDataContainer();
308 dc.ECMMState = outputOutlineHandlers;
309 dc.ANAState = anaStates;
310 qp.writeParams();
311 } catch (IOException e) {
312 throw new QuimpPluginException(e);
313 }
314
315 if (QuimP.newFileFormat.get() == false) {
316 FormatConverterystem/converter/FormatConverter.html#FormatConverter">FormatConverter foramtConv = new FormatConverter(qconfLoader);
317 foramtConv.doConversion();
318 }
319 IJ.log("The new data file " + qconfLoader.getQp().getParamFile().toString()
320 + " has been updated by results of ECMM analysis.");
321 }
322
323
324
325
326
327
328 @Override
329 protected void runFromPaqp() throws QuimpException {
330 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
331 outputOutlineHandlers = new OutlinesCollection(1);
332 oh = new OutlineHandler(qconfLoader.getQp());
333 try {
334 anap.setup(qconfLoader.getQp());
335 fluoStats = FrameStatistics.read(anap.statFile);
336 investigateChannels(oh.indexGetOutline(0));
337
338 if (anap.noData && oh.getSize() == 1) {
339
340 System.out.println("Only one frame. set marker res to 2");
341 oh.indexGetOutline(0).setResolution(anap.oneFrameRes);
342 }
343
344 setImageScale();
345 setupImage.setSlice(qconfLoader.getQp().getStartFrame());
346 if (!oh.readSuccess) {
347 throw new QuimpException("Could not read OutlineHandler");
348 }
349
350 if (apiCall == false && errorSink != MessageSinkTypes.IJERROR && !anaDialog()) {
351 IJ.log("ANA cancelled");
352 return;
353 } else {
354 frameOneClone = (Outline) oh.indexGetOutline(0).clone();
355 anap.setCortextWidthScale(opts.userScale);
356 if (opts.clearFlu && !anap.cleared) {
357 resetFluo();
358 }
359 }
360 System.out.println("CHannel: " + (opts.channel + 1));
361
362 anap.fluTiffs[opts.channel] = new File(setupImage.getOriginalFileInfo().directory,
363 setupImage.getOriginalFileInfo().fileName);
364
365 outputH = new OutlineHandler(oh.getStartFrame(), oh.getEndFrame());
366 runPlugin();
367
368 anap.inFile.delete();
369 anap.statFile.delete();
370 outputH.writeOutlines(anap.outFile, qconfLoader.getQp().isEcmmHasRun());
371 FrameStatistics.write(fluoStats, anap.statFile, anap.scale, anap.frameInterval);
372
373
374
375
376
377
378
379
380
381
382
383 qconfLoader.getQp().cortexWidth = anap.getCortexWidthScale();
384 qconfLoader.getQp().fluTiffs = anap.fluTiffs;
385 qconfLoader.getQp().writeParams();
386 } catch (IOException e) {
387 throw new QuimpPluginException(e);
388 }
389 outputOutlineHandlers.oHs.add(0, new OutlineHandler(outputH));
390
391 }
392
393
394
395
396
397
398 @Override
399 public void showUi(boolean val) throws Exception {
400
401 executer();
402 if (qconfLoader != null && qconfLoader.getQp() != null) {
403 options.paramFile = qconfLoader.getQp().getParamFile().getAbsolutePath();
404 }
405 }
406
407
408
409
410
411
412 private boolean anaDialog() {
413 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
414 GenericDialog pd = new GenericDialog("ANA Dialog", IJ.getInstance());
415
416 pd.addNumericField("Cortex width (\u00B5m)", anap.getCortexWidthScale(), 2);
417
418 String[] channelC = { "1", "2", "3" };
419 pd.addChoice("Save in channel", channelC, channelC[opts.channel]);
420 pd.addCheckbox("Normalise to interior", opts.normalise);
421 pd.addCheckbox("Sample at Ch" + (anap.useLocFromCh + 1) + " locations", opts.sampleAtSame);
422 pd.addCheckbox("Clear stored measurements", false);
423 pd.addCheckbox("New image with outlines? ", opts.plotOutlines);
424 pd.addCheckbox("Copy results to IJ Table?", opts.fluoResultTable);
425 pd.addCheckbox("Append results to IJ Table?", opts.fluoResultTableAppend);
426 pd.addDialogListener(this);
427
428 frameOneClone = (Outline) oh.indexGetOutline(0).clone();
429 drawOutlineAsOverlay(frameOneClone, Color.RED);
430 shrink(frameOneClone);
431 this.markFrozenNodesNormal(frameOneClone);
432 setupImage.draw();
433 drawOutlineAsOverlay(frameOneClone, Color.RED);
434 pd.showDialog();
435
436 return pd.wasOKed();
437
438 }
439
440
441
442
443
444
445 @Override
446 public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
447
448 if (gd.wasOKed()) {
449 return true;
450 }
451 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
452
453 {
454 Checkbox cb4 = (Checkbox) gd.getCheckboxes().elementAt(4);
455 Checkbox cb5 = (Checkbox) gd.getCheckboxes().elementAt(5);
456 if (e.getSource() == cb4) {
457 if (cb4.getState()) {
458 cb5.setState(false);
459 }
460 }
461 if (e.getSource() == cb5) {
462 if (cb5.getState()) {
463 cb4.setState(false);
464 }
465 }
466 }
467
468 Checkbox cb = (Checkbox) gd.getCheckboxes().elementAt(2);
469 opts.clearFlu = cb.getState();
470 Choice iob = (Choice) gd.getChoices().elementAt(0);
471 if (opts.clearFlu && !anap.cleared) {
472 System.out.println("reset fluo");
473 resetFluo();
474 cb.setLabel("Measurments Cleared");
475 IJ.log("All fluorescence measurements have been cleared");
476 iob.select(0);
477 return true;
478 }
479
480 opts.channel = gd.getNextChoiceIndex();
481 opts.normalise = gd.getNextBoolean();
482 opts.sampleAtSame = gd.getNextBoolean();
483 opts.plotOutlines = ((Checkbox) gd.getCheckboxes().elementAt(3)).getState();
484
485 opts.fluoResultTable = ((Checkbox) gd.getCheckboxes().elementAt(4)).getState();
486 opts.fluoResultTableAppend = ((Checkbox) gd.getCheckboxes().elementAt(5)).getState();
487
488 opts.userScale = gd.getNextNumber();
489 anap.setCortextWidthScale(opts.userScale);
490 if (anap.cleared) {
491 cb.setState(true);
492 }
493
494 frameOneClone = (Outline) oh.indexGetOutline(0).clone();
495 overlay.clear();
496 drawOutlineAsOverlay(frameOneClone, Color.RED);
497 shrink(frameOneClone);
498 this.markFrozenNodesNormal(frameOneClone);
499 setupImage.draw();
500 drawOutlineAsOverlay(frameOneClone, Color.RED);
501 return true;
502 }
503
504
505
506
507 void resetFluo() {
508
509 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
510 Outline o;
511 for (int i = 0; i < oh.getSize(); i++) {
512 o = oh.indexGetOutline(i);
513 o.clearFluores();
514 fluoStats[i].clearFluo();
515 }
516
517 if (oh.getSize() == 1) {
518
519 System.out.println("Only one frame. set marker res to 2");
520 oh.indexGetOutline(0).setResolution(anap.oneFrameRes);
521 }
522
523
524 anap.noData = true;
525 opts.channel = 0;
526 anap.useLocFromCh = -1;
527 anap.presentData[1] = 0;
528 anap.presentData[2] = 0;
529 anap.presentData[0] = 0;
530 anap.fluTiffs[0] = new File("/");
531 anap.fluTiffs[1] = new File("/");
532 anap.fluTiffs[2] = new File("/");
533
534 opts.channel = 0;
535 anap.cleared = true;
536 }
537
538
539
540
541 void setImageScale() {
542 setupImage.getCalibration().frameInterval = anap.frameInterval;
543 setupImage.getCalibration().pixelHeight = anap.scale;
544 setupImage.getCalibration().pixelWidth = anap.scale;
545 }
546
547
548
549
550
551
552
553 private void runPlugin() {
554 Roi outerRoi;
555 Roi innerRoi;
556 Outline o1;
557 Outline s1;
558 Outline s2;
559 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
560 IJ.showStatus("Running ANA (" + oh.getSize() + " frames)");
561 for (int f = oh.getStartFrame(); f <= oh.getEndFrame(); f++) {
562 IJ.log("Frame " + f);
563 IJ.showProgress(f, oh.getEndFrame());
564
565 setupImage.setSlice(f);
566 o1 = oh.getStoredOutline(f);
567
568 s1 = new Outline(o1);
569 s2 = new Outline(o1);
570 shrink(s2);
571
572
573
574
575
576
577
578 overlay = new Overlay();
579 setupImage.setOverlay(overlay);
580 outerRoi = o1.asFloatRoi();
581 innerRoi = s2.asFloatRoi();
582 outerRoi.setPosition(f);
583 outerRoi.setStrokeColor(Color.BLUE);
584 innerRoi.setPosition(f);
585 innerRoi.setStrokeColor(Color.RED);
586
587
588 storedInnerROI.add(innerRoi);
589 storedOuterROI.add(outerRoi);
590 overlay.add(outerRoi);
591 overlay.add(innerRoi);
592
593 Polygon polyS2 = s2.asPolygon();
594 setFluoStats(s1.asPolygon(), polyS2, f);
595
596
597
598 if (opts.sampleAtSame && anap.useLocFromCh != -1) {
599 useGivenSamplepoints(o1);
600 } else {
601
602 ecmH = new OutlineHandler(1, 2);
603 ecmH.setOutline(1, s1);
604 ecmH.setOutline(2, s2);
605
606 ecmH = ecmMapping.runByANA(ecmH, orgIpr, anap.getCortexWidthPixel());
607
608
609
610
611 Vert v = o1.getHead();
612 Vert v2 = ecmH.getStoredOutline(2).getHead();
613
614 while (v2.getTrackNum() != v.getTrackNum()) {
615 v = v.getNext();
616 if (v.isHead()) {
617 IJ.error("ANA fail");
618 break;
619
620 }
621 }
622
623 int vertStart;
624 do {
625 v.setFluoresChannel(v2.fluores[0], opts.channel);
626 v2 = v2.getNext();
627 if (v2.isHead()) {
628 break;
629 }
630 vertStart = v.getTrackNum();
631
632 do {
633 v = v.getNext();
634 v.setFluoresChannel((int) Math.round(v.getX()), (int) Math.round(v.getY()), -1,
635 opts.channel);
636 if (vertStart == v.getTrackNum()) {
637 System.out.println("ANA fail");
638 return;
639 }
640 } while (v2.getTrackNum() != v.getTrackNum());
641 } while (!v2.isHead());
642
643 interpolateFailures(o1);
644 }
645
646 if (opts.normalise) {
647 normalise2Interior(o1, f);
648 }
649 outputH.save(o1, f);
650 }
651 }
652
653 private void shrink(Outline o) {
654
655 o.scaleOutline(anap.getCortexWidthPixel(), -anap.stepRes, anap.angleTh, anap.freezeTh);
656
657 o.unfreezeAll();
658 }
659
660 private void markFrozenNodesNormal(Outline o) {
661 float[] x;
662 float[] y;
663 ExtendedVector2d norm;
664 PolygonRoi pr;
665 Vert v = o.getHead();
666 do {
667 if (v.isFrozen()) {
668 overlay.setStrokeColor(Color.RED);
669 norm = new ExtendedVector2d(v.getX(), v.getY());
670 norm.addVec(v.getNormal());
671
672
673 x = new float[2];
674 y = new float[2];
675
676 x[0] = (float) v.getX();
677 x[1] = (float) norm.getX();
678 y[0] = (float) v.getY();
679 y[1] = (float) norm.getY();
680 pr = new PolygonRoi(x, y, 2, Roi.POLYGON);
681 overlay.add(pr);
682 }
683
684 v = v.getNext();
685 } while (!v.isHead());
686 }
687
688
689
690
691
692
693
694
695
696
697
698 private void setFluoStats(Polygon outerPoly, Polygon innerPoly, int f) {
699 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
700 int store = f - anap.startFrame;
701
702 fluoStats[store].frame = f;
703
704 orgIpr.setRoi(outerPoly);
705
706 ImageStatistics is = ImageStatistics.getStatistics(orgIpr, m, null);
707 double outerAreaRaw = is.area;
708 fluoStats[store].channels[opts.channel].totalFluor = is.mean * outerAreaRaw;
709 fluoStats[store].channels[opts.channel].meanFluor = is.mean;
710
711 orgIpr.setRoi(innerPoly);
712 is = ImageStatistics.getStatistics(orgIpr, m, null);
713
714 fluoStats[store].channels[opts.channel].innerArea =
715 QuimpToolsCollection.areaToScale(is.area, anap.scale);
716 fluoStats[store].channels[opts.channel].totalInnerFluor = is.mean * is.area;
717 fluoStats[store].channels[opts.channel].meanInnerFluor = is.mean;
718
719 fluoStats[store].channels[opts.channel].cortexArea =
720 fluoStats[store].area - fluoStats[store].channels[opts.channel].innerArea;
721 fluoStats[store].channels[opts.channel].totalCorFluo =
722 fluoStats[store].channels[opts.channel].totalFluor
723 - fluoStats[store].channels[opts.channel].totalInnerFluor;
724 fluoStats[store].channels[opts.channel].meanCorFluo =
725 fluoStats[store].channels[opts.channel].totalCorFluo / (outerAreaRaw - is.area);
726
727 fluoStats[store].channels[opts.channel].percCortexFluo =
728 (fluoStats[store].channels[opts.channel].totalCorFluo
729 / fluoStats[store].channels[opts.channel].totalFluor) * 100;
730 fluoStats[store].channels[opts.channel].cortexWidth = anap.getCortexWidthScale();
731 }
732
733 private void normalise2Interior(Outline o, int f) {
734 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
735
736 int store = f - anap.startFrame;
737 Vert v = o.getHead();
738 do {
739 v.fluores[opts.channel].intensity = v.fluores[opts.channel].intensity
740 / fluoStats[store].channels[opts.channel].meanInnerFluor;
741 v = v.getNext();
742 } while (!v.isHead());
743
744 }
745
746 private void drawOutlineAsOverlay(Outline o, Color c) {
747 Roi r = o.asFloatRoi();
748 if (r.subPixelResolution()) {
749 System.out.println("is sub pixel");
750 } else {
751 System.out.println("is not sub pixel");
752 }
753 overlay.setStrokeColor(c);
754 overlay.add(r);
755 setupImage.updateAndDraw();
756 }
757
758 private void investigateChannels(Outline o) {
759
760 int firstEmptyCh = -1;
761 int firstFullCh = -1;
762 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
763
764 anap.presentData = new int[3];
765 anap.noData = true;
766
767 Vert v = o.getHead();
768 for (int i = 0; i < 3; i++) {
769 if (v.fluores[i].intensity == -2) {
770 anap.presentData[i] = 0;
771 if (firstEmptyCh == -1) {
772 firstEmptyCh = i;
773 }
774 } else {
775 anap.presentData[i] = 1;
776 IJ.log("Data exists in channel " + (i + 1));
777 anap.noData = false;
778 if (firstFullCh == -1) {
779 firstFullCh = i;
780 }
781
782 }
783 }
784
785 if (QuimPArrayUtils.sumArray(anap.presentData) == 3) {
786 firstEmptyCh = 0;
787 }
788
789 if (anap.noData) {
790 opts.channel = 0;
791 IJ.log("No previous sample points available.");
792 anap.useLocFromCh = -1;
793 } else {
794 opts.channel = firstEmptyCh;
795 IJ.log("Sample points from channel " + (firstFullCh + 1) + " available.");
796 anap.useLocFromCh = firstFullCh;
797 }
798
799 v = o.getHead();
800 for (int i = 0; i < 3; i++) {
801 if (v.fluores[i].intensity != -2) {
802 anap.setCortextWidthScale(fluoStats[0].channels[i].cortexWidth);
803 }
804 }
805 }
806
807 private void interpolateFailures(Outline o) {
808 Vert v = o.getHead();
809 Vert last;
810 Vert nex;
811 double disLtoN;
812 double disLtoV;
813 double ratio;
814 double intensityDiff;
815 boolean fail;
816 int firstID;
817 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
818 do {
819 fail = false;
820 if (v.fluores[opts.channel].intensity == -1) {
821 IJ.log("\tInterpolated failed node intensity (position: " + v.coord + ")");
822
823
824 last = v.getPrev();
825 firstID = last.getTrackNum();
826 while (last.fluores[opts.channel].intensity == -1) {
827 last = last.getPrev();
828 if (last.getTrackNum() == firstID) {
829 IJ.log("Could not interpolate as all nodes failed");
830 v.fluores[opts.channel].intensity = 0;
831 fail = true;
832 }
833 }
834
835 nex = v.getNext();
836 firstID = nex.getTrackNum();
837 while (nex.fluores[opts.channel].intensity == -1) {
838 nex = nex.getNext();
839 if (nex.getTrackNum() == firstID) {
840 IJ.log("Could not interpolate as all nodes failed");
841 v.fluores[opts.channel].intensity = 0;
842 fail = true;
843 }
844 }
845
846 if (fail) {
847 v = v.getNext();
848 continue;
849 }
850
851 disLtoN = ExtendedVector2d.lengthP2P(last.getPoint(), nex.getPoint());
852 disLtoV = ExtendedVector2d.lengthP2P(last.getPoint(), v.getPoint());
853 ratio = disLtoV / disLtoN;
854 if (ratio > 1) {
855 ratio = 1;
856 }
857 if (ratio < 0) {
858 ratio = 0;
859 }
860 intensityDiff = (nex.fluores[opts.channel].intensity - last.fluores[opts.channel].intensity)
861 * ratio;
862 v.fluores[opts.channel].intensity = last.fluores[opts.channel].intensity + intensityDiff;
863 if (v.fluores[opts.channel].intensity < 0 || v.fluores[opts.channel].intensity > 255) {
864 IJ.log("Error. Interpolated intensity out of range. Set to zero.");
865 v.fluores[opts.channel].intensity = 0;
866 }
867 }
868
869 v = v.getNext();
870 } while (!v.isHead());
871 }
872
873 private void drawSamplePointsFloat(Outline o, int frame) {
874 float x;
875 float y;
876 PointRoi pr;
877 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
878 Vert v = o.getHead();
879 do {
880 x = (float) v.fluores[opts.channel].x;
881 y = (float) v.fluores[opts.channel].y;
882 pr = new PointRoi(x + 0.5, y + 0.5);
883 pr.setPosition(frame);
884 overlay.add(pr);
885 v = v.getNext();
886 } while (!v.isHead());
887 }
888
889
890
891
892
893
894 private void useGivenSamplepoints(Outline o1) {
895 int x;
896 int y;
897 AnaOptions/../../../../../com/github/celldynamics/quimp/plugin/ana/AnaOptions.html#AnaOptions">AnaOptions opts = (AnaOptions) options;
898 Vert v = o1.getHead();
899 do {
900 x = (int) v.fluores[anap.useLocFromCh].x;
901 y = (int) v.fluores[anap.useLocFromCh].y;
902
903 v.fluores[opts.channel].intensity = ODEsolver.sampleFluo(orgIpr, x, y);
904 v.fluores[opts.channel].x = x;
905 v.fluores[opts.channel].y = y;
906 v = v.getNext();
907 } while (!v.isHead());
908
909 }
910 }