From 678e28dccd29f3067f9252420568ecdb1c938857 Mon Sep 17 00:00:00 2001 From: Jan Hansen <27991883+hansenjn@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:29:21 -0700 Subject: [PATCH] Improving headless mode - 3D Analyzer - #3 - avoid ProgressDialog Avoid ProgressDialog entirely in noGUIs (headless) macro mode. --- 3D Analyzer/pom.xml | 2 +- .../src/main/java/motiQ3D/MotiQ_3D.java | 75 +++++++++++-------- .../main/java/motiQ3D/TimelapseParticle.java | 48 ++++++------ 3D Analyzer/src/main/resources/plugins.config | 4 +- 4 files changed, 70 insertions(+), 59 deletions(-) diff --git a/3D Analyzer/pom.xml b/3D Analyzer/pom.xml index 68002a1..0297182 100644 --- a/3D Analyzer/pom.xml +++ b/3D Analyzer/pom.xml @@ -11,7 +11,7 @@ MotiQ_3D JNH - 0.3.2-SNAPSHOT + 0.3.3-SNAPSHOT MotiQ 3D Analyzer diff --git a/3D Analyzer/src/main/java/motiQ3D/MotiQ_3D.java b/3D Analyzer/src/main/java/motiQ3D/MotiQ_3D.java index e7e8f07..d9f6185 100644 --- a/3D Analyzer/src/main/java/motiQ3D/MotiQ_3D.java +++ b/3D Analyzer/src/main/java/motiQ3D/MotiQ_3D.java @@ -4,7 +4,7 @@ * * Copyright (C) 2014-2024 Jan N. Hansen * First version: July 28, 2014 - * This Version: July 29, 2024 + * This Version: July 30, 2024 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,7 +43,7 @@ public class MotiQ_3D implements PlugIn, Measurements{ //Name variables static final String PLUGINNAME = "MotiQ 3D Analyzer"; - static final String PLUGINVERSION = "v0.3.2"; + static final String PLUGINVERSION = "v0.3.3"; DecimalFormat dformat6 = new DecimalFormat("#0.000000"); DecimalFormat dformat3 = new DecimalFormat("#0.000"); @@ -313,6 +313,7 @@ record = true; //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& GenericDialog gd = new GenericDialog(PLUGINNAME + " - settings"); + gd.addHelp("https://github.com/hansenjn/MotiQ/wiki"); //show Dialog----------------------------------------------------------------- // gd.setInsets(0,0,0); (top, left, bottom) gd.setInsets(0,0,0); gd.addMessage(PLUGINNAME + ", version " + PLUGINVERSION @@ -534,8 +535,8 @@ public void windowClosing(WindowEvent winEvt) { } //add progressDialog - progress = new ProgressDialog(name, tasks, noGUIs); if(!noGUIs) { + progress = new ProgressDialog(name, tasks, noGUIs); progress.setLocation(0,0); progress.setVisible(true); progress.addWindowListener(new java.awt.event.WindowAdapter() { @@ -565,17 +566,21 @@ public void windowClosing(WindowEvent winEvt) { break continueAll; } Date startDate = new Date(); - progress.updateBarText(" in progress..."); + if(!noGUIs) progress.updateBarText(" in progress..."); running: while(true){ //Check for problems with image file if(name[task].substring(name[task].lastIndexOf("."),name[task].length()).equals(".txt")){ - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": File is no image! Could not be processed!",ProgressDialog.ERROR); - progress.moveTask(task); + if(!noGUIs) { + progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": File is no image! Could not be processed!",ProgressDialog.ERROR); + progress.moveTask(task); + } break running; } if(name[task].substring(name[task].lastIndexOf("."),name[task].length()).equals(".zip")){ - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": File is no image! Could not be processed!",ProgressDialog.ERROR); - progress.moveTask(task); + if(!noGUIs) { + progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": File is no image! Could not be processed!",ProgressDialog.ERROR); + progress.moveTask(task); + } break running; } //Check for problems with image file @@ -594,8 +599,10 @@ public void windowClosing(WindowEvent winEvt) { imp.deleteRoi(); } }catch (Exception e) { - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": file is no image - could not be processed!",ProgressDialog.ERROR); - progress.moveTask(task); + if(!noGUIs) { + progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": file is no image - could not be processed!",ProgressDialog.ERROR); + progress.moveTask(task); + } break running; } @@ -678,7 +685,7 @@ public void windowClosing(WindowEvent winEvt) { cal.fps = fps; timeUnit = calTimeUnit; }else{ - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": recalibration failed! Metadata calibration is used instead!!",ProgressDialog.ERROR); + if(!noGUIs) progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": recalibration failed! Metadata calibration is used instead!!",ProgressDialog.ERROR); } } //Calibrate @@ -845,8 +852,10 @@ public void windowClosing(WindowEvent winEvt) { floodNodes[index][3] = floodNodeT; } if(processedPxCount%(pxCount100) points, Calibration cal, double projectedFrames, boolean skeletonize, - //double gaussSigmaXY, double gaussSigmaZ, int orWidth, int orHeight, int orSlices, int orTimes, boolean minimizeImages, - //boolean binarizeBeforeSkeletonization, ProgressDialog progress) particleCollection.add(new TimelapseParticle(pointCollection, cal, totalGroupSize, skeletonize, gSigmaXY, gSigmaZ, width, height, slices, frames, true, - binarizeBeforeSkl, progress)); + binarizeBeforeSkl, progress, noGUIs)); } } } @@ -1112,7 +1121,7 @@ public void windowClosing(WindowEvent winEvt) { } //Filter particles - progress.setBar(0.8); + if(!noGUIs) progress.setBar(0.8); /*************************************************************************** *#########################################################################* @@ -1135,7 +1144,7 @@ public void windowClosing(WindowEvent winEvt) { try{ new File(dir [task] + filePrefix).mkdirs(); }catch(Exception e){ - progress.notifyMessage("failed to create subfolder to save additional plots! Will save plots into origianl folder!",ProgressDialog.NOTIFICATION); + if(!noGUIs) progress.notifyMessage("failed to create subfolder to save additional plots! Will save plots into origianl folder!",ProgressDialog.NOTIFICATION); } String RPSuffix = "_RP" + dformat0.format(minParticleVolume); @@ -1602,7 +1611,7 @@ public void windowClosing(WindowEvent winEvt) { } } }catch(Exception e){ - progress.notifyMessage("Task " + task + "/" + tasks + ": error - could not correctly write results...",ProgressDialog.ERROR); + if(!noGUIs) progress.notifyMessage("Task " + task + "/" + tasks + ": error - could not correctly write results...",ProgressDialog.ERROR); } tw1.append(""); } @@ -1640,7 +1649,7 @@ public void windowClosing(WindowEvent winEvt) { v3D = new Visualizer3D(imp, 3.0f); v3D.setAngle(10.0f, -10.0f, 0.0f); - progress.updateBarText("generating visualizations..."); + if(!noGUIs) progress.updateBarText("generating visualizations..."); if(mergeSelection.equals(mergeOrNotMerge[0])){ IJ.saveAs(allParticles.particleImp, "tif", subfolderPrefix + RPSuffix + ".tif"); IJ.saveAs(allParticles.convexHullImp, "tif", subfolderPrefix + "_H.tif"); @@ -1654,7 +1663,7 @@ public void windowClosing(WindowEvent winEvt) { for(int err = 0; err < e.getStackTrace().length; err++){ out += " \n " + e.getStackTrace()[err].toString(); } - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": No 3D visualization generated - an error occured: " + out,ProgressDialog.NOTIFICATION); + if(!noGUIs) progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": No 3D visualization generated - an error occured: " + out,ProgressDialog.NOTIFICATION); } allParticles.closeImps(); }else if(mergeSelection.equals(mergeOrNotMerge[1])){ @@ -1671,21 +1680,23 @@ public void windowClosing(WindowEvent winEvt) { for(int err = 0; err < e.getStackTrace().length; err++){ out += " \n " + e.getStackTrace()[err].toString(); } - progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": An error occured when generating a 3D visualization - the analysis and all other output files than the missing 3D file are however unaffected and valid!" + if(!noGUIs) progress.notifyMessage("Task " + (task+1) + "/" + tasks + ": An error occured when generating a 3D visualization - the analysis and all other output files than the missing 3D file are however unaffected and valid!" + " Debuggin information: " + out + "",ProgressDialog.NOTIFICATION); } particleCollection.get(i).closeImps(); } } - progress.setBar(0.9); + if(!noGUIs) progress.setBar(0.9); //Save Images //Save results text files //Update Multi-Task-Manager - progress.setBar(1.0); - progress.moveTask(task); + if(!noGUIs) { + progress.setBar(1.0); + progress.moveTask(task); + } break running; } } diff --git a/3D Analyzer/src/main/java/motiQ3D/TimelapseParticle.java b/3D Analyzer/src/main/java/motiQ3D/TimelapseParticle.java index 43a2a47..d76ff1c 100644 --- a/3D Analyzer/src/main/java/motiQ3D/TimelapseParticle.java +++ b/3D Analyzer/src/main/java/motiQ3D/TimelapseParticle.java @@ -4,7 +4,7 @@ * * Copyright (C) 2014-2023 Jan N. Hansen * First version: July 28, 2014 - * This Version: April 15, 2019 + * This Version: July 30, 2024 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -191,9 +191,9 @@ public class TimelapseParticle{ public TimelapseParticle(){} public TimelapseParticle(ArrayList points, Calibration cal, double projectedFrames, boolean skeletonize, double gaussSigmaXY, double gaussSigmaZ, - int orWidth, int orHeight, int orSlices, int orTimes, boolean minimizeImages, boolean binarizeBeforeSkeletonization, ProgressDialog progressDialog){ + int orWidth, int orHeight, int orSlices, int orTimes, boolean minimizeImages, boolean binarizeBeforeSkeletonization, ProgressDialog progressDialog, boolean noGUIs){ // SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); -// progressDialog.notifyMessage("Started particle generation " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Started particle generation " + df.format(new Date()),ProgressDialog.NOTIFICATION); final double calibration = cal.pixelWidth; final double voxelDepth = cal.pixelDepth; @@ -237,7 +237,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj height = 1+yMax-yMin; data = new double [width][height][slices][times]; -// progressDialog.notifyMessage("Step 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); //Determine static variables double maxIntensity = 0.0, maxPossibIntensity = 0.0; @@ -308,7 +308,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step static 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); int xCal, yCal, zCal, tCal; for(int i = 0; i < nPoints; i++){ @@ -345,7 +345,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj volume [tCal] += vxVolume; } -// progressDialog.notifyMessage("Step static 2 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 2 " + df.format(new Date()),ProgressDialog.NOTIFICATION); for(int t = 0; t < times; t++){ averageIntensity [t] /= (volume [t] / vxVolume); @@ -384,7 +384,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj surface [tCal] += transientSurface; } -// progressDialog.notifyMessage("Step static 3 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 3 " + df.format(new Date()),ProgressDialog.NOTIFICATION); double transientRadius; for(int t = 0; t < times; t++){ @@ -410,7 +410,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj RI [t] = surface [t] / (Math.PI * Math.pow(transientRadius,2) * 4); //RI } -// progressDialog.notifyMessage("Step static 4 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 4 " + df.format(new Date()),ProgressDialog.NOTIFICATION); { //convex hull calculation @@ -431,7 +431,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } //calculate hull - transHullData = getConv3DHull(transHullData, progressDialog); + transHullData = getConv3DHull(transHullData, progressDialog, noGUIs); for(int z = 0; z < slices; z++){ for(int x = 0; x < width; x++){ @@ -443,7 +443,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step static 5 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 5 " + df.format(new Date()),ProgressDialog.NOTIFICATION); { String bitDepth = "8-bit"; maxPossibIntensity = 255.0; @@ -580,7 +580,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj convexHullImp.setCalibration(cal); } -// progressDialog.notifyMessage("Step static 6 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step static 6 " + df.format(new Date()),ProgressDialog.NOTIFICATION); for(int t = 0; t < times; t++){ convexHullxC [t] /= (convexHullVolume [t]/vxVolume); @@ -607,7 +607,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step 2 SKL " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 2 SKL " + df.format(new Date()),ProgressDialog.NOTIFICATION); // SKELETON PARAMETERS if(skeletonize){ @@ -804,7 +804,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj particleImpGaussed.close(); } -// progressDialog.notifyMessage("Step 3 TIMEDEP " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 3 TIMEDEP " + df.format(new Date()),ProgressDialog.NOTIFICATION); //TIME DEPENDENT VARIABLES if(times>1){ @@ -866,7 +866,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj motility [t] = occupVolume [t] + lostVolume [t]; } -// progressDialog.notifyMessage("Step 3.1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 3.1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); //FloodFiller to find #extensions and #retractions int floodNodeX, floodNodeY, floodNodeZ, floodNodeT, index, maxExtRetr = 0; @@ -1067,7 +1067,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step 4 LTPs " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 4 LTPs " + df.format(new Date()),ProgressDialog.NOTIFICATION); //timegroup variables projectedTimes = (int)((double)times/(double)projectedFrames); @@ -1137,7 +1137,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step 4 LTPs 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 4 LTPs 1 " + df.format(new Date()),ProgressDialog.NOTIFICATION); for(int i = 0; i < projectedTimes; i++){ projectedDynamicFraction [i] = (projectedVolume [i] - projectedStaticVolume [i]) / projectedVolume [i]; @@ -1192,7 +1192,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step 4 LTPs 2 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 4 LTPs 2 " + df.format(new Date()),ProgressDialog.NOTIFICATION); //LONG TERM AVERAGES OF PARAMETERS if(times>=projectedFrames&&projectedFrames!=1){ @@ -1375,7 +1375,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } -// progressDialog.notifyMessage("Step 4 LTPs 3 " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Step 4 LTPs 3 " + df.format(new Date()),ProgressDialog.NOTIFICATION); //Dynamic parameters if(times>1){ @@ -1431,7 +1431,7 @@ public TimelapseParticle(ArrayList points, Calibration cal, double proj } } initialized = true; -// progressDialog.notifyMessage("Done " + df.format(new Date()),ProgressDialog.NOTIFICATION); +// if(!noGUIs) progressDialog.notifyMessage("Done " + df.format(new Date()),ProgressDialog.NOTIFICATION); } /** Closes all ImagePlus belonging to the particle*/ @@ -1452,12 +1452,12 @@ public void closeImps (){ * @param image * @param progressDialog should reference to the current progressDialog that visualises analysis progress * */ - private boolean [][][] getConv3DHull(boolean[][][] image, ProgressDialog progressDialog){ //TODO IMPROVE! + private boolean [][][] getConv3DHull(boolean[][][] image, ProgressDialog progressDialog, boolean noGUIs){ //TODO IMPROVE! int width = image.length; int height = image[0].length; int slices = image[0][0].length; - progressDialog.addToBar(0.01); + if(!noGUIs) progressDialog.addToBar(0.01); //initialize ArrayList pList = new ArrayList (); @@ -1708,7 +1708,7 @@ public void closeImps (){ } if((int)Math.round(100.0*doneConnectionsCount/(double)connectionsCount) % 10 == 0){ - progressDialog.updateBarText("Get convex hull ... " + (int)Math.round(100.0*doneConnectionsCount/(double)connectionsCount) + "%"); + if(!noGUIs) progressDialog.updateBarText("Get convex hull ... " + (int)Math.round(100.0*doneConnectionsCount/(double)connectionsCount) + "%"); } } } @@ -1716,7 +1716,7 @@ public void closeImps (){ } } } - progressDialog.updateBarText("Get convex hull ... 100%"); + if(!noGUIs) progressDialog.updateBarText("Get convex hull ... 100%"); //get 2D hull { @@ -1795,7 +1795,7 @@ public void closeImps (){ pList2.clear(); oldPList2.clear(); } - progressDialog.updateBarText("convex hull determined"); + if(!noGUIs) progressDialog.updateBarText("convex hull determined"); oldPList.clear(); pList.clear(); return image; diff --git a/3D Analyzer/src/main/resources/plugins.config b/3D Analyzer/src/main/resources/plugins.config index acde514..6e03ccd 100644 --- a/3D Analyzer/src/main/resources/plugins.config +++ b/3D Analyzer/src/main/resources/plugins.config @@ -24,8 +24,8 @@ # Belongs to the MotiQ toolbox for analyzing cellular morphology, dynamics, and signaling. MotiQ 3D analyzer analyzes segmented images that are either background-removed (in which intensity information in foreground pixels is preserved while the intensity of background pixels is set to zero) or binary images. After analysis, MotiQ 3D analyzer outputs a text-file containing many different parameter results and a set of images visualizing the results. # Author: Jan N. Hansen -# Version: 0.3.2 +# Version: 0.3.3 # Date: 2017/12/01 # Requires: ImageJ -Plugins>MotiQ, "MotiQ 3D Analyzer (v0.3.2)", motiQ3D.MotiQ_3D \ No newline at end of file +Plugins>MotiQ, "MotiQ 3D Analyzer (v0.3.3)", motiQ3D.MotiQ_3D \ No newline at end of file