diff --git a/src/main/java/ch/epfl/biop/DEVIL.java b/src/main/java/ch/epfl/biop/DEVIL.java index 084f216..fe91198 100644 --- a/src/main/java/ch/epfl/biop/DEVIL.java +++ b/src/main/java/ch/epfl/biop/DEVIL.java @@ -1,215 +1,217 @@ package ch.epfl.biop; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import ij.ImagePlus ; import ij.io.FileSaver; import ij.measure.Calibration; import ij.plugin.filter.BackgroundSubtracter; import ij.process.Blitter; import ij.process.ImageProcessor; import loci.formats.FormatException; // here is the logic of the plugin public class DEVIL { /* * THE runner(s) on an ImageProcessor , AUTO mode or Advanced mode (defined in DevilParam ) */ public static ImageProcessor DEVIL_ipr(DevilParam dp, DevilMeasure dm,int[] ZCTS_indexes,ImageProcessor ipr ) { // from DevilParam we retrieve some parameters - int particle_size = dp.objectSize ; + // We want to retrieve current channel parameters // in ZCTS_indexes ( Z[0],C[1],T[2],S[3] ), - float maxBlur = dp.getChannelMaxBlur(ZCTS_indexes[1]) ; + //float maxBlur = dp.getChannelMaxBlur(ZCTS_indexes[1]) ; + float maxBlur = dp.default_maxBlur ; float min_final = dp.getChannelMinFinal(ZCTS_indexes[1]) ; float max_final = dp.getChannelMaxFinal(ZCTS_indexes[1]) ; - + //int particle_size = dp.objectSize ; + float particle_size = dp.getChannelObjectSize(ZCTS_indexes[1]) ; /* * DEVIL is a very simple workflow that comprises : * - divide the image by a blurred version ( sigma = 2 * objectSize) * - make the sqrt * - apply a rollingBallBackground ( radius = objectSize) * * NB : some measurement are made during the process and stored in DevilMeasure */ // convert ipr to 32-bit and duplicate to process ImageProcessor ipr_ori_32 = ipr.convertToFloatProcessor(); ImageProcessor ipr_blur_32 = ipr_ori_32.duplicate(); // blur and normalize it ipr_blur_32.blurGaussian( 2 * particle_size); // Measure the max of the Blurred Image and store the value in the DevilMeasure // so we can output the value later on - double maxBlur_measured = ipr_blur_32.getStats().max; - dm.setMaxNorm(ZCTS_indexes, maxBlur_measured); + //double maxBlur_measured = ipr_blur_32.getStats().max; + //dm.setMaxNorm(ZCTS_indexes, maxBlur_measured); //String plane_index_str = new Integer(plane_index).toString(); //String maxOfChannel_str = new Double(maxBlur_measured).toString(); //ij.IJ.log("@"+plane_index_str+" maxOfChannel ipr : "+maxOfChannel_str); ipr_blur_32.multiply( 1.0 / maxBlur ); /* using a imagePlus ImageCalculator ipl_c = new ImageCalculator(); ImagePlus ipl_corr_32 = ipl_c.run("Divide create", new ImagePlus("",ipr_ori_32), new ImagePlus("",ipr_blur_32) ); ImageProcessor ipr_corr_32 = ipl_corr_32.getProcessor(); */ // Fortunately, Oli found a way to divide an ipr by another ipr without using an ImagePlus intermediate ! ipr_ori_32.copyBits(ipr_blur_32, 0, 0, Blitter.DIVIDE); // do sqrt ipr_ori_32.sqrt(); // and Background substraction BackgroundSubtracter bkgdSub = new BackgroundSubtracter(); bkgdSub.rollingBallBackground(ipr_ori_32,particle_size,false, false,false,false,false); // Measure the min and max of the final image and store the values in the DevilMeasure // so we can output the value later on double minFinal_measured = ipr_ori_32.getStats().min; dm.setMinFinal(ZCTS_indexes, minFinal_measured); double maxFinal_measured = ipr_ori_32.getStats().max; dm.setMaxFinal(ZCTS_indexes, maxFinal_measured); if ( dp.getOutputBitDepth() == "16-bit") { // set min and max to the defined values ipr_ori_32.setMinAndMax(min_final, max_final); // convert to 16-bit ImageProcessor ipr_corr_16 = ipr_ori_32.convertToShort(true); // return DEVILed ipr return ipr_corr_16; } else { return ipr_ori_32; } } /* * PARALLEL PROCESSING * - DEVIL_ipr(...) * - export multi .tif files * * inspired by : http://albert.rierol.net/imagej_programming_tutorials.html * */ private final static int n_cpus=Runtime.getRuntime().availableProcessors(); public static void run(DevilParam dp) throws IOException, FormatException { // to output suggestions for parameters DevilMeasure dm = new DevilMeasure(dp) ; for (int iSeries = 0 ; iSeries < dp.nSeries ; iSeries++ ){ // for each series of the selected file // set the current Series dp.setCurrentSeries(iSeries); // DECLARE A thread array of size Nbr of available CPU // final Thread[] threads = newThreadArray(); final Thread[] threads = new Thread[n_cpus]; // initiate an atomicInteger final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { // Concurrently run in as many threads as CPUs threads[ithread] = new Thread() { { setPriority(Thread.NORM_PRIORITY); } public void run() { // Each thread processes a few items in the total list // Each loop iteration within the run method // has a unique 'i' number to work with // and to use as index in the results array: for (int i = ai.getAndIncrement(); i < dp.perSeriesPlanesNbr; i = ai.getAndIncrement() ) { int[] ZCT_indexes = dp.ch_separator.getZCTCoords(i); int currentSerie = dp.ch_separator.getSeries(); int[] ZCTS_indexes= { ZCT_indexes[0], ZCT_indexes[1],ZCT_indexes[2],currentSerie }; // process each plane // get the imageProcessor at i+1 (because it starts at 1) ImageProcessor currentPlane_ipr = dp.vStack.getProcessor(i+1); // and define the name accordingly using String currentPlaneIndexes_str = "-c"+ZCTS_indexes[1]+"-z"+ZCTS_indexes[0]+"-t"+ZCTS_indexes[2]+"-i"+i; // if the file have multiple series , add serie nbr if ( dp.getnSeries() > 1 ) currentPlaneIndexes_str = "s"+ZCTS_indexes[3]+"-"+currentPlaneIndexes_str; // process the image processor ImageProcessor processed_currentPlane_ipr ; if (dp.advancedParam){ //processed_currentPlane_ipr = DEVIL_ipr(dp,dm,ZCTS_indexes,currentPlane_ipr, max_norm_arrayF[ ZCT_indexes[1] ], min_final_arrayF[ ZCT_indexes[1] ], max_final_arrayF[ ZCT_indexes[1] ] ); processed_currentPlane_ipr = DEVIL_ipr(dp,dm,ZCTS_indexes,currentPlane_ipr); }else{ processed_currentPlane_ipr = DEVIL_ipr(dp,dm,ZCTS_indexes,currentPlane_ipr); } // make ipl from ipr ImagePlus currentPlane_ipl_output = new ImagePlus(currentPlaneIndexes_str+"--processed" , processed_currentPlane_ipr); Calibration cal = new Calibration(currentPlane_ipl_output) ; cal.setUnit("micron"); cal.pixelWidth = dp.voxelSize[0]; cal.pixelHeight = dp.voxelSize[1]; cal.pixelDepth = dp.voxelSize[2]; //as no effect ! currentPlane_ipl_output.setCalibration(cal); // Output String ouput_filePath = dp.getOutputPath()+"_"+currentPlaneIndexes_str+".tif"; final FileSaver ipl_fileSaver = new FileSaver(currentPlane_ipl_output); ipl_fileSaver.saveAsTiff(ouput_filePath); } } }; } // DO IT ! startAndJoin(threads); } // Final Log print with measured value dm.logMeasure(); } /** Start all given threads and wait on each of them until all are done. * From Stephan Preibisch's Multithreading.java class. See: * http://repo.or.cz/w/trakem2.git?a=blob;f=mpi/fruitfly/general/MultiThreading.java;hb=HEAD */ public static void startAndJoin(Thread[] threads){ for (int ithread = 0; ithread < threads.length; ++ithread) { threads[ithread].setPriority(Thread.NORM_PRIORITY); threads[ithread].start(); } try { for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread].join(); } catch (InterruptedException ie) { throw new RuntimeException(ie); } } } // end of public class DEVIL diff --git a/src/main/java/ch/epfl/biop/DEVIL_.java b/src/main/java/ch/epfl/biop/DEVIL_.java index 8adcb09..9bf229d 100644 --- a/src/main/java/ch/epfl/biop/DEVIL_.java +++ b/src/main/java/ch/epfl/biop/DEVIL_.java @@ -1,140 +1,147 @@ package ch.epfl.biop; import java.io.IOException; import org.joda.time.DateTime; import fiji.util.gui.GenericDialogPlus; import ij.IJ; import ij.ImageJ; import ij.Prefs; import ij.plugin.PlugIn; import loci.formats.FormatException; // here is the User Interface that runs the class DEVIL.java public class DEVIL_ implements PlugIn { @Override public void run(String arg0) { String defaultPath = Prefs.get("ch.epfl.biop.devil.defaultPath" , Prefs.getImageJDir()); int objectSize = Prefs.getInt("ch.epfl.biop.devil.particle_size" , 25 ); boolean advancedParam = Prefs.getBoolean("ch.epfl.biop.devil.advancedParam" , false); GenericDialogPlus gd = new GenericDialogPlus("DEVIL parameters"); gd.addFileField("Browse", defaultPath); gd.addNumericField("Largest_object_size (in pixel)", objectSize, 0); gd.addCheckbox("Advanced_parameters", advancedParam); gd.showDialog(); // if "canceled" send error and return if ( gd.wasCanceled() ){ IJ.error("canceled by user"); return; } // otherwise, retrieve values defaultPath = gd.getNextString(); objectSize = (int) gd.getNextNumber(); advancedParam = gd.getNextBoolean(); // set choices in Prefs Prefs.set("ch.epfl.biop.devil.defaultPath" , defaultPath); Prefs.set("ch.epfl.biop.devil.particle_size" , objectSize ); Prefs.set("ch.epfl.biop.devil.advancedParam" , advancedParam ); - String maxNorm_string = "Default"; + //String maxNorm_string = "Default"; String minFinal_string = "Default"; String maxFinal_string = "Default"; + String objectSize_string= String.valueOf(objectSize); + Prefs.set("ch.epfl.biop.devil.objectSize" , objectSize_string ); String outputBitDepth_string= "16-bit"; // if advanced settings was selected if ( advancedParam ){ - maxNorm_string = Prefs.get("ch.epfl.biop.devil.max_norm" , "65535, 65535, ..." ); + //maxNorm_string = Prefs.get("ch.epfl.biop.devil.max_norm" , "65535, 65535, ..." ); minFinal_string = Prefs.get("ch.epfl.biop.devil.min_final" , "-10, -10, ..." ); maxFinal_string = Prefs.get("ch.epfl.biop.devil.max_final" , "1000, 1000, ..." ); + objectSize_string = Prefs.get("ch.epfl.biop.devil.objectSize" , "10, 10, ..." ); outputBitDepth_string = Prefs.get("ch.epfl.biop.devil.outputBitDepth" , "16-bit" ); String[] outputBitDepth = {"16-bit", "32-bit"}; GenericDialogPlus gd_adParam = new GenericDialogPlus("DEVIL advanced parameters"); gd_adParam.addMessage("You can specify values for each channel, separated by ',' .\n (*) non numerical values will be replaced by default"); - gd_adParam.addStringField("Maximum (for normalization step)" , maxNorm_string ,15 ); + //gd_adParam.addStringField("Maximum (for normalization step)" , maxNorm_string ,15 ); gd_adParam.addStringField("Minimum (for final conversion step)" , minFinal_string ,15 ); gd_adParam.addStringField("Maximum (for final conversion step)" , maxFinal_string ,15 ); + gd_adParam.addStringField("Object Size (in pixel)" , objectSize_string ,15 ); gd_adParam.addMessage("----------------------------------------------------------------------------------------"); gd_adParam.addChoice("Output_bit_depth", outputBitDepth , outputBitDepth_string); gd_adParam.addMessage("*16-bit images will be lighter, but requires conversion\nand thus to specify Min. and Max. values for final conversion "); gd_adParam.addMessage("**32-bit images will be heavier, but not need for conversion\nneither to know Min. and Max. values for final conversion"); gd_adParam.showDialog(); if ( gd_adParam.wasCanceled() ){ IJ.error("canceled by user"); return; } - maxNorm_string = gd_adParam.getNextString(); + //maxNorm_string = gd_adParam.getNextString(); minFinal_string = gd_adParam.getNextString(); maxFinal_string = gd_adParam.getNextString(); + objectSize_string = gd_adParam.getNextString(); outputBitDepth_string = gd_adParam.getNextChoice(); - Prefs.set("ch.epfl.biop.devil.max_norm" , maxNorm_string ); + //Prefs.set("ch.epfl.biop.devil.max_norm" , maxNorm_string ); Prefs.set("ch.epfl.biop.devil.min_final" , minFinal_string ); Prefs.set("ch.epfl.biop.devil.max_final" , maxFinal_string ); + Prefs.set("ch.epfl.biop.devil.objectSize" , objectSize_string ); Prefs.set("ch.epfl.biop.devil.outputBitDepth" , outputBitDepth_string ); } - DevilParam dp = new DevilParam(defaultPath, objectSize, advancedParam, maxNorm_string,minFinal_string,maxFinal_string, outputBitDepth_string); + //DevilParam dp = new DevilParam(defaultPath, objectSize, advancedParam, maxNorm_string,minFinal_string,maxFinal_string, outputBitDepth_string); + DevilParam dp = new DevilParam(defaultPath, objectSize, advancedParam, minFinal_string,maxFinal_string,objectSize_string, outputBitDepth_string); dp.logParam(); DateTime starter = DateTime.now(); IJ.log("Starts at : "+ starter); long starter_ms = System.currentTimeMillis(); try { DEVIL.run(dp); } catch (IOException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } DateTime ender = DateTime.now(); ij.IJ.log("Ends at : "+ ender); long ender_ms = System.currentTimeMillis(); ij.IJ.log("DEVIL consumed : "+ ( (ender_ms - starter_ms) / 1000 )+"sec of your life" ); } /** * Main method for debugging. * * For debugging, it is convenient to have a method that starts ImageJ, loads * an image and calls the plugin, e.g. after setting breakpoints. * * @param args unused */ public static void main(String[] args) { // set the plugins.dir property to make the plugin appear in the Plugins menu Class clazz = DEVIL_.class; String url = clazz.getResource("/" + clazz.getName().replace('.', '/') + ".class").toString(); String pluginsDir = url.substring("file:".length(), url.length() - clazz.getName().length() - ".class".length()); System.setProperty("plugins.dir", pluginsDir); // start ImageJ new ImageJ(); // run the plugin IJ.runPlugIn(clazz.getName(), ""); } } diff --git a/src/main/java/ch/epfl/biop/DevilMeasure.java b/src/main/java/ch/epfl/biop/DevilMeasure.java index e1ecd18..982196f 100644 --- a/src/main/java/ch/epfl/biop/DevilMeasure.java +++ b/src/main/java/ch/epfl/biop/DevilMeasure.java @@ -1,183 +1,183 @@ package ch.epfl.biop; import java.util.Arrays; public class DevilMeasure { /* * DEVIL Measure * * this class is used to store measurements made on plane(s) during DEVIL processing. * Indeed, DEVIL can be "optimized", by giving values for the maxNorm, minFinal and maxFinal of each channel * * At the end of the processing, the suggested parameters are printed within the Log * */ int nSeries; int nChannel; int nSlice; int nFrame; int totalPlane ; - double[][][][] maxNorm_da ; + //double[][][][] maxNorm_da ; double[][][][] minFinal_da ; double[][][][] maxFinal_da ; /* * constructor defines variable */ public DevilMeasure(DevilParam dp) { this.nSeries = dp.getnSeries() ; this.nChannel = dp.getnChannel(); this.nSlice = dp.getnSlice() ; this.nFrame = dp.getnFrame() ; totalPlane = nSeries*nChannel*nSlice*nFrame; - maxNorm_da = new double[nSlice][nChannel][nFrame][nSeries]; + //maxNorm_da = new double[nSlice][nChannel][nFrame][nSeries]; minFinal_da = new double[nSlice][nChannel][nFrame][nSeries]; maxFinal_da = new double[nSlice][nChannel][nFrame][nSeries]; } - + /* public void setMaxNorm(int[] position_ZCTS, double value) { maxNorm_da[ position_ZCTS[0] ][position_ZCTS[1]][position_ZCTS[2]][position_ZCTS[3]] = value ; } public double getMaxNormOfChannel(int channel){ double maxValue = 0; // maxNorm_da [nSlice][nChannel][nFrame][nSeries] for (int zi = 0 ; zi < nSlice ;zi++){ for (int ti = 0 ;ti < nFrame ;ti++){ for (int si = 0 ; si < nSeries ;si++){ if (maxNorm_da [zi][channel][ti][si] > maxValue){ maxValue = maxNorm_da [zi][channel][ti][si]; } } } } return maxValue; } - + */ public void setMinFinal(int[] position_ZCTS, double value) { minFinal_da[ position_ZCTS[0] ][position_ZCTS[1]][position_ZCTS[2]][position_ZCTS[3]] = value ; } public double getMinFinalOfChannel(int channel){ double minValue = 10^24; // maxNorm_da [nSlice][nChannel][nFrame][nSeries] for (int zi = 0 ; zi < nSlice ;zi++){ for (int ti = 0 ;ti < nFrame ;ti++){ for (int si = 0 ; si < nSeries ;si++){ if (minFinal_da [zi][channel][ti][si] < minValue){ minValue = minFinal_da [zi][channel][ti][si]; } } } } return minValue; } public void setMaxFinal(int[] position_ZCTS, double value) { maxFinal_da[ position_ZCTS[0] ][position_ZCTS[1]][position_ZCTS[2]][position_ZCTS[3]] = value ; } public double getMaxFinalOfChannel(int channel){ double maxValue = 0; // maxNorm_da [nSlice][nChannel][nFrame][nSeries] for (int zi = 0 ; zi < nSlice ;zi++){ for (int ti = 0 ;ti < nFrame ;ti++){ for (int si = 0 ; si < nSeries ;si++){ if (maxFinal_da [zi][channel][ti][si] > maxValue){ maxValue = maxFinal_da [zi][channel][ti][si]; } } } } return maxValue; } public void logMeasure(){ ij.IJ.log("--------------------------------------------------------"); for (int i=0 ; i < this.nChannel ; i++){ - + /* double maxOfChannel_d = getMaxNormOfChannel( i ); String maxOfChannel_str = new Double(maxOfChannel_d).toString(); ij.IJ.log("Channel"+(i+1)+" : maximum value of blurred image:"+maxOfChannel_str); - + */ double minFinal_d = getMinFinalOfChannel( i ); String minFinal_str = new Double(minFinal_d).toString(); ij.IJ.log("Channel"+(i+1)+" : minimum value of final :"+minFinal_str); double maxFinal_d = getMaxFinalOfChannel( i ); String maxFinal_str = new Double(maxFinal_d).toString(); ij.IJ.log("Channel"+(i+1)+" : maximum value of final:"+maxFinal_str); ij.IJ.log("--------------------------------------------------------"); } } /* * */ public double[] reduceArray(double[] an_array, int start, int increment){ int sub_array_size = (an_array.length)/increment; double[] sub_array = new double[sub_array_size]; for (int i = start ; i < sub_array_size ; i++ ){ sub_array[i] = an_array[i+increment]; //String i_str = new Integer(i+increment).toString(); //String maxOfChannel_str = new Double(sub_array[i]).toString(); //ij.IJ.log("maxOfChannel"+(start+1)+" : an_array["+i_str+"] = "+maxOfChannel_str); } return sub_array ; } public double[] sliceArray(double[] an_array, int start, int end){ int sliced_array_size = start - end + 1 ; double[] sliced_array = new double[sliced_array_size]; for (int i = start ; i < end ; i++ ){ sliced_array[i] = an_array[i]; //String i_str = new Integer(i+increment).toString(); //String maxOfChannel_str = new Double(sub_array[i]).toString(); //ij.IJ.log("maxOfChannel"+(start+1)+" : an_array["+i_str+"] = "+maxOfChannel_str); } return sliced_array ; } public double getMinOf(double[] an_array){ double min = Arrays.stream(an_array).min().getAsDouble(); // String minOfChannel_str = new Double(min).toString(); // ij.IJ.log("minOfChannel is devilMeasure: "+minOfChannel_str); return min; } public double getMaxOf(double[] an_array){ double max = Arrays.stream(an_array).max().getAsDouble(); // String maxOfChannel_str = new Double(max).toString(); // ij.IJ.log("maxOfChannel is devilMeasure: "+maxOfChannel_str); return max; } } diff --git a/src/main/java/ch/epfl/biop/DevilParam.java b/src/main/java/ch/epfl/biop/DevilParam.java index 777ca6d..04c6ffa 100644 --- a/src/main/java/ch/epfl/biop/DevilParam.java +++ b/src/main/java/ch/epfl/biop/DevilParam.java @@ -1,316 +1,333 @@ package ch.epfl.biop; import java.io.File; import java.util.Arrays; import ij.IJ; import loci.common.services.ServiceFactory; import loci.formats.ChannelSeparator; import loci.formats.IFormatWriter; import loci.formats.meta.IMetadata; import loci.formats.services.OMEXMLService; import loci.plugins.util.BFVirtualStack; import ome.units.quantity.Length; import ome.xml.meta.MetadataRetrieve; public class DevilParam { /* * DEVIL param * * this class is used to store many parameters required during DEVIL processing * */ public final float default_maxBlur = 65535 ; public final float default_min_final = -10 ; public final float default_max_final = 1000 ; String defaultPath; int objectSize; boolean advancedParam; - String maxNorm_string; + //String maxNorm_string; String minFinal_string; String maxFinal_string; + String objectSize_string; String outputBitDepth_string ; - float[] maxBlur ; - float[] minFinal ; - float[] maxFinal ; - + // to store parameters for each channels, we use arrays + //float[] maxBlur ; + float[] minFinal ; + float[] maxFinal ; + float[] objectSize_array ; /* * Directories Params */ // input File file ; String imageName ; String fileDir ; // output File output_dir ; String output_dir_str ; /* * Image Param */ ChannelSeparator ch_separator; BFVirtualStack vStack; IFormatWriter writer ; boolean littleEndian ; int nSeries; int nChannel; int nSlice; int nFrame; int perSeriesPlanesNbr ; int totalPlanesNbr ; double[] voxelSize = {1,1,1}; // initialized after GUI - public DevilParam(String defaultPath, int objectSize, boolean advancedParam, String max_norm_string, String min_final_string, String max_final_string, String outputBitDepth_string) { - + //public DevilParam(String defaultPath, int objectSize, boolean advancedParam, String max_norm_string, String min_final_string, String max_final_string, String outputBitDepth_string) { + public DevilParam(String defaultPath, int objectSize, boolean advancedParam, String min_final_string, String max_final_string, String objectSize_string, String outputBitDepth_string) { + this.defaultPath = defaultPath; this.objectSize = objectSize; this.advancedParam = advancedParam; - this.maxNorm_string = max_norm_string; + //this.maxNorm_string = max_norm_string; this.minFinal_string = min_final_string; this.maxFinal_string = max_final_string; + this.objectSize_string = objectSize_string; this.outputBitDepth_string = outputBitDepth_string; initFilesAndFolder(); initImage(); } /* * initialize filepath and create output directories */ public void initFilesAndFolder(){ this.file = new File(defaultPath) ; this.imageName = file.getName(); this.fileDir = file.getParent() + File.separator; // prepare output this.output_dir = new File(fileDir+"DEVIL"); output_dir.mkdir(); this.output_dir_str = output_dir.getAbsolutePath() + File.separator; } /* * initialize image reader , get image infos * * metadata reading adapted from :: http://www.programcreek.com/java-api-examples/index.php?source_dir=Stitching-master/src/main/java/Stitch_Multiple_Series_File.java * */ public void initImage() { try { // MAKE a virtual stack from the defined files // Create a ChannelSeparator to retrieve informations about the file ch_separator = new ChannelSeparator(); final ServiceFactory factory = new ServiceFactory(); final OMEXMLService service = factory.getInstance( OMEXMLService.class ); final IMetadata meta = service.createOMEXMLMetadata(); ch_separator.setMetadataStore( meta ); //very important to setId AFTER MetadataStore, otherwise send non null issue ! ch_separator.setId(defaultPath); this.littleEndian = ch_separator.isLittleEndian(); this.nSeries = ch_separator.getSeriesCount() ; this.nChannel = ch_separator.getSizeC(); this.nSlice = ch_separator.getSizeZ(); this.nFrame = ch_separator.getSizeT(); this.perSeriesPlanesNbr = nChannel * nSlice * nFrame; this.totalPlanesNbr = nSeries * nChannel * nSlice * nFrame; //this.vStack = new BFVirtualStack(this.defaultPath, this.ch_separator, false, false, false); IJ.log( "nSeries "+String.valueOf(nSeries)); IJ.log( "nChannel "+String.valueOf(nChannel)); IJ.log( "nSlice "+String.valueOf(nSlice)); IJ.log( "nFrame "+String.valueOf(nFrame)); IJ.log( "totalPlanesNbr "+String.valueOf(totalPlanesNbr)); // Now that we know file dimensions, we check that the parameters are in sufficient number (to cover all channels) - checkParamMaxNorm(); + //checkParamMaxNorm(); checkParamMinFinal(); checkParamMaxFinal(); - + checkParamObjectSize(); // Retrieve Calibrataion final MetadataRetrieve retrieve = service.asRetrieve(ch_separator.getMetadataStore()); // calibration final String dimOrder = ch_separator.getDimensionOrder().toUpperCase(); final int posX = dimOrder.indexOf( 'X' ); Length calX = retrieve.getPixelsPhysicalSizeX( 0 ); if ( posX >= 0 && calX != null && calX.value().doubleValue() != 0 ) voxelSize[0] = calX.value().doubleValue(); final int posY = dimOrder.indexOf( 'Y' ); Length calY = retrieve.getPixelsPhysicalSizeY( 0 ); if ( posY >= 0 && calY != null && calY.value().doubleValue() != 0 ) voxelSize[1] = calY.value().doubleValue(); final int posZ = dimOrder.indexOf( 'Z' ); Length calZ = retrieve.getPixelsPhysicalSizeZ( 0 ); if ( posZ >= 0 && calZ != null && calZ.value().doubleValue() != 0 ) voxelSize[2] = calZ.value().doubleValue(); //String voxel_depth = new Double(voxelSize[2]).toString(); //ij.IJ.log(" voxel_depth : "+voxel_depth); } catch (Exception e) { e.printStackTrace(); } } + + public void setCurrentSeries(int iSeries) { // TODO Auto-generated method stub ch_separator.setSeries(iSeries); IJ.log( "serieIndex "+iSeries); try { this.vStack = new BFVirtualStack(this.defaultPath,this.ch_separator, false, false, false); } catch (Exception e) { e.printStackTrace(); } } public String getOutputPath(){ return output_dir_str + imageName ; } public String getOutputBitDepth(){ return outputBitDepth_string; } /* // call in initImage() public void setImageParams(int nSeries, int nChannel, int nSlice, int nFrame) { this.nSeries = nSeries ; this.nChannel = nChannel ; this.nSlice = nSlice ; this.nFrame = nFrame ; this.totalPlanesNbr = nSeries * nChannel * nSlice * nFrame; // Now that we know file dimensions, we check that the parameters are in sufficient number (to cover all channels) checkParamMaxNorm(); checkParamMinFinal(); checkParamMaxFinal(); } */ // Image Param getters public int getnSeries() { return nSeries; } public int getnChannel() { return nChannel; } public int getnSlice() { return nSlice; } public int getnFrame() { return nFrame; } /* * DEALING WITH PARAMETERS */ + /* public void checkParamMaxNorm(){ this.maxBlur = checkParam( maxNorm_string , default_maxBlur); } + public float getChannelMaxBlur(int i) { return maxBlur[i]; } + */ public void checkParamMinFinal(){ this.minFinal = checkParam( minFinal_string , default_min_final ); } + private void checkParamObjectSize() { + this.objectSize_array = checkParam( objectSize_string , this.objectSize ); + } + + public float getChannelObjectSize(int i) { + return objectSize_array[i]; + } + public float getChannelMinFinal(int i) { return minFinal[i]; } public void checkParamMaxFinal(){ this.maxFinal = checkParam( maxFinal_string , default_max_final ); } public float getChannelMaxFinal(int i) { return maxFinal[i]; } /* * Check if there is enough parameters (respectively to the number of channel) * if empty replace by default * * requires function : stringToArrayFloat (String str , float defaultValue ) */ public float[] checkParam( String param_to_check, float defaultValue) { boolean advancedMode = this.advancedParam ; float[] param_checked = new float[nChannel]; if (advancedMode){ //make the string an float[] float[] param_to_check_array = stringToArrayFloat( param_to_check, defaultValue); // check if size of the array correspond to number of channels if (param_to_check_array.length == nChannel){ param_checked = param_to_check_array; }else{//otherwise replace by default value Arrays.fill(param_checked, defaultValue); } } else {// if automode, return a array filled with defaultValue Arrays.fill(param_checked, defaultValue); IJ.log("DEVIL default mode"); } return param_checked; } /* * Convert a string to an array of float * if not a float, replace it by default */ public static float[] stringToArrayFloat (String str , float defaultValue ){ String[] str_array = str.split(","); float[] a_flot_array = new float[str_array.length]; for (int ii = 0 ; ii < str_array.length ; ii++){ try { a_flot_array[ii] = Float.valueOf(str_array[ii].trim()).floatValue(); } catch (NumberFormatException nfe){ a_flot_array[ii] = defaultValue ; IJ.log("Ch"+(ii+1)+" : not an appropriate number : " + str_array[ii] +"replaced by "+defaultValue); } //IJ.log(ii+"-"+a_flot_array[ii]); } return a_flot_array; } public void logParam() { ij.IJ.log("Advanced parameters, defined by user :"+ defaultPath); - ij.IJ.log("Defined ObjectSize (pixel) :"+objectSize); + ij.IJ.log("Defined ObjectSize (pixel) :"+objectSize_string); ij.IJ.log("Advanced parameters, defined by user"); - ij.IJ.log("Channels, maximum value of blurred image :"+maxNorm_string); + //ij.IJ.log("Channels, maximum value of blurred image :"+maxNorm_string); ij.IJ.log("Channels, minimum value of final :"+minFinal_string); ij.IJ.log("Channels, maximum value of final :"+maxFinal_string); ij.IJ.log("Output bit_depth :"+outputBitDepth_string); } } diff --git a/target/DEVIL_-1.0.0-SNAPSHOT.jar b/target/DEVIL_-1.0.0-SNAPSHOT.jar index 222811f..9148495 100644 Binary files a/target/DEVIL_-1.0.0-SNAPSHOT.jar and b/target/DEVIL_-1.0.0-SNAPSHOT.jar differ