diff --git a/src/main/java/averagingND/AverageWithoutZero.java b/src/main/java/averagingND/AverageWithoutZero.java index 779584d..4525330 100644 --- a/src/main/java/averagingND/AverageWithoutZero.java +++ b/src/main/java/averagingND/AverageWithoutZero.java @@ -140,7 +140,7 @@ public static IntervalView averageArray(final ArrayList image, final RandomAccessibleInterval< FloatType > template, final boolean bShowCC)//, boolean bRegisterTemplate) //throws ImgIOException, IncompatibleTypeException + public boolean caclulateGenNormCC(final RandomAccessibleInterval< FloatType > image, final RandomAccessibleInterval< FloatType > template, final boolean bShowCC) { int i; @@ -57,8 +67,6 @@ public boolean caclulateGenNormCC(final RandomAccessibleInterval< FloatType > im IJ.log("Error! Different dimensions of input and template!"); return false; } - - nDim = image.numDimensions(); if(lim_fractions!= null) @@ -269,85 +277,111 @@ public boolean caclulateGenNormCC(final RandomAccessibleInterval< FloatType > im long [][] cropCorr = new long[2][nDim]; + long [][] cropFraction = new long[2][nDim]; - //determine the maximum shift of template with respect to original image, - //assuming that zero shift is when both images' are centered + //determine the maximum area (intervalCrop) of shifts for template with respect to original image double nHalfSpan, nCenter; for(i=0;i ivCCswapped; + //full available shift space + ivCCswapped = Views.interval(Views.translate(Views.extendPeriodic( invF1F2 ), nCCOrigin),intervalFull); + - IntervalView< FloatType > ivCCswapped = Views.interval(Views.translate(Views.extendPeriodic( invF1F2 ), nCCOrigin),intervalCrop); - //IntervalView< FloatType > ivCCswapped = Views.interval(Views.extendPeriodic( invF1F2 ),interval); + //let's apply constrains + + //voxel constrains + if(limInterval != null) + { + FinalInterval intConstrainPx; + //centered, let's move to the center + if(bCenteredLimit) + { + intConstrainPx = Intervals.intersect(ivCCswapped, Intervals.translate(limInterval, nCCOrigin)); + + } + //from the origin, no need to move + else + { + intConstrainPx = Intervals.intersect(ivCCswapped, limInterval); + } + ivCCswapped = Views.interval(ivCCswapped, intConstrainPx); + } + //fractional constrains + if(lim_fractions != null) + { + //centered, let's move to the center + if(bCenteredLimit) + { + constrainFr = Intervals.translate(constrainFr, nCCOrigin); + + } + ivCCswapped = Views.interval(ivCCswapped, constrainFr); + } + + +// if(bCenteredLimit) +// { +// ivCCswapped = Views.interval(Views.extendPeriodic( invF1F2 ),intervalCrop); +// } +// else +// { +// //ivCCswapped = Views.interval(Views.extendPeriodic( invF1F2 ),intervalCrop); +// ivCCswapped = Views.interval(Views.translate(Views.extendPeriodic( invF1F2 ), nCCOrigin),intervalCrop); +// //ivCCswapped = Views.interval(Views.translate(Views.extendPeriodic( invF1F2 ), nCCOrigin),intervalCrop); +// } + if(bShowCC) { - //ImagePlus outIP = ImageJFunctions.wrap(ivCCswapped,"General cross-correlation"); - //Calibration cal = outIP.getCalibration(); - //cal.xOrigin = - //outIP.show(); ImageJFunctions.show(ivCCswapped).setTitle( "General cross-correlation" ); - } - //ImageJFunctions.show(Views.interval( Views.extendPeriodic( invF1F1I2 ),interval)).setTitle( "Denominator" ); - + } //now find max value Point shift = new Point(nDim); + FloatType fCCvalue; fCCvalue = MiscUtils.computeMaxLocation(ivCCswapped,shift); - /* - else - { - //Point shiftZeroX =new Point(nDim-1); - long [] minX = ivCCswapped.minAsLongArray(); - long [] maxX = ivCCswapped.maxAsLongArray(); - minX[0]=0; - maxX[0]=0; - //minX[1]=-179; - //maxX[1]=180; - FinalInterval valX = new FinalInterval(minX,maxX); - //ImageJFunctions.show(Views.interval(ivCCswapped, valX)).setTitle( "XZero" ); - - fCCvalue = MiscUtils.computeMaxLocation(Views.interval(ivCCswapped, valX),shift); - - } - */ - if (bVerbose) { String sOutput = "Translation for template to overlap with image (px):\n("+Integer.toString(shift.getIntPosition(0)) ; @@ -363,6 +397,14 @@ public boolean caclulateGenNormCC(final RandomAccessibleInterval< FloatType > im // final shift of images shift.localize(dShift); +// if(bCenteredLimit) +// { +// //add center position +// for(i=0;i> imgs_shift; + + /** ND shift of each image **/ + ArrayList shifts; + + /** source of images + * 0 - images currently open in ImageJ + * 1 - tif files on disk **/ + public int nInputType = 0; + + /** initial template (alignment of images) + * 0 - centered images + * 1 - zero, origin of coordinates + * **/ + public int nIniTemplate = 0; + + /** total number of iterations **/ public int nIterN = 0; - public boolean bShowIntermediateAverage=false; - - public int nIniTemplate = 0; + /** whether or not generate intermediate average **/ + boolean bIntermediateAverage = false; + + boolean bSaveIntermediate = false; - public int nInput = 0; + String sPathIntermediate = ""; public boolean bExcludeZeros = false; public boolean bOutputInput = false; - - - /** shifted images for average calculation**/ - ArrayList> imgs_shift; - /** shift of each image **/ - ArrayList shifts; - - /** set of images for averaging and information about them **/ - ImageSet imageSet; + /** for now it cannot be changed by user **/ + public boolean bIgnoreZeroInAveraging = true; + /** constrains during the averaging * 0 - no constrains * 1 - constrains in pixels @@ -59,10 +76,15 @@ public class IterativeAveraging implements PlugIn, DialogListener { * **/ public int nConstrainReg = 0; + /** labels of constrain axes **/ Label [] limName; + + /** values of constrain axes **/ TextField [] limVal; + /** dimensions of dataset for averaging (always 1 channel) **/ int nDimReg; + /** format of the input dataset XYZTC **/ String sDims; @@ -74,6 +96,8 @@ public void run(String paramString) { double [] dLimits; + ArrayList> imgs_avrg_out; + //double format formatting toold DecimalFormatSymbols symbols = new DecimalFormatSymbols(); symbols.setDecimalSeparator('.'); @@ -93,8 +117,8 @@ public void run(String paramString) { return; IJ.log("Iterative ND averaging plugin, version " + ConstantsAveragingND.sVersion); - nInput = gdFiles.getNextChoiceIndex(); - Prefs.set("RegisterNDFFT.IA.nInput", sInput[nInput]); + nInputType = gdFiles.getNextChoiceIndex(); + Prefs.set("RegisterNDFFT.IA.nInput", sInput[nInputType]); imageSet = new ImageSet(); @@ -102,7 +126,7 @@ public void run(String paramString) { imgs_shift = new ArrayList>(); shifts = new ArrayList(); - if(nInput == 0) + if(nInputType == 0) { if(!imageSet.initializeFromOpenWindows()) return; @@ -139,7 +163,8 @@ public void run(String paramString) { gd1.addChoice( "Initial template:", sIniTemplate, Prefs.get("RegisterNDFFT.IA.nIniTemplate", sIniTemplate[0]) ); gd1.addNumericField("Number of iterations", Prefs.get("RegisterNDFFT.IA.nIterN",10),0); gd1.addCheckbox("Exclude zero values?", Prefs.get("RegisterNDFFT.IA.bExcludeZeros", false)); - gd1.addCheckbox("Show intermediate average", Prefs.get("RegisterNDFFT.IA.bShowIntermediateAverage",false)); + gd1.addCheckbox("Show intermediate average?", Prefs.get("RegisterNDFFT.IA.bShowIntermediateAverage",false)); + gd1.addCheckbox("If yes, save intermediate on disk?", Prefs.get("RegisterNDFFT.IA.bSaveIntermediate",false)); gd1.addCheckbox("Output registered inputs?", Prefs.get("RegisterNDFFT.IA.bOutputInput",false)); String sCurrChoice = Prefs.get("RegisterNDFFT.IA.sConstrain", "No"); gd1.addChoice("Constrain registration?", limitsReg, sCurrChoice); @@ -181,8 +206,10 @@ public void run(String paramString) { Prefs.set("RegisterNDFFT.IA.nIterN", nIterN); bExcludeZeros = gd1.getNextBoolean(); Prefs.set("RegisterNDFFT.IA.bExcludeZeros", bExcludeZeros); - bShowIntermediateAverage = gd1.getNextBoolean(); - Prefs.set("RegisterNDFFT.IA.bShowIntermediateAverage", bShowIntermediateAverage); + bIntermediateAverage = gd1.getNextBoolean(); + Prefs.set("RegisterNDFFT.IA.bShowIntermediateAverage", bIntermediateAverage); + bSaveIntermediate = gd1.getNextBoolean(); + Prefs.set("RegisterNDFFT.IA.bSaveIntermediate", bSaveIntermediate); bOutputInput = gd1.getNextBoolean(); Prefs.set("RegisterNDFFT.IA.bOutputInput", bOutputInput); nConstrainReg = gd1.getNextChoiceIndex(); @@ -247,11 +274,19 @@ public void run(String paramString) { lim_fractions[d] = dLimits[d]; } } - + if(bIntermediateAverage && bSaveIntermediate) + { + DirectoryChooser dc = new DirectoryChooser ( "Choose a folder to save intermediate averages..." ); + sPathIntermediate = dc.getDirectory(); + if(sPathIntermediate == null) + return; + + } if(!imageSet.loadAllImages()) return; + IJ.log("Running for "+Integer.toString(nIterN)+" iterations."); final int nImageN = imageSet.nImageN; @@ -266,16 +301,17 @@ public void run(String paramString) { sumAndCount = AverageWithoutZero.sumAndCountArray(imgs_shift); IntervalView currAverageImg; - if(bShowIntermediateAverage) + if(bIntermediateAverage) { - MiscUtils.wrapFloatImgCal(AverageWithoutZero.averageFromSumAndCount(sumAndCount), "average iteration 0", imageSet.cal, false).show(); + processIntermediate(0); } GenNormCC normCC = new GenNormCC(); normCC.bVerbose = false; - normCC.bExcludeZeros=bExcludeZeros; + normCC.bExcludeZeros = bExcludeZeros; normCC.lim_fractions = lim_fractions; normCC.limInterval = limInterval; + normCC.bCenteredLimit = true; ResultsTable ptable = ResultsTable.getResultsTable(); ptable.reset(); @@ -305,8 +341,6 @@ public void run(String paramString) { maxAverCCshifts.add(new long[nDimReg]); } - - long iterStartT, iterEndT; for(iter=0;(iter> imgs_avrg_out; - - if(imageSet.bMultiCh) - { - imgs_avrg_out = getMultiChAligned(shifts); - } - else - { - // calculate new img array with applied displacements - imgs_avrg_out = new ArrayList>(); - buildShiftedIntervals(imageSet.imgs, imgs_avrg_out,shifts); - } + //calculate final average image IJ.log("calculating final average image.."); - //calculate final average image - IntervalView finalAver = AverageWithoutZero.averageArray(imgs_avrg_out, true); - IJ.log("...done."); - MiscUtils.wrapFloatImgCal(finalAver,"final_average_"+Integer.toString(nIterMax),imageSet.cal,imageSet.bMultiCh).show(); + imgs_avrg_out = getAlignedRAI(shifts, true); + + IntervalView finalAver = AverageWithoutZero.averageArray(imgs_avrg_out, bIgnoreZeroInAveraging); + MiscUtils.wrapFloatImgCal(finalAver,"final_average_"+Integer.toString(nIterMax),imageSet.cal,imageSet.bMultiCh).show(); + IJ.log("...done."); //calculate STD image IJ.log("calculating final standard deviation image.."); - IntervalView finalSTD = AverageWithoutZero.stdArray(imgs_avrg_out, finalAver, true); + IntervalView finalSTD = AverageWithoutZero.stdArray(imgs_avrg_out, finalAver, bIgnoreZeroInAveraging); MiscUtils.wrapFloatImgCal(finalSTD,"final_std_"+Integer.toString(nIterMax),imageSet.cal,imageSet.bMultiCh).show(); IJ.log("...done."); @@ -625,6 +649,22 @@ public void medianCorrectShifts(final long [][] shifts_in) } } + + public void processIntermediate(final int nIt) + { + ArrayList> imgs_avrg_out = getAlignedRAI(shifts, true); + String sName = "intermediate_average_"+Integer.toString(nIt); + ImagePlus temp; + temp = MiscUtils.wrapFloatImgCal(AverageWithoutZero.averageArray(imgs_avrg_out, bIgnoreZeroInAveraging),sName,imageSet.cal,imageSet.bMultiCh); + if(bSaveIntermediate) + { + IJ.saveAsTiff(temp, sPathIntermediate +temp.getTitle()); + } + else + { + temp.show(); + } + } @Override public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { int d; @@ -671,6 +711,24 @@ public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { } return true; } + + /** function returns aligned intervals **/ + ArrayList> getAlignedRAI(final ArrayList shifts_, boolean bIgnoreZero) + { + ArrayList> imgs_avrg_out; + + if(imageSet.bMultiCh) + { + imgs_avrg_out = getMultiChAligned(shifts_); + } + else + { + // calculate new img array with applied displacements + imgs_avrg_out = new ArrayList>(); + buildShiftedIntervals(imageSet.imgs, imgs_avrg_out,shifts_); + } + return imgs_avrg_out; + } public static void main( final String[] args ) { diff --git a/src/main/java/averagingND/RegisterSingleND.java b/src/main/java/averagingND/RegisterSingleND.java index 76e36b3..27652cd 100644 --- a/src/main/java/averagingND/RegisterSingleND.java +++ b/src/main/java/averagingND/RegisterSingleND.java @@ -2,7 +2,6 @@ import java.awt.AWTEvent; -import java.awt.Checkbox; import java.awt.Label; import java.awt.TextField; import java.text.DecimalFormat; @@ -53,6 +52,7 @@ public class RegisterSingleND implements PlugIn, DialogListener TextField [] limVal; int nDimReg; String sDims; + boolean bCenteredLimit = false; @Override public void run(String arg) { @@ -149,6 +149,7 @@ public void run(String arg) { gd1.addCheckbox("Register template?", Prefs.get("RegisterNDFFT.bRegisterTemplate", false)); String sCurrChoice = Prefs.get("RegisterNDFFT.sConstrain", "No"); gd1.addChoice("Constrain registration?", limitsReg, sCurrChoice); + for (d=0;d