From fcb107a8f516d5940f182cc086cd32c492255e0e Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 17 Oct 2024 07:44:40 -0400 Subject: [PATCH 01/44] Temporal Analysis Initial GUI --- .../N5/analysis/TemporalAnalysisGUI.java | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java new file mode 100644 index 0000000..454fb5d --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java @@ -0,0 +1,204 @@ +package org.vcell.N5.analysis; + +import ij.WindowManager; +import ij.gui.Roi; +import ij.io.RoiDecoder; +import org.vcell.N5.UI.RangeSelector; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; + +public class TemporalAnalysisGUI extends JPanel implements ActionListener { + private JComboBox chosenImage; + private JComboBox chosenMeasurement; + private JCheckBox normalizeEntireImage = new JCheckBox("Normalize Entire Image"); + private JCheckBox normalizeROI = new JCheckBox("Normalize ROI"); + + private JTextField entireImageFramesFromImageStart; + private JTextField entireImageFramesFromImageEnd; + private JTextField entireImageFramesFromSimStart; + private JTextField entireImageFramesFromSimEnd; + private JPanel entireImageFramesJPanel; + + private JTextField roiFramesFromImageStart; + private JTextField roiFramesFromImageEnd; + private JTextField roiFramesFromSimStart; + private JTextField roiFramesFromSimEnd; + private JPanel roiFramesJPanel; + + private JButton imageROIFileButton; + private JButton simROIFileButton; + + private String notInMemoryWarning; + + private final JFileChooser imageROIFileChooser = new JFileChooser(); + private final JFileChooser simROIFileChooser = new JFileChooser(); + + private ArrayList imageROIList; + private ArrayList simROIList; + + private final JDialog jDialog; + private final JOptionPane pane; + +// private TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); + + public TemporalAnalysisGUI(){ + setLayout(new GridLayout(4, 1)); + + add(imageAndAnalysisType()); + add(roisSelectedGUI()); + add(normalizeEntireImageGUI()); + add(normalizeROIGUI()); + setSize(400, 400); + setVisible(true); + + pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); + jDialog = pane.createDialog("Temporal Analysis"); + } + + public void displayGUI(){ + jDialog.setVisible(true); + Integer returnValue = (Integer) pane.getValue(); + if (returnValue.equals(JOptionPane.OK_OPTION)){ + Thread thread = new Thread(() -> { + TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); + }); + thread.start(); + } + } + + private JPanel normalizeROIGUI(){ + JPanel jPanel = new JPanel(new GridLayout()); + normalizeROI.addActionListener(this); + + JPanel fromImage = new JPanel(new GridLayout()); + roiFramesFromImageStart = new JTextField(); + roiFramesFromImageEnd = new JTextField(); + fromImage.add(roiFramesFromImageStart); + fromImage.add(new JLabel("to")); + fromImage.add(roiFramesFromImageEnd); + + JPanel fromSim = new JPanel(new GridLayout()); + roiFramesFromSimStart = new JTextField(); + roiFramesFromSimEnd = new JTextField(); + fromSim.add(roiFramesFromSimStart); + fromSim.add(new JLabel("to")); + fromSim.add(roiFramesFromSimEnd); + + roiFramesJPanel = new JPanel(new GridLayout()); + roiFramesJPanel.add(fromImage); + roiFramesJPanel.add(fromSim); + roiFramesJPanel.setVisible(false); + + jPanel.add(normalizeROI); + jPanel.add(roiFramesJPanel); + + return jPanel; + } + + private JPanel normalizeEntireImageGUI(){ + JPanel jPanel = new JPanel(new GridLayout()); + normalizeEntireImage.addActionListener(this); + + JPanel fromImage = new JPanel(new GridLayout()); + entireImageFramesFromImageStart = new JTextField(); + entireImageFramesFromImageEnd = new JTextField(); + fromImage.add(entireImageFramesFromImageStart); + fromImage.add(new JLabel("to")); + fromImage.add(entireImageFramesFromImageEnd); + + JPanel fromSim = new JPanel(new GridLayout()); + entireImageFramesFromSimStart = new JTextField(); + entireImageFramesFromSimEnd = new JTextField(); + fromSim.add(entireImageFramesFromSimStart); + fromSim.add(new JLabel("to")); + fromSim.add(entireImageFramesFromSimEnd); + + entireImageFramesJPanel = new JPanel(new GridLayout()); + entireImageFramesJPanel.add(fromImage); + entireImageFramesJPanel.add(fromSim); + entireImageFramesJPanel.setVisible(false); + + jPanel.add(normalizeEntireImage); + jPanel.add(entireImageFramesJPanel); + return jPanel; + } + + private JPanel roisSelectedGUI(){ + JPanel jPanel = new JPanel(new BorderLayout()); + imageROIFileButton = new JButton("ROI's For Image"); + simROIFileButton = new JButton("ROI's For Simulation"); + + imageROIFileButton.addActionListener(this); + simROIFileButton.addActionListener(this); + + jPanel.add(imageROIFileButton, BorderLayout.WEST); + jPanel.add(simROIFileButton, BorderLayout.EAST); + return jPanel; + } + + + private JPanel imageAndAnalysisType(){ + JPanel jPanel = new JPanel(new BorderLayout()); + chosenImage = new JComboBox<>(WindowManager.getImageTitles()); + chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.MEDIAN.publicName}); + + chosenMeasurement.addActionListener(this); + chosenImage.addActionListener(this); + jPanel.add(chosenImage, BorderLayout.NORTH); + jPanel.add(chosenMeasurement, BorderLayout.SOUTH); + + return jPanel; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(imageROIFileButton)){ + imageROIList = fillROIList(imageROIFileChooser); + } else if (e.getSource().equals(simROIFileButton)) { + simROIList = fillROIList(simROIFileChooser); + } else if (e.getSource().equals(normalizeEntireImage)) { + entireImageFramesJPanel.setVisible(normalizeEntireImage.isSelected()); + } else if (e.getSource().equals(normalizeROI)) { + roiFramesJPanel.setVisible(normalizeROI.isSelected()); + } + } + + private ArrayList fillROIList(JFileChooser fileChooser){ + fileChooser.setMultiSelectionEnabled(true); + int choice = fileChooser.showDialog(this, ""); + ArrayList roiList = new ArrayList<>(); + if (choice == JFileChooser.APPROVE_OPTION){ + for (File file: fileChooser.getSelectedFiles()){ + roiList.add(RoiDecoder.open(file.getAbsolutePath())); + } + } + return roiList; + } + + enum AvailableMeasurements{ + MEDIAN("Median"); + + public final String publicName; + AvailableMeasurements(String publicName){ + this.publicName = publicName; + } + } + + public static void main(String[] args) { + TemporalAnalysisGUI temporalAnalysisGUI = new TemporalAnalysisGUI(); + temporalAnalysisGUI.displayGUI(); + } +} + + + + + + + + From 802ca0e403b6c0947a3642b794a640322197e3e6 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 18 Oct 2024 10:37:13 -0400 Subject: [PATCH 02/44] Add Data Reduction Capabilites --- view-simulation-results/pom.xml | 7 + .../org/vcell/N5/analysis/DataReduction.java | 160 ++++++++++++++++++ .../N5/analysis/TemporalAnalysisGUI.java | 23 ++- 3 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 9b27f8b..6307af2 100644 --- a/view-simulation-results/pom.xml +++ b/view-simulation-results/pom.xml @@ -192,6 +192,13 @@ s3 + + com.opencsv + opencsv + 4.1 + + + diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java new file mode 100644 index 0000000..4d37fd2 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -0,0 +1,160 @@ +package org.vcell.N5.analysis; + +import com.opencsv.CSVWriter; +import ij.ImagePlus; +import ij.gui.Roi; +import org.vcell.N5.retrieving.SimLoadingListener; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +public class DataReduction implements SimLoadingListener { + private final ArrayList arrayOfSimRois; + + private final Object csvMatrixLock = new Object(); + private File file; + + private final ArrayList> csvMatrix = new ArrayList<>(); + + private final double normalPreChange; + private final double normalPostChange; + private final int timeWhenChangeOccurs; + + private int numOfSimImages; + + /* +Open an image from file (assume 2D for now). +Open a saved ROI (or allow one to be created and saved). +Apply the ROI to a selected channel(s) in the image. +collect the average intensity value for all times in the image. +Save to cvs file of some kind (something that can be imported into excel). +Open a set of N5 exported files- in reality these will likely be scanned parameters all from the same "simulation". From each N5 data set, select the appropriate channel and z plane. +Apply the same ROI used previously and measure average intensity for each time. +save data to the cvs or equivalent file. Ideally, these should be organized so they are easy to use excel. +If possible would like to compare N5 data to image data using a least squares analysis. Users should be able to see the summed square differences and have the "best fit" identified. +Would be extra nice to plot the experimental data vs the "best fit" VCell simulation. + */ + + // GUI: + + // Create ROI beforehand, and have the user select what they want for ROI in addition to actual Image + // For the N5 files that will be opened up, select the range for what you want to do analysis on + // Select the type of statistical analysis, average intensity or something else (idk yet) + // Take results and place them within a spreadsheet + // Create a graph from that spreadsheet + + public DataReduction(boolean normalizePostChange, boolean normalizeWithPreChangeValues, + ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int startPreChange, int endPreChange, + int timeWhenChangeOccurs, int numOfSimImages, File fileToSaveResultsTo){ + this.arrayOfSimRois = arrayOfSimRois; + this.timeWhenChangeOccurs = timeWhenChangeOccurs; + this.numOfSimImages = numOfSimImages; + this.file = fileToSaveResultsTo; + ArrayList headers = new ArrayList(){{add("Time Frame");}}; + csvMatrix.add(headers); + + normalPreChange = normalizeWithPreChangeValues ? calculateNormalValue(labResults, startPreChange, endPreChange) : Double.MIN_NORMAL; + normalPostChange = normalizePostChange ? calculateNormalValue(labResults, timeWhenChangeOccurs, timeWhenChangeOccurs) : Double.MIN_NORMAL; + + HashMap> reducedData = calculateMean(labResults, arrayOfLabRois); + synchronized (csvMatrixLock){ + for (int t = 0; t < labResults.getNFrames(); t++){ + ArrayList rowForTime = new ArrayList<>(); + rowForTime.add(String.valueOf(t)); + csvMatrix.add(rowForTime); + } + + } + addValuesToCSVMatrix(labResults, reducedData); + + } + + private void addValuesToCSVMatrix(ImagePlus imagePlus, HashMap> reducedData){ + synchronized (csvMatrixLock){ + csvMatrix.get(0).add(""); + csvMatrix.get(0).add(imagePlus.getTitle()); + for (String roiName: reducedData.keySet()){ + csvMatrix.get(0).add(roiName); + for(int t = 0; t < imagePlus.getNFrames(); t++){ + double mean = reducedData.get(roiName).get(t); + csvMatrix.get(t + 1).add(String.valueOf(mean)); + } + } + numOfSimImages -= 1; + if (numOfSimImages == 0){ + writeCSVMatrix(); + } + } + } + + private double calculateNormalValue(ImagePlus imagePlus, int startT, int endT){ + double normal = 0; + for (int k = startT; k <= endT; k++){ + imagePlus.setT(k); + normal += imagePlus.getProcessor().getStatistics().mean; + } + normal = normal / (endT - startT); + return normal; + } + + + + private HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList){ +// ResultsTable resultsTable = new ResultsTable(); + + HashMap> roiListOfMeans = new HashMap<>(); + for (Roi roi: roiList) { + imagePlus.setRoi(roi); + ArrayList meanValues = new ArrayList<>(); + for (int t = 0; t < imagePlus.getNFrames(); t++){ +// Analyzer analyzer = new Analyzer(imagePlus, Analyzer.MEAN, resultsTable); +// analyzer.measure(); +// +// double meanValue = resultsTable.getValueAsDouble(resultsTable.getColumnIndex("Mean"), 0); + double meanValue = imagePlus.getProcessor().getStatistics().mean; + if (normalPreChange != Double.MIN_NORMAL){ + meanValue = meanValue / normalPreChange; + } + if (normalPostChange != Double.MIN_NORMAL && t >= timeWhenChangeOccurs){ + meanValue = meanValue / normalPostChange; + } + meanValues.add(meanValue); + } + roiListOfMeans.put(roi.getName(), meanValues); + } + return roiListOfMeans; + } + + private void writeCSVMatrix(){ + try (FileWriter fileWriter = new FileWriter(file)) { + CSVWriter csvWriter = new CSVWriter(fileWriter); + for (ArrayList row: csvMatrix){ + csvWriter.writeNext(row.toArray(new String[0])); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + @Override + public void simIsLoading(int itemRow, String exportID) { + + } + + @Override + public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus) { + + HashMap> calculations = calculateMean(imagePlus, arrayOfSimRois); + addValuesToCSVMatrix(imagePlus, calculations); + } +} + + + + + diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java index 454fb5d..5a10dcf 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java @@ -3,7 +3,7 @@ import ij.WindowManager; import ij.gui.Roi; import ij.io.RoiDecoder; -import org.vcell.N5.UI.RangeSelector; +import org.vcell.N5.N5ImageHandler; import javax.swing.*; import java.awt.*; @@ -57,17 +57,28 @@ public TemporalAnalysisGUI(){ setVisible(true); pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); - jDialog = pane.createDialog("Temporal Analysis"); + jDialog = pane.createDialog("Data Reduction"); } public void displayGUI(){ jDialog.setVisible(true); Integer returnValue = (Integer) pane.getValue(); if (returnValue.equals(JOptionPane.OK_OPTION)){ - Thread thread = new Thread(() -> { - TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); - }); - thread.start(); + JFileChooser saveToFile = new JFileChooser(); + saveToFile.setFileSelectionMode(JFileChooser.FILES_ONLY); + int response = saveToFile.showDialog(this, "Save Results To File"); + if (response == JFileChooser.APPROVE_OPTION){ + Thread thread = new Thread(() -> { + DataReduction dataReduction = new DataReduction( + normalizeROI.isSelected(), normalizeEntireImage.isSelected(), simROIList, + imageROIList, WindowManager.getImage((String) chosenImage.getSelectedItem()), + 0, 0, 0, + 5, saveToFile.getSelectedFile() + ); + N5ImageHandler.loadingFactory.addSimLoadingListener(dataReduction); + }); + thread.start(); + } } } From f941014da5aedd346e6d575ca678bc91dcea1a92 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 18 Oct 2024 10:41:17 -0400 Subject: [PATCH 03/44] Sim Listeners Pass Image Result --- .../main/java/org/vcell/N5/N5ImageHandler.java | 7 +++---- .../java/org/vcell/N5/UI/N5ExportTable.java | 10 ++++++---- .../org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../vcell/N5/analysis/TemporalAnalysisGUI.java | 2 +- ...LoadingFactory.java => LoadingManager.java} | 18 +++++++++--------- .../N5/retrieving/SimLoadingEventCreator.java | 4 +++- .../N5/retrieving/SimLoadingListener.java | 4 +++- 7 files changed, 26 insertions(+), 21 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/retrieving/{LoadingFactory.java => LoadingManager.java} (91%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index b2695e0..be9fe6c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -11,8 +11,7 @@ import org.scijava.plugin.Parameter; import org.scijava.plugin.Plugin; import org.vcell.N5.UI.MainPanel; -import org.vcell.N5.UI.N5ExportTable; -import org.vcell.N5.retrieving.LoadingFactory; +import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; import java.io.*; @@ -34,12 +33,12 @@ public class N5ImageHandler implements Command { public static MainPanel exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; - public static LoadingFactory loadingFactory; + public static LoadingManager loadingManager; @Override public void run() { initializeLogService(); - loadingFactory = new LoadingFactory(); + loadingManager = new LoadingManager(); exportTable = new MainPanel(); setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index f9de4e0..b75cf70 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -1,5 +1,6 @@ package org.vcell.N5.UI; +import ij.ImagePlus; import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; @@ -41,7 +42,7 @@ public N5ExportTable(){} public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPanel exportDetailsPanel){ this.controlPanel = controlButtonsPanel; this.exportDetailsPanel = exportDetailsPanel; - N5ImageHandler.loadingFactory.addSimLoadingListener(this); + N5ImageHandler.loadingManager.addSimLoadingListener(this); n5ExportTableModel = new N5ExportTableModel(); exportListTable = new JTable(n5ExportTableModel); this.setViewportView(exportListTable); @@ -181,7 +182,7 @@ public void openSelectedRows(boolean inMemory){ SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); filesToOpen.add(simResultsLoader); } - N5ImageHandler.loadingFactory.openN5FileDataset(filesToOpen, inMemory); + N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, inMemory); } public void copySelectedRowLink(){ @@ -227,7 +228,7 @@ public void valueChanged(ListSelectionEvent e) { public void removeFromLoadingRows(){ int row = exportListTable.getSelectedRow(); - N5ImageHandler.loadingFactory.stopOpeningSimulation(n5ExportTableModel.tableData.get(row).jobID); + N5ImageHandler.loadingManager.stopOpeningSimulation(n5ExportTableModel.tableData.get(row).jobID); loadingRowsJobID.remove(row); exportListTable.repaint(); } @@ -239,10 +240,11 @@ public void simIsLoading(int itemRow, String exportID) { } @Override - public void simFinishedLoading(int itemRow, String exportID) { + public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus) { loadingRowsJobID.remove(itemRow); exportListTable.repaint(); controlPanel.allowCancel(false); + imagePlus.show(); } static class N5ExportTableModel extends AbstractTableModel { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index 6f0f827..ec9c518 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -96,7 +96,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); - N5ImageHandler.loadingFactory.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false); + N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false); this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java index 5a10dcf..f673a79 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java @@ -75,7 +75,7 @@ public void displayGUI(){ 0, 0, 0, 5, saveToFile.getSelectedFile() ); - N5ImageHandler.loadingFactory.addSimLoadingListener(dataReduction); + N5ImageHandler.loadingManager.addSimLoadingListener(dataReduction); }); thread.start(); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java similarity index 91% rename from view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java rename to view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index a673257..63a75d9 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingFactory.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -18,7 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; -public class LoadingFactory implements SimLoadingEventCreator { +public class LoadingManager implements SimLoadingEventCreator { private static final EventListenerList eventListenerList = new EventListenerList(); private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; @@ -35,6 +35,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o for (int i = 0; i < filesToOpen.size(); i++){ SimResultsLoader simResultsLoader = filesToOpen.get(i); Thread openThread = new Thread(() -> { + ImagePlus imagePlus = null; try{ simResultsLoader.createS3ClientAndReader(); notifySimIsLoading(simResultsLoader); @@ -44,12 +45,11 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o rangeSelector = new RangeSelector(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader.userSetFileName); rangeSelector.displayRangeMenu(); if (!rangeSelector.cancel){ - openInMemory(simResultsLoader, rangeSelector); + imagePlus = openInMemory(simResultsLoader, rangeSelector); } rangeSelector.dispose(); } else{ - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - imagePlus.show(); + imagePlus = simResultsLoader.getImgPlusFromN5File(); } } catch (RuntimeException e) { @@ -65,7 +65,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } finally { MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); controlButtonsPanel.enableCriticalButtons(true); - notifySimIsDoneLoading(simResultsLoader); + notifySimIsDoneLoading(simResultsLoader, imagePlus); synchronized (openSimulationsLock){ openingSimulations.remove(simResultsLoader.exportID); } @@ -79,7 +79,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } } - private void openInMemory(SimResultsLoader simResultsLoader, RangeSelector rangeSelector) throws IOException { + private ImagePlus openInMemory(SimResultsLoader simResultsLoader, RangeSelector rangeSelector) throws IOException { ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); long start = System.currentTimeMillis(); logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory"); @@ -87,7 +87,7 @@ private void openInMemory(SimResultsLoader simResultsLoader, RangeSelector range rangeSelector.endZ, rangeSelector.startT, rangeSelector.endT); long end = System.currentTimeMillis(); logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s"); - imagePlus.show(); + return imagePlus; } public void stopOpeningSimulation(String exportID){ @@ -145,9 +145,9 @@ public void notifySimIsLoading(SimResultsLoader simResultsLoader) { } @Override - public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader) { + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader, ImagePlus imagePlus) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID); + simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID, imagePlus); } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java index 2a0a357..a69ac7e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingEventCreator.java @@ -1,10 +1,12 @@ package org.vcell.N5.retrieving; +import ij.ImagePlus; + public interface SimLoadingEventCreator { public void addSimLoadingListener(SimLoadingListener simLoadingListener); public void notifySimIsLoading(SimResultsLoader simResultsLoader); - public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader); + public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader, ImagePlus imagePlus); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java index d2ddf09..a53f46d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java @@ -1,11 +1,13 @@ package org.vcell.N5.retrieving; +import ij.ImagePlus; + import java.util.EventListener; public interface SimLoadingListener extends EventListener { public void simIsLoading(int itemRow, String exportID); - public void simFinishedLoading(int itemRow, String exportID); + public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus); } From 912e0333611b851b998b028cb638688eb2a1c71e Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 21 Oct 2024 07:30:03 -0400 Subject: [PATCH 04/44] Integrate New Time Filter --- .../org/vcell/N5/UI/ControlButtonsPanel.java | 68 +------------ .../org/vcell/N5/UI/Filters/TimeFilter.java | 95 +++++++++++++++++++ .../main/java/org/vcell/N5/UI/MainPanel.java | 13 ++- .../java/org/vcell/N5/UI/N5ExportTable.java | 16 ++-- 4 files changed, 118 insertions(+), 74 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 9eb0579..5e51007 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -19,12 +19,6 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private final JButton useN5Link; private final JButton questionMark; private final JButton openInMemory; - private final JCheckBox includeExampleExports; - private final JCheckBox todayInterval; - private final JCheckBox monthInterval; - private final JCheckBox yearlyInterval; - private final JCheckBox anyInterval; - private final JPanel timeFilter; private N5ExportTable n5ExportTable; private RemoteFileSelection remoteFileSelection; @@ -37,8 +31,6 @@ public ControlButtonsPanel(){ questionMark.setPreferredSize(new Dimension(20, 20)); openInMemory = new JButton("Open In Memory"); openInMemory.setSelected(false); - includeExampleExports = new JCheckBox("Show Example Exports"); - includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); GridBagConstraints gridBagConstraints = new GridBagConstraints(); @@ -72,38 +64,15 @@ public ControlButtonsPanel(){ // buttonsPanel.add(questionMark); - todayInterval = new JCheckBox("Past 24 Hours"); - monthInterval = new JCheckBox("Past Month"); - yearlyInterval = new JCheckBox("Past Year"); - anyInterval = new JCheckBox("Any Time"); - anyInterval.setSelected(true); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(todayInterval); - buttonGroup.add(monthInterval); - buttonGroup.add(yearlyInterval); - buttonGroup.add(anyInterval); - - JPanel filters = new JPanel(); - filters.setLayout(new BorderLayout()); - timeFilter = new JPanel(new GridBagLayout()); - timeFilter.add(anyInterval); - timeFilter.add(todayInterval); - timeFilter.add(monthInterval); - timeFilter.add(yearlyInterval); -// timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); - filters.add(timeFilter, BorderLayout.NORTH); - filters.add(includeExampleExports, BorderLayout.SOUTH); - Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); - filters.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); + int paneWidth = 800; this.setPreferredSize(new Dimension(paneWidth, 100)); this.setLayout(new BorderLayout()); // topBar.add(openLocal); + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); this.add(userButtonsPanel, BorderLayout.EAST); - this.add(filters, BorderLayout.WEST); this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " User Options ")); @@ -111,14 +80,10 @@ public ControlButtonsPanel(){ copyLink.addActionListener(this); questionMark.addActionListener(this); useN5Link.addActionListener(this); - includeExampleExports.addActionListener(this); // openLocal.addActionListener(this); openInMemory.addActionListener(this); - Enumeration b = buttonGroup.getElements(); - while (b.hasMoreElements()){ - b.nextElement().addActionListener(this); - } + openOrCancel.setEnabled(false); copyLink.setEnabled(false); @@ -144,34 +109,7 @@ public void actionPerformed(ActionEvent e) { new HelpExplanation().displayHelpMenu(); } else if (e.getSource().equals(useN5Link)) { remoteFileSelection.setVisible(true); - } else if (e.getSource().equals(includeExampleExports)){ - if(includeExampleExports.isSelected()){ - n5ExportTable.updateExampleExportsToTable(); - return; - } - n5ExportTable.updateTableData(); - } else if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) - || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { - if(includeExampleExports.isSelected()){ - n5ExportTable.updateExampleExportsToTable(); - return; - } - n5ExportTable.updateTableData(); - } - } - - public LocalDateTime oldestTimeAllowed(){ - LocalDateTime pastTime = LocalDateTime.now(); - if (todayInterval.isSelected()){ - pastTime = pastTime.minusDays(1); - } else if (monthInterval.isSelected()) { - pastTime = pastTime.minusMonths(1); - } else if (yearlyInterval.isSelected()) { - pastTime = pastTime.minusYears(1); - } else { - pastTime = pastTime.minusYears(10); //Max date back is 10 years } - return pastTime; } public void allowCancel(boolean allow){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java new file mode 100644 index 0000000..bf2e7c5 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java @@ -0,0 +1,95 @@ +package org.vcell.N5.UI.Filters; + +import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.UI.N5ExportTable; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.time.LocalDateTime; +import java.util.Enumeration; + + +public class TimeFilter extends JPanel implements ActionListener { + private final JCheckBox todayInterval; + private final JCheckBox monthInterval; + private final JCheckBox yearlyInterval; + private final JCheckBox anyInterval; + private final JPanel timeFilter; + private final JCheckBox includeExampleExports; + + private final N5ExportTable n5ExportTable; + + + public TimeFilter(){ + includeExampleExports = new JCheckBox("Show Example Exports"); + includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); + n5ExportTable = MainPanel.n5ExportTable; + + todayInterval = new JCheckBox("Past 24 Hours"); + monthInterval = new JCheckBox("Past Month"); + yearlyInterval = new JCheckBox("Past Year"); + anyInterval = new JCheckBox("Any Time"); + anyInterval.setSelected(true); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(todayInterval); + buttonGroup.add(monthInterval); + buttonGroup.add(yearlyInterval); + buttonGroup.add(anyInterval); + + this.setLayout(new BorderLayout()); + timeFilter = new JPanel(new GridBagLayout()); + timeFilter.add(anyInterval); + timeFilter.add(todayInterval); + timeFilter.add(monthInterval); + timeFilter.add(yearlyInterval); +// timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); + this.add(timeFilter, BorderLayout.NORTH); + this.add(includeExampleExports, BorderLayout.SOUTH); + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); + + Enumeration b = buttonGroup.getElements(); + while (b.hasMoreElements()){ + b.nextElement().addActionListener(this); + } + includeExampleExports.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) + || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { + if(includeExampleExports.isSelected()){ + n5ExportTable.updateExampleExportsToTable(); + return; + } + n5ExportTable.updateTableData(); + } else if (e.getSource().equals(includeExampleExports)){ + if(includeExampleExports.isSelected()){ + n5ExportTable.updateExampleExportsToTable(); + return; + } + n5ExportTable.updateTableData(); + } + } + + public LocalDateTime oldestTimeAllowed(){ + LocalDateTime pastTime = LocalDateTime.now(); + if (todayInterval.isSelected()){ + pastTime = pastTime.minusDays(1); + } else if (monthInterval.isSelected()) { + pastTime = pastTime.minusMonths(1); + } else if (yearlyInterval.isSelected()) { + pastTime = pastTime.minusYears(1); + } else { + pastTime = pastTime.minusYears(10); //Max date back is 10 years + } + return pastTime; + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index a49f5b7..efeba55 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -1,5 +1,7 @@ package org.vcell.N5.UI; +import org.vcell.N5.UI.Filters.TimeFilter; + import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; @@ -11,21 +13,26 @@ public class MainPanel { private final int paneWidth = 800; public final static ControlButtonsPanel controlButtonsPanel = new ControlButtonsPanel(); - public final N5ExportTable n5ExportTable = new N5ExportTable(); + public final static N5ExportTable n5ExportTable = new N5ExportTable(); public final ExportDetailsPanel exportDetailsPanel = new ExportDetailsPanel(); public final RemoteFileSelection remoteFileSelection = new RemoteFileSelection(); + public final TimeFilter timeFilter = new TimeFilter(); public MainPanel(){ JPanel parentPanel = new JPanel(); - n5ExportTable.initialize(controlButtonsPanel, exportDetailsPanel); + n5ExportTable.initialize(controlButtonsPanel, exportDetailsPanel, timeFilter); controlButtonsPanel.initialize(n5ExportTable, remoteFileSelection); + JPanel bottomPortion = new JPanel(new BorderLayout()); + bottomPortion.add(timeFilter, BorderLayout.NORTH); + bottomPortion.add(exportDetailsPanel, BorderLayout.SOUTH); + parentPanel.setLayout(new BorderLayout()); parentPanel.add(controlButtonsPanel, BorderLayout.NORTH); - JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, exportDetailsPanel); + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, bottomPortion); jSplitPane.setContinuousLayout(true); parentPanel.add(jSplitPane, BorderLayout.CENTER); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index b75cf70..2b2c6b7 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -4,6 +4,7 @@ import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.Filters.TimeFilter; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; @@ -33,15 +34,18 @@ public class N5ExportTable extends JScrollPane implements ListSelectionListener, private ControlButtonsPanel controlPanel; private ExportDetailsPanel exportDetailsPanel; + private TimeFilter timeFilter; private final Logger logger = N5ImageHandler.getLogger(N5ExportTable.class); public N5ExportTable(){} - public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPanel exportDetailsPanel){ + public void initialize(ControlButtonsPanel controlButtonsPanel, ExportDetailsPanel exportDetailsPanel, + TimeFilter timeFilter){ this.controlPanel = controlButtonsPanel; this.exportDetailsPanel = exportDetailsPanel; + this.timeFilter = timeFilter; N5ImageHandler.loadingManager.addSimLoadingListener(this); n5ExportTableModel = new N5ExportTableModel(); exportListTable = new JTable(n5ExportTableModel); @@ -81,12 +85,12 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole automaticRefresh(); } - void updateTableData(){ + public void updateTableData(){ // when initializing it is null if (controlPanel == null){ updateTableData(LocalDateTime.now().minusYears(10)); } else { - updateTableData(controlPanel.oldestTimeAllowed()); + updateTableData(timeFilter.oldestTimeAllowed()); } } @@ -111,12 +115,12 @@ void updateTableData(LocalDateTime oldestTimeAllowed){ } } - void updateExampleExportsToTable(){ + public void updateExampleExportsToTable(){ // when initializing it is null if (controlPanel == null){ updateExampleExportsToTable(LocalDateTime.now().minusYears(10)); } else { - updateExampleExportsToTable(controlPanel.oldestTimeAllowed()); + updateExampleExportsToTable(timeFilter.oldestTimeAllowed()); } } @@ -155,7 +159,7 @@ private void automaticRefresh(){ || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ break; } - isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), controlPanel.oldestTimeAllowed()); + isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), timeFilter.oldestTimeAllowed()); } if(isUpdated){ n5ExportTableModel.fireTableDataChanged(); From 47c4908aebca2a0f3bda031453c80a1c8bfdff27 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 21 Oct 2024 09:41:38 -0400 Subject: [PATCH 05/44] Advanced Features Panel --- .../org/vcell/N5/UI/AdvancedFeatures.java | 26 +++++++++ .../org/vcell/N5/UI/ControlButtonsPanel.java | 53 ++++++++++++------- .../org/vcell/N5/UI/Filters/TimeFilter.java | 13 +---- .../main/java/org/vcell/N5/UI/MainPanel.java | 2 +- 4 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java new file mode 100644 index 0000000..16c5a97 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java @@ -0,0 +1,26 @@ +package org.vcell.N5.UI; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; + +public class AdvancedFeatures extends JPanel { + public final JCheckBox inMemory; + private JCheckBox dataReduction; + private JCheckBox rangeSelection; + + + public AdvancedFeatures(){ + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + + inMemory = new JCheckBox("Open In Memory"); + dataReduction = new JCheckBox("Data Reduction"); + rangeSelection = new JCheckBox("Select Range"); + + add(inMemory); + add(dataReduction); + add(rangeSelection); + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Advanced Features ")); + } + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 5e51007..0a9f861 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -18,19 +18,25 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private final JButton copyLink; private final JButton useN5Link; private final JButton questionMark; - private final JButton openInMemory; + + public final JCheckBox includeExampleExports; + public final JCheckBox displayAdvancedFeatures; private N5ExportTable n5ExportTable; private RemoteFileSelection remoteFileSelection; + private final AdvancedFeatures advancedFeatures = new AdvancedFeatures(); public ControlButtonsPanel(){ + includeExampleExports = new JCheckBox("Show Example Exports"); + includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); + + displayAdvancedFeatures = new JCheckBox("Advanced Features"); + openOrCancel = new JButton("Open"); copyLink = new JButton("Copy Link"); useN5Link = new JButton("Use N5 Link"); questionMark = new JButton("?"); questionMark.setPreferredSize(new Dimension(20, 20)); - openInMemory = new JButton("Open In Memory"); - openInMemory.setSelected(false); GridBagConstraints gridBagConstraints = new GridBagConstraints(); @@ -38,20 +44,20 @@ public ControlButtonsPanel(){ gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; topRow.add(openOrCancel, gridBagConstraints); - gridBagConstraints.gridwidth = 1; gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - topRow.add(openInMemory, gridBagConstraints); + topRow.add(copyLink, gridBagConstraints); + gridBagConstraints.gridx = 2; + topRow.add(useN5Link, gridBagConstraints); + + gridBagConstraints.gridx = 3; + topRow.add(questionMark); JPanel bottomRow = new JPanel(new GridBagLayout()); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - bottomRow.add(copyLink, gridBagConstraints); + bottomRow.add(includeExampleExports); gridBagConstraints.gridx = 1; - bottomRow.add(useN5Link, gridBagConstraints); - bottomRow.add(questionMark); + bottomRow.add(displayAdvancedFeatures, gridBagConstraints); JPanel userButtonsPanel = new JPanel(new GridBagLayout()); @@ -68,26 +74,28 @@ public ControlButtonsPanel(){ int paneWidth = 800; - this.setPreferredSize(new Dimension(paneWidth, 100)); + this.setPreferredSize(new Dimension(paneWidth, 80)); this.setLayout(new BorderLayout()); // topBar.add(openLocal); Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); this.add(userButtonsPanel, BorderLayout.EAST); this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " User Options ")); + advancedFeatures.setVisible(false); + add(advancedFeatures, BorderLayout.WEST); + openOrCancel.addActionListener(this); copyLink.addActionListener(this); questionMark.addActionListener(this); useN5Link.addActionListener(this); // openLocal.addActionListener(this); - openInMemory.addActionListener(this); - + includeExampleExports.addActionListener(this); + displayAdvancedFeatures.addActionListener(this); openOrCancel.setEnabled(false); copyLink.setEnabled(false); - openInMemory.setEnabled(false); } public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFileSelection){ @@ -97,11 +105,11 @@ public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFi @Override public void actionPerformed(ActionEvent e) { - if(e.getSource().equals(openOrCancel) || e.getSource().equals(openInMemory)){ + if(e.getSource().equals(openOrCancel)){ if (openOrCancel.getText().equals("Cancel")){ n5ExportTable.removeFromLoadingRows(); } else { - n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); + n5ExportTable.openSelectedRows(advancedFeatures.inMemory.isSelected()); } } else if (e.getSource().equals(copyLink)) { n5ExportTable.copySelectedRowLink(); @@ -109,13 +117,20 @@ public void actionPerformed(ActionEvent e) { new HelpExplanation().displayHelpMenu(); } else if (e.getSource().equals(useN5Link)) { remoteFileSelection.setVisible(true); + } else if (e.getSource().equals(includeExampleExports)){ + if(includeExampleExports.isSelected()){ + n5ExportTable.updateExampleExportsToTable(); + return; + } + n5ExportTable.updateTableData(); + } else if (e.getSource().equals(displayAdvancedFeatures)) { + advancedFeatures.setVisible(displayAdvancedFeatures.isSelected()); } } public void allowCancel(boolean allow){ openOrCancel.setEnabled(true); copyLink.setEnabled(true); - openInMemory.setEnabled(!allow); useN5Link.setEnabled(true); remoteFileSelection.submitS3Info.setEnabled(true); if (allow){ @@ -128,7 +143,6 @@ public void allowCancel(boolean allow){ public void enableRowContextDependentButtons(boolean enable){ openOrCancel.setEnabled(enable); copyLink.setEnabled(enable); - openInMemory.setEnabled(enable); } public void enableCriticalButtons(boolean enable){ @@ -136,6 +150,5 @@ public void enableCriticalButtons(boolean enable){ openOrCancel.setEnabled(enable); copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); - openInMemory.setEnabled(enable); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java index bf2e7c5..1925766 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java @@ -20,14 +20,11 @@ public class TimeFilter extends JPanel implements ActionListener { private final JCheckBox yearlyInterval; private final JCheckBox anyInterval; private final JPanel timeFilter; - private final JCheckBox includeExampleExports; private final N5ExportTable n5ExportTable; public TimeFilter(){ - includeExampleExports = new JCheckBox("Show Example Exports"); - includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); n5ExportTable = MainPanel.n5ExportTable; todayInterval = new JCheckBox("Past 24 Hours"); @@ -50,7 +47,6 @@ public TimeFilter(){ timeFilter.add(yearlyInterval); // timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); this.add(timeFilter, BorderLayout.NORTH); - this.add(includeExampleExports, BorderLayout.SOUTH); Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); @@ -58,20 +54,13 @@ public TimeFilter(){ while (b.hasMoreElements()){ b.nextElement().addActionListener(this); } - includeExampleExports.addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { - if(includeExampleExports.isSelected()){ - n5ExportTable.updateExampleExportsToTable(); - return; - } - n5ExportTable.updateTableData(); - } else if (e.getSource().equals(includeExampleExports)){ - if(includeExampleExports.isSelected()){ + if(MainPanel.controlButtonsPanel.includeExampleExports.isSelected()){ n5ExportTable.updateExampleExportsToTable(); return; } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index efeba55..ee6acc7 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -16,7 +16,7 @@ public class MainPanel { public final static N5ExportTable n5ExportTable = new N5ExportTable(); public final ExportDetailsPanel exportDetailsPanel = new ExportDetailsPanel(); public final RemoteFileSelection remoteFileSelection = new RemoteFileSelection(); - public final TimeFilter timeFilter = new TimeFilter(); + public final static TimeFilter timeFilter = new TimeFilter(); public MainPanel(){ From 9d2d4b9080857c1ce2bdfb5e8f2b39df00a73fce Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 22 Oct 2024 08:09:35 -0400 Subject: [PATCH 06/44] Add Search Bar --- .../org/vcell/N5/UI/ControlButtonsPanel.java | 6 -- .../org/vcell/N5/UI/Filters/SearchBar.java | 37 +++++++ .../org/vcell/N5/UI/Filters/TimeFilter.java | 5 +- .../main/java/org/vcell/N5/UI/MainPanel.java | 21 ++-- .../java/org/vcell/N5/UI/N5ExportTable.java | 99 +++++++------------ 5 files changed, 90 insertions(+), 78 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/SearchBar.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 0a9f861..bcc14cc 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -8,8 +8,6 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.time.LocalDateTime; -import java.util.Enumeration; public class ControlButtonsPanel extends JPanel implements ActionListener { @@ -118,10 +116,6 @@ public void actionPerformed(ActionEvent e) { } else if (e.getSource().equals(useN5Link)) { remoteFileSelection.setVisible(true); } else if (e.getSource().equals(includeExampleExports)){ - if(includeExampleExports.isSelected()){ - n5ExportTable.updateExampleExportsToTable(); - return; - } n5ExportTable.updateTableData(); } else if (e.getSource().equals(displayAdvancedFeatures)) { advancedFeatures.setVisible(displayAdvancedFeatures.isSelected()); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/SearchBar.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/SearchBar.java new file mode 100644 index 0000000..cc0db5d --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/SearchBar.java @@ -0,0 +1,37 @@ +package org.vcell.N5.UI.Filters; + +import org.vcell.N5.UI.MainPanel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +public class SearchBar extends JPanel implements KeyListener { + public static final JTextField searchTextField = new JTextField(); + + public SearchBar(){ + this.add(new JLabel("Search: ")); + searchTextField.setPreferredSize(new Dimension(600, 20)); + searchTextField.addKeyListener(this); + this.add(searchTextField); +// this.setPreferredSize(new Dimension(600, 20)); + } + + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getSource().equals(searchTextField)){ + MainPanel.n5ExportTable.updateTableData(searchTextField.getText()); + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java index 1925766..6a29fd7 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/Filters/TimeFilter.java @@ -1,6 +1,5 @@ package org.vcell.N5.UI.Filters; -import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; @@ -47,8 +46,6 @@ public TimeFilter(){ timeFilter.add(yearlyInterval); // timeFilter.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Time ")); this.add(timeFilter, BorderLayout.NORTH); - Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); - this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); Enumeration b = buttonGroup.getElements(); while (b.hasMoreElements()){ @@ -61,7 +58,7 @@ public void actionPerformed(ActionEvent e) { if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { if(MainPanel.controlButtonsPanel.includeExampleExports.isSelected()){ - n5ExportTable.updateExampleExportsToTable(); + n5ExportTable.updateTableData(); return; } n5ExportTable.updateTableData(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index ee6acc7..6a05bb6 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -1,8 +1,11 @@ package org.vcell.N5.UI; +import org.vcell.N5.UI.Filters.SearchBar; import org.vcell.N5.UI.Filters.TimeFilter; import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import java.awt.*; @@ -17,7 +20,7 @@ public class MainPanel { public final ExportDetailsPanel exportDetailsPanel = new ExportDetailsPanel(); public final RemoteFileSelection remoteFileSelection = new RemoteFileSelection(); public final static TimeFilter timeFilter = new TimeFilter(); - + public final static SearchBar searchBar = new SearchBar(); public MainPanel(){ JPanel parentPanel = new JPanel(); @@ -26,16 +29,22 @@ public MainPanel(){ n5ExportTable.initialize(controlButtonsPanel, exportDetailsPanel, timeFilter); controlButtonsPanel.initialize(n5ExportTable, remoteFileSelection); - JPanel bottomPortion = new JPanel(new BorderLayout()); - bottomPortion.add(timeFilter, BorderLayout.NORTH); - bottomPortion.add(exportDetailsPanel, BorderLayout.SOUTH); + JPanel northPanel = new JPanel(new BorderLayout()); + northPanel.add(controlButtonsPanel, BorderLayout.SOUTH); parentPanel.setLayout(new BorderLayout()); - parentPanel.add(controlButtonsPanel, BorderLayout.NORTH); - JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, bottomPortion); + parentPanel.add(northPanel, BorderLayout.NORTH); + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, exportDetailsPanel); jSplitPane.setContinuousLayout(true); parentPanel.add(jSplitPane, BorderLayout.CENTER); + JPanel filters = new JPanel(new BorderLayout()); + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + filters.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); + filters.add(timeFilter, BorderLayout.NORTH); + filters.add(searchBar, BorderLayout.SOUTH); + parentPanel.add(filters, BorderLayout.SOUTH); + parentPanel.setPreferredSize(new Dimension(paneWidth, 650)); JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); exportTableDialog = pane.createDialog("VCell Exports"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 2b2c6b7..e6b9253 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -4,6 +4,7 @@ import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.Filters.SearchBar; import org.vcell.N5.UI.Filters.TimeFilter; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; @@ -76,38 +77,41 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); exportListTable.getSelectionModel().addListSelectionListener(this); - if(!N5ImageHandler.exportedDataExists()){ - updateExampleExportsToTable(); - } - else{ - updateTableData(); - } + updateTableData(""); automaticRefresh(); } public void updateTableData(){ + updateTableData(SearchBar.searchTextField.getText()); + } + + public void updateTableData(String strFilter){ // when initializing it is null if (controlPanel == null){ - updateTableData(LocalDateTime.now().minusYears(10)); + updateTableData(LocalDateTime.now().minusYears(10), strFilter); } else { - updateTableData(timeFilter.oldestTimeAllowed()); + updateTableData(timeFilter.oldestTimeAllowed(), strFilter); } } - void updateTableData(LocalDateTime oldestTimeAllowed){ + void updateTableData(LocalDateTime oldestTimeAllowed, String strFilter){ n5ExportTableModel.resetData(); - this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Personal Exports")); + if (!controlPanel.includeExampleExports.isSelected()){ + this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Personal Exports")); + } else { + this.setBorder(exampleBorder); + } try { - ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.getJsonData(); - if (formatExportData != null){ - Stack jobStack = formatExportData.formatJobIDs; - while (!jobStack.isEmpty()){ - String jobID = jobStack.pop(); - if (!n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(jobID), oldestTimeAllowed)){ - break; - } - } + ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.exportedDataExists() && !controlPanel.includeExampleExports.isSelected() ? + N5ImageHandler.getJsonData() : N5ImageHandler.getExampleJSONData(); + + Stack jobStack = (Stack) formatExportData.formatJobIDs.clone(); + while (!jobStack.isEmpty()){ + String jobID = jobStack.pop(); + n5ExportTableModel.addToRowData(formatExportData.simulationDataMap.get(jobID), oldestTimeAllowed, + strFilter, true); } + n5ExportTableModel.fireTableDataChanged(); this.updateUI(); } catch (FileNotFoundException e) { @@ -115,41 +119,12 @@ void updateTableData(LocalDateTime oldestTimeAllowed){ } } - public void updateExampleExportsToTable(){ - // when initializing it is null - if (controlPanel == null){ - updateExampleExportsToTable(LocalDateTime.now().minusYears(10)); - } else { - updateExampleExportsToTable(timeFilter.oldestTimeAllowed()); - } - } - - void updateExampleExportsToTable(LocalDateTime oldestTimeAllowed){ - n5ExportTableModel.resetData(); - this.setBorder(exampleBorder); - try{ - ExportDataRepresentation.FormatExportDataRepresentation exampleFormatExportData = N5ImageHandler.getExampleJSONData(); - Stack exampleJobStack = (Stack) exampleFormatExportData.formatJobIDs.clone(); - while (!exampleJobStack.isEmpty()){ - String jobID = exampleJobStack.pop(); - if (!n5ExportTableModel.appendRowData(exampleFormatExportData.simulationDataMap.get(jobID), oldestTimeAllowed)){ - break; - } - } - n5ExportTableModel.fireTableDataChanged(); - this.updateUI(); - } - catch (FileNotFoundException e){ - throw new RuntimeException("Can't open example N5 export table.", e); - } - } - private void automaticRefresh(){ Thread refreshTableThread = new Thread(() -> { try { while(true){ ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.getJsonData(); - if (formatExportData != null && !this.getBorder().equals(exampleBorder)){ + if (formatExportData != null && !controlPanel.includeExampleExports.isSelected()){ ExportDataRepresentation.SimulationExportDataRepresentation mostRecentTableEntry = !n5ExportTableModel.tableData.isEmpty() ? n5ExportTableModel.tableData.getFirst() : null; Stack jobStack = formatExportData.formatJobIDs; boolean isUpdated = false; @@ -159,7 +134,9 @@ private void automaticRefresh(){ || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ break; } - isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), timeFilter.oldestTimeAllowed()); + isUpdated = n5ExportTableModel.addToRowData(formatExportData.simulationDataMap.get(currentJob), + timeFilter.oldestTimeAllowed(), SearchBar.searchTextField.getText(), + false); } if(isUpdated){ n5ExportTableModel.fireTableDataChanged(); @@ -306,23 +283,21 @@ public ExportDataRepresentation.SimulationExportDataRepresentation getRowData(in public void resetData(){ tableData = new LinkedList<>(); } - public boolean appendRowData(ExportDataRepresentation.SimulationExportDataRepresentation rowData, LocalDateTime oldestExportAllowed){ - DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime exportDate = LocalDateTime.parse(rowData.exportDate, dateFormat); - if (exportDate.isBefore(oldestExportAllowed)){ - return false; - } - tableData.add(rowData); - return true; + private boolean stringFilter(ExportDataRepresentation.SimulationExportDataRepresentation rowData, String strFilter){ + return rowData.biomodelName.contains(strFilter) || rowData.applicationName.contains(strFilter) || + rowData.simulationName.contains(strFilter) || rowData.savedFileName.contains(strFilter); } - - public boolean prependRowData(ExportDataRepresentation.SimulationExportDataRepresentation rowData, LocalDateTime oldestExportAllowed){ + public boolean addToRowData(ExportDataRepresentation.SimulationExportDataRepresentation rowData, LocalDateTime oldestExportAllowed, String strFilter, boolean append){ DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime exportDate = LocalDateTime.parse(rowData.exportDate, dateFormat); - if (exportDate.isBefore(oldestExportAllowed)){ + if (exportDate.isBefore(oldestExportAllowed) || !stringFilter(rowData, strFilter)){ return false; } - tableData.addFirst(rowData); + if (append){ + tableData.add(rowData); + } else { + tableData.addFirst(rowData); + } return true; } From ce35f5287e171cbf12fba18767e08dc6746d4213 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 24 Oct 2024 09:07:22 -0400 Subject: [PATCH 07/44] Functional GUI For Data Reduction You can now go through the entire process of data reduction through the GUI. --- .../org/vcell/N5/UI/AdvancedFeatures.java | 4 +- .../org/vcell/N5/UI/ControlButtonsPanel.java | 4 +- .../java/org/vcell/N5/UI/N5ExportTable.java | 6 +- .../java/org/vcell/N5/UI/RangeSelector.java | 37 ++--- .../org/vcell/N5/UI/RemoteFileSelection.java | 5 +- .../org/vcell/N5/analysis/DataReduction.java | 70 ++++----- ...AnalysisGUI.java => DataReductionGUI.java} | 141 +++++++++--------- .../vcell/N5/retrieving/LoadingManager.java | 105 +++++++------ .../vcell/N5/retrieving/SimResultsLoader.java | 18 ++- 9 files changed, 202 insertions(+), 188 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/analysis/{TemporalAnalysisGUI.java => DataReductionGUI.java} (53%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java index 16c5a97..31d1834 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java @@ -6,8 +6,8 @@ public class AdvancedFeatures extends JPanel { public final JCheckBox inMemory; - private JCheckBox dataReduction; - private JCheckBox rangeSelection; + public final JCheckBox dataReduction; + public final JCheckBox rangeSelection; public AdvancedFeatures(){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index bcc14cc..83b2d52 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -22,7 +22,7 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private N5ExportTable n5ExportTable; private RemoteFileSelection remoteFileSelection; - private final AdvancedFeatures advancedFeatures = new AdvancedFeatures(); + public final AdvancedFeatures advancedFeatures = new AdvancedFeatures(); public ControlButtonsPanel(){ includeExampleExports = new JCheckBox("Show Example Exports"); @@ -107,7 +107,7 @@ public void actionPerformed(ActionEvent e) { if (openOrCancel.getText().equals("Cancel")){ n5ExportTable.removeFromLoadingRows(); } else { - n5ExportTable.openSelectedRows(advancedFeatures.inMemory.isSelected()); + n5ExportTable.openSelectedRows(); } } else if (e.getSource().equals(copyLink)) { n5ExportTable.copySelectedRowLink(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index e6b9253..cf21e7f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -155,7 +155,7 @@ private void automaticRefresh(){ refreshTableThread.start(); } - public void openSelectedRows(boolean inMemory){ + public void openSelectedRows(){ ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; @@ -163,7 +163,9 @@ public void openSelectedRows(boolean inMemory){ SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); filesToOpen.add(simResultsLoader); } - N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, inMemory); + AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; + N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, advancedFeatures.inMemory.isSelected(), + advancedFeatures.rangeSelection.isSelected(), advancedFeatures.dataReduction.isSelected()); } public void copySelectedRowLink(){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java index feb47c8..d5ed49d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java @@ -19,35 +19,39 @@ public class RangeSelector extends JDialog implements ActionListener { public int startZ; public int endZ; - private final JTextField channelStartTextField; - private final JTextField channelEndTextField; - private final JTextField timeStartTextField; - private final JTextField timeEndTextField; - private final JTextField zStartTextField; - private final JTextField zEndTextField; + private JTextField channelStartTextField; + private JTextField channelEndTextField; + private JTextField timeStartTextField; + private JTextField timeEndTextField; + private JTextField zStartTextField; + private JTextField zEndTextField; public boolean cancel; private static final String okayButtonText = "Okay"; private static final String cancelButtonText = "Cancel"; - public final JButton okayButton; - public final JButton cancelButton; - private final JFrame frame; + public JButton okayButton; + public JButton cancelButton; + private JFrame frame; - private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); private static final EventListenerList eventListenerList = new EventListenerList(); private final ControlButtonsPanel controlButtonsPanel = MainPanel.controlButtonsPanel; - public RangeSelector(double cDim, double zDim, double tDim, String userSetFileName){ - channelStartTextField = new HintTextField("1"); + public RangeSelector(){ + + } + + public void displayRangeMenu(double cDim, double zDim, double tDim){ channelEndTextField = new HintTextField("" + (int) cDim); + zEndTextField = new HintTextField("" + (int) zDim); + timeEndTextField = new HintTextField("" + (int) tDim); + String userSetFileName = "Range for All Images Used"; + channelStartTextField = new HintTextField("1"); zStartTextField = new HintTextField("1"); - zEndTextField = new HintTextField("" + (int) zDim); timeStartTextField = new HintTextField("1"); - timeEndTextField = new HintTextField("" + (int) tDim); // Create the frame frame = new JFrame("Select " + userSetFileName + " Dimensions"); @@ -93,15 +97,12 @@ public RangeSelector(double cDim, double zDim, double tDim, String userSetFileNa frame.add(panel); this.setContentPane(panel); this.setModal(true); - } - - public void displayRangeMenu(){ // Make the window visible this.setVisible(true); } public static void main(String[] args) { - RangeSelector inMemoryPopUp = new RangeSelector(1, 2, 3, null); + RangeSelector inMemoryPopUp = new RangeSelector(); } @Override diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index ec9c518..374adae 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -96,7 +96,10 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); - N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false); + AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; + N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, + advancedFeatures.inMemory.isSelected(), advancedFeatures.rangeSelection.isSelected(), + advancedFeatures.dataReduction.isSelected()); this.setVisible(false); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index 4d37fd2..67b0d0e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -19,11 +19,10 @@ public class DataReduction implements SimLoadingListener { private final ArrayList> csvMatrix = new ArrayList<>(); - private final double normalPreChange; - private final double normalPostChange; - private final int timeWhenChangeOccurs; + private int numOfImagesToBeOpened; + private final boolean normalize; - private int numOfSimImages; + public final DataReductionGUI.DataReductionSubmission submission; /* Open an image from file (assume 2D for now). @@ -46,64 +45,67 @@ Save to cvs file of some kind (something that can be imported into excel). // Take results and place them within a spreadsheet // Create a graph from that spreadsheet - public DataReduction(boolean normalizePostChange, boolean normalizeWithPreChangeValues, - ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, - ImagePlus labResults, int startPreChange, int endPreChange, - int timeWhenChangeOccurs, int numOfSimImages, File fileToSaveResultsTo){ - this.arrayOfSimRois = arrayOfSimRois; - this.timeWhenChangeOccurs = timeWhenChangeOccurs; - this.numOfSimImages = numOfSimImages; - this.file = fileToSaveResultsTo; + public DataReduction(DataReductionGUI.DataReductionSubmission submission){ + this.submission = submission; + this.arrayOfSimRois = submission.arrayOfSimRois; + this.numOfImagesToBeOpened = submission.numOfSimImages + 1; // Plus one for the lab image + this.file = submission.fileToSaveResultsTo; + this.normalize = submission.normalizeMeasurementsBool; ArrayList headers = new ArrayList(){{add("Time Frame");}}; csvMatrix.add(headers); - normalPreChange = normalizeWithPreChangeValues ? calculateNormalValue(labResults, startPreChange, endPreChange) : Double.MIN_NORMAL; - normalPostChange = normalizePostChange ? calculateNormalValue(labResults, timeWhenChangeOccurs, timeWhenChangeOccurs) : Double.MIN_NORMAL; + double normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, submission.imageEndPointNorm); - HashMap> reducedData = calculateMean(labResults, arrayOfLabRois); + HashMap> reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue); synchronized (csvMatrixLock){ - for (int t = 0; t < labResults.getNFrames(); t++){ + for (int t = 0; t < submission.labResults.getNFrames(); t++){ ArrayList rowForTime = new ArrayList<>(); rowForTime.add(String.valueOf(t)); csvMatrix.add(rowForTime); } } - addValuesToCSVMatrix(labResults, reducedData); + addValuesToCSVMatrix(submission.labResults, reducedData); } private void addValuesToCSVMatrix(ImagePlus imagePlus, HashMap> reducedData){ synchronized (csvMatrixLock){ csvMatrix.get(0).add(""); - csvMatrix.get(0).add(imagePlus.getTitle()); for (String roiName: reducedData.keySet()){ - csvMatrix.get(0).add(roiName); + csvMatrix.get(0).add(imagePlus.getTitle()+" : " + roiName); for(int t = 0; t < imagePlus.getNFrames(); t++){ double mean = reducedData.get(roiName).get(t); + csvMatrix.get(t + 1).add(""); csvMatrix.get(t + 1).add(String.valueOf(mean)); } } - numOfSimImages -= 1; - if (numOfSimImages == 0){ + numOfImagesToBeOpened -= 1; + if (numOfImagesToBeOpened == 0){ writeCSVMatrix(); } } } private double calculateNormalValue(ImagePlus imagePlus, int startT, int endT){ - double normal = 0; - for (int k = startT; k <= endT; k++){ - imagePlus.setT(k); - normal += imagePlus.getProcessor().getStatistics().mean; + if (normalize){ + double normal = 0; + for (int k = startT; k <= endT; k++){ + imagePlus.setT(k); + normal += imagePlus.getProcessor().getStatistics().mean; + } + normal = normal / (endT - startT); + return normal; + } else { + return Double.MIN_NORMAL; } - normal = normal / (endT - startT); - return normal; + } - private HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList){ + private HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList, + double normalizationValue){ // ResultsTable resultsTable = new ResultsTable(); HashMap> roiListOfMeans = new HashMap<>(); @@ -116,11 +118,8 @@ private HashMap> calculateMean(ImagePlus imagePlus, Ar // // double meanValue = resultsTable.getValueAsDouble(resultsTable.getColumnIndex("Mean"), 0); double meanValue = imagePlus.getProcessor().getStatistics().mean; - if (normalPreChange != Double.MIN_NORMAL){ - meanValue = meanValue / normalPreChange; - } - if (normalPostChange != Double.MIN_NORMAL && t >= timeWhenChangeOccurs){ - meanValue = meanValue / normalPostChange; + if (normalizationValue != Double.MIN_NORMAL){ + meanValue = meanValue / normalizationValue; } meanValues.add(meanValue); } @@ -135,6 +134,7 @@ private void writeCSVMatrix(){ for (ArrayList row: csvMatrix){ csvWriter.writeNext(row.toArray(new String[0])); } + csvWriter.close(); } catch (IOException e) { throw new RuntimeException(e); } @@ -148,8 +148,8 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus) { - - HashMap> calculations = calculateMean(imagePlus, arrayOfSimRois); + double normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, submission.simEndPointNorm); + HashMap> calculations = calculateMean(imagePlus, arrayOfSimRois, normValue); addValuesToCSVMatrix(imagePlus, calculations); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java similarity index 53% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index f673a79..9ea4a93 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/TemporalAnalysisGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -1,5 +1,6 @@ package org.vcell.N5.analysis; +import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; import ij.io.RoiDecoder; @@ -12,24 +13,17 @@ import java.io.File; import java.util.ArrayList; -public class TemporalAnalysisGUI extends JPanel implements ActionListener { +public class DataReductionGUI extends JPanel implements ActionListener { private JComboBox chosenImage; private JComboBox chosenMeasurement; - private JCheckBox normalizeEntireImage = new JCheckBox("Normalize Entire Image"); - private JCheckBox normalizeROI = new JCheckBox("Normalize ROI"); + private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); - private JTextField entireImageFramesFromImageStart; - private JTextField entireImageFramesFromImageEnd; - private JTextField entireImageFramesFromSimStart; - private JTextField entireImageFramesFromSimEnd; + private JTextField createNormFromImageStart; + private JTextField createNormFromImageEnd; + private JTextField createNormFromSimStart; + private JTextField createNormFromSimEnd; private JPanel entireImageFramesJPanel; - private JTextField roiFramesFromImageStart; - private JTextField roiFramesFromImageEnd; - private JTextField roiFramesFromSimStart; - private JTextField roiFramesFromSimEnd; - private JPanel roiFramesJPanel; - private JButton imageROIFileButton; private JButton simROIFileButton; @@ -43,16 +37,47 @@ public class TemporalAnalysisGUI extends JPanel implements ActionListener { private final JDialog jDialog; private final JOptionPane pane; + private File chosenFile; + + private int numSimsToOpen; + + public int mainGUIReturnValue; + public int fileChooserReturnValue; // private TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); - public TemporalAnalysisGUI(){ + public class DataReductionSubmission{ + public final boolean normalizeMeasurementsBool; + public final ArrayList arrayOfSimRois; + public final ArrayList arrayOfLabRois; + public final ImagePlus labResults; + public final int simStartPointNorm; + public final int simEndPointNorm; + public final int imageStartPointNorm; + public final int imageEndPointNorm; + public final int numOfSimImages; + public final File fileToSaveResultsTo; + public DataReductionSubmission(){ + normalizeMeasurementsBool = normalizeMeasurement.isSelected(); + arrayOfSimRois = simROIList; + arrayOfLabRois = imageROIList; + labResults = WindowManager.getImage((String) chosenImage.getSelectedItem()); + simStartPointNorm = createNormFromSimStart.getText().isEmpty() ? Integer.MIN_VALUE : Integer.parseInt(createNormFromSimStart.getText()); + simEndPointNorm = createNormFromSimEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromSimEnd.getText()); + imageStartPointNorm = createNormFromImageStart.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageStart.getText()); + imageEndPointNorm = createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()); + numOfSimImages = numSimsToOpen; + fileToSaveResultsTo = chosenFile; + } + } + + public DataReductionGUI(int numSimsToOpen){ + this.numSimsToOpen = numSimsToOpen; setLayout(new GridLayout(4, 1)); add(imageAndAnalysisType()); add(roisSelectedGUI()); - add(normalizeEntireImageGUI()); - add(normalizeROIGUI()); + add(normalizeGUI()); setSize(400, 400); setVisible(true); @@ -62,19 +87,15 @@ public TemporalAnalysisGUI(){ public void displayGUI(){ jDialog.setVisible(true); - Integer returnValue = (Integer) pane.getValue(); - if (returnValue.equals(JOptionPane.OK_OPTION)){ + mainGUIReturnValue = (Integer) pane.getValue(); + if (mainGUIReturnValue == JOptionPane.OK_OPTION){ JFileChooser saveToFile = new JFileChooser(); saveToFile.setFileSelectionMode(JFileChooser.FILES_ONLY); - int response = saveToFile.showDialog(this, "Save Results To File"); - if (response == JFileChooser.APPROVE_OPTION){ + fileChooserReturnValue = saveToFile.showDialog(this, "Save Results To File"); + if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ + chosenFile = saveToFile.getSelectedFile(); Thread thread = new Thread(() -> { - DataReduction dataReduction = new DataReduction( - normalizeROI.isSelected(), normalizeEntireImage.isSelected(), simROIList, - imageROIList, WindowManager.getImage((String) chosenImage.getSelectedItem()), - 0, 0, 0, - 5, saveToFile.getSelectedFile() - ); + DataReduction dataReduction = new DataReduction(new DataReductionSubmission()); N5ImageHandler.loadingManager.addSimLoadingListener(dataReduction); }); thread.start(); @@ -82,59 +103,33 @@ public void displayGUI(){ } } - private JPanel normalizeROIGUI(){ - JPanel jPanel = new JPanel(new GridLayout()); - normalizeROI.addActionListener(this); - - JPanel fromImage = new JPanel(new GridLayout()); - roiFramesFromImageStart = new JTextField(); - roiFramesFromImageEnd = new JTextField(); - fromImage.add(roiFramesFromImageStart); - fromImage.add(new JLabel("to")); - fromImage.add(roiFramesFromImageEnd); - - JPanel fromSim = new JPanel(new GridLayout()); - roiFramesFromSimStart = new JTextField(); - roiFramesFromSimEnd = new JTextField(); - fromSim.add(roiFramesFromSimStart); - fromSim.add(new JLabel("to")); - fromSim.add(roiFramesFromSimEnd); - - roiFramesJPanel = new JPanel(new GridLayout()); - roiFramesJPanel.add(fromImage); - roiFramesJPanel.add(fromSim); - roiFramesJPanel.setVisible(false); - - jPanel.add(normalizeROI); - jPanel.add(roiFramesJPanel); - - return jPanel; - } - - private JPanel normalizeEntireImageGUI(){ - JPanel jPanel = new JPanel(new GridLayout()); - normalizeEntireImage.addActionListener(this); + private JPanel normalizeGUI(){ + JPanel jPanel = new JPanel(new GridLayout(2, 1)); + normalizeMeasurement.addActionListener(this); + JLabel explainInput = new JLabel("Timeline Range to Create Norm"); JPanel fromImage = new JPanel(new GridLayout()); - entireImageFramesFromImageStart = new JTextField(); - entireImageFramesFromImageEnd = new JTextField(); - fromImage.add(entireImageFramesFromImageStart); + createNormFromImageStart = new JTextField(); + createNormFromImageEnd = new JTextField(); + fromImage.add(new JLabel("Exp. Timeline: ")); + fromImage.add(createNormFromImageStart); fromImage.add(new JLabel("to")); - fromImage.add(entireImageFramesFromImageEnd); + fromImage.add(createNormFromImageEnd); JPanel fromSim = new JPanel(new GridLayout()); - entireImageFramesFromSimStart = new JTextField(); - entireImageFramesFromSimEnd = new JTextField(); - fromSim.add(entireImageFramesFromSimStart); + createNormFromSimStart = new JTextField(); + createNormFromSimEnd = new JTextField(); + fromSim.add(new JLabel("Sim Timeline: ")); + fromSim.add(createNormFromSimStart); fromSim.add(new JLabel("to")); - fromSim.add(entireImageFramesFromSimEnd); + fromSim.add(createNormFromSimEnd); - entireImageFramesJPanel = new JPanel(new GridLayout()); + entireImageFramesJPanel = new JPanel(new GridLayout(2, 1)); entireImageFramesJPanel.add(fromImage); entireImageFramesJPanel.add(fromSim); entireImageFramesJPanel.setVisible(false); - jPanel.add(normalizeEntireImage); + jPanel.add(normalizeMeasurement); jPanel.add(entireImageFramesJPanel); return jPanel; } @@ -172,10 +167,8 @@ public void actionPerformed(ActionEvent e) { imageROIList = fillROIList(imageROIFileChooser); } else if (e.getSource().equals(simROIFileButton)) { simROIList = fillROIList(simROIFileChooser); - } else if (e.getSource().equals(normalizeEntireImage)) { - entireImageFramesJPanel.setVisible(normalizeEntireImage.isSelected()); - } else if (e.getSource().equals(normalizeROI)) { - roiFramesJPanel.setVisible(normalizeROI.isSelected()); + } else if (e.getSource().equals(normalizeMeasurement)) { + entireImageFramesJPanel.setVisible(normalizeMeasurement.isSelected()); } } @@ -201,8 +194,8 @@ enum AvailableMeasurements{ } public static void main(String[] args) { - TemporalAnalysisGUI temporalAnalysisGUI = new TemporalAnalysisGUI(); - temporalAnalysisGUI.displayGUI(); + DataReductionGUI dataReductionGUI = new DataReductionGUI(0); + dataReductionGUI.displayGUI(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 63a75d9..8e83d88 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -9,6 +9,7 @@ import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.analysis.DataReductionGUI; import javax.swing.*; import javax.swing.event.EventListenerList; @@ -28,68 +29,66 @@ public class LoadingManager implements SimLoadingEventCreator { private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); - public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ - controlButtonsPanel.allowCancel(true); - MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); - - for (int i = 0; i < filesToOpen.size(); i++){ - SimResultsLoader simResultsLoader = filesToOpen.get(i); - Thread openThread = new Thread(() -> { - ImagePlus imagePlus = null; - try{ - simResultsLoader.createS3ClientAndReader(); - notifySimIsLoading(simResultsLoader); - RangeSelector rangeSelector; - if (openInMemory){ - ArrayList dimensions = simResultsLoader.getN5Dimensions(); - rangeSelector = new RangeSelector(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader.userSetFileName); - rangeSelector.displayRangeMenu(); - if (!rangeSelector.cancel){ - imagePlus = openInMemory(simResultsLoader, rangeSelector); + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory, + boolean selectRange, boolean dataReduction){ + RangeSelector rangeSelector = new RangeSelector(); + if (selectRange){ + SimResultsLoader firstSim = filesToOpen.get(0); + firstSim.createS3ClientAndReader(); + ArrayList dimensions = firstSim.getN5Dimensions(); + rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); + } + DataReductionGUI dataReductionGUI = new DataReductionGUI(filesToOpen.size()); + if (dataReduction){ + dataReductionGUI.displayGUI(); + } + boolean dataReductionOkay = dataReduction && dataReductionGUI.mainGUIReturnValue == JOptionPane.OK_OPTION && dataReductionGUI.fileChooserReturnValue == JFileChooser.APPROVE_OPTION; + if (dataReductionOkay || !dataReduction){ + controlButtonsPanel.allowCancel(true); + MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); + for (int i = 0; i < filesToOpen.size(); i++){ + SimResultsLoader simResultsLoader = filesToOpen.get(i); + Thread openThread = new Thread(() -> { + ImagePlus imagePlus = null; + try{ + simResultsLoader.createS3ClientAndReader(); + notifySimIsLoading(simResultsLoader); + if (openInMemory){ + if (!rangeSelector.cancel){ + imagePlus = simResultsLoader.openInMemory(rangeSelector); + } + } else{ + imagePlus = simResultsLoader.getImgPlusFromN5File(); } - rangeSelector.dispose(); - } else{ - imagePlus = simResultsLoader.getImgPlusFromN5File(); } - } - catch (RuntimeException e) { - if (e.getCause().getCause().getCause() instanceof SdkInterruptedException || - e.getCause().getCause() instanceof AbortedException){ - logger.debug("Simulation stopped loading"); - } else { - throw new RuntimeException(e); + catch (RuntimeException e) { + if (e.getCause().getCause().getCause() instanceof SdkInterruptedException || + e.getCause().getCause() instanceof AbortedException){ + logger.debug("Simulation stopped loading"); + } else { + throw new RuntimeException(e); + } } - } - catch (Exception e){ - throw new RuntimeException(e); - } finally { - MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); - notifySimIsDoneLoading(simResultsLoader, imagePlus); - synchronized (openSimulationsLock){ - openingSimulations.remove(simResultsLoader.exportID); + catch (Exception e){ + throw new RuntimeException(e); + } finally { + MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + controlButtonsPanel.enableCriticalButtons(true); + notifySimIsDoneLoading(simResultsLoader, imagePlus); + synchronized (openSimulationsLock){ + openingSimulations.remove(simResultsLoader.exportID); + } } + }); + openThread.setName("Opening sim number: " + i + ". With id: " + simResultsLoader.exportID); + synchronized (openSimulationsLock){ + openingSimulations.put(simResultsLoader.exportID, openThread); } - }); - openThread.setName("Opening sim number: " + i + ". With id: " + simResultsLoader.exportID); - synchronized (openSimulationsLock){ - openingSimulations.put(simResultsLoader.exportID, openThread); + openThread.start(); } - openThread.start(); } } - private ImagePlus openInMemory(SimResultsLoader simResultsLoader, RangeSelector rangeSelector) throws IOException { - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - long start = System.currentTimeMillis(); - logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory"); - imagePlus = new Duplicator().run(imagePlus, rangeSelector.startC, rangeSelector.endC, rangeSelector.startZ, - rangeSelector.endZ, rangeSelector.startT, rangeSelector.endT); - long end = System.currentTimeMillis(); - logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s"); - return imagePlus; - } - public void stopOpeningSimulation(String exportID){ Thread stopOtherThread = new Thread(() -> { synchronized (openSimulationsLock){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index a3e9495..159fc9f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -9,9 +9,12 @@ import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.google.gson.GsonBuilder; import ij.ImagePlus; +import ij.VirtualStack; import ij.plugin.ContrastEnhancer; +import ij.plugin.Duplicator; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; +import net.imglib2.img.display.imagej.ImageJVirtualStackFloat; import net.imglib2.type.numeric.real.DoubleType; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; @@ -24,6 +27,7 @@ import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.library.extensions.S3KeyValueAccess; import org.vcell.N5.library.extensions.SimCacheLoader; @@ -121,7 +125,8 @@ public boolean verify(String hostname, SSLSession session) { don't originate from amazon this is not a format we can possibly mimic, so we have to use path based buckets because it's the fallback style chosen by the N5 libraries if standard format is unavailable. */ - public ImagePlus getImgPlusFromN5File() throws IOException { + + public ImagePlus getImgPlusFromN5File() { // N5AmazonS3Reader n5AmazonS3Reader = new N5AmazonS3Reader(s3Client, bucketName, "/" + s3ObjectKey); long start = System.currentTimeMillis(); @@ -148,6 +153,17 @@ public ImagePlus getImgPlusFromN5File() throws IOException { return imagePlus; } + public ImagePlus openInMemory(RangeSelector rangeSelector){ + ImagePlus imagePlus = this.getImgPlusFromN5File(); + long start = System.currentTimeMillis(); + logger.debug("Loading Virtual N5 File " + userSetFileName + " Into Memory"); + imagePlus = new Duplicator().run(imagePlus, rangeSelector.startC, rangeSelector.endC, rangeSelector.startZ, + rangeSelector.endZ, rangeSelector.startT, rangeSelector.endT); + long end = System.currentTimeMillis(); + logger.debug("Loaded Virtual N5 File " + userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s"); + return imagePlus; + } + private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ try{ double pixelWidth = n5Reader.getAttribute(dataSetChosen, "pixelWidth", double.class); From b6fea45e198be42351460e97511b4b0c41d0d93a Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 25 Oct 2024 10:27:56 -0400 Subject: [PATCH 08/44] Data Reduction GUI Update Have the data reduction GUI be more coherent, and select range only be available for "Open In Memory" --- .../org/vcell/N5/UI/AdvancedFeatures.java | 22 ++- .../org/vcell/N5/UI/ControlButtonsPanel.java | 46 +++--- .../main/java/org/vcell/N5/UI/MainPanel.java | 2 +- .../java/org/vcell/N5/UI/N5ExportTable.java | 6 +- .../org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../vcell/N5/analysis/DataReductionGUI.java | 156 ++++++++++++++---- .../vcell/N5/retrieving/LoadingManager.java | 5 +- 7 files changed, 169 insertions(+), 70 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java index 31d1834..f2d6884 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java @@ -3,23 +3,33 @@ import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; +import java.awt.*; public class AdvancedFeatures extends JPanel { public final JCheckBox inMemory; public final JCheckBox dataReduction; - public final JCheckBox rangeSelection; + public final JButton copyLink; + public final JButton useN5Link; public AdvancedFeatures(){ Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + inMemory = new JCheckBox("Open In Memory"); - dataReduction = new JCheckBox("Data Reduction"); - rangeSelection = new JCheckBox("Select Range"); + dataReduction = new JCheckBox("Run Measurement Script"); + JPanel checkBoxPanel = new JPanel(); + checkBoxPanel.add(dataReduction); + + JPanel buttonPanel = new JPanel(); + copyLink = new JButton("Copy Link"); + useN5Link = new JButton("Use N5 Link"); + buttonPanel.add(copyLink); + buttonPanel.add(useN5Link); - add(inMemory); - add(dataReduction); - add(rangeSelection); + setLayout(new BorderLayout()); + add(buttonPanel, BorderLayout.NORTH); + add(checkBoxPanel, BorderLayout.SOUTH); this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Advanced Features ")); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 83b2d52..2f3f872 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -12,9 +12,8 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private static JButton openOrCancel; + private JButton openInMemory; // private final JButton openLocal = new JButton("Open N5 Local"); - private final JButton copyLink; - private final JButton useN5Link; private final JButton questionMark; public final JCheckBox includeExampleExports; @@ -30,9 +29,8 @@ public ControlButtonsPanel(){ displayAdvancedFeatures = new JCheckBox("Advanced Features"); - openOrCancel = new JButton("Open"); - copyLink = new JButton("Copy Link"); - useN5Link = new JButton("Use N5 Link"); + openOrCancel = new JButton("Open Virtually"); + openInMemory = new JButton("Open In Memory"); questionMark = new JButton("?"); questionMark.setPreferredSize(new Dimension(20, 20)); @@ -44,12 +42,9 @@ public ControlButtonsPanel(){ topRow.add(openOrCancel, gridBagConstraints); gridBagConstraints.gridx = 1; - topRow.add(copyLink, gridBagConstraints); + topRow.add(openInMemory, gridBagConstraints); gridBagConstraints.gridx = 2; - topRow.add(useN5Link, gridBagConstraints); - - gridBagConstraints.gridx = 3; topRow.add(questionMark); JPanel bottomRow = new JPanel(new GridBagLayout()); @@ -72,7 +67,7 @@ public ControlButtonsPanel(){ int paneWidth = 800; - this.setPreferredSize(new Dimension(paneWidth, 80)); + this.setPreferredSize(new Dimension(paneWidth, 110)); this.setLayout(new BorderLayout()); // topBar.add(openLocal); Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); @@ -84,16 +79,18 @@ public ControlButtonsPanel(){ openOrCancel.addActionListener(this); - copyLink.addActionListener(this); + advancedFeatures.copyLink.addActionListener(this); questionMark.addActionListener(this); - useN5Link.addActionListener(this); + advancedFeatures.useN5Link.addActionListener(this); // openLocal.addActionListener(this); includeExampleExports.addActionListener(this); displayAdvancedFeatures.addActionListener(this); + openInMemory.addActionListener(this); openOrCancel.setEnabled(false); - copyLink.setEnabled(false); + openInMemory.setEnabled(false); + advancedFeatures.copyLink.setEnabled(false); } public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFileSelection){ @@ -103,17 +100,17 @@ public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFi @Override public void actionPerformed(ActionEvent e) { - if(e.getSource().equals(openOrCancel)){ + if(e.getSource().equals(openOrCancel) || e.getSource().equals(openInMemory)){ if (openOrCancel.getText().equals("Cancel")){ n5ExportTable.removeFromLoadingRows(); } else { - n5ExportTable.openSelectedRows(); + n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); } - } else if (e.getSource().equals(copyLink)) { + } else if (e.getSource().equals(advancedFeatures.copyLink)) { n5ExportTable.copySelectedRowLink(); } else if (e.getSource().equals(questionMark)) { new HelpExplanation().displayHelpMenu(); - } else if (e.getSource().equals(useN5Link)) { + } else if (e.getSource().equals(advancedFeatures.useN5Link)) { remoteFileSelection.setVisible(true); } else if (e.getSource().equals(includeExampleExports)){ n5ExportTable.updateTableData(); @@ -124,25 +121,28 @@ public void actionPerformed(ActionEvent e) { public void allowCancel(boolean allow){ openOrCancel.setEnabled(true); - copyLink.setEnabled(true); - useN5Link.setEnabled(true); + advancedFeatures.copyLink.setEnabled(true); + advancedFeatures.useN5Link.setEnabled(true); remoteFileSelection.submitS3Info.setEnabled(true); + openInMemory.setEnabled(!allow); if (allow){ openOrCancel.setText("Cancel"); } else { - openOrCancel.setText("Open"); + openOrCancel.setText("Open Virtually"); } } public void enableRowContextDependentButtons(boolean enable){ openOrCancel.setEnabled(enable); - copyLink.setEnabled(enable); + advancedFeatures.copyLink.setEnabled(enable); + openInMemory.setEnabled(enable); } public void enableCriticalButtons(boolean enable){ - useN5Link.setEnabled(enable); + advancedFeatures.useN5Link.setEnabled(enable); openOrCancel.setEnabled(enable); - copyLink.setEnabled(enable); + advancedFeatures.copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); + openInMemory.setEnabled(enable); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index 6a05bb6..8f82d9f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -45,7 +45,7 @@ public MainPanel(){ filters.add(searchBar, BorderLayout.SOUTH); parentPanel.add(filters, BorderLayout.SOUTH); - parentPanel.setPreferredSize(new Dimension(paneWidth, 650)); + parentPanel.setPreferredSize(new Dimension(paneWidth, 750)); JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); exportTableDialog = pane.createDialog("VCell Exports"); exportTableDialog.setModal(false); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index cf21e7f..27ad19a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -155,7 +155,7 @@ private void automaticRefresh(){ refreshTableThread.start(); } - public void openSelectedRows(){ + public void openSelectedRows(boolean openInMemory){ ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; @@ -164,8 +164,8 @@ public void openSelectedRows(){ filesToOpen.add(simResultsLoader); } AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; - N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, advancedFeatures.inMemory.isSelected(), - advancedFeatures.rangeSelection.isSelected(), advancedFeatures.dataReduction.isSelected()); + N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, openInMemory, + advancedFeatures.dataReduction.isSelected()); } public void copySelectedRowLink(){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index 374adae..fbe16b9 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -98,7 +98,7 @@ public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, - advancedFeatures.inMemory.isSelected(), advancedFeatures.rangeSelection.isSelected(), + advancedFeatures.inMemory.isSelected(), advancedFeatures.dataReduction.isSelected()); this.setVisible(false); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 9ea4a93..4f1dedd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -7,6 +7,7 @@ import org.vcell.N5.N5ImageHandler; import javax.swing.*; +import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -29,11 +30,8 @@ public class DataReductionGUI extends JPanel implements ActionListener { private String notInMemoryWarning; - private final JFileChooser imageROIFileChooser = new JFileChooser(); - private final JFileChooser simROIFileChooser = new JFileChooser(); - - private ArrayList imageROIList; private ArrayList simROIList; + private ArrayList imageROIList; private final JDialog jDialog; private final JOptionPane pane; @@ -73,12 +71,11 @@ public DataReductionSubmission(){ public DataReductionGUI(int numSimsToOpen){ this.numSimsToOpen = numSimsToOpen; - setLayout(new GridLayout(4, 1)); + setLayout(new BorderLayout()); - add(imageAndAnalysisType()); - add(roisSelectedGUI()); - add(normalizeGUI()); - setSize(400, 400); + add(imageAndAnalysisType(), BorderLayout.NORTH); + add(new ROISelection(), BorderLayout.CENTER); + add(normalizeGUI(), BorderLayout.SOUTH); setVisible(true); pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); @@ -124,7 +121,8 @@ private JPanel normalizeGUI(){ fromSim.add(new JLabel("to")); fromSim.add(createNormFromSimEnd); - entireImageFramesJPanel = new JPanel(new GridLayout(2, 1)); + entireImageFramesJPanel = new JPanel(new GridLayout(3, 1)); + entireImageFramesJPanel.add(explainInput); entireImageFramesJPanel.add(fromImage); entireImageFramesJPanel.add(fromSim); entireImageFramesJPanel.setVisible(false); @@ -134,40 +132,34 @@ private JPanel normalizeGUI(){ return jPanel; } - private JPanel roisSelectedGUI(){ - JPanel jPanel = new JPanel(new BorderLayout()); - imageROIFileButton = new JButton("ROI's For Image"); - simROIFileButton = new JButton("ROI's For Simulation"); - - imageROIFileButton.addActionListener(this); - simROIFileButton.addActionListener(this); - - jPanel.add(imageROIFileButton, BorderLayout.WEST); - jPanel.add(simROIFileButton, BorderLayout.EAST); - return jPanel; - } - private JPanel imageAndAnalysisType(){ - JPanel jPanel = new JPanel(new BorderLayout()); + JPanel jPanel = new JPanel(new GridLayout(2,4)); + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + jPanel.add(new JLabel("Select Experimental Image"), gridBagConstraints); + gridBagConstraints.gridy = 1; chosenImage = new JComboBox<>(WindowManager.getImageTitles()); - chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.MEDIAN.publicName}); + jPanel.add(chosenImage, gridBagConstraints); + gridBagConstraints.gridy = 2; + jPanel.add(new JLabel("Measurement Type"), gridBagConstraints); + gridBagConstraints.gridy = 3; + chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.AVERAGE.publicName}); + jPanel.add(chosenMeasurement, gridBagConstraints); chosenMeasurement.addActionListener(this); chosenImage.addActionListener(this); - jPanel.add(chosenImage, BorderLayout.NORTH); - jPanel.add(chosenMeasurement, BorderLayout.SOUTH); + return jPanel; } + + @Override public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(imageROIFileButton)){ - imageROIList = fillROIList(imageROIFileChooser); - } else if (e.getSource().equals(simROIFileButton)) { - simROIList = fillROIList(simROIFileChooser); - } else if (e.getSource().equals(normalizeMeasurement)) { + if (e.getSource().equals(normalizeMeasurement)) { entireImageFramesJPanel.setVisible(normalizeMeasurement.isSelected()); } } @@ -185,7 +177,7 @@ private ArrayList fillROIList(JFileChooser fileChooser){ } enum AvailableMeasurements{ - MEDIAN("Median"); + AVERAGE("Average"); public final String publicName; AvailableMeasurements(String publicName){ @@ -197,6 +189,104 @@ public static void main(String[] args) { DataReductionGUI dataReductionGUI = new DataReductionGUI(0); dataReductionGUI.displayGUI(); } + + class ROISelection extends JPanel implements ActionListener{ + private final JFileChooser imageROIFileChooser = new JFileChooser(); + private final ROIDataModel imageTableModel = new ROIDataModel(); + private final JTable imageROITable = new JTable(imageTableModel); + + private final JFileChooser simROIFileChooser = new JFileChooser(); + private final ROIDataModel simTableModel = new ROIDataModel(); + private final JTable simROITable = new JTable(simTableModel); + public ROISelection(){ + JPanel roisForImage = new JPanel(new GridBagLayout()); + JPanel roisForSims = new JPanel(new GridBagLayout()); + Dimension tableDimensions = new Dimension(100, 70); + imageROITable.getTableHeader().setBackground(Color.WHITE); + imageROITable.setEnabled(false); + simROITable.getTableHeader().setBackground(Color.WHITE); + simROITable.setEnabled(false); + + imageROIFileButton = new JButton("ROI's For Image"); + JScrollPane displayImageROIList = new JScrollPane(imageROITable); + displayImageROIList.setPreferredSize(tableDimensions); + setROIPanelSettings(roisForImage, imageROIFileButton, displayImageROIList); + + simROIFileButton = new JButton("ROI's For Simulation"); + JScrollPane displaySimROIList = new JScrollPane(simROITable); + displaySimROIList.setPreferredSize(tableDimensions); + setROIPanelSettings(roisForSims, simROIFileButton, displaySimROIList); + + imageROIFileButton.addActionListener(this); + simROIFileButton.addActionListener(this); + + this.setLayout(new BorderLayout()); + this.add(roisForImage, BorderLayout.WEST); + this.add(roisForSims, BorderLayout.EAST); + } + + public void setROIPanelSettings(JPanel jPanel, JButton button, JScrollPane jScrollPane){ + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 0; + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.insets = new Insets(5, 5, 5, 5); + jPanel.add(button, gridBagConstraints); + gridBagConstraints.gridy = 1; + jPanel.add(jScrollPane, gridBagConstraints); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(imageROIFileButton)){ + imageROIList = fillROIList(imageROIFileChooser); + imageTableModel.clear(); + for (Roi roi : imageROIList){ + imageTableModel.addRow(roi.getName()); + } + imageROITable.updateUI(); + } else if (e.getSource().equals(simROIFileButton)) { + simROIList = fillROIList(simROIFileChooser); + simTableModel.clear(); + for (Roi roi : simROIList){ + simTableModel.addRow(roi.getName()); + } + simROITable.updateUI(); + } + } + + class ROIDataModel extends AbstractTableModel { + private final ArrayList data = new ArrayList<>(); + private final String[] headers = new String[]{"ROI's Selected"}; + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return headers.length; + } + + @Override + public String getColumnName(int column) { + return headers[column]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return data.get(rowIndex); + } + + public void addRow(String roiName){ + data.add(roiName); + } + + public void clear(){ + data.clear(); + } + } + } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 8e83d88..9aa3cab 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -29,10 +29,9 @@ public class LoadingManager implements SimLoadingEventCreator { private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); - public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory, - boolean selectRange, boolean dataReduction){ + public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory, boolean dataReduction){ RangeSelector rangeSelector = new RangeSelector(); - if (selectRange){ + if (openInMemory){ SimResultsLoader firstSim = filesToOpen.get(0); firstSim.createS3ClientAndReader(); ArrayList dimensions = firstSim.getN5Dimensions(); From bafda869420ecd332153d8eefff7bb8fff00ef8f Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 25 Oct 2024 14:07:57 -0400 Subject: [PATCH 09/44] User Safe Data Reduction Disable all simulation control buttons while the data reduction process is occurring. This allows for all listened events to correspond to data reduction. --- .../org/vcell/N5/UI/ControlButtonsPanel.java | 30 +++++++++++-------- .../org/vcell/N5/analysis/DataReduction.java | 5 ++++ .../vcell/N5/analysis/DataReductionGUI.java | 2 ++ .../vcell/N5/retrieving/LoadingManager.java | 4 +++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 2f3f872..de063b9 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -22,6 +22,7 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private N5ExportTable n5ExportTable; private RemoteFileSelection remoteFileSelection; public final AdvancedFeatures advancedFeatures = new AdvancedFeatures(); + private boolean allowButtons = true; public ControlButtonsPanel(){ includeExampleExports = new JCheckBox("Show Example Exports"); @@ -120,22 +121,26 @@ public void actionPerformed(ActionEvent e) { } public void allowCancel(boolean allow){ - openOrCancel.setEnabled(true); - advancedFeatures.copyLink.setEnabled(true); - advancedFeatures.useN5Link.setEnabled(true); - remoteFileSelection.submitS3Info.setEnabled(true); - openInMemory.setEnabled(!allow); - if (allow){ - openOrCancel.setText("Cancel"); - } else { - openOrCancel.setText("Open Virtually"); + if (allowButtons){ + openOrCancel.setEnabled(true); + advancedFeatures.copyLink.setEnabled(true); + advancedFeatures.useN5Link.setEnabled(true); + remoteFileSelection.submitS3Info.setEnabled(true); + openInMemory.setEnabled(!allow); + if (allow){ + openOrCancel.setText("Cancel"); + } else { + openOrCancel.setText("Open Virtually"); + } } } public void enableRowContextDependentButtons(boolean enable){ - openOrCancel.setEnabled(enable); - advancedFeatures.copyLink.setEnabled(enable); - openInMemory.setEnabled(enable); + if (allowButtons){ + openOrCancel.setEnabled(enable); + advancedFeatures.copyLink.setEnabled(enable); + openInMemory.setEnabled(enable); + } } public void enableCriticalButtons(boolean enable){ @@ -144,5 +149,6 @@ public void enableCriticalButtons(boolean enable){ advancedFeatures.copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); openInMemory.setEnabled(enable); + allowButtons = enable; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index 67b0d0e..fb2a789 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -3,6 +3,8 @@ import com.opencsv.CSVWriter; import ij.ImagePlus; import ij.gui.Roi; +import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.MainPanel; import org.vcell.N5.retrieving.SimLoadingListener; import java.io.File; @@ -137,6 +139,9 @@ private void writeCSVMatrix(){ csvWriter.close(); } catch (IOException e) { throw new RuntimeException(e); + } finally { + N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); + MainPanel.controlButtonsPanel.enableCriticalButtons(true); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 4f1dedd..be8e374 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -5,6 +5,7 @@ import ij.gui.Roi; import ij.io.RoiDecoder; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.MainPanel; import javax.swing.*; import javax.swing.table.AbstractTableModel; @@ -91,6 +92,7 @@ public void displayGUI(){ fileChooserReturnValue = saveToFile.showDialog(this, "Save Results To File"); if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ chosenFile = saveToFile.getSelectedFile(); + MainPanel.controlButtonsPanel.enableCriticalButtons(false); Thread thread = new Thread(() -> { DataReduction dataReduction = new DataReduction(new DataReductionSubmission()); N5ImageHandler.loadingManager.addSimLoadingListener(dataReduction); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 9aa3cab..bd17b08 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -135,6 +135,10 @@ public void addSimLoadingListener(SimLoadingListener simLoadingListener) { eventListenerList.add(SimLoadingListener.class, simLoadingListener); } + public void removeFromSimLoadingListener(SimLoadingListener simLoadingListener){ + eventListenerList.remove(SimLoadingListener.class, simLoadingListener); + } + @Override public void notifySimIsLoading(SimResultsLoader simResultsLoader) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ From 9e5ce30350eda97b0b20fecd1d7b8b92fb7ae37d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 29 Oct 2024 09:50:00 -0400 Subject: [PATCH 10/44] 5D Data Reduction and Tests --- .../org/vcell/N5/analysis/DataReduction.java | 59 +++++++------- .../vcell/N5/analysis/DataReductionGUI.java | 67 +++++++++------ .../vcell/N5/retrieving/SimResultsLoader.java | 2 +- .../vcell/N5/analysis/DataReductionTest.java | 77 ++++++++++++++++++ .../src/test/resources/ROIs/Lab ROI.roi | Bin 0 -> 142 bytes .../test/resources/ROIs/Mitosis Center.roi | Bin 0 -> 156 bytes .../src/test/resources/ROIs/Sim ROI.roi | Bin 0 -> 142 bytes 7 files changed, 149 insertions(+), 56 deletions(-) create mode 100644 view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java create mode 100644 view-simulation-results/src/test/resources/ROIs/Lab ROI.roi create mode 100644 view-simulation-results/src/test/resources/ROIs/Mitosis Center.roi create mode 100644 view-simulation-results/src/test/resources/ROIs/Sim ROI.roi diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index fb2a789..417c42d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -26,18 +26,7 @@ public class DataReduction implements SimLoadingListener { public final DataReductionGUI.DataReductionSubmission submission; - /* -Open an image from file (assume 2D for now). -Open a saved ROI (or allow one to be created and saved). -Apply the ROI to a selected channel(s) in the image. -collect the average intensity value for all times in the image. -Save to cvs file of some kind (something that can be imported into excel). -Open a set of N5 exported files- in reality these will likely be scanned parameters all from the same "simulation". From each N5 data set, select the appropriate channel and z plane. -Apply the same ROI used previously and measure average intensity for each time. -save data to the cvs or equivalent file. Ideally, these should be organized so they are easy to use excel. -If possible would like to compare N5 data to image data using a least squares analysis. Users should be able to see the summed square differences and have the "best fit" identified. -Would be extra nice to plot the experimental data vs the "best fit" VCell simulation. - */ + // // GUI: @@ -53,7 +42,7 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ this.numOfImagesToBeOpened = submission.numOfSimImages + 1; // Plus one for the lab image this.file = submission.fileToSaveResultsTo; this.normalize = submission.normalizeMeasurementsBool; - ArrayList headers = new ArrayList(){{add("Time Frame");}}; + ArrayList headers = new ArrayList(){{add("Time Frame"); add("Z Index"); add("Channel");}}; csvMatrix.add(headers); double normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, submission.imageEndPointNorm); @@ -61,9 +50,15 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ HashMap> reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue); synchronized (csvMatrixLock){ for (int t = 0; t < submission.labResults.getNFrames(); t++){ - ArrayList rowForTime = new ArrayList<>(); - rowForTime.add(String.valueOf(t)); - csvMatrix.add(rowForTime); + for (int z = 0; z < submission.labResults.getNSlices(); z++){ + for (int c = 0; c < submission.labResults.getNChannels(); c++){ + ArrayList rowForTime = new ArrayList<>(); + rowForTime.add(String.valueOf(t)); + rowForTime.add(String.valueOf(z)); + rowForTime.add(String.valueOf(c)); + csvMatrix.add(rowForTime); + } + } } } @@ -76,10 +71,13 @@ private void addValuesToCSVMatrix(ImagePlus imagePlus, HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList, + HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList, double normalizationValue){ // ResultsTable resultsTable = new ResultsTable(); @@ -115,15 +113,16 @@ private HashMap> calculateMean(ImagePlus imagePlus, Ar imagePlus.setRoi(roi); ArrayList meanValues = new ArrayList<>(); for (int t = 0; t < imagePlus.getNFrames(); t++){ -// Analyzer analyzer = new Analyzer(imagePlus, Analyzer.MEAN, resultsTable); -// analyzer.measure(); -// -// double meanValue = resultsTable.getValueAsDouble(resultsTable.getColumnIndex("Mean"), 0); - double meanValue = imagePlus.getProcessor().getStatistics().mean; - if (normalizationValue != Double.MIN_NORMAL){ - meanValue = meanValue / normalizationValue; + for (int z = 0; z < imagePlus.getNSlices(); z++){ + for (int c = 0; c < imagePlus.getNChannels(); c++){ + imagePlus.setPosition(c + 1, z + 1, t + 1); + double meanValue = imagePlus.getStatistics().mean; + if (normalize){ + meanValue = meanValue / normalizationValue; + } + meanValues.add(meanValue); + } } - meanValues.add(meanValue); } roiListOfMeans.put(roi.getName(), meanValues); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index be8e374..9e61ff6 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -45,7 +45,7 @@ public class DataReductionGUI extends JPanel implements ActionListener { // private TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); - public class DataReductionSubmission{ + public static class DataReductionSubmission{ public final boolean normalizeMeasurementsBool; public final ArrayList arrayOfSimRois; public final ArrayList arrayOfLabRois; @@ -56,20 +56,38 @@ public class DataReductionSubmission{ public final int imageEndPointNorm; public final int numOfSimImages; public final File fileToSaveResultsTo; - public DataReductionSubmission(){ - normalizeMeasurementsBool = normalizeMeasurement.isSelected(); - arrayOfSimRois = simROIList; - arrayOfLabRois = imageROIList; - labResults = WindowManager.getImage((String) chosenImage.getSelectedItem()); - simStartPointNorm = createNormFromSimStart.getText().isEmpty() ? Integer.MIN_VALUE : Integer.parseInt(createNormFromSimStart.getText()); - simEndPointNorm = createNormFromSimEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromSimEnd.getText()); - imageStartPointNorm = createNormFromImageStart.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageStart.getText()); - imageEndPointNorm = createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()); - numOfSimImages = numSimsToOpen; - fileToSaveResultsTo = chosenFile; + public DataReductionSubmission(boolean normalizeMeasurementsBool,ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int numOfSimImages, File fileToSaveResultsTo){ + this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, + 0,0,0,0, numOfSimImages, fileToSaveResultsTo); + } + + public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, + int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo){ + this.normalizeMeasurementsBool = normalizeMeasurementsBool; + this.arrayOfLabRois = arrayOfLabRois; + this.arrayOfSimRois = arrayOfSimRois; + this.labResults = labResults; + this.simStartPointNorm = simStartPointNorm; + this.simEndPointNorm = simEndPointNorm; + this.imageStartPointNorm = imageStartPointNorm; + this.imageEndPointNorm = imageEndPointNorm; + this.numOfSimImages = numOfSimImages; + this.fileToSaveResultsTo = fileToSaveResultsTo; + } } + private DataReductionSubmission createSubmission(){ + int simStartPointNorm = createNormFromSimStart.getText().isEmpty() ? Integer.MIN_VALUE : Integer.parseInt(createNormFromSimStart.getText()); + int simEndPointNorm = createNormFromSimEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromSimEnd.getText()); + int imageStartPointNorm = createNormFromImageStart.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageStart.getText()); + int imageEndPointNorm = createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()); + return new DataReductionSubmission(normalizeMeasurement.isSelected(), simROIList, imageROIList, WindowManager.getImage((String) chosenImage.getSelectedItem()), + simStartPointNorm, simEndPointNorm, imageStartPointNorm, imageEndPointNorm, numSimsToOpen, chosenFile); + } + public DataReductionGUI(int numSimsToOpen){ this.numSimsToOpen = numSimsToOpen; setLayout(new BorderLayout()); @@ -94,7 +112,7 @@ public void displayGUI(){ chosenFile = saveToFile.getSelectedFile(); MainPanel.controlButtonsPanel.enableCriticalButtons(false); Thread thread = new Thread(() -> { - DataReduction dataReduction = new DataReduction(new DataReductionSubmission()); + DataReduction dataReduction = new DataReduction(createSubmission()); N5ImageHandler.loadingManager.addSimLoadingListener(dataReduction); }); thread.start(); @@ -166,18 +184,6 @@ public void actionPerformed(ActionEvent e) { } } - private ArrayList fillROIList(JFileChooser fileChooser){ - fileChooser.setMultiSelectionEnabled(true); - int choice = fileChooser.showDialog(this, ""); - ArrayList roiList = new ArrayList<>(); - if (choice == JFileChooser.APPROVE_OPTION){ - for (File file: fileChooser.getSelectedFiles()){ - roiList.add(RoiDecoder.open(file.getAbsolutePath())); - } - } - return roiList; - } - enum AvailableMeasurements{ AVERAGE("Average"); @@ -256,6 +262,17 @@ public void actionPerformed(ActionEvent e) { simROITable.updateUI(); } } + private ArrayList fillROIList(JFileChooser fileChooser){ + fileChooser.setMultiSelectionEnabled(true); + int choice = fileChooser.showDialog(this, "Open ROI's"); + ArrayList roiList = new ArrayList<>(); + if (choice == JFileChooser.APPROVE_OPTION){ + for (File file: fileChooser.getSelectedFiles()){ + roiList.add(RoiDecoder.open(file.getAbsolutePath())); + } + } + return roiList; + } class ROIDataModel extends AbstractTableModel { private final ArrayList data = new ArrayList<>(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index 159fc9f..a731e69 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -83,7 +83,7 @@ public SimResultsLoader(String stringURI, String userSetFileName){ } } - void createS3ClientAndReader(){ + public void createS3ClientAndReader(){ logger.debug("Creating S3 Client with url: " + uri); if (uri.getHost().equals("minikube.remote") || uri.getHost().equals("minikube.island")){ SSLContext sslContext = null; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java new file mode 100644 index 0000000..b5338cf --- /dev/null +++ b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java @@ -0,0 +1,77 @@ +package org.vcell.N5.analysis; + +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import ij.ImagePlus; +import ij.gui.Roi; +import ij.io.RoiDecoder; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.retrieving.SimResultsLoader; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; + +public class DataReductionTest { + private final double[] labMeans2DLabROI = new double[]{6, 0, 6.489, 0, 7.247, 0}; //calculated through IJ measurement tool + private final double[] labMeans2DSimROI = new double[]{18, 0, 16.341, 0, 14.469, 0}; + + private final double[] threeDMeans = new double[]{2884.526,3102.159, 3884.279, 4668.205, 5016.744, 5524.792, 4794.329, 5624.351, + 4559.778, 5510.099 + }; + + private File getTestResourceFiles(String filePath){ + try { + URL url = ClassLoader.getSystemClassLoader().getResource(filePath); + return new File(url.toURI().getPath()); + } + catch (URISyntaxException e){ + throw new RuntimeException(e); + } + } + + @BeforeClass + public static void init(){ + N5ImageHandler.initializeLogService(); + SimResultsLoader.s3ClientBuilder = AmazonS3ClientBuilder.standard(); + } + + private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, HashMap expectedResults){ + DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( + false, roiList, roiList, imagePlus,4, null); + DataReduction dataReduction = new DataReduction(dataReductionSubmission); + HashMap> result = dataReduction.calculateMean(imagePlus, roiList, Double.MIN_VALUE); + for (Roi roi : roiList){ + for (int i = 0; i < expectedResults.get(roi.getName()).length; i++){ + Assert.assertEquals(expectedResults.get(roi.getName())[i], result.get(roi.getName()).get(i), 0.0009); + } + } + } + + @Test + public void testMean2DCalculation(){ + // Ensure the mean calculated for each ROI, and each time point is what's to be expected + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); + simResultsLoader.createS3ClientAndReader(); + ImagePlus labResultImage2D = simResultsLoader.getImgPlusFromN5File(); + + Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); + Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); + ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; + HashMap expectedResults = new HashMap(){{put(labRoi.getName(), labMeans2DLabROI); put(simROI.getName(), labMeans2DSimROI);}}; + compareExpectedCalculations(labResultImage2D, roiList, expectedResults); + } + + @Test + public void testMean3DCalculation(){ + ImagePlus mitosis = new ImagePlus(getTestResourceFiles("mitosis.tif").getAbsolutePath()); + Roi mitosisROI = RoiDecoder.open(getTestResourceFiles("ROIs/Mitosis Center.roi").getAbsolutePath()); + ArrayList roiList = new ArrayList(){{add(mitosisROI);}}; + HashMap expectedResults = new HashMap(){{put(mitosisROI.getName(), threeDMeans);}}; + compareExpectedCalculations(mitosis, roiList, expectedResults); + } +} diff --git a/view-simulation-results/src/test/resources/ROIs/Lab ROI.roi b/view-simulation-results/src/test/resources/ROIs/Lab ROI.roi new file mode 100644 index 0000000000000000000000000000000000000000..6e4170b5abc57adc33c8becccf3a55c88be2bafe GIT binary patch literal 142 zcmeawFD+qs!pOkD2!zZ)NE&c}DhC<>)DOW8K$;zhi32_ii3~{$3JgIE{tTV~rhNr+ literal 0 HcmV?d00001 diff --git a/view-simulation-results/src/test/resources/ROIs/Mitosis Center.roi b/view-simulation-results/src/test/resources/ROIs/Mitosis Center.roi new file mode 100644 index 0000000000000000000000000000000000000000..15225b476a17d8fa80b73c8c25a6befa72b95dcc GIT binary patch literal 156 zcmeawFD+qs!pOkj&tS>W!%)sZ8gM{T4m5-Tgd2dE4~U5az6_ZRB@Fot#X!24L4m=U NA(bHyD3Z!h1OV&T3QGV0 literal 0 HcmV?d00001 diff --git a/view-simulation-results/src/test/resources/ROIs/Sim ROI.roi b/view-simulation-results/src/test/resources/ROIs/Sim ROI.roi new file mode 100644 index 0000000000000000000000000000000000000000..c3b634498583b86991843f6a480b71ea1057b7db GIT binary patch literal 142 xcmeawFD+qs!pOkD3WV%HNE&c}DhC?C0K*MHHu2^JGh{O4GAJ+vG59lh0sybG1)Kl? literal 0 HcmV?d00001 From 1ec5e2fd4cf3563e1a84e70dac68e3ffd9c65df7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 31 Oct 2024 12:36:01 -0400 Subject: [PATCH 11/44] Add .xls File Support and Enable Range Data Reduction --- view-simulation-results/pom.xml | 6 + .../org/vcell/N5/analysis/DataReduction.java | 172 +++++++++++++----- .../vcell/N5/analysis/DataReductionGUI.java | 22 ++- .../vcell/N5/analysis/DataReductionTest.java | 30 +-- 4 files changed, 164 insertions(+), 66 deletions(-) diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 6307af2..163f06f 100644 --- a/view-simulation-results/pom.xml +++ b/view-simulation-results/pom.xml @@ -198,6 +198,12 @@ 4.1 + + + org.apache.poi + poi-ooxml + 5.3.0 + diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index 417c42d..c5e2f09 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -1,15 +1,20 @@ package org.vcell.N5.analysis; -import com.opencsv.CSVWriter; +import com.google.gson.internal.LinkedTreeMap; import ij.ImagePlus; import ij.gui.Roi; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.retrieving.SimLoadingListener; +import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.HashMap; @@ -19,13 +24,31 @@ public class DataReduction implements SimLoadingListener { private final Object csvMatrixLock = new Object(); private File file; - private final ArrayList> csvMatrix = new ArrayList<>(); - private int numOfImagesToBeOpened; private final boolean normalize; public final DataReductionGUI.DataReductionSubmission submission; + private final Workbook workbook = new HSSFWorkbook(); + private final Sheet dataSheet = workbook.createSheet("Average"); + private final Sheet metaDataSheet = workbook.createSheet("Metadata"); + + private int colIndex; + + private final DataReductionGUI.RangeOfImage simRange; + + // Per Image + static class ReducedData{ + public final double[][] data; + public final ArrayList columnHeaders; + public final DataReductionGUI.AvailableMeasurements measurementType; + public ReducedData(int rowLen, int colLen, DataReductionGUI.AvailableMeasurements measurementType){ + data = new double[rowLen][colLen]; + columnHeaders = new ArrayList<>(); + this.measurementType = measurementType; + } + } + // // GUI: @@ -42,45 +65,57 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ this.numOfImagesToBeOpened = submission.numOfSimImages + 1; // Plus one for the lab image this.file = submission.fileToSaveResultsTo; this.normalize = submission.normalizeMeasurementsBool; - ArrayList headers = new ArrayList(){{add("Time Frame"); add("Z Index"); add("Channel");}}; - csvMatrix.add(headers); + this.simRange = submission.simImageRange; + + ArrayList headers = new ArrayList(){{add("Time Frame");}}; + boolean is3D = submission.labResults.getNSlices() > 1; + if (is3D){ + headers.add("Z Index"); + } + + Row headerRow = dataSheet.createRow(0); + for (int i = 0; i < headers.size(); i++){ + headerRow.createCell(i).setCellValue(headers.get(i)); + } + colIndex = headers.size() + 1; double normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, submission.imageEndPointNorm); - HashMap> reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue); + int nFrames = submission.experimentImageRange.timeEnd - submission.experimentImageRange.timeStart + 1; + int nSlices = submission.experimentImageRange.zEnd - submission.experimentImageRange.zStart + 1; + int nChannels = submission.experimentImageRange.channelEnd - submission.experimentImageRange.channelStart + 1; + ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), DataReductionGUI.AvailableMeasurements.AVERAGE); + reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, submission.experimentImageRange); synchronized (csvMatrixLock){ - for (int t = 0; t < submission.labResults.getNFrames(); t++){ - for (int z = 0; z < submission.labResults.getNSlices(); z++){ - for (int c = 0; c < submission.labResults.getNChannels(); c++){ - ArrayList rowForTime = new ArrayList<>(); - rowForTime.add(String.valueOf(t)); - rowForTime.add(String.valueOf(z)); - rowForTime.add(String.valueOf(c)); - csvMatrix.add(rowForTime); + int rowI = 1; + for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ + for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ + Row pointRow = dataSheet.createRow(rowI); + rowI += 1; + pointRow.createCell(0).setCellValue(t); + if (is3D){ + pointRow.createCell(1).setCellValue(z); } } } - } - addValuesToCSVMatrix(submission.labResults, reducedData); - + addValuesToCSVMatrix(reducedData); } - private void addValuesToCSVMatrix(ImagePlus imagePlus, HashMap> reducedData){ + private void addValuesToCSVMatrix(ReducedData reducedData){ synchronized (csvMatrixLock){ - csvMatrix.get(0).add(""); - for (String roiName: reducedData.keySet()){ - csvMatrix.get(0).add(imagePlus.getTitle()+" : " + roiName); - int tN = imagePlus.getNFrames(); - int zN = imagePlus.getNSlices(); - int cN = imagePlus.getNChannels(); - for (int i = 0; i < (tN * zN * cN); i++){ - double mean = reducedData.get(roiName).get(i); - csvMatrix.get(i + 1).add(""); // every array is a row - csvMatrix.get(i + 1).add(String.valueOf(mean)); + for (int c = 0; c < reducedData.columnHeaders.size(); c++){ + dataSheet.getRow(0).createCell(colIndex + c).setCellValue(reducedData.columnHeaders.get(c)); + } + for (int i = 0; i < reducedData.data.length; i++){ + for (int c = 0; c < reducedData.data[i].length; c++){ + Row row = dataSheet.getRow(i + 1); + double mean = reducedData.data[i][c]; + row.createCell(colIndex + c).setCellValue(mean); } } numOfImagesToBeOpened -= 1; + colIndex += 1 + reducedData.data[0].length; if (numOfImagesToBeOpened == 0){ writeCSVMatrix(); } @@ -103,39 +138,58 @@ private void addValuesToCSVMatrix(ImagePlus imagePlus, HashMap roiList, + double normalizationValue, ReducedData reducedData){ + DataReductionGUI.RangeOfImage entireRange = new DataReductionGUI.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), + 1, imagePlus.getNChannels()); + return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, entireRange); + } - HashMap> calculateMean(ImagePlus imagePlus, ArrayList roiList, - double normalizationValue){ -// ResultsTable resultsTable = new ResultsTable(); + ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, + double normalizationValue, ReducedData reducedData, DataReductionGUI.RangeOfImage rangeOfImage){ + return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, rangeOfImage); + } - HashMap> roiListOfMeans = new HashMap<>(); + ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, + double normalizationValue, ReducedData reducedData, + LinkedTreeMap> channelInfo, DataReductionGUI.RangeOfImage rangeOfImage){ + int roiCounter = 0; for (Roi roi: roiList) { imagePlus.setRoi(roi); - ArrayList meanValues = new ArrayList<>(); - for (int t = 0; t < imagePlus.getNFrames(); t++){ - for (int z = 0; z < imagePlus.getNSlices(); z++){ - for (int c = 0; c < imagePlus.getNChannels(); c++){ - imagePlus.setPosition(c + 1, z + 1, t + 1); + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable + String stringC = String.valueOf(c - 1); + String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); + reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + } + int tzCounter = 0; + for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ + for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ + int channelSize = rangeOfImage.channelEnd - rangeOfImage.channelStart + 1; + imagePlus.setPosition(c, z, t); double meanValue = imagePlus.getStatistics().mean; if (normalize){ meanValue = meanValue / normalizationValue; } - meanValues.add(meanValue); + reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = meanValue; } + tzCounter += 1; } } - roiListOfMeans.put(roi.getName(), meanValues); + roiCounter += 1; } - return roiListOfMeans; + return reducedData; + } + + private void addMetaData(){ + } private void writeCSVMatrix(){ - try (FileWriter fileWriter = new FileWriter(file)) { - CSVWriter csvWriter = new CSVWriter(fileWriter); - for (ArrayList row: csvMatrix){ - csvWriter.writeNext(row.toArray(new String[0])); - } - csvWriter.close(); + + try { + file = new File(file.getAbsolutePath() + ".xls"); + workbook.write(Files.newOutputStream(file.toPath())); } catch (IOException e) { throw new RuntimeException(e); } finally { @@ -151,10 +205,28 @@ public void simIsLoading(int itemRow, String exportID) { } @Override - public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus) { + public void simFinishedLoading(SimResultsLoader loadedResults) { + ImagePlus imagePlus = loadedResults.getImagePlus(); double normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, submission.simEndPointNorm); - HashMap> calculations = calculateMean(imagePlus, arrayOfSimRois, normValue); - addValuesToCSVMatrix(imagePlus, calculations); + ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), + imagePlus.getNChannels(), DataReductionGUI.AvailableMeasurements.AVERAGE); + reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); + addValuesToCSVMatrix(reducedData); + } + + public static void main(String[] args) { + File file = new File("/Users/evalencia/Documents/testv2.xlsx"); + + try { + Workbook workbook = new HSSFWorkbook(); +// Files.createFile(file.toPath()); + Sheet sheet = workbook.createSheet("Hello"); + sheet.createRow(1).createCell(0).setCellValue("2"); + workbook.write(Files.newOutputStream(file.toPath())); + workbook.close(); + } catch (IOException e){ + throw new RuntimeException(e); + } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 9e61ff6..69dba59 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -45,6 +45,22 @@ public class DataReductionGUI extends JPanel implements ActionListener { // private TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); + public static class RangeOfImage{ + public final int timeStart; + public final int timeEnd; + public final int zStart; + public final int zEnd; + public final int channelStart; + public final int channelEnd; + public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channelStart, int channelEnd){ + this.timeStart = timeStart; + this.timeEnd = timeEnd; + this.zStart = zStart; + this.zEnd = zEnd; + this.channelStart = channelStart; + this.channelEnd = channelEnd; + } + } public static class DataReductionSubmission{ public final boolean normalizeMeasurementsBool; public final ArrayList arrayOfSimRois; @@ -56,6 +72,8 @@ public static class DataReductionSubmission{ public final int imageEndPointNorm; public final int numOfSimImages; public final File fileToSaveResultsTo; + public final RangeOfImage experimentImageRange; + public final RangeOfImage simImageRange; public DataReductionSubmission(boolean normalizeMeasurementsBool,ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, ImagePlus labResults, int numOfSimImages, File fileToSaveResultsTo){ this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, @@ -75,7 +93,9 @@ public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList this.imageEndPointNorm = imageEndPointNorm; this.numOfSimImages = numOfSimImages; this.fileToSaveResultsTo = fileToSaveResultsTo; - + this.experimentImageRange = new RangeOfImage(1, labResults.getNFrames(), + 1, labResults.getNSlices(), 1, labResults.getNChannels()); + this.simImageRange = experimentImageRange; } } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java index b5338cf..d989b74 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java @@ -17,11 +17,12 @@ import java.util.HashMap; public class DataReductionTest { - private final double[] labMeans2DLabROI = new double[]{6, 0, 6.489, 0, 7.247, 0}; //calculated through IJ measurement tool - private final double[] labMeans2DSimROI = new double[]{18, 0, 16.341, 0, 14.469, 0}; + // First two are SimROI, last two are LabROI + private final double[][] labMeans2D = new double[][]{{6, 0, 18, 0}, {6.489, 0, 16.341, 0}, + {7.247, 0, 14.469, 0}}; //calculated through IJ measurement tool - private final double[] threeDMeans = new double[]{2884.526,3102.159, 3884.279, 4668.205, 5016.744, 5524.792, 4794.329, 5624.351, - 4559.778, 5510.099 + private final double[][] threeDMeans = new double[][]{{2884.526, 3102.159}, {3884.279, 4668.205}, {5016.744, 5524.792}, {4794.329, 5624.351}, + {4559.778, 5510.099} }; private File getTestResourceFiles(String filePath){ @@ -40,14 +41,16 @@ public static void init(){ SimResultsLoader.s3ClientBuilder = AmazonS3ClientBuilder.standard(); } - private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, HashMap expectedResults){ + private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults){ DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( false, roiList, roiList, imagePlus,4, null); DataReduction dataReduction = new DataReduction(dataReductionSubmission); - HashMap> result = dataReduction.calculateMean(imagePlus, roiList, Double.MIN_VALUE); - for (Roi roi : roiList){ - for (int i = 0; i < expectedResults.get(roi.getName()).length; i++){ - Assert.assertEquals(expectedResults.get(roi.getName())[i], result.get(roi.getName()).get(i), 0.0009); + DataReduction.ReducedData reducedData = new DataReduction.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), + imagePlus.getNChannels() * roiList.size(), DataReductionGUI.AvailableMeasurements.AVERAGE); + DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, Double.MIN_VALUE, reducedData); + for (int r = 0; r < expectedResults.length; r++){ + for (int c = 0; c < expectedResults[r].length; c++){ + Assert.assertEquals(expectedResults[r][c], result.data[r][c], 0.0009); } } } @@ -56,14 +59,12 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi public void testMean2DCalculation(){ // Ensure the mean calculated for each ROI, and each time point is what's to be expected SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); - simResultsLoader.createS3ClientAndReader(); - ImagePlus labResultImage2D = simResultsLoader.getImgPlusFromN5File(); + ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; - HashMap expectedResults = new HashMap(){{put(labRoi.getName(), labMeans2DLabROI); put(simROI.getName(), labMeans2DSimROI);}}; - compareExpectedCalculations(labResultImage2D, roiList, expectedResults); + compareExpectedCalculations(labResultImage2D, roiList, labMeans2D); } @Test @@ -71,7 +72,6 @@ public void testMean3DCalculation(){ ImagePlus mitosis = new ImagePlus(getTestResourceFiles("mitosis.tif").getAbsolutePath()); Roi mitosisROI = RoiDecoder.open(getTestResourceFiles("ROIs/Mitosis Center.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(mitosisROI);}}; - HashMap expectedResults = new HashMap(){{put(mitosisROI.getName(), threeDMeans);}}; - compareExpectedCalculations(mitosis, roiList, expectedResults); + compareExpectedCalculations(mitosis, roiList, threeDMeans); } } From 5ce1235a7a7e33ad7bf9910cc92bdb25119833ae Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 31 Oct 2024 12:37:54 -0400 Subject: [PATCH 12/44] SimResultsLoader as Central Image Object Instead of passing around ImagePlus internally, pass the SimResultsLoader which allows for extra commands to be executed (ex. meta data retrieval) in addition image data. --- .../java/org/vcell/N5/UI/N5ExportTable.java | 6 +- .../vcell/N5/retrieving/LoadingManager.java | 6 +- .../N5/retrieving/SimLoadingListener.java | 2 +- .../vcell/N5/retrieving/SimResultsLoader.java | 125 +++++++++--------- .../N5/retrieving/N5ImageHandlerTest.java | 25 +--- 5 files changed, 78 insertions(+), 86 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 27ad19a..5429c62 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -223,11 +223,11 @@ public void simIsLoading(int itemRow, String exportID) { } @Override - public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus) { - loadingRowsJobID.remove(itemRow); + public void simFinishedLoading(SimResultsLoader loadedResults) { + loadingRowsJobID.remove(loadedResults.rowNumber); exportListTable.repaint(); controlPanel.allowCancel(false); - imagePlus.show(); + loadedResults.getImagePlus().show(); } static class N5ExportTableModel extends AbstractTableModel { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index bd17b08..7c05c13 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -3,7 +3,6 @@ import com.amazonaws.AbortedException; import com.amazonaws.http.timers.client.SdkInterruptedException; import ij.ImagePlus; -import ij.plugin.Duplicator; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.ControlButtonsPanel; @@ -57,7 +56,8 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o imagePlus = simResultsLoader.openInMemory(rangeSelector); } } else{ - imagePlus = simResultsLoader.getImgPlusFromN5File(); + simResultsLoader.loadImageFromN5File(); + imagePlus = simResultsLoader.getImagePlus(); } } catch (RuntimeException e) { @@ -149,7 +149,7 @@ public void notifySimIsLoading(SimResultsLoader simResultsLoader) { @Override public void notifySimIsDoneLoading(SimResultsLoader simResultsLoader, ImagePlus imagePlus) { for (SimLoadingListener simLoadingListener: eventListenerList.getListeners(SimLoadingListener.class)){ - simLoadingListener.simFinishedLoading(simResultsLoader.rowNumber, simResultsLoader.exportID, imagePlus); + simLoadingListener.simFinishedLoading(simResultsLoader); } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java index a53f46d..e517f11 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimLoadingListener.java @@ -8,6 +8,6 @@ public interface SimLoadingListener extends EventListener { public void simIsLoading(int itemRow, String exportID); - public void simFinishedLoading(int itemRow, String exportID, ImagePlus imagePlus); + public void simFinishedLoading(SimResultsLoader loadedResult); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index a731e69..fa72d3c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -8,13 +8,12 @@ import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.google.gson.GsonBuilder; +import com.google.gson.internal.LinkedTreeMap; import ij.ImagePlus; -import ij.VirtualStack; import ij.plugin.ContrastEnhancer; import ij.plugin.Duplicator; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; -import net.imglib2.img.display.imagej.ImageJVirtualStackFloat; import net.imglib2.type.numeric.real.DoubleType; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; @@ -24,7 +23,6 @@ import org.janelia.saalfeldlab.n5.N5KeyValueReader; import org.janelia.saalfeldlab.n5.N5Reader; import org.janelia.saalfeldlab.n5.imglib2.N5Utils; -import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.RangeSelector; @@ -43,22 +41,21 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; +import java.util.TreeMap; public class SimResultsLoader { private File selectedLocalFile; - private AmazonS3 s3Client; - private String bucketName; - private String s3ObjectKey; private URI uri; private String dataSetChosen; - public String userSetFileName = null; private static final String defaultS3Region = "site2-low"; - private N5Reader n5AmazonS3Reader; - + private N5Reader n5AmazonS3Reader = null; private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; + private ImagePlus imagePlus = null; + + + public String userSetFileName = null; public int rowNumber; public String exportID; @@ -83,42 +80,52 @@ public SimResultsLoader(String stringURI, String userSetFileName){ } } + ///////////////////////////////// + // Loading Simulation Results // + /////////////////////////////// + public void createS3ClientAndReader(){ logger.debug("Creating S3 Client with url: " + uri); if (uri.getHost().equals("minikube.remote") || uri.getHost().equals("minikube.island")){ - SSLContext sslContext = null; - try { - sslContext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build(); - } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException ex) { - throw new RuntimeException("Custom ssl context not functional.",ex); - } - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - ConnectionSocketFactory connectionSocketFactory = new SdkTLSSocketFactory(sslContext, hostnameVerifier); - ClientConfiguration clientConfiguration = new ClientConfiguration(); - clientConfiguration.getApacheHttpClientConfig().setSslSocketFactory(connectionSocketFactory); - s3ClientBuilder.setClientConfiguration(clientConfiguration); + allowInsecureConnections(); } + ////////////////////////////////////////////// + // assume it is one of our URLs // + // http://vcell:8000/bucket/object/object2 // + ////////////////////////////////////////////// - // assume it is one of our URLs - // http://vcell:8000/bucket/object/object2 String[] pathSubStrings = uri.getPath().split("/", 3); - this.s3ObjectKey = pathSubStrings[2]; - this.bucketName = pathSubStrings[1]; + String s3ObjectKey = pathSubStrings[2]; + String bucketName = pathSubStrings[1]; s3ClientBuilder.withPathStyleAccessEnabled(true); logger.debug("Creating S3 Client with Path Based Buckets"); s3ClientBuilder.withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())); s3ClientBuilder.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(uri.getScheme() + "://" + uri.getAuthority(), defaultS3Region)); - this.s3Client = s3ClientBuilder.build(); + AmazonS3 s3Client = s3ClientBuilder.build(); S3KeyValueAccess amazonS3KeyValueAccess = new S3KeyValueAccess(s3Client, bucketName, false); n5AmazonS3Reader = new N5KeyValueReader(amazonS3KeyValueAccess, s3ObjectKey, new GsonBuilder(), false); } + private void allowInsecureConnections(){ + SSLContext sslContext = null; + try { + sslContext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build(); + } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException ex) { + throw new RuntimeException("Custom ssl context not functional.",ex); + } + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + ConnectionSocketFactory connectionSocketFactory = new SdkTLSSocketFactory(sslContext, hostnameVerifier); + ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.getApacheHttpClientConfig().setSslSocketFactory(connectionSocketFactory); + s3ClientBuilder.setClientConfiguration(clientConfiguration); + } + /** By default N5 library assumes that S3 URL's are formated in the standard amazon format. That being https://BUCKETNAME.s3.REGION.amazonaws.com {@link org.janelia.saalfeldlab.n5.s3.AmazonS3Utils}. Because our objects @@ -126,35 +133,42 @@ public boolean verify(String hostname, SSLSession session) { it's the fallback style chosen by the N5 libraries if standard format is unavailable. */ - public ImagePlus getImgPlusFromN5File() { + public ImagePlus getImagePlus(){ + if (imagePlus != null){ + return imagePlus; + } + if (n5AmazonS3Reader == null){ + createS3ClientAndReader(); + } + loadImageFromN5File(); + return imagePlus; + } -// N5AmazonS3Reader n5AmazonS3Reader = new N5AmazonS3Reader(s3Client, bucketName, "/" + s3ObjectKey); + public void loadImageFromN5File() { long start = System.currentTimeMillis(); logger.debug("Reading N5 File " + userSetFileName + " Into Virtual Image"); if (userSetFileName == null || userSetFileName.isEmpty()){ userSetFileName = n5AmazonS3Reader.getAttribute(dataSetChosen, "name", String.class); } - SimCacheLoader simCacheLoader = SimCacheLoader.factoryDefault(n5AmazonS3Reader, dataSetChosen); CachedCellImg cachedCellImg = simCacheLoader.createCachedCellImage(); - ImagePlus imagePlus = ImageJFunctions.wrap(cachedCellImg, userSetFileName); + imagePlus = ImageJFunctions.wrap(cachedCellImg, userSetFileName); simCacheLoader.setImagesResponsibleFor(imagePlus); long end = System.currentTimeMillis(); logger.debug("Read N5 File " + userSetFileName + " Into ImageJ taking: " + ((end - start) / 1000.0) + "s"); setUnits(n5AmazonS3Reader, imagePlus); - imagePlus.setProperty("channelInfo", n5AmazonS3Reader.getAttribute(dataSetChosen, "channelInfo", HashMap.class)); + imagePlus.setProperty("channelInfo", getChannelInfo()); imagePlus.setProperty("maskInfo", n5AmazonS3Reader.getAttribute(dataSetChosen, "maskMapping", HashMap.class)); imagePlus.setZ(Math.floorDiv(imagePlus.getNSlices(), 2)); imagePlus.setT(Math.floorDiv(imagePlus.getNFrames(), 2)); new ContrastEnhancer().stretchHistogram(imagePlus, 1); - return imagePlus; } public ImagePlus openInMemory(RangeSelector rangeSelector){ - ImagePlus imagePlus = this.getImgPlusFromN5File(); + loadImageFromN5File(); long start = System.currentTimeMillis(); logger.debug("Loading Virtual N5 File " + userSetFileName + " Into Memory"); imagePlus = new Duplicator().run(imagePlus, rangeSelector.startC, rangeSelector.endC, rangeSelector.startZ, @@ -164,6 +178,11 @@ public ImagePlus openInMemory(RangeSelector rangeSelector){ return imagePlus; } + + //////////////// + // Properties // + //////////////// + private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ try{ double pixelWidth = n5Reader.getAttribute(dataSetChosen, "pixelWidth", double.class); @@ -186,38 +205,24 @@ public ArrayList getN5Dimensions(){ return n5AmazonS3Reader.getAttribute(dataSetChosen, "dimensions", ArrayList.class); } + public LinkedTreeMap> getChannelInfo(){ + return (LinkedTreeMap>) n5AmazonS3Reader.getAttribute(dataSetChosen, "channelInfo", LinkedTreeMap.class); + } + void setDataSetChosen(String dataSetChosen) { this.dataSetChosen = dataSetChosen; } + ///////////////////////// + // Local File Reading // + //////////////////////// + void setSelectedLocalFile(File selectedLocalFile){ this.selectedLocalFile = selectedLocalFile; } - ArrayList getS3N5DatasetList() throws IOException { - // used as a flag to tell that remote access is occurring, and that there is no local files - try(N5AmazonS3Reader n5AmazonS3Reader = new N5AmazonS3Reader(this.s3Client, this.bucketName)) { - return new ArrayList<>(Arrays.asList(n5AmazonS3Reader.deepListDatasets(this.s3ObjectKey))); - } - } ImagePlus getImgPlusFromLocalN5File() throws IOException { N5Reader n5Reader = new N5FSReader(selectedLocalFile.getPath()); return ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5Reader, dataSetChosen), userSetFileName); } - - ArrayList getN5DatasetList() throws IOException { - // auto closes reader - logger.debug("Getting List of N5 Datasets"); - try (N5FSReader n5Reader = new N5FSReader(selectedLocalFile.getPath())) { - String[] metaList = n5Reader.deepList("/"); - ArrayList fList = new ArrayList<>(); - for (String s : metaList) { - if (n5Reader.datasetExists(s)) { - fList.add(s); - }; - } - logger.debug("Got List of N5 Datasets"); - return fList; - } - } } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java index 1403cb3..140fd13 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java @@ -59,13 +59,6 @@ public void run(){ N5ImageHandler.initializeLogService(); } - @Test - public void testN5DatasetList() throws IOException { - SimResultsLoader simResultsLoader = new SimResultsLoader(); - simResultsLoader.setSelectedLocalFile(this.getTestResourceFiles(n5FileName)); - this.dataSetListTest(simResultsLoader.getN5DatasetList()); - } - @Test public void testGettingImgPlus() throws IOException { SimResultsLoader simResultsLoader = new SimResultsLoader(); @@ -84,7 +77,8 @@ public void testS3AlphaInstance() throws IOException{ for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); simResultsLoader.createS3ClientAndReader(); - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + simResultsLoader.loadImageFromN5File(); + ImagePlus imagePlus = simResultsLoader.getImagePlus(); //stats that have been preemptively calculated within VCell alphaStatsTest(imagePlus, n5DataSetFile, stats.HISTMAX); @@ -99,7 +93,8 @@ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); simResultsLoader.createS3ClientAndReader(); - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + simResultsLoader.loadImageFromN5File(); + ImagePlus imagePlus = simResultsLoader.getImagePlus(); ImagePlus inMemory = new Duplicator().run(imagePlus); for (Object property : imagePlus.getProperties().keySet()){ inMemory.setProperty((String) property, imagePlus.getProperty((String) property)); @@ -120,7 +115,8 @@ public void testUnits() throws IOException { for (N5DataSetFile n5DataSetFile: n5DataSetFiles){ SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); simResultsLoader.createS3ClientAndReader(); - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + simResultsLoader.loadImageFromN5File(); + ImagePlus imagePlus = simResultsLoader.getImagePlus(); double areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1); double totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight(); @@ -287,15 +283,6 @@ private ImagePlus setImageMask(ImagePlus imagePlus){ return imagePlus; } - - private void remoteN5ImgPlusTests(SimResultsLoader simResultsLoader) throws IOException { - ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - dataSetListTest(simResultsLoader.getS3N5DatasetList()); - fiveDStackTests(imagePlus); - imagePlus = new Duplicator().run(imagePlus); //Tests taking the N5 file from streaming to in memory - fiveDStackTests(imagePlus); - } - private void fiveDStackTests(ImagePlus variableImgPlus){ ImagePlus controlImgPlus = Opener.openUsingBioFormats(this.getTestResourceFiles("mitosis.tif").getAbsolutePath()); int[] variableDimensions = variableImgPlus.getDimensions(); From 115fecf7403418151558388882bb16604173f087 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 1 Nov 2024 07:57:01 -0400 Subject: [PATCH 13/44] Test Normalization of 2D Images --- .../org/vcell/N5/analysis/DataReduction.java | 2 +- .../vcell/N5/analysis/DataReductionTest.java | 27 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index c5e2f09..db5acd7 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -129,7 +129,7 @@ private void addValuesToCSVMatrix(ReducedData reducedData){ imagePlus.setT(k); normal += imagePlus.getProcessor().getStatistics().mean; } - normal = normal / (endT - startT); + normal = normal / (endT - startT + 1); // inclusive of final point return normal; } else { return Double.MIN_NORMAL; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java index d989b74..d016c66 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java @@ -44,10 +44,15 @@ public static void init(){ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults){ DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( false, roiList, roiList, imagePlus,4, null); + compareExpectedCalculations(imagePlus, roiList, expectedResults, dataReductionSubmission, Double.MIN_VALUE); + } + + private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults, + DataReductionGUI.DataReductionSubmission dataReductionSubmission, double normValue){ DataReduction dataReduction = new DataReduction(dataReductionSubmission); DataReduction.ReducedData reducedData = new DataReduction.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), imagePlus.getNChannels() * roiList.size(), DataReductionGUI.AvailableMeasurements.AVERAGE); - DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, Double.MIN_VALUE, reducedData); + DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, normValue, reducedData); for (int r = 0; r < expectedResults.length; r++){ for (int c = 0; c < expectedResults[r].length; c++){ Assert.assertEquals(expectedResults[r][c], result.data[r][c], 0.0009); @@ -74,4 +79,24 @@ public void testMean3DCalculation(){ ArrayList roiList = new ArrayList(){{add(mitosisROI);}}; compareExpectedCalculations(mitosis, roiList, threeDMeans); } + + @Test + public void testMeanAndNormalization2DCalculation(){ + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); + ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); + double mean = labResultImage2D.getStatistics().mean; // the normal for a single frame normalization + double[][] normalizedValues = new double[labMeans2D.length][labMeans2D[0].length]; + for (int r = 0; r < labMeans2D.length; r++){ + for (int c =0; c < labMeans2D[0].length; c++){ + normalizedValues[r][c] = labMeans2D[r][c] / mean; + } + } + Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); + Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); + ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; + DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( + true, roiList, roiList, labResultImage2D, 1, 1, 1, 1,4, null); + + compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, dataReductionSubmission, mean); + } } From 06af5688fd14c39498c2acffe0c5cc7497a43ab2 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 1 Nov 2024 10:29:08 -0400 Subject: [PATCH 14/44] Add Metadata to Exported Data Sheet --- .../java/org/vcell/N5/UI/N5ExportTable.java | 4 +- .../org/vcell/N5/analysis/DataReduction.java | 55 +++++++++++++------ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 5429c62..b4643dd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit; public class N5ExportTable extends JScrollPane implements ListSelectionListener, SimLoadingListener { - private N5ExportTableModel n5ExportTableModel; + public N5ExportTableModel n5ExportTableModel; private JTable exportListTable; private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); @@ -230,7 +230,7 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { loadedResults.getImagePlus().show(); } - static class N5ExportTableModel extends AbstractTableModel { + public static class N5ExportTableModel extends AbstractTableModel { public final ArrayList headers = new ArrayList(){{ add("BioModel"); add("Application"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index db5acd7..e23c31f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -7,8 +7,10 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; @@ -22,6 +24,7 @@ public class DataReduction implements SimLoadingListener { private final ArrayList arrayOfSimRois; private final Object csvMatrixLock = new Object(); + private final Object metaDataLock = new Object(); private File file; private int numOfImagesToBeOpened; @@ -34,6 +37,9 @@ public class DataReduction implements SimLoadingListener { private final Sheet metaDataSheet = workbook.createSheet("Metadata"); private int colIndex; + private int metaDataRow = 1; + private int metaDataParameterCol = 5; + private final HashMap parameterNameToCol = new HashMap<>(); private final DataReductionGUI.RangeOfImage simRange; @@ -100,6 +106,12 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ } } addValuesToCSVMatrix(reducedData); + synchronized (metaDataLock){ + metaDataSheet.createRow(0).createCell(1).setCellValue("BioModel Name"); + metaDataSheet.getRow(0).createCell(2).setCellValue("Application Name"); + metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); + metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); + } } private void addValuesToCSVMatrix(ReducedData reducedData){ @@ -181,8 +193,31 @@ ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, return reducedData; } - private void addMetaData(){ - + // If parameter is not in list of parameters, add new column. If simulation does not have parameter say "not-present" + private void addMetaData(SimResultsLoader loadedResults){ + synchronized (metaDataLock){ + N5ExportTable n5ExportTable = MainPanel.n5ExportTable; + ExportDataRepresentation.SimulationExportDataRepresentation data = n5ExportTable.n5ExportTableModel.getRowData(loadedResults.rowNumber); + metaDataSheet.createRow(metaDataRow).createCell(0).setCellValue(loadedResults.userSetFileName); + metaDataSheet.getRow(metaDataRow).createCell(1).setCellValue(data.biomodelName); + metaDataSheet.getRow(metaDataRow).createCell(2).setCellValue(data.applicationName); + metaDataSheet.getRow(metaDataRow).createCell(3).setCellValue(data.simulationName); + metaDataSheet.getRow(metaDataRow).createCell(4).setCellValue(data.uri); + ArrayList parameterValues = data.differentParameterValues; + for (String s : parameterValues){ + String[] tokens = s.split(":"); + String colValue = tokens[1] + ":" + tokens[2]; + if (parameterNameToCol.containsKey(tokens[0])){ + metaDataSheet.getRow(metaDataRow).createCell(parameterNameToCol.get(tokens[0])).setCellValue(colValue); + } else{ + metaDataSheet.getRow(0).createCell(metaDataParameterCol).setCellValue(tokens[0] + "\n(Default:Set Value)"); + metaDataSheet.getRow(metaDataRow).createCell(metaDataParameterCol).setCellValue(colValue); + parameterNameToCol.put(tokens[0], metaDataParameterCol); + metaDataParameterCol += 1; + } + } + metaDataRow += 1; + } } private void writeCSVMatrix(){ @@ -211,23 +246,9 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), imagePlus.getNChannels(), DataReductionGUI.AvailableMeasurements.AVERAGE); reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); + addMetaData(loadedResults); addValuesToCSVMatrix(reducedData); } - - public static void main(String[] args) { - File file = new File("/Users/evalencia/Documents/testv2.xlsx"); - - try { - Workbook workbook = new HSSFWorkbook(); -// Files.createFile(file.toPath()); - Sheet sheet = workbook.createSheet("Hello"); - sheet.createRow(1).createCell(0).setCellValue("2"); - workbook.write(Files.newOutputStream(file.toPath())); - workbook.close(); - } catch (IOException e){ - throw new RuntimeException(e); - } - } } From 58487a417213bd2bf3e5ce027d7282cc0dfedc8d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 1 Nov 2024 14:06:25 -0400 Subject: [PATCH 15/44] Update Main Panel GUI --- .../org/vcell/N5/UI/AdvancedFeatures.java | 17 +++++----- .../org/vcell/N5/UI/ControlButtonsPanel.java | 32 +++++++++++-------- .../main/java/org/vcell/N5/UI/MainPanel.java | 24 +++++++------- .../java/org/vcell/N5/UI/N5ExportTable.java | 5 ++- .../org/vcell/N5/UI/RemoteFileSelection.java | 5 ++- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java index f2d6884..62c6152 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/AdvancedFeatures.java @@ -6,8 +6,7 @@ import java.awt.*; public class AdvancedFeatures extends JPanel { - public final JCheckBox inMemory; - public final JCheckBox dataReduction; + public final JButton openInMemory; public final JButton copyLink; public final JButton useN5Link; @@ -16,21 +15,21 @@ public AdvancedFeatures(){ Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); - inMemory = new JCheckBox("Open In Memory"); - dataReduction = new JCheckBox("Run Measurement Script"); + openInMemory = new JButton("Open In Memory"); JPanel checkBoxPanel = new JPanel(); - checkBoxPanel.add(dataReduction); +// checkBoxPanel.add(openInMemory); JPanel buttonPanel = new JPanel(); copyLink = new JButton("Copy Link"); useN5Link = new JButton("Use N5 Link"); buttonPanel.add(copyLink); buttonPanel.add(useN5Link); + buttonPanel.add(openInMemory); - setLayout(new BorderLayout()); - add(buttonPanel, BorderLayout.NORTH); - add(checkBoxPanel, BorderLayout.SOUTH); +// setLayout(new BorderLayout()); +// add(buttonPanel, BorderLayout.NORTH); +// add(checkBoxPanel, BorderLayout.SOUTH); + add(buttonPanel); this.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Advanced Features ")); } - } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index de063b9..4c72ab0 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -12,7 +12,7 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private static JButton openOrCancel; - private JButton openInMemory; + private final JButton dataReduction; // private final JButton openLocal = new JButton("Open N5 Local"); private final JButton questionMark; @@ -31,7 +31,7 @@ public ControlButtonsPanel(){ displayAdvancedFeatures = new JCheckBox("Advanced Features"); openOrCancel = new JButton("Open Virtually"); - openInMemory = new JButton("Open In Memory"); + dataReduction = new JButton("Run Measurement Script"); questionMark = new JButton("?"); questionMark.setPreferredSize(new Dimension(20, 20)); @@ -43,16 +43,16 @@ public ControlButtonsPanel(){ topRow.add(openOrCancel, gridBagConstraints); gridBagConstraints.gridx = 1; - topRow.add(openInMemory, gridBagConstraints); + topRow.add(dataReduction, gridBagConstraints); + - gridBagConstraints.gridx = 2; - topRow.add(questionMark); JPanel bottomRow = new JPanel(new GridBagLayout()); bottomRow.add(includeExampleExports); gridBagConstraints.gridx = 1; bottomRow.add(displayAdvancedFeatures, gridBagConstraints); - + gridBagConstraints.gridx = 2; + bottomRow.add(questionMark); JPanel userButtonsPanel = new JPanel(new GridBagLayout()); gridBagConstraints.gridx = 0; @@ -86,11 +86,12 @@ public ControlButtonsPanel(){ // openLocal.addActionListener(this); includeExampleExports.addActionListener(this); displayAdvancedFeatures.addActionListener(this); - openInMemory.addActionListener(this); + dataReduction.addActionListener(this); + advancedFeatures.openInMemory.addActionListener(this); openOrCancel.setEnabled(false); - openInMemory.setEnabled(false); + dataReduction.setEnabled(false); advancedFeatures.copyLink.setEnabled(false); } @@ -101,11 +102,13 @@ public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFi @Override public void actionPerformed(ActionEvent e) { - if(e.getSource().equals(openOrCancel) || e.getSource().equals(openInMemory)){ + boolean inMemory = e.getSource().equals(advancedFeatures.openInMemory); + boolean performDataReduction = e.getSource().equals(dataReduction); + if(e.getSource().equals(openOrCancel) || inMemory || performDataReduction){ if (openOrCancel.getText().equals("Cancel")){ n5ExportTable.removeFromLoadingRows(); } else { - n5ExportTable.openSelectedRows(e.getSource().equals(openInMemory)); + n5ExportTable.openSelectedRows(inMemory, performDataReduction); } } else if (e.getSource().equals(advancedFeatures.copyLink)) { n5ExportTable.copySelectedRowLink(); @@ -126,7 +129,8 @@ public void allowCancel(boolean allow){ advancedFeatures.copyLink.setEnabled(true); advancedFeatures.useN5Link.setEnabled(true); remoteFileSelection.submitS3Info.setEnabled(true); - openInMemory.setEnabled(!allow); + dataReduction.setEnabled(!allow); + advancedFeatures.openInMemory.setEnabled(!allow); if (allow){ openOrCancel.setText("Cancel"); } else { @@ -139,7 +143,8 @@ public void enableRowContextDependentButtons(boolean enable){ if (allowButtons){ openOrCancel.setEnabled(enable); advancedFeatures.copyLink.setEnabled(enable); - openInMemory.setEnabled(enable); + dataReduction.setEnabled(enable); + advancedFeatures.openInMemory.setEnabled(enable); } } @@ -148,7 +153,8 @@ public void enableCriticalButtons(boolean enable){ openOrCancel.setEnabled(enable); advancedFeatures.copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); - openInMemory.setEnabled(enable); + dataReduction.setEnabled(enable); + advancedFeatures.openInMemory.setEnabled(enable); allowButtons = enable; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index 8f82d9f..4a5690b 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -5,6 +5,7 @@ import javax.swing.*; import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; @@ -12,8 +13,7 @@ import java.util.Enumeration; public class MainPanel { - private static JDialog exportTableDialog; - private final int paneWidth = 800; + private static JFrame exportTableDialog; public final static ControlButtonsPanel controlButtonsPanel = new ControlButtonsPanel(); public final static N5ExportTable n5ExportTable = new N5ExportTable(); @@ -23,32 +23,30 @@ public class MainPanel { public final static SearchBar searchBar = new SearchBar(); public MainPanel(){ - JPanel parentPanel = new JPanel(); - - n5ExportTable.initialize(controlButtonsPanel, exportDetailsPanel, timeFilter); controlButtonsPanel.initialize(n5ExportTable, remoteFileSelection); + JPanel contentPanel = new JPanel(new BorderLayout()); JPanel northPanel = new JPanel(new BorderLayout()); northPanel.add(controlButtonsPanel, BorderLayout.SOUTH); - parentPanel.setLayout(new BorderLayout()); - parentPanel.add(northPanel, BorderLayout.NORTH); JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, n5ExportTable, exportDetailsPanel); jSplitPane.setContinuousLayout(true); - parentPanel.add(jSplitPane, BorderLayout.CENTER); JPanel filters = new JPanel(new BorderLayout()); Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); filters.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Filters ")); filters.add(timeFilter, BorderLayout.NORTH); filters.add(searchBar, BorderLayout.SOUTH); - parentPanel.add(filters, BorderLayout.SOUTH); - parentPanel.setPreferredSize(new Dimension(paneWidth, 750)); - JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); - exportTableDialog = pane.createDialog("VCell Exports"); - exportTableDialog.setModal(false); + contentPanel.add(northPanel, BorderLayout.NORTH); + contentPanel.add(jSplitPane, BorderLayout.CENTER); + contentPanel.add(filters, BorderLayout.SOUTH); + contentPanel.setBorder(new EmptyBorder(15, 12, 15, 12)); + + exportTableDialog = new JFrame("VCell Exports"); + exportTableDialog.add(contentPanel); + exportTableDialog.pack(); exportTableDialog.setResizable(true); exportTableDialog.setVisible(true); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index b4643dd..c8bfc39 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -155,7 +155,7 @@ private void automaticRefresh(){ refreshTableThread.start(); } - public void openSelectedRows(boolean openInMemory){ + public void openSelectedRows(boolean openInMemory, boolean performDataReduction){ ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; @@ -163,9 +163,8 @@ public void openSelectedRows(boolean openInMemory){ SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); filesToOpen.add(simResultsLoader); } - AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, openInMemory, - advancedFeatures.dataReduction.isSelected()); + performDataReduction); } public void copySelectedRowLink(){ diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index fbe16b9..7ed8a78 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -96,10 +96,9 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); - AdvancedFeatures advancedFeatures = MainPanel.controlButtonsPanel.advancedFeatures; N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, - advancedFeatures.inMemory.isSelected(), - advancedFeatures.dataReduction.isSelected()); + false, + false); this.setVisible(false); } } From 92c50d2378d0a17744971579deea6b87adbdd6de Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 4 Nov 2024 11:37:39 -0500 Subject: [PATCH 16/44] Create Selection Range GUI --- .../org/vcell/N5/analysis/SelectSimRange.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java new file mode 100644 index 0000000..5bbadc9 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java @@ -0,0 +1,104 @@ +package org.vcell.N5.analysis; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; + +class SelectSimRange extends JPanel implements ActionListener { + private final JCheckBox selectRangeOfMeasurement = new JCheckBox("Select Measurement Range: "); + + private final JTextField cStart = new JTextField(); + private final JTextField cEnd = new JTextField(); + + private final JTextField zStart = new JTextField(); + private final JTextField zEnd = new JTextField(); + + private final JTextField tStart = new JTextField(); + private final JTextField tEnd = new JTextField(); + + private final JPanel rangeSelectionPanel; + + public SelectSimRange(JDialog jDialog){ + selectRangeOfMeasurement.addActionListener(this); + JLabel explainInput = new JLabel("Range of Simulation to Perform Measurement"); + + JPanel cRange = new JPanel(new GridLayout()); + cRange.add(new JLabel("Channel Range: ")); + cRange.add(cStart); + cRange.add(new JLabel("to")); + cRange.add(cEnd); + + JPanel zRange = new JPanel(new GridLayout()); + zRange.add(new JLabel("Z Range: ")); + zRange.add(zStart); + zRange.add(new JLabel("to")); + zRange.add(zEnd); + + JPanel tRange = new JPanel(new GridLayout()); + tRange.add(new JLabel("Time Range: ")); + tRange.add(tStart); + tRange.add(new JLabel("to")); + tRange.add(tEnd); + + rangeSelectionPanel = new JPanel(new GridLayout(4, 1)); + rangeSelectionPanel.add(explainInput); + rangeSelectionPanel.add(cRange); + rangeSelectionPanel.add(zRange); + rangeSelectionPanel.add(tRange); + rangeSelectionPanel.addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + jDialog.revalidate(); + jDialog.repaint(); + jDialog.pack(); + } + @Override + public void componentHidden(ComponentEvent e) { + jDialog.revalidate(); + jDialog.repaint(); + jDialog.pack(); + } + }); + rangeSelectionPanel.setVisible(false); + + this.add(selectRangeOfMeasurement); + this.add(rangeSelectionPanel); + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + } + + public RangeOfImage getRangeOfSim(){ + RangeOfImage rangeOfImage = new RangeOfImage( + Integer.parseInt(tStart.getText()), Integer.parseInt(tEnd.getText()), + Integer.parseInt(zStart.getText()), Integer.parseInt(zEnd.getText()), + Integer.parseInt(cStart.getText()), Integer.parseInt(cEnd.getText()) + ); + return rangeOfImage; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(selectRangeOfMeasurement)){ + rangeSelectionPanel.setVisible(selectRangeOfMeasurement.isSelected()); + } + } + + public static class RangeOfImage{ + public final int timeStart; + public final int timeEnd; + public final int zStart; + public final int zEnd; + public final int channelStart; + public final int channelEnd; + public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channelStart, int channelEnd){ + this.timeStart = timeStart; + this.timeEnd = timeEnd; + this.zStart = zStart; + this.zEnd = zEnd; + this.channelStart = channelStart; + this.channelEnd = channelEnd; + } + } +} From 0b998cbc2daa4255f6e39367f6000d5c3b4bff37 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 4 Nov 2024 12:01:20 -0500 Subject: [PATCH 17/44] Seperate GUI Components into Respective Classes --- .../org/vcell/N5/analysis/DataReduction.java | 10 +- .../vcell/N5/analysis/DataReductionGUI.java | 312 ++++-------------- .../org/vcell/N5/analysis/NoramalizeGUI.java | 87 +++++ .../org/vcell/N5/analysis/RoiSelection.java | 136 ++++++++ 4 files changed, 299 insertions(+), 246 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index e23c31f..df7a985 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -41,7 +41,7 @@ public class DataReduction implements SimLoadingListener { private int metaDataParameterCol = 5; private final HashMap parameterNameToCol = new HashMap<>(); - private final DataReductionGUI.RangeOfImage simRange; + private final SelectSimRange.RangeOfImage simRange; // Per Image static class ReducedData{ @@ -152,19 +152,19 @@ private void addValuesToCSVMatrix(ReducedData reducedData){ ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, double normalizationValue, ReducedData reducedData){ - DataReductionGUI.RangeOfImage entireRange = new DataReductionGUI.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), + SelectSimRange.RangeOfImage entireRange = new SelectSimRange.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), 1, imagePlus.getNChannels()); return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, entireRange); } ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, - double normalizationValue, ReducedData reducedData, DataReductionGUI.RangeOfImage rangeOfImage){ + double normalizationValue, ReducedData reducedData, SelectSimRange.RangeOfImage rangeOfImage){ return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, rangeOfImage); } ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, double normalizationValue, ReducedData reducedData, - LinkedTreeMap> channelInfo, DataReductionGUI.RangeOfImage rangeOfImage){ + LinkedTreeMap> channelInfo, SelectSimRange.RangeOfImage rangeOfImage){ int roiCounter = 0; for (Roi roi: roiList) { imagePlus.setRoi(roi); @@ -244,7 +244,7 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { ImagePlus imagePlus = loadedResults.getImagePlus(); double normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, submission.simEndPointNorm); ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), - imagePlus.getNChannels(), DataReductionGUI.AvailableMeasurements.AVERAGE); + simRange.channelEnd - simRange.channelStart + 1, DataReductionGUI.AvailableMeasurements.AVERAGE); reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); addMetaData(loadedResults); addValuesToCSVMatrix(reducedData); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 69dba59..6de7b2d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -3,122 +3,48 @@ import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; -import ij.io.RoiDecoder; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; import javax.swing.*; -import javax.swing.table.AbstractTableModel; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; -public class DataReductionGUI extends JPanel implements ActionListener { +public class DataReductionGUI extends JPanel { private JComboBox chosenImage; private JComboBox chosenMeasurement; - private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); - - private JTextField createNormFromImageStart; - private JTextField createNormFromImageEnd; - private JTextField createNormFromSimStart; - private JTextField createNormFromSimEnd; - private JPanel entireImageFramesJPanel; - - private JButton imageROIFileButton; - private JButton simROIFileButton; - - private String notInMemoryWarning; - - private ArrayList simROIList; - private ArrayList imageROIList; private final JDialog jDialog; private final JOptionPane pane; private File chosenFile; - private int numSimsToOpen; + private final int numSimsToOpen; public int mainGUIReturnValue; public int fileChooserReturnValue; -// private TemporalAnalysis temporalAnalysis = new TemporalAnalysis(); - - public static class RangeOfImage{ - public final int timeStart; - public final int timeEnd; - public final int zStart; - public final int zEnd; - public final int channelStart; - public final int channelEnd; - public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channelStart, int channelEnd){ - this.timeStart = timeStart; - this.timeEnd = timeEnd; - this.zStart = zStart; - this.zEnd = zEnd; - this.channelStart = channelStart; - this.channelEnd = channelEnd; - } - } - public static class DataReductionSubmission{ - public final boolean normalizeMeasurementsBool; - public final ArrayList arrayOfSimRois; - public final ArrayList arrayOfLabRois; - public final ImagePlus labResults; - public final int simStartPointNorm; - public final int simEndPointNorm; - public final int imageStartPointNorm; - public final int imageEndPointNorm; - public final int numOfSimImages; - public final File fileToSaveResultsTo; - public final RangeOfImage experimentImageRange; - public final RangeOfImage simImageRange; - public DataReductionSubmission(boolean normalizeMeasurementsBool,ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, - ImagePlus labResults, int numOfSimImages, File fileToSaveResultsTo){ - this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, - 0,0,0,0, numOfSimImages, fileToSaveResultsTo); - } - - public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, - ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, - int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo){ - this.normalizeMeasurementsBool = normalizeMeasurementsBool; - this.arrayOfLabRois = arrayOfLabRois; - this.arrayOfSimRois = arrayOfSimRois; - this.labResults = labResults; - this.simStartPointNorm = simStartPointNorm; - this.simEndPointNorm = simEndPointNorm; - this.imageStartPointNorm = imageStartPointNorm; - this.imageEndPointNorm = imageEndPointNorm; - this.numOfSimImages = numOfSimImages; - this.fileToSaveResultsTo = fileToSaveResultsTo; - this.experimentImageRange = new RangeOfImage(1, labResults.getNFrames(), - 1, labResults.getNSlices(), 1, labResults.getNChannels()); - this.simImageRange = experimentImageRange; - } - } - - private DataReductionSubmission createSubmission(){ - int simStartPointNorm = createNormFromSimStart.getText().isEmpty() ? Integer.MIN_VALUE : Integer.parseInt(createNormFromSimStart.getText()); - int simEndPointNorm = createNormFromSimEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromSimEnd.getText()); - int imageStartPointNorm = createNormFromImageStart.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageStart.getText()); - int imageEndPointNorm = createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()); - return new DataReductionSubmission(normalizeMeasurement.isSelected(), simROIList, imageROIList, WindowManager.getImage((String) chosenImage.getSelectedItem()), - simStartPointNorm, simEndPointNorm, imageStartPointNorm, imageEndPointNorm, numSimsToOpen, chosenFile); - } + private final SelectSimRange selectSimRange; + private final RoiSelection roiSelection; + private final NoramalizeGUI normalizeGUI; public DataReductionGUI(int numSimsToOpen){ this.numSimsToOpen = numSimsToOpen; - setLayout(new BorderLayout()); - - add(imageAndAnalysisType(), BorderLayout.NORTH); - add(new ROISelection(), BorderLayout.CENTER); - add(normalizeGUI(), BorderLayout.SOUTH); - setVisible(true); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); jDialog = pane.createDialog("Data Reduction"); + jDialog.setResizable(true); + + selectSimRange = new SelectSimRange(jDialog); + roiSelection = new RoiSelection(); + normalizeGUI = new NoramalizeGUI(jDialog); + + add(imageAndAnalysisType()); + add(roiSelection); + add(normalizeGUI); + add(selectSimRange); + setVisible(true); } public void displayGUI(){ @@ -140,36 +66,14 @@ public void displayGUI(){ } } - private JPanel normalizeGUI(){ - JPanel jPanel = new JPanel(new GridLayout(2, 1)); - normalizeMeasurement.addActionListener(this); - JLabel explainInput = new JLabel("Timeline Range to Create Norm"); - - JPanel fromImage = new JPanel(new GridLayout()); - createNormFromImageStart = new JTextField(); - createNormFromImageEnd = new JTextField(); - fromImage.add(new JLabel("Exp. Timeline: ")); - fromImage.add(createNormFromImageStart); - fromImage.add(new JLabel("to")); - fromImage.add(createNormFromImageEnd); - - JPanel fromSim = new JPanel(new GridLayout()); - createNormFromSimStart = new JTextField(); - createNormFromSimEnd = new JTextField(); - fromSim.add(new JLabel("Sim Timeline: ")); - fromSim.add(createNormFromSimStart); - fromSim.add(new JLabel("to")); - fromSim.add(createNormFromSimEnd); - - entireImageFramesJPanel = new JPanel(new GridLayout(3, 1)); - entireImageFramesJPanel.add(explainInput); - entireImageFramesJPanel.add(fromImage); - entireImageFramesJPanel.add(fromSim); - entireImageFramesJPanel.setVisible(false); - - jPanel.add(normalizeMeasurement); - jPanel.add(entireImageFramesJPanel); - return jPanel; + private DataReductionSubmission createSubmission(){ + int[] simRange = normalizeGUI.getSimTimRange(); + int[] labRange = normalizeGUI.getImageTimeRange(); + return new DataReductionSubmission(normalizeGUI.performNormalization(), + roiSelection.getSimROIList(), roiSelection.getImageROIList(), + WindowManager.getImage((String) chosenImage.getSelectedItem()), + simRange[0], simRange[1], labRange[0], labRange[1], numSimsToOpen, chosenFile, + selectSimRange.getRangeOfSim()); } @@ -187,23 +91,9 @@ private JPanel imageAndAnalysisType(){ gridBagConstraints.gridy = 3; chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.AVERAGE.publicName}); jPanel.add(chosenMeasurement, gridBagConstraints); - - chosenMeasurement.addActionListener(this); - chosenImage.addActionListener(this); - - return jPanel; } - - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(normalizeMeasurement)) { - entireImageFramesJPanel.setVisible(normalizeMeasurement.isSelected()); - } - } - enum AvailableMeasurements{ AVERAGE("Average"); @@ -213,119 +103,59 @@ enum AvailableMeasurements{ } } - public static void main(String[] args) { - DataReductionGUI dataReductionGUI = new DataReductionGUI(0); - dataReductionGUI.displayGUI(); - } - - class ROISelection extends JPanel implements ActionListener{ - private final JFileChooser imageROIFileChooser = new JFileChooser(); - private final ROIDataModel imageTableModel = new ROIDataModel(); - private final JTable imageROITable = new JTable(imageTableModel); - - private final JFileChooser simROIFileChooser = new JFileChooser(); - private final ROIDataModel simTableModel = new ROIDataModel(); - private final JTable simROITable = new JTable(simTableModel); - public ROISelection(){ - JPanel roisForImage = new JPanel(new GridBagLayout()); - JPanel roisForSims = new JPanel(new GridBagLayout()); - Dimension tableDimensions = new Dimension(100, 70); - imageROITable.getTableHeader().setBackground(Color.WHITE); - imageROITable.setEnabled(false); - simROITable.getTableHeader().setBackground(Color.WHITE); - simROITable.setEnabled(false); - - imageROIFileButton = new JButton("ROI's For Image"); - JScrollPane displayImageROIList = new JScrollPane(imageROITable); - displayImageROIList.setPreferredSize(tableDimensions); - setROIPanelSettings(roisForImage, imageROIFileButton, displayImageROIList); - - simROIFileButton = new JButton("ROI's For Simulation"); - JScrollPane displaySimROIList = new JScrollPane(simROITable); - displaySimROIList.setPreferredSize(tableDimensions); - setROIPanelSettings(roisForSims, simROIFileButton, displaySimROIList); - - imageROIFileButton.addActionListener(this); - simROIFileButton.addActionListener(this); - - this.setLayout(new BorderLayout()); - this.add(roisForImage, BorderLayout.WEST); - this.add(roisForSims, BorderLayout.EAST); - } + public static class DataReductionSubmission{ + public final boolean normalizeMeasurementsBool; + public final ArrayList arrayOfSimRois; + public final ArrayList arrayOfLabRois; + public final ImagePlus labResults; + public final int simStartPointNorm; + public final int simEndPointNorm; + public final int imageStartPointNorm; + public final int imageEndPointNorm; + public final int numOfSimImages; + public final File fileToSaveResultsTo; + public final SelectSimRange.RangeOfImage experimentImageRange; + public final SelectSimRange.RangeOfImage simImageRange; - public void setROIPanelSettings(JPanel jPanel, JButton button, JScrollPane jScrollPane){ - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridy = 0; - gridBagConstraints.gridx = 0; - gridBagConstraints.fill = GridBagConstraints.BOTH; - gridBagConstraints.insets = new Insets(5, 5, 5, 5); - jPanel.add(button, gridBagConstraints); - gridBagConstraints.gridy = 1; - jPanel.add(jScrollPane, gridBagConstraints); + public DataReductionSubmission(boolean normalizeMeasurementsBool,ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int numOfSimImages, File fileToSaveResultsTo){ + this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, + 0,0,0,0, numOfSimImages, fileToSaveResultsTo); } - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(imageROIFileButton)){ - imageROIList = fillROIList(imageROIFileChooser); - imageTableModel.clear(); - for (Roi roi : imageROIList){ - imageTableModel.addRow(roi.getName()); - } - imageROITable.updateUI(); - } else if (e.getSource().equals(simROIFileButton)) { - simROIList = fillROIList(simROIFileChooser); - simTableModel.clear(); - for (Roi roi : simROIList){ - simTableModel.addRow(roi.getName()); - } - simROITable.updateUI(); - } - } - private ArrayList fillROIList(JFileChooser fileChooser){ - fileChooser.setMultiSelectionEnabled(true); - int choice = fileChooser.showDialog(this, "Open ROI's"); - ArrayList roiList = new ArrayList<>(); - if (choice == JFileChooser.APPROVE_OPTION){ - for (File file: fileChooser.getSelectedFiles()){ - roiList.add(RoiDecoder.open(file.getAbsolutePath())); - } - } - return roiList; + public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, + int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo){ + this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, simStartPointNorm, simEndPointNorm, imageStartPointNorm, imageEndPointNorm, + numOfSimImages, fileToSaveResultsTo, + new SelectSimRange.RangeOfImage(1, labResults.getNFrames(), + 1, labResults.getNSlices(), 1, labResults.getNChannels())); } - class ROIDataModel extends AbstractTableModel { - private final ArrayList data = new ArrayList<>(); - private final String[] headers = new String[]{"ROI's Selected"}; - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return headers.length; - } - - @Override - public String getColumnName(int column) { - return headers[column]; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return data.get(rowIndex); - } - - public void addRow(String roiName){ - data.add(roiName); - } - - public void clear(){ - data.clear(); - } + public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, + ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, + int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo, + SelectSimRange.RangeOfImage simRange){ + this.normalizeMeasurementsBool = normalizeMeasurementsBool; + this.arrayOfLabRois = arrayOfLabRois; + this.arrayOfSimRois = arrayOfSimRois; + this.labResults = labResults; + this.simStartPointNorm = simStartPointNorm; + this.simEndPointNorm = simEndPointNorm; + this.imageStartPointNorm = imageStartPointNorm; + this.imageEndPointNorm = imageEndPointNorm; + this.numOfSimImages = numOfSimImages; + this.fileToSaveResultsTo = fileToSaveResultsTo; + this.experimentImageRange = new SelectSimRange.RangeOfImage(1, labResults.getNFrames(), + 1, labResults.getNSlices(), 1, labResults.getNChannels()); + this.simImageRange = simRange; } } + + public static void main(String[] args) { + DataReductionGUI dataReductionGUI = new DataReductionGUI(0); + dataReductionGUI.displayGUI(); + } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java new file mode 100644 index 0000000..e74921f --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java @@ -0,0 +1,87 @@ +package org.vcell.N5.analysis; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; + +class NoramalizeGUI extends JPanel implements ActionListener { + private JTextField createNormFromImageStart; + private JTextField createNormFromImageEnd; + private JTextField createNormFromSimStart; + private JTextField createNormFromSimEnd; + private JPanel entireImageFramesJPanel; + private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); + + public NoramalizeGUI(JDialog jDialog){ + normalizeMeasurement.addActionListener(this); + JLabel explainInput = new JLabel("Timeline Range to Create Norm"); + + JPanel fromImage = new JPanel(new GridLayout()); + createNormFromImageStart = new JTextField(); + createNormFromImageEnd = new JTextField(); + fromImage.add(new JLabel("Exp. Timeline: ")); + fromImage.add(createNormFromImageStart); + fromImage.add(new JLabel("to")); + fromImage.add(createNormFromImageEnd); + + JPanel fromSim = new JPanel(new GridLayout()); + createNormFromSimStart = new JTextField(); + createNormFromSimEnd = new JTextField(); + fromSim.add(new JLabel("Sim Timeline: ")); + fromSim.add(createNormFromSimStart); + fromSim.add(new JLabel("to")); + fromSim.add(createNormFromSimEnd); + + entireImageFramesJPanel = new JPanel(new GridLayout(3, 1)); + entireImageFramesJPanel.add(explainInput); + entireImageFramesJPanel.add(fromImage); + entireImageFramesJPanel.add(fromSim); + entireImageFramesJPanel.addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + jDialog.revalidate(); + jDialog.repaint(); + jDialog.pack(); + } + @Override + public void componentHidden(ComponentEvent e) { + jDialog.revalidate(); + jDialog.repaint(); + jDialog.pack(); + } + }); + entireImageFramesJPanel.setVisible(false); + + this.add(normalizeMeasurement); + this.add(entireImageFramesJPanel); + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + } + + public int[] getSimTimRange(){ + return new int[]{ + createNormFromSimStart.getText().isEmpty() ? Integer.MIN_VALUE : Integer.parseInt(createNormFromSimStart.getText()), + createNormFromSimEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromSimEnd.getText()) + }; + } + + public int[] getImageTimeRange(){ + return new int[]{ + createNormFromImageStart.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageStart.getText()), + createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()) + }; + } + + public boolean performNormalization(){ + return normalizeMeasurement.isSelected(); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(normalizeMeasurement)) { + entireImageFramesJPanel.setVisible(normalizeMeasurement.isSelected()); + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java new file mode 100644 index 0000000..5290198 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java @@ -0,0 +1,136 @@ +package org.vcell.N5.analysis; + +import ij.gui.Roi; +import ij.io.RoiDecoder; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; + +class RoiSelection extends JPanel implements ActionListener { + private final JFileChooser imageROIFileChooser = new JFileChooser(); + private final ROIDataModel imageTableModel = new ROIDataModel(); + private final JTable imageROITable = new JTable(imageTableModel); + + private final JFileChooser simROIFileChooser = new JFileChooser(); + private final ROIDataModel simTableModel = new ROIDataModel(); + private final JTable simROITable = new JTable(simTableModel); + + private final JButton imageROIFileButton; + private final JButton simROIFileButton; + + private ArrayList imageROIList; + private ArrayList simROIList; + + public RoiSelection(){ + JPanel roisForImage = new JPanel(new GridBagLayout()); + JPanel roisForSims = new JPanel(new GridBagLayout()); + Dimension tableDimensions = new Dimension(100, 70); + imageROITable.getTableHeader().setBackground(Color.WHITE); + imageROITable.setEnabled(false); + simROITable.getTableHeader().setBackground(Color.WHITE); + simROITable.setEnabled(false); + + imageROIFileButton = new JButton("ROI's For Image"); + JScrollPane displayImageROIList = new JScrollPane(imageROITable); + displayImageROIList.setPreferredSize(tableDimensions); + setROIPanelSettings(roisForImage, imageROIFileButton, displayImageROIList); + + simROIFileButton = new JButton("ROI's For Simulation"); + JScrollPane displaySimROIList = new JScrollPane(simROITable); + displaySimROIList.setPreferredSize(tableDimensions); + setROIPanelSettings(roisForSims, simROIFileButton, displaySimROIList); + + imageROIFileButton.addActionListener(this); + simROIFileButton.addActionListener(this); + + this.setLayout(new BorderLayout()); + this.add(roisForImage, BorderLayout.WEST); + this.add(roisForSims, BorderLayout.EAST); + } + + public ArrayList getImageROIList(){ + return imageROIList; + } + + public ArrayList getSimROIList(){ + return simROIList; + } + + private void setROIPanelSettings(JPanel jPanel, JButton button, JScrollPane jScrollPane){ + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 0; + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.insets = new Insets(5, 5, 5, 5); + jPanel.add(button, gridBagConstraints); + gridBagConstraints.gridy = 1; + jPanel.add(jScrollPane, gridBagConstraints); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(imageROIFileButton)){ + imageROIList = fillROIList(imageROIFileChooser); + imageTableModel.clear(); + for (Roi roi : imageROIList){ + imageTableModel.addRow(roi.getName()); + } + imageROITable.updateUI(); + } else if (e.getSource().equals(simROIFileButton)) { + simROIList = fillROIList(simROIFileChooser); + simTableModel.clear(); + for (Roi roi : simROIList){ + simTableModel.addRow(roi.getName()); + } + simROITable.updateUI(); + } + } + private ArrayList fillROIList(JFileChooser fileChooser){ + fileChooser.setMultiSelectionEnabled(true); + int choice = fileChooser.showDialog(this, "Open ROI's"); + ArrayList roiList = new ArrayList<>(); + if (choice == JFileChooser.APPROVE_OPTION){ + for (File file: fileChooser.getSelectedFiles()){ + roiList.add(RoiDecoder.open(file.getAbsolutePath())); + } + } + return roiList; + } + + class ROIDataModel extends AbstractTableModel { + private final ArrayList data = new ArrayList<>(); + private final String[] headers = new String[]{"ROI's Selected"}; + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return headers.length; + } + + @Override + public String getColumnName(int column) { + return headers[column]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return data.get(rowIndex); + } + + public void addRow(String roiName){ + data.add(roiName); + } + + public void clear(){ + data.clear(); + } + } +} From 9c2266a303be71efb145a029c7d14c23862601e7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 4 Nov 2024 12:38:11 -0500 Subject: [PATCH 18/44] Fix Data Reduction GUI Size and Refactor Measurement Selection GUI --- .../org/vcell/N5/analysis/DataReduction.java | 8 ++-- .../vcell/N5/analysis/DataReductionGUI.java | 37 +++++-------------- .../{NoramalizeGUI.java => NormalizeGUI.java} | 14 +++---- .../vcell/N5/analysis/SelectMeasurements.java | 24 ++++++++++++ .../vcell/N5/analysis/DataReductionTest.java | 3 +- 5 files changed, 46 insertions(+), 40 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/analysis/{NoramalizeGUI.java => NormalizeGUI.java} (89%) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index df7a985..522624a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -47,8 +47,8 @@ public class DataReduction implements SimLoadingListener { static class ReducedData{ public final double[][] data; public final ArrayList columnHeaders; - public final DataReductionGUI.AvailableMeasurements measurementType; - public ReducedData(int rowLen, int colLen, DataReductionGUI.AvailableMeasurements measurementType){ + public final SelectMeasurements.AvailableMeasurements measurementType; + public ReducedData(int rowLen, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ data = new double[rowLen][colLen]; columnHeaders = new ArrayList<>(); this.measurementType = measurementType; @@ -90,7 +90,7 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ int nFrames = submission.experimentImageRange.timeEnd - submission.experimentImageRange.timeStart + 1; int nSlices = submission.experimentImageRange.zEnd - submission.experimentImageRange.zStart + 1; int nChannels = submission.experimentImageRange.channelEnd - submission.experimentImageRange.channelStart + 1; - ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), DataReductionGUI.AvailableMeasurements.AVERAGE); + ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, submission.experimentImageRange); synchronized (csvMatrixLock){ int rowI = 1; @@ -244,7 +244,7 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { ImagePlus imagePlus = loadedResults.getImagePlus(); double normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, submission.simEndPointNorm); ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), - simRange.channelEnd - simRange.channelStart + 1, DataReductionGUI.AvailableMeasurements.AVERAGE); + simRange.channelEnd - simRange.channelStart + 1, SelectMeasurements.AvailableMeasurements.AVERAGE); reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); addMetaData(loadedResults); addValuesToCSVMatrix(reducedData); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 6de7b2d..042b48f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -13,7 +13,6 @@ public class DataReductionGUI extends JPanel { private JComboBox chosenImage; - private JComboBox chosenMeasurement; private final JDialog jDialog; private final JOptionPane pane; @@ -26,7 +25,7 @@ public class DataReductionGUI extends JPanel { private final SelectSimRange selectSimRange; private final RoiSelection roiSelection; - private final NoramalizeGUI normalizeGUI; + private final NormalizeGUI normalizeGUI; public DataReductionGUI(int numSimsToOpen){ this.numSimsToOpen = numSimsToOpen; @@ -38,13 +37,16 @@ public DataReductionGUI(int numSimsToOpen){ selectSimRange = new SelectSimRange(jDialog); roiSelection = new RoiSelection(); - normalizeGUI = new NoramalizeGUI(jDialog); + normalizeGUI = new NormalizeGUI(jDialog); - add(imageAndAnalysisType()); + add(imageSelectionPanel()); + add(new SelectMeasurements()); add(roiSelection); add(normalizeGUI); add(selectSimRange); setVisible(true); + + jDialog.pack(); } public void displayGUI(){ @@ -76,33 +78,14 @@ private DataReductionSubmission createSubmission(){ selectSimRange.getRangeOfSim()); } - - private JPanel imageAndAnalysisType(){ - JPanel jPanel = new JPanel(new GridLayout(2,4)); - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - jPanel.add(new JLabel("Select Experimental Image"), gridBagConstraints); - gridBagConstraints.gridy = 1; + private JPanel imageSelectionPanel(){ + JPanel jPanel = new JPanel(new GridLayout(1, 2)); + jPanel.add(new JLabel("Select Experimental Image")); chosenImage = new JComboBox<>(WindowManager.getImageTitles()); - jPanel.add(chosenImage, gridBagConstraints); - gridBagConstraints.gridy = 2; - jPanel.add(new JLabel("Measurement Type"), gridBagConstraints); - gridBagConstraints.gridy = 3; - chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.AVERAGE.publicName}); - jPanel.add(chosenMeasurement, gridBagConstraints); + jPanel.add(chosenImage); return jPanel; } - enum AvailableMeasurements{ - AVERAGE("Average"); - - public final String publicName; - AvailableMeasurements(String publicName){ - this.publicName = publicName; - } - } - public static class DataReductionSubmission{ public final boolean normalizeMeasurementsBool; public final ArrayList arrayOfSimRois; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java similarity index 89% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java index e74921f..c2528c1 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NoramalizeGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java @@ -7,15 +7,15 @@ import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -class NoramalizeGUI extends JPanel implements ActionListener { - private JTextField createNormFromImageStart; - private JTextField createNormFromImageEnd; - private JTextField createNormFromSimStart; - private JTextField createNormFromSimEnd; - private JPanel entireImageFramesJPanel; +class NormalizeGUI extends JPanel implements ActionListener { + private final JTextField createNormFromImageStart; + private final JTextField createNormFromImageEnd; + private final JTextField createNormFromSimStart; + private final JTextField createNormFromSimEnd; + private final JPanel entireImageFramesJPanel; private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); - public NoramalizeGUI(JDialog jDialog){ + public NormalizeGUI(JDialog jDialog){ normalizeMeasurement.addActionListener(this); JLabel explainInput = new JLabel("Timeline Range to Create Norm"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java new file mode 100644 index 0000000..43a8a56 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java @@ -0,0 +1,24 @@ +package org.vcell.N5.analysis; + +import javax.swing.*; +import java.awt.*; + +class SelectMeasurements extends JPanel{ + private final JComboBox chosenMeasurement; + + public SelectMeasurements(){ + setLayout(new GridLayout(1, 2)); + this.add(new JLabel("Measurement Type")); + chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.AVERAGE.publicName}); + this.add(chosenMeasurement); + } + + enum AvailableMeasurements{ + AVERAGE("Average"); + + public final String publicName; + AvailableMeasurements(String publicName){ + this.publicName = publicName; + } + } +} diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java index d016c66..a8b9ef9 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java @@ -14,7 +14,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; public class DataReductionTest { // First two are SimROI, last two are LabROI @@ -51,7 +50,7 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi DataReductionGUI.DataReductionSubmission dataReductionSubmission, double normValue){ DataReduction dataReduction = new DataReduction(dataReductionSubmission); DataReduction.ReducedData reducedData = new DataReduction.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), - imagePlus.getNChannels() * roiList.size(), DataReductionGUI.AvailableMeasurements.AVERAGE); + imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, normValue, reducedData); for (int r = 0; r < expectedResults.length; r++){ for (int c = 0; c < expectedResults[r].length; c++){ From 852dde4bcc14055b785464be574f7035e3446326 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 5 Nov 2024 09:05:36 -0500 Subject: [PATCH 19/44] Hint's In Available Text Boxes --- .../java/org/vcell/N5/UI/HintTextField.java | 43 +++++++++++++++ .../java/org/vcell/N5/UI/RangeSelector.java | 46 ---------------- .../vcell/N5/analysis/DataReductionGUI.java | 38 +++++++++++-- .../org/vcell/N5/analysis/NormalizeGUI.java | 38 +++++-------- .../org/vcell/N5/analysis/SelectSimRange.java | 55 +++++++++---------- .../vcell/N5/retrieving/LoadingManager.java | 14 +++-- 6 files changed, 122 insertions(+), 112 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/HintTextField.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/HintTextField.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/HintTextField.java new file mode 100644 index 0000000..4fa9cff --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/HintTextField.java @@ -0,0 +1,43 @@ +package org.vcell.N5.UI; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; + +public class HintTextField extends JTextField { + Font gainFont = new Font("Tahoma", Font.PLAIN, 11); + Font lostFont = new Font("Tahoma", Font.ITALIC, 11); + public HintTextField(final String hint) { + setText(hint); + setFont(lostFont); + setForeground(Color.GRAY); + + this.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { + if (getText().equals(hint)) { + setText(""); + setFont(gainFont); + } else { + setText(getText()); + setFont(gainFont); + } + } + + @Override + public void focusLost(FocusEvent e) { + if (getText().equals(hint)|| getText().isEmpty()) { + setText(hint); + setFont(lostFont); + setForeground(Color.GRAY); + } else { + setText(getText()); + setFont(gainFont); + setForeground(Color.BLACK); + } + } + }); + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java index d5ed49d..4fc1ddd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java @@ -1,15 +1,10 @@ package org.vcell.N5.UI; -import org.scijava.log.Logger; -import org.vcell.N5.N5ImageHandler; - import javax.swing.*; import javax.swing.event.EventListenerList; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; public class RangeSelector extends JDialog implements ActionListener { public int startC; @@ -128,45 +123,4 @@ else if (e.getSource().equals(cancelButton)) { this.setVisible(false); } } - - static class HintTextField extends JTextField { - - Font gainFont = new Font("Tahoma", Font.PLAIN, 11); - Font lostFont = new Font("Tahoma", Font.ITALIC, 11); - - public HintTextField(final String hint) { - - setText(hint); - setFont(lostFont); - setForeground(Color.GRAY); - - this.addFocusListener(new FocusAdapter() { - - @Override - public void focusGained(FocusEvent e) { - if (getText().equals(hint)) { - setText(""); - setFont(gainFont); - } else { - setText(getText()); - setFont(gainFont); - } - } - - @Override - public void focusLost(FocusEvent e) { - if (getText().equals(hint)|| getText().isEmpty()) { - setText(hint); - setFont(lostFont); - setForeground(Color.GRAY); - } else { - setText(getText()); - setFont(gainFont); - setForeground(Color.BLACK); - } - } - }); - - } - } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 042b48f..7a8fa05 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -8,11 +8,16 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; -public class DataReductionGUI extends JPanel { +public class DataReductionGUI extends JPanel implements ActionListener { private JComboBox chosenImage; + private final JCheckBox selectRangeOfMeasurement = new JCheckBox("Select Measurement Range: "); + private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); + private final JDialog jDialog; private final JOptionPane pane; @@ -27,7 +32,7 @@ public class DataReductionGUI extends JPanel { private final RoiSelection roiSelection; private final NormalizeGUI normalizeGUI; - public DataReductionGUI(int numSimsToOpen){ + public DataReductionGUI(int numSimsToOpen, double simCSize, double simZSize, double simTSize){ this.numSimsToOpen = numSimsToOpen; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); @@ -35,17 +40,21 @@ public DataReductionGUI(int numSimsToOpen){ jDialog = pane.createDialog("Data Reduction"); jDialog.setResizable(true); - selectSimRange = new SelectSimRange(jDialog); + selectSimRange = new SelectSimRange(jDialog, simCSize, simZSize, simTSize); roiSelection = new RoiSelection(); - normalizeGUI = new NormalizeGUI(jDialog); + normalizeGUI = new NormalizeGUI(jDialog, simTSize); add(imageSelectionPanel()); add(new SelectMeasurements()); add(roiSelection); + add(displayOptionsPanel()); add(normalizeGUI); add(selectSimRange); setVisible(true); + normalizeMeasurement.addActionListener(this); + selectRangeOfMeasurement.addActionListener(this); + jDialog.pack(); } @@ -71,7 +80,7 @@ public void displayGUI(){ private DataReductionSubmission createSubmission(){ int[] simRange = normalizeGUI.getSimTimRange(); int[] labRange = normalizeGUI.getImageTimeRange(); - return new DataReductionSubmission(normalizeGUI.performNormalization(), + return new DataReductionSubmission(normalizeMeasurement.isSelected(), roiSelection.getSimROIList(), roiSelection.getImageROIList(), WindowManager.getImage((String) chosenImage.getSelectedItem()), simRange[0], simRange[1], labRange[0], labRange[1], numSimsToOpen, chosenFile, @@ -86,6 +95,23 @@ private JPanel imageSelectionPanel(){ return jPanel; } + private JPanel displayOptionsPanel(){ + JPanel jPanel = new JPanel(); + jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.X_AXIS)); + jPanel.add(normalizeMeasurement); + jPanel.add(selectRangeOfMeasurement); + return jPanel; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(normalizeMeasurement)) { + normalizeGUI.setVisible(normalizeMeasurement.isSelected()); + } else if (e.getSource().equals(selectRangeOfMeasurement)){ + selectSimRange.setVisible(selectRangeOfMeasurement.isSelected()); + } + } + public static class DataReductionSubmission{ public final boolean normalizeMeasurementsBool; public final ArrayList arrayOfSimRois; @@ -136,7 +162,7 @@ public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList } public static void main(String[] args) { - DataReductionGUI dataReductionGUI = new DataReductionGUI(0); + DataReductionGUI dataReductionGUI = new DataReductionGUI(0, 0, 0, 0); dataReductionGUI.displayGUI(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java index c2528c1..7661840 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java @@ -1,23 +1,24 @@ package org.vcell.N5.analysis; +import org.vcell.N5.UI.HintTextField; + import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -class NormalizeGUI extends JPanel implements ActionListener { +class NormalizeGUI extends JPanel { private final JTextField createNormFromImageStart; private final JTextField createNormFromImageEnd; private final JTextField createNormFromSimStart; private final JTextField createNormFromSimEnd; private final JPanel entireImageFramesJPanel; - private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); - public NormalizeGUI(JDialog jDialog){ - normalizeMeasurement.addActionListener(this); - JLabel explainInput = new JLabel("Timeline Range to Create Norm"); + public NormalizeGUI(JDialog jDialog, double simTSize){ + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + Border normalizeBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Timeline Range to Create Norm"); JPanel fromImage = new JPanel(new GridLayout()); createNormFromImageStart = new JTextField(); @@ -28,18 +29,17 @@ public NormalizeGUI(JDialog jDialog){ fromImage.add(createNormFromImageEnd); JPanel fromSim = new JPanel(new GridLayout()); - createNormFromSimStart = new JTextField(); - createNormFromSimEnd = new JTextField(); + createNormFromSimStart = new HintTextField("1"); + createNormFromSimEnd = new HintTextField(String.valueOf((int) simTSize)); fromSim.add(new JLabel("Sim Timeline: ")); fromSim.add(createNormFromSimStart); fromSim.add(new JLabel("to")); fromSim.add(createNormFromSimEnd); entireImageFramesJPanel = new JPanel(new GridLayout(3, 1)); - entireImageFramesJPanel.add(explainInput); entireImageFramesJPanel.add(fromImage); entireImageFramesJPanel.add(fromSim); - entireImageFramesJPanel.addComponentListener(new ComponentAdapter() { + this.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { jDialog.revalidate(); @@ -53,10 +53,9 @@ public void componentHidden(ComponentEvent e) { jDialog.pack(); } }); - entireImageFramesJPanel.setVisible(false); - - this.add(normalizeMeasurement); this.add(entireImageFramesJPanel); + this.setBorder(normalizeBorder); + this.setVisible(false); this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); } @@ -73,15 +72,4 @@ public int[] getImageTimeRange(){ createNormFromImageEnd.getText().isEmpty() ? Integer.MIN_VALUE: Integer.parseInt(createNormFromImageEnd.getText()) }; } - - public boolean performNormalization(){ - return normalizeMeasurement.isSelected(); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(normalizeMeasurement)) { - entireImageFramesJPanel.setVisible(normalizeMeasurement.isSelected()); - } - } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java index 5bbadc9..de39140 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java @@ -1,29 +1,30 @@ package org.vcell.N5.analysis; +import org.vcell.N5.UI.HintTextField; + import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -class SelectSimRange extends JPanel implements ActionListener { - private final JCheckBox selectRangeOfMeasurement = new JCheckBox("Select Measurement Range: "); - - private final JTextField cStart = new JTextField(); - private final JTextField cEnd = new JTextField(); +class SelectSimRange extends JPanel { + private final JTextField cStart = new HintTextField("1"); + private final JTextField cEnd; - private final JTextField zStart = new JTextField(); - private final JTextField zEnd = new JTextField(); + private final JTextField zStart = new HintTextField("1"); + private final JTextField zEnd; - private final JTextField tStart = new JTextField(); - private final JTextField tEnd = new JTextField(); + private final JTextField tStart = new HintTextField("1"); + private final JTextField tEnd; - private final JPanel rangeSelectionPanel; - - public SelectSimRange(JDialog jDialog){ - selectRangeOfMeasurement.addActionListener(this); - JLabel explainInput = new JLabel("Range of Simulation to Perform Measurement"); + public SelectSimRange(JDialog jDialog, double simCSize, double simZSize, double simTSize){ + Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + Border rangeBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Range of Simulation to Perform Measurement"); + cEnd = new HintTextField(String.valueOf((int) simCSize - 1)); + zEnd = new HintTextField(String.valueOf((int) simZSize)); + tEnd = new HintTextField(String.valueOf((int) simTSize)); JPanel cRange = new JPanel(new GridLayout()); cRange.add(new JLabel("Channel Range: ")); @@ -43,29 +44,32 @@ public SelectSimRange(JDialog jDialog){ tRange.add(new JLabel("to")); tRange.add(tEnd); - rangeSelectionPanel = new JPanel(new GridLayout(4, 1)); - rangeSelectionPanel.add(explainInput); + JPanel rangeSelectionPanel = new JPanel(new GridLayout(4, 1)); rangeSelectionPanel.add(cRange); rangeSelectionPanel.add(zRange); rangeSelectionPanel.add(tRange); - rangeSelectionPanel.addComponentListener(new ComponentAdapter() { + + this.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { + SelectSimRange.this.revalidate(); + SelectSimRange.this.repaint(); jDialog.revalidate(); jDialog.repaint(); jDialog.pack(); } @Override public void componentHidden(ComponentEvent e) { + SelectSimRange.this.revalidate(); + SelectSimRange.this.repaint(); jDialog.revalidate(); jDialog.repaint(); jDialog.pack(); } }); - rangeSelectionPanel.setVisible(false); - - this.add(selectRangeOfMeasurement); this.add(rangeSelectionPanel); + this.setBorder(rangeBorder); + this.setVisible(false); this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); } @@ -78,13 +82,6 @@ public RangeOfImage getRangeOfSim(){ return rangeOfImage; } - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(selectRangeOfMeasurement)){ - rangeSelectionPanel.setVisible(selectRangeOfMeasurement.isSelected()); - } - } - public static class RangeOfImage{ public final int timeStart; public final int timeEnd; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 7c05c13..ec19b3f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -30,15 +30,17 @@ public class LoadingManager implements SimLoadingEventCreator { public void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory, boolean dataReduction){ RangeSelector rangeSelector = new RangeSelector(); - if (openInMemory){ + DataReductionGUI dataReductionGUI = null; + if (dataReduction || openInMemory){ SimResultsLoader firstSim = filesToOpen.get(0); firstSim.createS3ClientAndReader(); ArrayList dimensions = firstSim.getN5Dimensions(); - rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); - } - DataReductionGUI dataReductionGUI = new DataReductionGUI(filesToOpen.size()); - if (dataReduction){ - dataReductionGUI.displayGUI(); + if (dataReduction){ + dataReductionGUI = new DataReductionGUI(filesToOpen.size(), dimensions.get(2), dimensions.get(3), dimensions.get(4)); + dataReductionGUI.displayGUI(); + } else { + rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); + } } boolean dataReductionOkay = dataReduction && dataReductionGUI.mainGUIReturnValue == JOptionPane.OK_OPTION && dataReductionGUI.fileChooserReturnValue == JFileChooser.APPROVE_OPTION; if (dataReductionOkay || !dataReduction){ From 2a6f0954e0e6cbd5228185f7b93de08cd07184a7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 5 Nov 2024 12:19:08 -0500 Subject: [PATCH 20/44] Fix Multithreading Issue Rows in the metadata and data sheet where not being created before being written to which lead to errors. --- .../org/vcell/N5/analysis/DataReduction.java | 44 ++++++++++--------- .../vcell/N5/analysis/DataReductionGUI.java | 1 - 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index 522624a..f60c928 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -66,6 +66,7 @@ public ReducedData(int rowLen, int colLen, SelectMeasurements.AvailableMeasureme // Create a graph from that spreadsheet public DataReduction(DataReductionGUI.DataReductionSubmission submission){ + N5ImageHandler.loadingManager.addSimLoadingListener(this); this.submission = submission; this.arrayOfSimRois = submission.arrayOfSimRois; this.numOfImagesToBeOpened = submission.numOfSimImages + 1; // Plus one for the lab image @@ -85,6 +86,24 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ } colIndex = headers.size() + 1; + metaDataSheet.createRow(0).createCell(1).setCellValue("BioModel Name"); + metaDataSheet.getRow(0).createCell(2).setCellValue("Application Name"); + metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); + metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); + + int rowI = 1; + for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ + for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ + Row pointRow = dataSheet.createRow(rowI); + rowI += 1; + pointRow.createCell(0).setCellValue(t); + if (is3D){ + pointRow.createCell(1).setCellValue(z); + } + } + } + + double normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, submission.imageEndPointNorm); int nFrames = submission.experimentImageRange.timeEnd - submission.experimentImageRange.timeStart + 1; @@ -92,26 +111,7 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ int nChannels = submission.experimentImageRange.channelEnd - submission.experimentImageRange.channelStart + 1; ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, submission.experimentImageRange); - synchronized (csvMatrixLock){ - int rowI = 1; - for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ - for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ - Row pointRow = dataSheet.createRow(rowI); - rowI += 1; - pointRow.createCell(0).setCellValue(t); - if (is3D){ - pointRow.createCell(1).setCellValue(z); - } - } - } - } addValuesToCSVMatrix(reducedData); - synchronized (metaDataLock){ - metaDataSheet.createRow(0).createCell(1).setCellValue("BioModel Name"); - metaDataSheet.getRow(0).createCell(2).setCellValue("Application Name"); - metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); - metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); - } } private void addValuesToCSVMatrix(ReducedData reducedData){ @@ -171,7 +171,7 @@ ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable String stringC = String.valueOf(c - 1); String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); - reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + reducedData.columnHeaders.add("Average:" + imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); } int tzCounter = 0; for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ @@ -249,6 +249,10 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { addMetaData(loadedResults); addValuesToCSVMatrix(reducedData); } + + + // Queue for digesting information, add one's self to the queue and then notify when data has been recieved + } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 7a8fa05..93f03de 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -70,7 +70,6 @@ public void displayGUI(){ MainPanel.controlButtonsPanel.enableCriticalButtons(false); Thread thread = new Thread(() -> { DataReduction dataReduction = new DataReduction(createSubmission()); - N5ImageHandler.loadingManager.addSimLoadingListener(dataReduction); }); thread.start(); } From 78f1621d03b59e10e2886c5fa4d2417a4c2eddaa Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 6 Nov 2024 09:09:34 -0500 Subject: [PATCH 21/44] Update Reduction GUI and ROI File Selection --- .../vcell/N5/analysis/DataReductionGUI.java | 44 ++++-- .../org/vcell/N5/analysis/RoiSelection.java | 137 ++++++++---------- .../vcell/N5/retrieving/LoadingManager.java | 2 +- 3 files changed, 95 insertions(+), 88 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java index 93f03de..b800e4e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java @@ -3,10 +3,12 @@ import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; -import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -23,7 +25,7 @@ public class DataReductionGUI extends JPanel implements ActionListener { private final JOptionPane pane; private File chosenFile; - private final int numSimsToOpen; + private final ArrayList filesToOpen; public int mainGUIReturnValue; public int fileChooserReturnValue; @@ -32,8 +34,10 @@ public class DataReductionGUI extends JPanel implements ActionListener { private final RoiSelection roiSelection; private final NormalizeGUI normalizeGUI; - public DataReductionGUI(int numSimsToOpen, double simCSize, double simZSize, double simTSize){ - this.numSimsToOpen = numSimsToOpen; + private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + + public DataReductionGUI(ArrayList filesToOpen, double simCSize, double simZSize, double simTSize){ + this.filesToOpen = filesToOpen; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); @@ -44,9 +48,15 @@ public DataReductionGUI(int numSimsToOpen, double simCSize, double simZSize, dou roiSelection = new RoiSelection(); normalizeGUI = new NormalizeGUI(jDialog, simTSize); - add(imageSelectionPanel()); - add(new SelectMeasurements()); + JPanel imagesToMeasurePanel = new JPanel(); + imagesToMeasurePanel.setLayout(new BoxLayout(imagesToMeasurePanel, BoxLayout.Y_AXIS)); + imagesToMeasurePanel.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Images To Measure")); + imagesToMeasurePanel.add(imageSelectionPanel()); + imagesToMeasurePanel.add(selectedImagesToOpenPanel()); + + add(imagesToMeasurePanel); add(roiSelection); + add(new SelectMeasurements()); add(displayOptionsPanel()); add(normalizeGUI); add(selectSimRange); @@ -82,18 +92,34 @@ private DataReductionSubmission createSubmission(){ return new DataReductionSubmission(normalizeMeasurement.isSelected(), roiSelection.getSimROIList(), roiSelection.getImageROIList(), WindowManager.getImage((String) chosenImage.getSelectedItem()), - simRange[0], simRange[1], labRange[0], labRange[1], numSimsToOpen, chosenFile, + simRange[0], simRange[1], labRange[0], labRange[1], filesToOpen.size(), chosenFile, selectSimRange.getRangeOfSim()); } private JPanel imageSelectionPanel(){ JPanel jPanel = new JPanel(new GridLayout(1, 2)); - jPanel.add(new JLabel("Select Experimental Image")); + jPanel.add(new JLabel("Experimental")); chosenImage = new JComboBox<>(WindowManager.getImageTitles()); jPanel.add(chosenImage); return jPanel; } + private JPanel selectedImagesToOpenPanel(){ + JPanel jPanel = new JPanel(); + String[] namesOfImagesToOpen = new String[filesToOpen.size()]; + for (int i = 0; i < filesToOpen.size(); i++){ + namesOfImagesToOpen[i] = filesToOpen.get(i).userSetFileName; + } + JList selectedImagesToOpen = new JList<>(namesOfImagesToOpen); + selectedImagesToOpen.setEnabled(false); + selectedImagesToOpen.setVisibleRowCount(4); + JScrollPane jScrollPane = new JScrollPane(selectedImagesToOpen); + jPanel.add(new JLabel("Selected Simulations")); + jPanel.add(jScrollPane); + jPanel.setLayout(new GridLayout(1, 2)); + return jPanel; + } + private JPanel displayOptionsPanel(){ JPanel jPanel = new JPanel(); jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.X_AXIS)); @@ -161,7 +187,7 @@ public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList } public static void main(String[] args) { - DataReductionGUI dataReductionGUI = new DataReductionGUI(0, 0, 0, 0); + DataReductionGUI dataReductionGUI = new DataReductionGUI(new ArrayList<>(), 0, 0, 0); dataReductionGUI.displayGUI(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java index 5290198..c52d308 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java @@ -11,54 +11,67 @@ import java.io.File; import java.util.ArrayList; -class RoiSelection extends JPanel implements ActionListener { - private final JFileChooser imageROIFileChooser = new JFileChooser(); +class RoiSelection extends JPanel { private final ROIDataModel imageTableModel = new ROIDataModel(); - private final JTable imageROITable = new JTable(imageTableModel); - - private final JFileChooser simROIFileChooser = new JFileChooser(); private final ROIDataModel simTableModel = new ROIDataModel(); - private final JTable simROITable = new JTable(simTableModel); - private final JButton imageROIFileButton; - private final JButton simROIFileButton; + public RoiSelection(){ + this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - private ArrayList imageROIList; - private ArrayList simROIList; + JList imageROITable = new JList<>(imageTableModel); + JFileChooser imageROIFileChooser = new JFileChooser(); + this.add(createROIInput(imageROITable, imageTableModel, imageROIFileChooser, "Experimental")); - public RoiSelection(){ - JPanel roisForImage = new JPanel(new GridBagLayout()); - JPanel roisForSims = new JPanel(new GridBagLayout()); - Dimension tableDimensions = new Dimension(100, 70); - imageROITable.getTableHeader().setBackground(Color.WHITE); - imageROITable.setEnabled(false); - simROITable.getTableHeader().setBackground(Color.WHITE); - simROITable.setEnabled(false); - - imageROIFileButton = new JButton("ROI's For Image"); - JScrollPane displayImageROIList = new JScrollPane(imageROITable); - displayImageROIList.setPreferredSize(tableDimensions); - setROIPanelSettings(roisForImage, imageROIFileButton, displayImageROIList); - - simROIFileButton = new JButton("ROI's For Simulation"); - JScrollPane displaySimROIList = new JScrollPane(simROITable); - displaySimROIList.setPreferredSize(tableDimensions); - setROIPanelSettings(roisForSims, simROIFileButton, displaySimROIList); - - imageROIFileButton.addActionListener(this); - simROIFileButton.addActionListener(this); - - this.setLayout(new BorderLayout()); - this.add(roisForImage, BorderLayout.WEST); - this.add(roisForSims, BorderLayout.EAST); + JList simROITable = new JList<>(simTableModel); + JFileChooser simROIFileChooser = new JFileChooser(); + this.add(createROIInput(simROITable, simTableModel, simROIFileChooser, "Sim")); + this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "ROI Files")); + } + + private JPanel createROIInput(JList jList, ROIDataModel roiDataModel, + JFileChooser fileChooser, String label){ + JPanel jPanel = new JPanel(); + jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.Y_AXIS)); + jList.setVisibleRowCount(4); + JScrollPane jScrollPane = new JScrollPane(jList); + jPanel.add(jScrollPane); + + JButton addButton = new JButton("+"); + addButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ArrayList roiList = fillROIList(fileChooser); + for (Roi roi : roiList){ + roiDataModel.addRow(roi); + } + jList.updateUI(); + } + }); + JButton minusButton = new JButton("-"); + minusButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (int roiIndex: jList.getSelectedIndices()){ + roiDataModel.removeRow(roiIndex); + } + jList.updateUI(); + } + }); + JPanel buttonPanel = new JPanel(new GridLayout(1, 2)); + buttonPanel.add(addButton); + buttonPanel.add(minusButton); + jPanel.add(buttonPanel); + jPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), label)); + + return jPanel; } public ArrayList getImageROIList(){ - return imageROIList; + return imageTableModel.data; } public ArrayList getSimROIList(){ - return simROIList; + return simTableModel.data; } private void setROIPanelSettings(JPanel jPanel, JButton button, JScrollPane jScrollPane){ @@ -72,24 +85,6 @@ private void setROIPanelSettings(JPanel jPanel, JButton button, JScrollPane jScr jPanel.add(jScrollPane, gridBagConstraints); } - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource().equals(imageROIFileButton)){ - imageROIList = fillROIList(imageROIFileChooser); - imageTableModel.clear(); - for (Roi roi : imageROIList){ - imageTableModel.addRow(roi.getName()); - } - imageROITable.updateUI(); - } else if (e.getSource().equals(simROIFileButton)) { - simROIList = fillROIList(simROIFileChooser); - simTableModel.clear(); - for (Roi roi : simROIList){ - simTableModel.addRow(roi.getName()); - } - simROITable.updateUI(); - } - } private ArrayList fillROIList(JFileChooser fileChooser){ fileChooser.setMultiSelectionEnabled(true); int choice = fileChooser.showDialog(this, "Open ROI's"); @@ -102,35 +97,21 @@ private ArrayList fillROIList(JFileChooser fileChooser){ return roiList; } - class ROIDataModel extends AbstractTableModel { - private final ArrayList data = new ArrayList<>(); - private final String[] headers = new String[]{"ROI's Selected"}; - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return headers.length; + static class ROIDataModel extends AbstractListModel { + private final ArrayList data = new ArrayList<>(); + public void addRow(Roi roi){ + data.add(roi); } + public void removeRow(int index){data.remove(index);} @Override - public String getColumnName(int column) { - return headers[column]; + public int getSize() { + return data.size(); } @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return data.get(rowIndex); - } - - public void addRow(String roiName){ - data.add(roiName); - } - - public void clear(){ - data.clear(); + public String getElementAt(int index) { + return data.get(index).getName(); } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index ec19b3f..c07e590 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -36,7 +36,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o firstSim.createS3ClientAndReader(); ArrayList dimensions = firstSim.getN5Dimensions(); if (dataReduction){ - dataReductionGUI = new DataReductionGUI(filesToOpen.size(), dimensions.get(2), dimensions.get(3), dimensions.get(4)); + dataReductionGUI = new DataReductionGUI(filesToOpen, dimensions.get(2), dimensions.get(3), dimensions.get(4)); dataReductionGUI.displayGUI(); } else { rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); From 39b3d884c4685e1f0e814168a9c2e807a64970c7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 6 Nov 2024 12:30:07 -0500 Subject: [PATCH 22/44] Separate Normalization Values For Each Channel and ROI --- .../org/vcell/N5/analysis/DataReduction.java | 79 ++++++++++--------- .../vcell/N5/analysis/DataReductionTest.java | 36 ++++++--- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java index f60c928..7842da8 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java @@ -91,26 +91,29 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); - int rowI = 1; - for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ - for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ - Row pointRow = dataSheet.createRow(rowI); - rowI += 1; - pointRow.createCell(0).setCellValue(t); - if (is3D){ - pointRow.createCell(1).setCellValue(z); + synchronized (csvMatrixLock){ + int rowI = 1; + for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ + for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ + Row pointRow = dataSheet.createRow(rowI); + rowI += 1; + pointRow.createCell(0).setCellValue(t); + if (is3D){ + pointRow.createCell(1).setCellValue(z); + } } } } - double normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, submission.imageEndPointNorm); + HashMap normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, + submission.imageEndPointNorm, submission.arrayOfLabRois, submission.experimentImageRange); int nFrames = submission.experimentImageRange.timeEnd - submission.experimentImageRange.timeStart + 1; int nSlices = submission.experimentImageRange.zEnd - submission.experimentImageRange.zStart + 1; int nChannels = submission.experimentImageRange.channelEnd - submission.experimentImageRange.channelStart + 1; ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, submission.experimentImageRange); + reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, null, submission.experimentImageRange); addValuesToCSVMatrix(reducedData); } @@ -134,36 +137,34 @@ private void addValuesToCSVMatrix(ReducedData reducedData){ } } - double calculateNormalValue(ImagePlus imagePlus, int startT, int endT){ - if (normalize){ - double normal = 0; - for (int k = startT; k <= endT; k++){ - imagePlus.setT(k); - normal += imagePlus.getProcessor().getStatistics().mean; + HashMap calculateNormalValue(ImagePlus imagePlus, int startT, int endT, + ArrayList roiList, SelectSimRange.RangeOfImage rangeOfImage){ + if (!normalize){ + return null; + } + HashMap result = new HashMap<>(); + for (Roi roi : roiList){ + imagePlus.setRoi(roi); + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ + double normal = 0; + for (int t = startT; t <= endT; t++){ + double zAverage = 0; + for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ + imagePlus.setPosition(c, z, t); + zAverage += imagePlus.getProcessor().getStatistics().mean; + } + zAverage = zAverage / (rangeOfImage.zEnd - rangeOfImage.zStart + 1); + normal += zAverage; + } + normal = normal / (endT - startT + 1); // inclusive of final point + result.put(roi.getName() + c, normal); } - normal = normal / (endT - startT + 1); // inclusive of final point - return normal; - } else { - return Double.MIN_NORMAL; } - - } - - - ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, - double normalizationValue, ReducedData reducedData){ - SelectSimRange.RangeOfImage entireRange = new SelectSimRange.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), - 1, imagePlus.getNChannels()); - return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, entireRange); - } - - ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, - double normalizationValue, ReducedData reducedData, SelectSimRange.RangeOfImage rangeOfImage){ - return calculateMean(imagePlus, roiList, normalizationValue, reducedData, null, rangeOfImage); + return result; } ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, - double normalizationValue, ReducedData reducedData, + HashMap normalizationValue, ReducedData reducedData, LinkedTreeMap> channelInfo, SelectSimRange.RangeOfImage rangeOfImage){ int roiCounter = 0; for (Roi roi: roiList) { @@ -171,7 +172,7 @@ ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable String stringC = String.valueOf(c - 1); String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); - reducedData.columnHeaders.add("Average:" + imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); } int tzCounter = 0; for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ @@ -181,7 +182,7 @@ ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, imagePlus.setPosition(c, z, t); double meanValue = imagePlus.getStatistics().mean; if (normalize){ - meanValue = meanValue / normalizationValue; + meanValue = meanValue / normalizationValue.get(roi.getName() + c); } reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = meanValue; } @@ -242,7 +243,9 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(SimResultsLoader loadedResults) { ImagePlus imagePlus = loadedResults.getImagePlus(); - double normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, submission.simEndPointNorm); + imagePlus.show(); + HashMap normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, + submission.simEndPointNorm, submission.arrayOfSimRois, simRange); ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), simRange.channelEnd - simRange.channelStart + 1, SelectMeasurements.AvailableMeasurements.AVERAGE); reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java index a8b9ef9..41c8843 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java @@ -8,12 +8,14 @@ import org.junit.BeforeClass; import org.junit.Test; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; public class DataReductionTest { // First two are SimROI, last two are LabROI @@ -38,20 +40,24 @@ private File getTestResourceFiles(String filePath){ public static void init(){ N5ImageHandler.initializeLogService(); SimResultsLoader.s3ClientBuilder = AmazonS3ClientBuilder.standard(); + N5ImageHandler.loadingManager = new LoadingManager(); } private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults){ DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( false, roiList, roiList, imagePlus,4, null); - compareExpectedCalculations(imagePlus, roiList, expectedResults, dataReductionSubmission, Double.MIN_VALUE); + compareExpectedCalculations(imagePlus, roiList, expectedResults, dataReductionSubmission); } private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults, - DataReductionGUI.DataReductionSubmission dataReductionSubmission, double normValue){ + DataReductionGUI.DataReductionSubmission dataReductionSubmission){ DataReduction dataReduction = new DataReduction(dataReductionSubmission); DataReduction.ReducedData reducedData = new DataReduction.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, normValue, reducedData); + SelectSimRange.RangeOfImage entireRange = new SelectSimRange.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), + 1, imagePlus.getNChannels()); + HashMap norms = dataReduction.calculateNormalValue(imagePlus, 1, 1, roiList, entireRange); + DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, norms, reducedData, null, entireRange); for (int r = 0; r < expectedResults.length; r++){ for (int c = 0; c < expectedResults[r].length; c++){ Assert.assertEquals(expectedResults[r][c], result.data[r][c], 0.0009); @@ -83,19 +89,31 @@ public void testMean3DCalculation(){ public void testMeanAndNormalization2DCalculation(){ SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); - double mean = labResultImage2D.getStatistics().mean; // the normal for a single frame normalization + Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); + Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); + ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; + HashMap normValues = new HashMap<>(); + + for (Roi roi: roiList){ + labResultImage2D.setRoi(roi); + for (int c = 1; c <= labResultImage2D.getNChannels(); c++){ + labResultImage2D.setC(c); + normValues.put(roi.getName() + c, labResultImage2D.getStatistics().mean); + } + } double[][] normalizedValues = new double[labMeans2D.length][labMeans2D[0].length]; + for (int r = 0; r < labMeans2D.length; r++){ for (int c =0; c < labMeans2D[0].length; c++){ - normalizedValues[r][c] = labMeans2D[r][c] / mean; + String roiName = c < 2 ? labRoi.getName() : simROI.getName(); + double normValue = c % 2 == 0 ? normValues.get(roiName + 1) : normValues.get(roiName + 2); + normalizedValues[r][c] = labMeans2D[r][c] / normValue; } } - Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); - Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); - ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; + DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( true, roiList, roiList, labResultImage2D, 1, 1, 1, 1,4, null); - compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, dataReductionSubmission, mean); + compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, dataReductionSubmission); } } From 78d5ca792755fc59c4c8ed7e5285b30cc43982d3 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 8 Nov 2024 09:28:57 -0500 Subject: [PATCH 23/44] Add Std-Deviation Capability --- .../vcell/N5/analysis/SelectMeasurements.java | 24 --- .../vcell/N5/reduction/DTO/RangeOfImage.java | 33 ++++ .../DataReductionGUI.java | 56 +++--- .../DataReductionWriter.java} | 183 ++++++++---------- .../{analysis => reduction}/NormalizeGUI.java | 2 +- .../N5/reduction/ReductionCalculations.java | 102 ++++++++++ .../{analysis => reduction}/RoiSelection.java | 3 +- .../N5/reduction/SelectMeasurements.java | 54 ++++++ .../SelectSimRange.java | 20 +- .../vcell/N5/retrieving/LoadingManager.java | 8 +- .../ReductionCalculationsTest.java} | 41 ++-- 11 files changed, 322 insertions(+), 204 deletions(-) delete mode 100644 view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java rename view-simulation-results/src/main/java/org/vcell/N5/{analysis => reduction}/DataReductionGUI.java (74%) rename view-simulation-results/src/main/java/org/vcell/N5/{analysis/DataReduction.java => reduction/DataReductionWriter.java} (52%) rename view-simulation-results/src/main/java/org/vcell/N5/{analysis => reduction}/NormalizeGUI.java (98%) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java rename view-simulation-results/src/main/java/org/vcell/N5/{analysis => reduction}/RoiSelection.java (98%) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java rename view-simulation-results/src/main/java/org/vcell/N5/{analysis => reduction}/SelectSimRange.java (82%) rename view-simulation-results/src/test/java/org/vcell/N5/{analysis/DataReductionTest.java => reduction/ReductionCalculationsTest.java} (72%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java deleted file mode 100644 index 43a8a56..0000000 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectMeasurements.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.vcell.N5.analysis; - -import javax.swing.*; -import java.awt.*; - -class SelectMeasurements extends JPanel{ - private final JComboBox chosenMeasurement; - - public SelectMeasurements(){ - setLayout(new GridLayout(1, 2)); - this.add(new JLabel("Measurement Type")); - chosenMeasurement = new JComboBox<>(new String[]{AvailableMeasurements.AVERAGE.publicName}); - this.add(chosenMeasurement); - } - - enum AvailableMeasurements{ - AVERAGE("Average"); - - public final String publicName; - AvailableMeasurements(String publicName){ - this.publicName = publicName; - } - } -} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java new file mode 100644 index 0000000..1613c24 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java @@ -0,0 +1,33 @@ +package org.vcell.N5.reduction.DTO; + +public class RangeOfImage { + public final int timeStart; + public final int timeEnd; + public final int zStart; + public final int zEnd; + public final int channelStart; + public final int channelEnd; + + public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channelStart, int channelEnd) { + this.timeStart = timeStart; + this.timeEnd = timeEnd; + this.zStart = zStart; + this.zEnd = zEnd; + this.channelStart = channelStart; + this.channelEnd = channelEnd; + } + + /** + * Only regards time for range, and is used for normalization. + * @param timeStart + * @param timeEnd + */ + public RangeOfImage(int timeStart, int timeEnd){ + this.timeStart = timeStart; + this.timeEnd = timeEnd; + this.zStart = Integer.MIN_VALUE; + this.zEnd = Integer.MIN_VALUE; + this.channelStart = Integer.MIN_VALUE; + this.channelEnd = Integer.MIN_VALUE; + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java similarity index 74% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java index b800e4e..a42fdea 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java @@ -1,9 +1,10 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; @@ -33,6 +34,7 @@ public class DataReductionGUI extends JPanel implements ActionListener { private final SelectSimRange selectSimRange; private final RoiSelection roiSelection; private final NormalizeGUI normalizeGUI; + private final SelectMeasurements selectMeasurements; private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); @@ -47,6 +49,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize selectSimRange = new SelectSimRange(jDialog, simCSize, simZSize, simTSize); roiSelection = new RoiSelection(); normalizeGUI = new NormalizeGUI(jDialog, simTSize); + selectMeasurements = new SelectMeasurements(); JPanel imagesToMeasurePanel = new JPanel(); imagesToMeasurePanel.setLayout(new BoxLayout(imagesToMeasurePanel, BoxLayout.Y_AXIS)); @@ -56,7 +59,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize add(imagesToMeasurePanel); add(roiSelection); - add(new SelectMeasurements()); + add(selectMeasurements); add(displayOptionsPanel()); add(normalizeGUI); add(selectSimRange); @@ -68,7 +71,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize jDialog.pack(); } - public void displayGUI(){ + public DataReductionSubmission displayGUI(){ jDialog.setVisible(true); mainGUIReturnValue = (Integer) pane.getValue(); if (mainGUIReturnValue == JOptionPane.OK_OPTION){ @@ -78,22 +81,20 @@ public void displayGUI(){ if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ chosenFile = saveToFile.getSelectedFile(); MainPanel.controlButtonsPanel.enableCriticalButtons(false); - Thread thread = new Thread(() -> { - DataReduction dataReduction = new DataReduction(createSubmission()); - }); - thread.start(); + return createSubmission(); } } + return null; } - private DataReductionSubmission createSubmission(){ + public DataReductionSubmission createSubmission(){ int[] simRange = normalizeGUI.getSimTimRange(); int[] labRange = normalizeGUI.getImageTimeRange(); return new DataReductionSubmission(normalizeMeasurement.isSelected(), roiSelection.getSimROIList(), roiSelection.getImageROIList(), WindowManager.getImage((String) chosenImage.getSelectedItem()), simRange[0], simRange[1], labRange[0], labRange[1], filesToOpen.size(), chosenFile, - selectSimRange.getRangeOfSim()); + selectSimRange.getRangeOfSim(), selectMeasurements.getChosenMeasurements()); } private JPanel imageSelectionPanel(){ @@ -142,47 +143,34 @@ public static class DataReductionSubmission{ public final ArrayList arrayOfSimRois; public final ArrayList arrayOfLabRois; public final ImagePlus labResults; - public final int simStartPointNorm; - public final int simEndPointNorm; - public final int imageStartPointNorm; - public final int imageEndPointNorm; public final int numOfSimImages; public final File fileToSaveResultsTo; - public final SelectSimRange.RangeOfImage experimentImageRange; - public final SelectSimRange.RangeOfImage simImageRange; - public DataReductionSubmission(boolean normalizeMeasurementsBool,ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, - ImagePlus labResults, int numOfSimImages, File fileToSaveResultsTo){ - this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, - 0,0,0,0, numOfSimImages, fileToSaveResultsTo); - } + public final RangeOfImage experiementNormRange; + public final RangeOfImage simNormRange; - public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, - ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, - int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo){ - this(normalizeMeasurementsBool, arrayOfSimRois, arrayOfLabRois, labResults, simStartPointNorm, simEndPointNorm, imageStartPointNorm, imageEndPointNorm, - numOfSimImages, fileToSaveResultsTo, - new SelectSimRange.RangeOfImage(1, labResults.getNFrames(), - 1, labResults.getNSlices(), 1, labResults.getNChannels())); - } + public final RangeOfImage experimentImageRange; + public final RangeOfImage simImageRange; + public final ArrayList selectedMeasurements; public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo, - SelectSimRange.RangeOfImage simRange){ + RangeOfImage simRange, ArrayList selectedMeasurements){ this.normalizeMeasurementsBool = normalizeMeasurementsBool; this.arrayOfLabRois = arrayOfLabRois; this.arrayOfSimRois = arrayOfSimRois; this.labResults = labResults; - this.simStartPointNorm = simStartPointNorm; - this.simEndPointNorm = simEndPointNorm; - this.imageStartPointNorm = imageStartPointNorm; - this.imageEndPointNorm = imageEndPointNorm; this.numOfSimImages = numOfSimImages; this.fileToSaveResultsTo = fileToSaveResultsTo; - this.experimentImageRange = new SelectSimRange.RangeOfImage(1, labResults.getNFrames(), + + this.experiementNormRange = new RangeOfImage(imageStartPointNorm, imageEndPointNorm); + this.simNormRange = new RangeOfImage(simStartPointNorm, simEndPointNorm); + + this.experimentImageRange = new RangeOfImage(1, labResults.getNFrames(), 1, labResults.getNSlices(), 1, labResults.getNChannels()); this.simImageRange = simRange; + this.selectedMeasurements = selectedMeasurements; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java similarity index 52% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 7842da8..bf7e9ed 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/DataReduction.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -1,4 +1,4 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import com.google.gson.internal.LinkedTreeMap; import ij.ImagePlus; @@ -11,6 +11,7 @@ import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; +import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; @@ -20,7 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; -public class DataReduction implements SimLoadingListener { +public class DataReductionWriter implements SimLoadingListener { private final ArrayList arrayOfSimRois; private final Object csvMatrixLock = new Object(); @@ -28,20 +29,23 @@ public class DataReduction implements SimLoadingListener { private File file; private int numOfImagesToBeOpened; - private final boolean normalize; + private final ReductionCalculations calculations; public final DataReductionGUI.DataReductionSubmission submission; private final Workbook workbook = new HSSFWorkbook(); - private final Sheet dataSheet = workbook.createSheet("Average"); + private final HashMap sheetsAvailable = new HashMap(){{ + put(SelectMeasurements.AvailableMeasurements.AVERAGE, workbook.createSheet("Average")); + put(SelectMeasurements.AvailableMeasurements.STD_DEV, workbook.createSheet("Standard Deviation")); + }}; + private final HashMap columnsForSheets = new HashMap<>(); private final Sheet metaDataSheet = workbook.createSheet("Metadata"); - private int colIndex; private int metaDataRow = 1; private int metaDataParameterCol = 5; private final HashMap parameterNameToCol = new HashMap<>(); - private final SelectSimRange.RangeOfImage simRange; + private final ArrayList selectedMeasurements; // Per Image static class ReducedData{ @@ -55,43 +59,63 @@ public ReducedData(int rowLen, int colLen, SelectMeasurements.AvailableMeasureme } } - // + /////////////////////////////////////// + // Initialize Sheet and Lab results // + ///////////////////////////////////// - // GUI: - - // Create ROI beforehand, and have the user select what they want for ROI in addition to actual Image - // For the N5 files that will be opened up, select the range for what you want to do analysis on - // Select the type of statistical analysis, average intensity or something else (idk yet) - // Take results and place them within a spreadsheet - // Create a graph from that spreadsheet + public static void createDataReductionProcess(DataReductionGUI.DataReductionSubmission submission){ + new DataReductionWriter(submission); + } - public DataReduction(DataReductionGUI.DataReductionSubmission submission){ + public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ N5ImageHandler.loadingManager.addSimLoadingListener(this); this.submission = submission; + this.selectedMeasurements = submission.selectedMeasurements; + synchronized (csvMatrixLock){ + synchronized (metaDataLock){ + initializeDataSheets(); + } + } this.arrayOfSimRois = submission.arrayOfSimRois; - this.numOfImagesToBeOpened = submission.numOfSimImages + 1; // Plus one for the lab image + this.numOfImagesToBeOpened = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image this.file = submission.fileToSaveResultsTo; - this.normalize = submission.normalizeMeasurementsBool; - this.simRange = submission.simImageRange; + this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); + + + + Thread processLabResults = new Thread(() -> { + calculateAndAddResults(submission.labResults, submission.experiementNormRange, submission.experimentImageRange, + submission.arrayOfLabRois, null); + }, "Processing Lab Image"); + processLabResults.start(); + } + private void initializeDataSheets(){ ArrayList headers = new ArrayList(){{add("Time Frame");}}; boolean is3D = submission.labResults.getNSlices() > 1; if (is3D){ headers.add("Z Index"); } - Row headerRow = dataSheet.createRow(0); - for (int i = 0; i < headers.size(); i++){ - headerRow.createCell(i).setCellValue(headers.get(i)); + // Add Time and Z-Index Columns + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ + Sheet dataSheet = sheetsAvailable.get(measurement); + Row headerRow = dataSheet.createRow(0); + for (int i = 0; i < headers.size(); i++){ + headerRow.createCell(i).setCellValue(headers.get(i)); + } + columnsForSheets.put(measurement, headers.size() + 1); } - colIndex = headers.size() + 1; metaDataSheet.createRow(0).createCell(1).setCellValue("BioModel Name"); metaDataSheet.getRow(0).createCell(2).setCellValue("Application Name"); metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); - synchronized (csvMatrixLock){ + // Fill in Time and Z-Index Columns with selected range + + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ + Sheet dataSheet = sheetsAvailable.get(measurement); int rowI = 1; for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ @@ -104,21 +128,40 @@ public DataReduction(DataReductionGUI.DataReductionSubmission submission){ } } } + } + //////////////////////// + // General Functions // + ////////////////////// - HashMap normValue = calculateNormalValue(submission.labResults, submission.imageStartPointNorm, - submission.imageEndPointNorm, submission.arrayOfLabRois, submission.experimentImageRange); + private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, + RangeOfImage imageRange, ArrayList rois, + LinkedTreeMap> channelInfo){ + HashMap normValue = null; + if (submission.normalizeMeasurementsBool){ + normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); + } + + int nFrames = imageRange.timeEnd - imageRange.timeStart + 1; + int nSlices = imageRange.zEnd - imageRange.zStart + 1; + int nChannels = imageRange.channelEnd - imageRange.channelStart + 1; - int nFrames = submission.experimentImageRange.timeEnd - submission.experimentImageRange.timeStart + 1; - int nSlices = submission.experimentImageRange.zEnd - submission.experimentImageRange.zStart + 1; - int nChannels = submission.experimentImageRange.channelEnd - submission.experimentImageRange.channelStart + 1; - ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - reducedData = calculateMean(submission.labResults, submission.arrayOfLabRois, normValue, reducedData, null, submission.experimentImageRange); - addValuesToCSVMatrix(reducedData); + ArrayList reducedDataArrayList = new ArrayList<>(); + for (SelectMeasurements.AvailableMeasurements measurement : submission.selectedMeasurements){ + ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), measurement); + reducedDataArrayList.add(reducedData); + calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); + } + calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange); + for (ReducedData reducedData: reducedDataArrayList){ + addValuesToCSVMatrix(reducedData); + } } private void addValuesToCSVMatrix(ReducedData reducedData){ synchronized (csvMatrixLock){ + Sheet dataSheet = sheetsAvailable.get(reducedData.measurementType); + int colIndex = columnsForSheets.get(reducedData.measurementType); for (int c = 0; c < reducedData.columnHeaders.size(); c++){ dataSheet.getRow(0).createCell(colIndex + c).setCellValue(reducedData.columnHeaders.get(c)); } @@ -131,69 +174,13 @@ private void addValuesToCSVMatrix(ReducedData reducedData){ } numOfImagesToBeOpened -= 1; colIndex += 1 + reducedData.data[0].length; + columnsForSheets.replace(reducedData.measurementType, colIndex); if (numOfImagesToBeOpened == 0){ writeCSVMatrix(); } } } - HashMap calculateNormalValue(ImagePlus imagePlus, int startT, int endT, - ArrayList roiList, SelectSimRange.RangeOfImage rangeOfImage){ - if (!normalize){ - return null; - } - HashMap result = new HashMap<>(); - for (Roi roi : roiList){ - imagePlus.setRoi(roi); - for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ - double normal = 0; - for (int t = startT; t <= endT; t++){ - double zAverage = 0; - for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ - imagePlus.setPosition(c, z, t); - zAverage += imagePlus.getProcessor().getStatistics().mean; - } - zAverage = zAverage / (rangeOfImage.zEnd - rangeOfImage.zStart + 1); - normal += zAverage; - } - normal = normal / (endT - startT + 1); // inclusive of final point - result.put(roi.getName() + c, normal); - } - } - return result; - } - - ReducedData calculateMean(ImagePlus imagePlus, ArrayList roiList, - HashMap normalizationValue, ReducedData reducedData, - LinkedTreeMap> channelInfo, SelectSimRange.RangeOfImage rangeOfImage){ - int roiCounter = 0; - for (Roi roi: roiList) { - imagePlus.setRoi(roi); - for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable - String stringC = String.valueOf(c - 1); - String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); - reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); - } - int tzCounter = 0; - for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ - for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ - for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ - int channelSize = rangeOfImage.channelEnd - rangeOfImage.channelStart + 1; - imagePlus.setPosition(c, z, t); - double meanValue = imagePlus.getStatistics().mean; - if (normalize){ - meanValue = meanValue / normalizationValue.get(roi.getName() + c); - } - reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = meanValue; - } - tzCounter += 1; - } - } - roiCounter += 1; - } - return reducedData; - } - // If parameter is not in list of parameters, add new column. If simulation does not have parameter say "not-present" private void addMetaData(SimResultsLoader loadedResults){ synchronized (metaDataLock){ @@ -242,20 +229,16 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(SimResultsLoader loadedResults) { - ImagePlus imagePlus = loadedResults.getImagePlus(); - imagePlus.show(); - HashMap normValue = calculateNormalValue(imagePlus, submission.simStartPointNorm, - submission.simEndPointNorm, submission.arrayOfSimRois, simRange); - ReducedData reducedData = new ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), - simRange.channelEnd - simRange.channelStart + 1, SelectMeasurements.AvailableMeasurements.AVERAGE); - reducedData = calculateMean(imagePlus, arrayOfSimRois, normValue, reducedData, loadedResults.getChannelInfo(), simRange); - addMetaData(loadedResults); - addValuesToCSVMatrix(reducedData); + Thread imageProcessingThread = new Thread(() -> { + ImagePlus imagePlus = loadedResults.getImagePlus(); + imagePlus.show(); + addMetaData(loadedResults); + calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, + submission.arrayOfSimRois, loadedResults.getChannelInfo()); + }, "Processing Image: " + loadedResults.userSetFileName); + imageProcessingThread.start(); } - - // Queue for digesting information, add one's self to the queue and then notify when data has been recieved - } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java index 7661840..4f5b204 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/NormalizeGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java @@ -1,4 +1,4 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import org.vcell.N5.UI.HintTextField; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java new file mode 100644 index 0000000..b553351 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -0,0 +1,102 @@ +package org.vcell.N5.reduction; + +import com.google.gson.internal.LinkedTreeMap; +import ij.ImagePlus; +import ij.gui.Roi; +import org.vcell.N5.reduction.DTO.RangeOfImage; + +import java.util.ArrayList; +import java.util.HashMap; + +class ReductionCalculations { + private final boolean normalize; + + public ReductionCalculations(boolean normalize){ + this.normalize = normalize; + } + + public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, RangeOfImage rangeOfImage, + DataReductionWriter.ReducedData reducedData, + LinkedTreeMap> channelInfo){ + for (Roi roi: roiList){ + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable + String stringC = String.valueOf(c - 1); + String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); + reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + } + } + } + + /** + * Set position in image with specific ROI, and then with the appropriate reduced data store, perform the calculation + * and add it to reduced data. + * @param imagePlus + * @param roiList + * @param normalizationValue + * @param reducedDataArrayList + * @param rangeOfImage + */ + void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, + HashMap normalizationValue, + ArrayList reducedDataArrayList, + RangeOfImage rangeOfImage){ + int roiCounter = 0; + for (Roi roi: roiList) { + imagePlus.setRoi(roi); + int tzCounter = 0; + for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ + for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ + int channelSize = rangeOfImage.channelEnd - rangeOfImage.channelStart + 1; + imagePlus.setPosition(c, z, t); + double calculatedValue; + for (DataReductionWriter.ReducedData reducedData : reducedDataArrayList){ + switch (reducedData.measurementType){ + case AVERAGE: + calculatedValue = imagePlus.getStatistics().mean; + break; + case STD_DEV: + calculatedValue = imagePlus.getStatistics().stdDev; + break; + default: + throw new RuntimeException("Unknown measurement type selected."); + } + if (normalize && reducedData.measurementType == SelectMeasurements.AvailableMeasurements.AVERAGE){ + calculatedValue = calculatedValue / normalizationValue.get(roi.getName() + c); + } + reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = calculatedValue; + } + } + tzCounter += 1; + } + } + roiCounter += 1; + } + } + + HashMap calculateNormalValue(ImagePlus imagePlus, RangeOfImage normRange, + ArrayList roiList, RangeOfImage rangeOfImage){ + int startT = normRange.timeStart; + int endT = normRange.timeEnd; + HashMap result = new HashMap<>(); + for (Roi roi : roiList){ + imagePlus.setRoi(roi); + for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ + double normal = 0; + for (int t = startT; t <= endT; t++){ + double zAverage = 0; + for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ + imagePlus.setPosition(c, z, t); + zAverage += imagePlus.getProcessor().getStatistics().mean; + } + zAverage = zAverage / (rangeOfImage.zEnd - rangeOfImage.zStart + 1); + normal += zAverage; + } + normal = normal / (endT - startT + 1); // inclusive of final point + result.put(roi.getName() + c, normal); + } + } + return result; + } + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java index c52d308..62be394 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java @@ -1,10 +1,9 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import ij.gui.Roi; import ij.io.RoiDecoder; import javax.swing.*; -import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java new file mode 100644 index 0000000..1fe534e --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java @@ -0,0 +1,54 @@ +package org.vcell.N5.reduction; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; + +class SelectMeasurements extends JPanel{ + private final JList chosenMeasurement; + private final MeasurementsDataModel measurementsDataModel = new MeasurementsDataModel(); + + public SelectMeasurements(){ + setLayout(new GridLayout(1, 2)); + this.add(new JLabel("Measurement Type")); + chosenMeasurement = new JList<>(measurementsDataModel); + this.add(chosenMeasurement); + } + + public ArrayList getChosenMeasurements(){ + return measurementsDataModel.getSelectedMeasurements(chosenMeasurement.getSelectedIndices()); + } + + public enum AvailableMeasurements{ + AVERAGE("Average"), + STD_DEV("Standard Deviation"); + + public final String publicName; + AvailableMeasurements(String publicName){ + this.publicName = publicName; + } + } + + static class MeasurementsDataModel extends AbstractListModel{ + private final AvailableMeasurements[] availableMeasurements = new AvailableMeasurements[]{AvailableMeasurements.AVERAGE, AvailableMeasurements.STD_DEV}; + + public ArrayList getSelectedMeasurements(int[] indices){ + ArrayList selected = new ArrayList<>(); + for (int i : indices){ + selected.add(availableMeasurements[i]); + } + return selected; + } + + @Override + public int getSize() { + return availableMeasurements.length; + } + + @Override + public String getElementAt(int index) { + return availableMeasurements[index].publicName; + } + } + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java similarity index 82% rename from view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java index de39140..db40f65 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/analysis/SelectSimRange.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java @@ -1,6 +1,7 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import org.vcell.N5.UI.HintTextField; +import org.vcell.N5.reduction.DTO.RangeOfImage; import javax.swing.*; import javax.swing.border.Border; @@ -81,21 +82,4 @@ public RangeOfImage getRangeOfSim(){ ); return rangeOfImage; } - - public static class RangeOfImage{ - public final int timeStart; - public final int timeEnd; - public final int zStart; - public final int zEnd; - public final int channelStart; - public final int channelEnd; - public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channelStart, int channelEnd){ - this.timeStart = timeStart; - this.timeEnd = timeEnd; - this.zStart = zStart; - this.zEnd = zEnd; - this.channelStart = channelStart; - this.channelEnd = channelEnd; - } - } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index c07e590..ded44db 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -8,7 +8,8 @@ import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.UI.MainPanel; -import org.vcell.N5.analysis.DataReductionGUI; +import org.vcell.N5.reduction.DataReductionGUI; +import org.vcell.N5.reduction.DataReductionWriter; import javax.swing.*; import javax.swing.event.EventListenerList; @@ -37,7 +38,10 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o ArrayList dimensions = firstSim.getN5Dimensions(); if (dataReduction){ dataReductionGUI = new DataReductionGUI(filesToOpen, dimensions.get(2), dimensions.get(3), dimensions.get(4)); - dataReductionGUI.displayGUI(); + DataReductionGUI.DataReductionSubmission submission = dataReductionGUI.displayGUI(); + if (submission != null){ + DataReductionWriter.createDataReductionProcess(submission); + } } else { rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java similarity index 72% rename from view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java rename to view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 41c8843..f9f6f0d 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/analysis/DataReductionTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -1,4 +1,4 @@ -package org.vcell.N5.analysis; +package org.vcell.N5.reduction; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import ij.ImagePlus; @@ -8,6 +8,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; @@ -17,7 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; -public class DataReductionTest { +public class ReductionCalculationsTest { // First two are SimROI, last two are LabROI private final double[][] labMeans2D = new double[][]{{6, 0, 18, 0}, {6.489, 0, 16.341, 0}, {7.247, 0, 14.469, 0}}; //calculated through IJ measurement tool @@ -43,24 +44,21 @@ public static void init(){ N5ImageHandler.loadingManager = new LoadingManager(); } - private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults){ - DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( - false, roiList, roiList, imagePlus,4, null); - compareExpectedCalculations(imagePlus, roiList, expectedResults, dataReductionSubmission); - } - private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults, - DataReductionGUI.DataReductionSubmission dataReductionSubmission){ - DataReduction dataReduction = new DataReduction(dataReductionSubmission); - DataReduction.ReducedData reducedData = new DataReduction.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), - imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - SelectSimRange.RangeOfImage entireRange = new SelectSimRange.RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), - 1, imagePlus.getNChannels()); - HashMap norms = dataReduction.calculateNormalValue(imagePlus, 1, 1, roiList, entireRange); - DataReduction.ReducedData result = dataReduction.calculateMean(imagePlus, roiList, norms, reducedData, null, entireRange); + boolean normalizeMeasurementsBool){ + ReductionCalculations reductionCalculations = new ReductionCalculations(normalizeMeasurementsBool); + + DataReductionWriter.ReducedData reducedData = new DataReductionWriter.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); + RangeOfImage entireRange = new RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), 1, imagePlus.getNChannels()); + RangeOfImage normRange = new RangeOfImage(1, 1); + ArrayList reducedDataArrayList = new ArrayList<>(); + reducedDataArrayList.add(reducedData); + + HashMap norms = reductionCalculations.calculateNormalValue(imagePlus, normRange, roiList, entireRange); + reductionCalculations.calculateStatistics(imagePlus, roiList, norms, reducedDataArrayList, entireRange); for (int r = 0; r < expectedResults.length; r++){ for (int c = 0; c < expectedResults[r].length; c++){ - Assert.assertEquals(expectedResults[r][c], result.data[r][c], 0.0009); + Assert.assertEquals(expectedResults[r][c], reducedData.data[r][c], 0.0009); } } } @@ -74,7 +72,7 @@ public void testMean2DCalculation(){ Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; - compareExpectedCalculations(labResultImage2D, roiList, labMeans2D); + compareExpectedCalculations(labResultImage2D, roiList, labMeans2D, false); } @Test @@ -82,7 +80,7 @@ public void testMean3DCalculation(){ ImagePlus mitosis = new ImagePlus(getTestResourceFiles("mitosis.tif").getAbsolutePath()); Roi mitosisROI = RoiDecoder.open(getTestResourceFiles("ROIs/Mitosis Center.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(mitosisROI);}}; - compareExpectedCalculations(mitosis, roiList, threeDMeans); + compareExpectedCalculations(mitosis, roiList, threeDMeans, false); } @Test @@ -111,9 +109,6 @@ public void testMeanAndNormalization2DCalculation(){ } } - DataReductionGUI.DataReductionSubmission dataReductionSubmission = new DataReductionGUI.DataReductionSubmission( - true, roiList, roiList, labResultImage2D, 1, 1, 1, 1,4, null); - - compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, dataReductionSubmission); + compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, true); } } From 6ae2fb1dbfb57695dd264437440978266a8b90cc Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 12 Nov 2024 14:05:35 -0500 Subject: [PATCH 24/44] Replace XLS File With CSV --- view-simulation-results/pom.xml | 24 +--- .../N5/reduction/DataReductionWriter.java | 108 ++++++++++++------ 2 files changed, 74 insertions(+), 58 deletions(-) diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 163f06f..d01e897 100644 --- a/view-simulation-results/pom.xml +++ b/view-simulation-results/pom.xml @@ -11,7 +11,7 @@ view-simulation-results - 1.0-SNAPSHOT + 2.0 VCell View Simulation Results Virtual Cell ImageJ plugin to retrieve VCell simulation results for analysis within ImageJ @@ -159,34 +159,26 @@ 4.1.1 - - - org.jsoup - jsoup - 1.16.1 - - org.scijava scijava-log-slf4j - 1.0.6 + org.slf4j slf4j-api - + org.slf4j slf4j-simple - com.google.code.gson gson - 2.10.1 + software.amazon.awssdk s3 @@ -195,14 +187,6 @@ com.opencsv opencsv - 4.1 - - - - - org.apache.poi - poi-ooxml - 5.3.0 diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index bf7e9ed..a75a7bd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -1,12 +1,9 @@ package org.vcell.N5.reduction; import com.google.gson.internal.LinkedTreeMap; +import com.opencsv.CSVWriter; import ij.ImagePlus; import ij.gui.Roi; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.MainPanel; @@ -16,8 +13,8 @@ import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; +import java.io.FileWriter; import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.HashMap; @@ -26,20 +23,22 @@ public class DataReductionWriter implements SimLoadingListener { private final Object csvMatrixLock = new Object(); private final Object metaDataLock = new Object(); - private File file; + private final File file; private int numOfImagesToBeOpened; private final ReductionCalculations calculations; public final DataReductionGUI.DataReductionSubmission submission; - private final Workbook workbook = new HSSFWorkbook(); - private final HashMap sheetsAvailable = new HashMap(){{ - put(SelectMeasurements.AvailableMeasurements.AVERAGE, workbook.createSheet("Average")); - put(SelectMeasurements.AvailableMeasurements.STD_DEV, workbook.createSheet("Standard Deviation")); + private final ArrayList> averageMatrix = new ArrayList<>(); + private final ArrayList> standardDivMatrix = new ArrayList<>(); + private final ArrayList> metaDataSheet = new ArrayList<>(); + + private final HashMap>> sheetsAvailable = new HashMap>>(){{ + put(SelectMeasurements.AvailableMeasurements.AVERAGE, averageMatrix); + put(SelectMeasurements.AvailableMeasurements.STD_DEV, standardDivMatrix); }}; private final HashMap columnsForSheets = new HashMap<>(); - private final Sheet metaDataSheet = workbook.createSheet("Metadata"); private int metaDataRow = 1; private int metaDataParameterCol = 5; @@ -99,32 +98,35 @@ private void initializeDataSheets(){ // Add Time and Z-Index Columns for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ - Sheet dataSheet = sheetsAvailable.get(measurement); - Row headerRow = dataSheet.createRow(0); + ArrayList> dataSheet = sheetsAvailable.get(measurement); + dataSheet.add(new ArrayList<>()); + ArrayList headerRow = dataSheet.get(0); + for (int i = 0; i < headers.size(); i++){ - headerRow.createCell(i).setCellValue(headers.get(i)); + headerRow.add(i, headers.get(i)); } columnsForSheets.put(measurement, headers.size() + 1); } - metaDataSheet.createRow(0).createCell(1).setCellValue("BioModel Name"); - metaDataSheet.getRow(0).createCell(2).setCellValue("Application Name"); - metaDataSheet.getRow(0).createCell(3).setCellValue("Simulation Name"); - metaDataSheet.getRow(0).createCell(4).setCellValue("N5 URL"); + metaDataSheet.add(new ArrayList<>()); + metaDataSheet.get(0).add(""); + metaDataSheet.get(0).add("BioModel Name"); + metaDataSheet.get(0).add("Application Name"); + metaDataSheet.get(0).add("Simulation Name"); + metaDataSheet.get(0).add("N5 URL"); // Fill in Time and Z-Index Columns with selected range for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ - Sheet dataSheet = sheetsAvailable.get(measurement); - int rowI = 1; + ArrayList> dataSheet = sheetsAvailable.get(measurement); for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ - Row pointRow = dataSheet.createRow(rowI); - rowI += 1; - pointRow.createCell(0).setCellValue(t); + ArrayList pointRow = new ArrayList<>(); + pointRow.add(0, String.valueOf(t)); if (is3D){ - pointRow.createCell(1).setCellValue(z); + pointRow.add(1, String.valueOf(z)); } + dataSheet.add(pointRow); } } } @@ -160,16 +162,18 @@ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, private void addValuesToCSVMatrix(ReducedData reducedData){ synchronized (csvMatrixLock){ - Sheet dataSheet = sheetsAvailable.get(reducedData.measurementType); + ArrayList> dataSheet = sheetsAvailable.get(reducedData.measurementType); int colIndex = columnsForSheets.get(reducedData.measurementType); + fillWithEmptySpace(dataSheet.get(0), colIndex); for (int c = 0; c < reducedData.columnHeaders.size(); c++){ - dataSheet.getRow(0).createCell(colIndex + c).setCellValue(reducedData.columnHeaders.get(c)); + dataSheet.get(0).add(colIndex, reducedData.columnHeaders.get(c)); } for (int i = 0; i < reducedData.data.length; i++){ for (int c = 0; c < reducedData.data[i].length; c++){ - Row row = dataSheet.getRow(i + 1); + ArrayList row = dataSheet.get(i + 1); + fillWithEmptySpace(row, colIndex); double mean = reducedData.data[i][c]; - row.createCell(colIndex + c).setCellValue(mean); + row.add(String.valueOf(mean)); } } numOfImagesToBeOpened -= 1; @@ -186,20 +190,24 @@ private void addMetaData(SimResultsLoader loadedResults){ synchronized (metaDataLock){ N5ExportTable n5ExportTable = MainPanel.n5ExportTable; ExportDataRepresentation.SimulationExportDataRepresentation data = n5ExportTable.n5ExportTableModel.getRowData(loadedResults.rowNumber); - metaDataSheet.createRow(metaDataRow).createCell(0).setCellValue(loadedResults.userSetFileName); - metaDataSheet.getRow(metaDataRow).createCell(1).setCellValue(data.biomodelName); - metaDataSheet.getRow(metaDataRow).createCell(2).setCellValue(data.applicationName); - metaDataSheet.getRow(metaDataRow).createCell(3).setCellValue(data.simulationName); - metaDataSheet.getRow(metaDataRow).createCell(4).setCellValue(data.uri); + ArrayList newMetaData = new ArrayList<>(); + newMetaData.add(loadedResults.userSetFileName); + newMetaData.add(data.biomodelName); + newMetaData.add(data.applicationName); + newMetaData.add(data.simulationName); + newMetaData.add(data.uri); ArrayList parameterValues = data.differentParameterValues; for (String s : parameterValues){ String[] tokens = s.split(":"); String colValue = tokens[1] + ":" + tokens[2]; if (parameterNameToCol.containsKey(tokens[0])){ - metaDataSheet.getRow(metaDataRow).createCell(parameterNameToCol.get(tokens[0])).setCellValue(colValue); + int col = parameterNameToCol.get(tokens[0]); + fillWithEmptySpace(newMetaData, col); + newMetaData.add(col, colValue); } else{ - metaDataSheet.getRow(0).createCell(metaDataParameterCol).setCellValue(tokens[0] + "\n(Default:Set Value)"); - metaDataSheet.getRow(metaDataRow).createCell(metaDataParameterCol).setCellValue(colValue); + metaDataSheet.get(0).add(tokens[0] + " (Default:Set Value)"); + fillWithEmptySpace(newMetaData, metaDataParameterCol); + newMetaData.add(metaDataParameterCol, colValue); parameterNameToCol.put(tokens[0], metaDataParameterCol); metaDataParameterCol += 1; } @@ -208,11 +216,35 @@ private void addMetaData(SimResultsLoader loadedResults){ } } + // If specific entry to be added isn't in array list length, add empty space until it is + private void fillWithEmptySpace(ArrayList arrayList, int col){ + while (arrayList.size() < col){ + arrayList.add(""); + } + } + private void writeCSVMatrix(){ try { - file = new File(file.getAbsolutePath() + ".xls"); - workbook.write(Files.newOutputStream(file.toPath())); + for (SelectMeasurements.AvailableMeasurements measurements : sheetsAvailable.keySet()){ + if (!sheetsAvailable.get(measurements).isEmpty()){ + File currentFile = new File(file.getAbsolutePath() + "-" + measurements.publicName + ".csv"); + try (FileWriter fileWriter = new FileWriter(currentFile)){ + CSVWriter csvWriter = new CSVWriter(fileWriter); + for (ArrayList row : sheetsAvailable.get(measurements)){ + csvWriter.writeNext(row.toArray(new String[0])); + } + } + } + } + File currentFile = new File(file.getAbsolutePath() + "-metadata.csv"); + try (FileWriter fileWriter = new FileWriter(currentFile)){ + CSVWriter csvWriter = new CSVWriter(fileWriter); + for (ArrayList row : metaDataSheet){ + csvWriter.writeNext(row.toArray(new String[0])); + } + } + } catch (IOException e) { throw new RuntimeException(e); } finally { From 5777315c8c408f1e64f214aeff2719ecc0bf91bb Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 12 Nov 2024 14:05:49 -0500 Subject: [PATCH 25/44] Update GUI --- .../main/java/org/vcell/N5/UI/ControlButtonsPanel.java | 2 +- .../java/org/vcell/N5/reduction/DataReductionGUI.java | 2 +- .../java/org/vcell/N5/reduction/SelectMeasurements.java | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 4c72ab0..b25b90f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -30,7 +30,7 @@ public ControlButtonsPanel(){ displayAdvancedFeatures = new JCheckBox("Advanced Features"); - openOrCancel = new JButton("Open Virtually"); + openOrCancel = new JButton("Open Virtual Stack"); dataReduction = new JButton("Run Measurement Script"); questionMark = new JButton("?"); questionMark.setPreferredSize(new Dimension(20, 20)); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java index a42fdea..838cefe 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java @@ -43,7 +43,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); - jDialog = pane.createDialog("Data Reduction"); + jDialog = pane.createDialog("Measurement Script"); jDialog.setResizable(true); selectSimRange = new SelectSimRange(jDialog, simCSize, simZSize, simTSize); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java index 1fe534e..019823f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java @@ -9,10 +9,12 @@ class SelectMeasurements extends JPanel{ private final MeasurementsDataModel measurementsDataModel = new MeasurementsDataModel(); public SelectMeasurements(){ - setLayout(new GridLayout(1, 2)); - this.add(new JLabel("Measurement Type")); + setLayout(new GridLayout(1, 1)); + this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Measurement Type")); chosenMeasurement = new JList<>(measurementsDataModel); - this.add(chosenMeasurement); + chosenMeasurement.setVisibleRowCount(3); + JScrollPane jScrollPane = new JScrollPane(chosenMeasurement); + this.add(jScrollPane); } public ArrayList getChosenMeasurements(){ From 42ef820c44b014e5ece1fc4288385f0b96aac020 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 12 Nov 2024 14:24:39 -0500 Subject: [PATCH 26/44] Add Image Open Tagging Tag the images which are being opened to distinguish between "Viewing" and "Data Reduction". --- .../org/vcell/N5/UI/ControlButtonsPanel.java | 4 +++- .../java/org/vcell/N5/UI/N5ExportTable.java | 8 +++++--- .../org/vcell/N5/UI/RemoteFileSelection.java | 2 +- .../N5/reduction/DataReductionWriter.java | 18 ++++++++++-------- .../vcell/N5/retrieving/SimResultsLoader.java | 16 ++++++++++++---- .../reduction/ReductionCalculationsTest.java | 4 ++-- .../N5/retrieving/N5ImageHandlerTest.java | 6 +++--- 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index b25b90f..70ba03f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -1,6 +1,7 @@ package org.vcell.N5.UI; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.retrieving.SimResultsLoader; import javax.swing.*; import javax.swing.border.Border; @@ -108,7 +109,8 @@ public void actionPerformed(ActionEvent e) { if (openOrCancel.getText().equals("Cancel")){ n5ExportTable.removeFromLoadingRows(); } else { - n5ExportTable.openSelectedRows(inMemory, performDataReduction); + SimResultsLoader.OpenTag openTag = performDataReduction ? SimResultsLoader.OpenTag.DATA_REDUCTION : SimResultsLoader.OpenTag.VIEW; + n5ExportTable.openSelectedRows(inMemory, performDataReduction, openTag); } } else if (e.getSource().equals(advancedFeatures.copyLink)) { n5ExportTable.copySelectedRowLink(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index c8bfc39..c72889e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -155,12 +155,12 @@ private void automaticRefresh(){ refreshTableThread.start(); } - public void openSelectedRows(boolean openInMemory, boolean performDataReduction){ + public void openSelectedRows(boolean openInMemory, boolean performDataReduction, SimResultsLoader.OpenTag openTag){ ArrayList filesToOpen = new ArrayList<>(); for(int row: exportListTable.getSelectedRows()){ String uri = n5ExportTableModel.getRowData(row).uri; ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); - SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID); + SimResultsLoader simResultsLoader = new SimResultsLoader(uri, rowData.savedFileName, row, rowData.jobID, openTag); filesToOpen.add(simResultsLoader); } N5ImageHandler.loadingManager.openN5FileDataset(filesToOpen, openInMemory, @@ -226,7 +226,9 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { loadingRowsJobID.remove(loadedResults.rowNumber); exportListTable.repaint(); controlPanel.allowCancel(false); - loadedResults.getImagePlus().show(); + if (loadedResults.openTag == SimResultsLoader.OpenTag.VIEW){ + loadedResults.getImagePlus().show(); + } } public static class N5ExportTableModel extends AbstractTableModel { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java index 7ed8a78..eadf2bd 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RemoteFileSelection.java @@ -95,7 +95,7 @@ public String getS3URL(){ @Override public void actionPerformed(ActionEvent e) { - SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, ""); + SimResultsLoader simResultsLoader = new SimResultsLoader(getS3URL(), "", -1, "", SimResultsLoader.OpenTag.VIEW); N5ImageHandler.loadingManager.openN5FileDataset(new ArrayList(){{add(simResultsLoader);}}, false, false); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index a75a7bd..4024f9d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -261,14 +261,16 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(SimResultsLoader loadedResults) { - Thread imageProcessingThread = new Thread(() -> { - ImagePlus imagePlus = loadedResults.getImagePlus(); - imagePlus.show(); - addMetaData(loadedResults); - calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, - submission.arrayOfSimRois, loadedResults.getChannelInfo()); - }, "Processing Image: " + loadedResults.userSetFileName); - imageProcessingThread.start(); + if (loadedResults.openTag == SimResultsLoader.OpenTag.DATA_REDUCTION){ + Thread imageProcessingThread = new Thread(() -> { + ImagePlus imagePlus = loadedResults.getImagePlus(); + imagePlus.show(); + addMetaData(loadedResults); + calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, + submission.arrayOfSimRois, loadedResults.getChannelInfo()); + }, "Processing Image: " + loadedResults.userSetFileName); + imageProcessingThread.start(); + } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index fa72d3c..75a42ea 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -53,6 +53,7 @@ public class SimResultsLoader { private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; private ImagePlus imagePlus = null; + public final OpenTag openTag; public String userSetFileName = null; @@ -60,14 +61,14 @@ public class SimResultsLoader { public String exportID; public SimResultsLoader(){ - + openTag = OpenTag.NONE; } - public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber, String exportID){ - this(stringURI, userSetFileName); + public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber, String exportID, OpenTag openTag){ + this(stringURI, userSetFileName, openTag); this.rowNumber = rowNumber; this.exportID = exportID; } - public SimResultsLoader(String stringURI, String userSetFileName){ + public SimResultsLoader(String stringURI, String userSetFileName, OpenTag openTag){ uri = URI.create(stringURI); this.userSetFileName = userSetFileName; if(!(uri.getQuery() == null)){ @@ -78,6 +79,7 @@ public SimResultsLoader(String stringURI, String userSetFileName){ throw new RuntimeException(e); } } + this.openTag = openTag; } ///////////////////////////////// @@ -225,4 +227,10 @@ ImagePlus getImgPlusFromLocalN5File() throws IOException { N5Reader n5Reader = new N5FSReader(selectedLocalFile.getPath()); return ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5Reader, dataSetChosen), userSetFileName); } + + public enum OpenTag{ + VIEW, + DATA_REDUCTION, + NONE + } } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index f9f6f0d..0a7fd88 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -66,7 +66,7 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi @Test public void testMean2DCalculation(){ // Ensure the mean calculated for each ROI, and each time point is what's to be expected - SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.NONE); ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); @@ -85,7 +85,7 @@ public void testMean3DCalculation(){ @Test public void testMeanAndNormalization2DCalculation(){ - SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1"); + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.NONE); ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); diff --git a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java index 140fd13..481e6e5 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java @@ -75,7 +75,7 @@ public void testGettingImgPlus() throws IOException { public void testS3AlphaInstance() throws IOException{ N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); @@ -91,7 +91,7 @@ public void testS3AlphaInstance() throws IOException{ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); @@ -113,7 +113,7 @@ interface PixelCalculations { public void testUnits() throws IOException { N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for (N5DataSetFile n5DataSetFile: n5DataSetFiles){ - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); From e1ede1e8ea220eae9ce2b45ee994d09cc0dd3e4c Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 12 Nov 2024 14:31:41 -0500 Subject: [PATCH 27/44] Get Metadata to Be Writing Forgot to append metadata row to metadata sheet. --- .../java/org/vcell/N5/reduction/DataReductionWriter.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 4024f9d..63a0041 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -40,7 +40,6 @@ public class DataReductionWriter implements SimLoadingListener { }}; private final HashMap columnsForSheets = new HashMap<>(); - private int metaDataRow = 1; private int metaDataParameterCol = 5; private final HashMap parameterNameToCol = new HashMap<>(); @@ -212,7 +211,7 @@ private void addMetaData(SimResultsLoader loadedResults){ metaDataParameterCol += 1; } } - metaDataRow += 1; + metaDataSheet.add(newMetaData); } } @@ -237,7 +236,7 @@ private void writeCSVMatrix(){ } } } - File currentFile = new File(file.getAbsolutePath() + "-metadata.csv"); + File currentFile = new File(file.getAbsolutePath() + "-Metadata.csv"); try (FileWriter fileWriter = new FileWriter(currentFile)){ CSVWriter csvWriter = new CSVWriter(fileWriter); for (ArrayList row : metaDataSheet){ From b4429e6659b6329d4ce7b9a8addd8ad2f7756761 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 13 Nov 2024 09:57:39 -0500 Subject: [PATCH 28/44] Add Cancel Tag and Test Better descriptive tags for the simulation loader. --- .../java/org/vcell/N5/retrieving/LoadingManager.java | 1 + .../org/vcell/N5/retrieving/SimResultsLoader.java | 12 ++++++++---- .../N5/reduction/ReductionCalculationsTest.java | 4 ++-- .../org/vcell/N5/retrieving/N5ImageHandlerTest.java | 6 +++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index ded44db..bea3a32 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -67,6 +67,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } } catch (RuntimeException e) { + simResultsLoader.setTagToCanceled(); if (e.getCause().getCause().getCause() instanceof SdkInterruptedException || e.getCause().getCause() instanceof AbortedException){ logger.debug("Simulation stopped loading"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java index 75a42ea..c005edf 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/SimResultsLoader.java @@ -42,7 +42,6 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashMap; -import java.util.TreeMap; public class SimResultsLoader { private File selectedLocalFile; @@ -53,7 +52,7 @@ public class SimResultsLoader { private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public static AmazonS3ClientBuilder s3ClientBuilder; private ImagePlus imagePlus = null; - public final OpenTag openTag; + public OpenTag openTag; public String userSetFileName = null; @@ -61,7 +60,7 @@ public class SimResultsLoader { public String exportID; public SimResultsLoader(){ - openTag = OpenTag.NONE; + openTag = OpenTag.TEST; } public SimResultsLoader(String stringURI, String userSetFileName, int rowNumber, String exportID, OpenTag openTag){ this(stringURI, userSetFileName, openTag); @@ -215,6 +214,10 @@ void setDataSetChosen(String dataSetChosen) { this.dataSetChosen = dataSetChosen; } + public void setTagToCanceled(){ + openTag = OpenTag.CANCELED; + } + ///////////////////////// // Local File Reading // //////////////////////// @@ -231,6 +234,7 @@ ImagePlus getImgPlusFromLocalN5File() throws IOException { public enum OpenTag{ VIEW, DATA_REDUCTION, - NONE + CANCELED, + TEST } } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 0a7fd88..9c183b1 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -66,7 +66,7 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi @Test public void testMean2DCalculation(){ // Ensure the mean calculated for each ROI, and each time point is what's to be expected - SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.NONE); + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.TEST); ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); @@ -85,7 +85,7 @@ public void testMean3DCalculation(){ @Test public void testMeanAndNormalization2DCalculation(){ - SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.NONE); + SimResultsLoader simResultsLoader = new SimResultsLoader("https://vcell.cam.uchc.edu/n5Data/ezequiel23/ddf7f4f0c77dffd.n5?dataSetName=4864003788", "test1", SimResultsLoader.OpenTag.TEST); ImagePlus labResultImage2D = simResultsLoader.getImagePlus(); Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); diff --git a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java index 481e6e5..3f189a1 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/retrieving/N5ImageHandlerTest.java @@ -75,7 +75,7 @@ public void testGettingImgPlus() throws IOException { public void testS3AlphaInstance() throws IOException{ N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.TEST); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); @@ -91,7 +91,7 @@ public void testS3AlphaInstance() throws IOException{ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for(N5DataSetFile n5DataSetFile : n5DataSetFiles) { - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.TEST); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); @@ -113,7 +113,7 @@ interface PixelCalculations { public void testUnits() throws IOException { N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); for (N5DataSetFile n5DataSetFile: n5DataSetFiles){ - SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.NONE); + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "", SimResultsLoader.OpenTag.TEST); simResultsLoader.createS3ClientAndReader(); simResultsLoader.loadImageFromN5File(); ImagePlus imagePlus = simResultsLoader.getImagePlus(); From 7261ca7dbfcede073bacce8f97d1e0cecb623ad5 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 13 Nov 2024 10:54:48 -0500 Subject: [PATCH 29/44] Update GUI Make loading status more reliable and remove images once they've been analyzed. --- .../main/java/org/vcell/N5/N5ImageHandler.java | 2 ++ .../org/vcell/N5/UI/ControlButtonsPanel.java | 4 ++-- .../main/java/org/vcell/N5/UI/N5ExportTable.java | 16 +++++++++++----- .../vcell/N5/reduction/DataReductionWriter.java | 2 ++ .../org/vcell/N5/reduction/NormalizeGUI.java | 6 +++--- .../org/vcell/N5/retrieving/LoadingManager.java | 9 +++------ 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index be9fe6c..c62b6e4 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -40,6 +40,7 @@ public void run() { initializeLogService(); loadingManager = new LoadingManager(); exportTable = new MainPanel(); + MainPanel.controlButtonsPanel.enableCriticalButtons(false); setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); Thread thread = new Thread(() -> { @@ -47,6 +48,7 @@ public void run() { // So create one upon initialization, while the user is focused on the GUI // and by the time they open an Image it's already loaded. SimResultsLoader.s3ClientBuilder = AmazonS3ClientBuilder.standard(); + MainPanel.controlButtonsPanel.enableCriticalButtons(true); }); thread.start(); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index 70ba03f..e733783 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -107,7 +107,7 @@ public void actionPerformed(ActionEvent e) { boolean performDataReduction = e.getSource().equals(dataReduction); if(e.getSource().equals(openOrCancel) || inMemory || performDataReduction){ if (openOrCancel.getText().equals("Cancel")){ - n5ExportTable.removeFromLoadingRows(); + n5ExportTable.stopSelectedImageFromLoading(); } else { SimResultsLoader.OpenTag openTag = performDataReduction ? SimResultsLoader.OpenTag.DATA_REDUCTION : SimResultsLoader.OpenTag.VIEW; n5ExportTable.openSelectedRows(inMemory, performDataReduction, openTag); @@ -136,7 +136,7 @@ public void allowCancel(boolean allow){ if (allow){ openOrCancel.setText("Cancel"); } else { - openOrCancel.setText("Open Virtually"); + openOrCancel.setText("Open Virtual Stack"); } } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index c72889e..9202e9e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -1,6 +1,5 @@ package org.vcell.N5.UI; -import ij.ImagePlus; import org.scijava.log.Logger; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; @@ -208,13 +207,22 @@ public void valueChanged(ListSelectionEvent e) { controlPanel.allowCancel(loadingRow != -1); } - public void removeFromLoadingRows(){ + public void stopSelectedImageFromLoading(){ int row = exportListTable.getSelectedRow(); N5ImageHandler.loadingManager.stopOpeningSimulation(n5ExportTableModel.tableData.get(row).jobID); loadingRowsJobID.remove(row); exportListTable.repaint(); } + public void removeSpecificRowFromLoadingRows(int rowNumber){ + loadingRowsJobID.remove(rowNumber); + int selected = exportListTable.getSelectedRow(); + if (selected == rowNumber){ + controlPanel.allowCancel(false); + exportListTable.repaint(); + } + } + @Override public void simIsLoading(int itemRow, String exportID) { loadingRowsJobID.put(itemRow, exportID); @@ -223,10 +231,8 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(SimResultsLoader loadedResults) { - loadingRowsJobID.remove(loadedResults.rowNumber); - exportListTable.repaint(); - controlPanel.allowCancel(false); if (loadedResults.openTag == SimResultsLoader.OpenTag.VIEW){ + removeSpecificRowFromLoadingRows(loadedResults.rowNumber); loadedResults.getImagePlus().show(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 63a0041..294612f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -267,6 +267,8 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { addMetaData(loadedResults); calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, submission.arrayOfSimRois, loadedResults.getChannelInfo()); + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); + imagePlus.close(); }, "Processing Image: " + loadedResults.userSetFileName); imageProcessingThread.start(); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java index 4f5b204..46c9b10 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java @@ -18,12 +18,12 @@ class NormalizeGUI extends JPanel { public NormalizeGUI(JDialog jDialog, double simTSize){ Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); - Border normalizeBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Timeline Range to Create Norm"); + Border normalizeBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Timeframe Range to Create Norm"); JPanel fromImage = new JPanel(new GridLayout()); createNormFromImageStart = new JTextField(); createNormFromImageEnd = new JTextField(); - fromImage.add(new JLabel("Exp. Timeline: ")); + fromImage.add(new JLabel("Exp. Timeframe: ")); fromImage.add(createNormFromImageStart); fromImage.add(new JLabel("to")); fromImage.add(createNormFromImageEnd); @@ -31,7 +31,7 @@ public NormalizeGUI(JDialog jDialog, double simTSize){ JPanel fromSim = new JPanel(new GridLayout()); createNormFromSimStart = new HintTextField("1"); createNormFromSimEnd = new HintTextField(String.valueOf((int) simTSize)); - fromSim.add(new JLabel("Sim Timeline: ")); + fromSim.add(new JLabel("Sim Timeframe: ")); fromSim.add(createNormFromSimStart); fromSim.add(new JLabel("to")); fromSim.add(createNormFromSimEnd); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index bea3a32..8f42bd5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -68,22 +68,19 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } catch (RuntimeException e) { simResultsLoader.setTagToCanceled(); - if (e.getCause().getCause().getCause() instanceof SdkInterruptedException || - e.getCause().getCause() instanceof AbortedException){ + if (e instanceof AbortedException){ logger.debug("Simulation stopped loading"); } else { throw new RuntimeException(e); } - } - catch (Exception e){ - throw new RuntimeException(e); } finally { MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); notifySimIsDoneLoading(simResultsLoader, imagePlus); synchronized (openSimulationsLock){ openingSimulations.remove(simResultsLoader.exportID); } + controlButtonsPanel.enableRowContextDependentButtons(true); + MainPanel.controlButtonsPanel.allowCancel(false); } }); openThread.setName("Opening sim number: " + i + ". With id: " + simResultsLoader.exportID); From 0e4b7dc0856fb3eec7bd2cb88d32d7c31261cd66 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 13 Nov 2024 14:35:38 -0500 Subject: [PATCH 30/44] Make Okay Button Context Aware --- .../main/java/org/vcell/N5/UI/MainPanel.java | 2 +- .../vcell/N5/reduction/DataReductionGUI.java | 79 ++++++++++++------- .../org/vcell/N5/reduction/RoiSelection.java | 6 +- .../N5/reduction/SelectMeasurements.java | 16 +++- .../vcell/N5/retrieving/LoadingManager.java | 6 +- 5 files changed, 73 insertions(+), 36 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java index 4a5690b..5d4bb24 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/MainPanel.java @@ -13,7 +13,7 @@ import java.util.Enumeration; public class MainPanel { - private static JFrame exportTableDialog; + public static JFrame exportTableDialog; public final static ControlButtonsPanel controlButtonsPanel = new ControlButtonsPanel(); public final static N5ExportTable n5ExportTable = new N5ExportTable(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java index 838cefe..6dd8265 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java @@ -9,6 +9,7 @@ import javax.swing.*; import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import java.awt.*; import java.awt.event.ActionEvent; @@ -20,15 +21,14 @@ public class DataReductionGUI extends JPanel implements ActionListener { private JComboBox chosenImage; private final JCheckBox selectRangeOfMeasurement = new JCheckBox("Select Measurement Range: "); private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); - - - private final JDialog jDialog; - private final JOptionPane pane; + + private final JDialog jDialog = new JDialog(MainPanel.exportTableDialog, true); + private final JButton okayButton = new JButton("Okay"); + private final JButton cancelButton = new JButton("Cancel"); private File chosenFile; private final ArrayList filesToOpen; - public int mainGUIReturnValue; public int fileChooserReturnValue; private final SelectSimRange selectSimRange; @@ -36,20 +36,20 @@ public class DataReductionGUI extends JPanel implements ActionListener { private final NormalizeGUI normalizeGUI; private final SelectMeasurements selectMeasurements; + private boolean continueWithProcess = false; + private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); public DataReductionGUI(ArrayList filesToOpen, double simCSize, double simZSize, double simTSize){ - this.filesToOpen = filesToOpen; + this.filesToOpen = filesToOpen; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + okayButton.setEnabled(false); - pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); - jDialog = pane.createDialog("Measurement Script"); - jDialog.setResizable(true); selectSimRange = new SelectSimRange(jDialog, simCSize, simZSize, simTSize); - roiSelection = new RoiSelection(); + roiSelection = new RoiSelection(this); normalizeGUI = new NormalizeGUI(jDialog, simTSize); - selectMeasurements = new SelectMeasurements(); + selectMeasurements = new SelectMeasurements(this); JPanel imagesToMeasurePanel = new JPanel(); imagesToMeasurePanel.setLayout(new BoxLayout(imagesToMeasurePanel, BoxLayout.Y_AXIS)); @@ -63,28 +63,23 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize add(displayOptionsPanel()); add(normalizeGUI); add(selectSimRange); + add(okayCancelPanel()); + setVisible(true); + okayButton.addActionListener(this); + cancelButton.addActionListener(this); normalizeMeasurement.addActionListener(this); selectRangeOfMeasurement.addActionListener(this); - jDialog.pack(); - } + this.setBorder(new EmptyBorder(15, 12, 15, 12)); - public DataReductionSubmission displayGUI(){ + jDialog.add(this); jDialog.setVisible(true); - mainGUIReturnValue = (Integer) pane.getValue(); - if (mainGUIReturnValue == JOptionPane.OK_OPTION){ - JFileChooser saveToFile = new JFileChooser(); - saveToFile.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooserReturnValue = saveToFile.showDialog(this, "Save Results To File"); - if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ - chosenFile = saveToFile.getSelectedFile(); - MainPanel.controlButtonsPanel.enableCriticalButtons(false); - return createSubmission(); - } - } - return null; + jDialog.setResizable(true); + jDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); + jDialog.setTitle("Measurement Script"); + jDialog.pack(); } public DataReductionSubmission createSubmission(){ @@ -97,6 +92,13 @@ public DataReductionSubmission createSubmission(){ selectSimRange.getRangeOfSim(), selectMeasurements.getChosenMeasurements()); } + private JPanel okayCancelPanel(){ + JPanel jPanel = new JPanel(); + jPanel.add(okayButton); + jPanel.add(cancelButton); + return jPanel; + } + private JPanel imageSelectionPanel(){ JPanel jPanel = new JPanel(new GridLayout(1, 2)); jPanel.add(new JLabel("Experimental")); @@ -129,15 +131,39 @@ private JPanel displayOptionsPanel(){ return jPanel; } + public void activateOkayButton(){ + boolean selectedAMeasurement = !selectMeasurements.getChosenMeasurements().isEmpty(); + boolean chosenExperimentImage = chosenImage.getSelectedItem() != null; + boolean roisIsSelected = !roiSelection.getImageROIList().isEmpty() && !roiSelection.getSimROIList().isEmpty(); + okayButton.setEnabled(selectedAMeasurement && chosenExperimentImage && roisIsSelected); + } + @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(normalizeMeasurement)) { normalizeGUI.setVisible(normalizeMeasurement.isSelected()); } else if (e.getSource().equals(selectRangeOfMeasurement)){ selectSimRange.setVisible(selectRangeOfMeasurement.isSelected()); + } else if (e.getSource().equals(okayButton)) { + JFileChooser saveToFile = new JFileChooser(); + saveToFile.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooserReturnValue = saveToFile.showDialog(this, "Save Results To File"); + if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ + chosenFile = saveToFile.getSelectedFile(); + MainPanel.controlButtonsPanel.enableCriticalButtons(false); + DataReductionWriter.createDataReductionProcess(createSubmission()); + continueWithProcess = true; + jDialog.dispose(); + } + } else if (e.getSource().equals(cancelButton)) { + jDialog.dispose(); } } + public boolean shouldContinueWithProcess() { + return continueWithProcess; + } + public static class DataReductionSubmission{ public final boolean normalizeMeasurementsBool; public final ArrayList arrayOfSimRois; @@ -176,7 +202,6 @@ public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList public static void main(String[] args) { DataReductionGUI dataReductionGUI = new DataReductionGUI(new ArrayList<>(), 0, 0, 0); - dataReductionGUI.displayGUI(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java index 62be394..6f1072f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java @@ -13,8 +13,9 @@ class RoiSelection extends JPanel { private final ROIDataModel imageTableModel = new ROIDataModel(); private final ROIDataModel simTableModel = new ROIDataModel(); + private final DataReductionGUI parentGUI; - public RoiSelection(){ + public RoiSelection(DataReductionGUI parentGUI){ this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); JList imageROITable = new JList<>(imageTableModel); @@ -25,6 +26,7 @@ public RoiSelection(){ JFileChooser simROIFileChooser = new JFileChooser(); this.add(createROIInput(simROITable, simTableModel, simROIFileChooser, "Sim")); this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "ROI Files")); + this.parentGUI = parentGUI; } private JPanel createROIInput(JList jList, ROIDataModel roiDataModel, @@ -43,6 +45,7 @@ public void actionPerformed(ActionEvent e) { for (Roi roi : roiList){ roiDataModel.addRow(roi); } + parentGUI.activateOkayButton(); jList.updateUI(); } }); @@ -53,6 +56,7 @@ public void actionPerformed(ActionEvent e) { for (int roiIndex: jList.getSelectedIndices()){ roiDataModel.removeRow(roiIndex); } + parentGUI.activateOkayButton(); jList.updateUI(); } }); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java index 019823f..1579f08 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java @@ -1,26 +1,38 @@ package org.vcell.N5.reduction; import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import java.awt.*; import java.util.ArrayList; -class SelectMeasurements extends JPanel{ +class SelectMeasurements extends JPanel implements ListSelectionListener { private final JList chosenMeasurement; private final MeasurementsDataModel measurementsDataModel = new MeasurementsDataModel(); + private final DataReductionGUI parentGUI; - public SelectMeasurements(){ + public SelectMeasurements(DataReductionGUI parentGUI){ setLayout(new GridLayout(1, 1)); this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Measurement Type")); chosenMeasurement = new JList<>(measurementsDataModel); chosenMeasurement.setVisibleRowCount(3); + chosenMeasurement.addListSelectionListener(this); JScrollPane jScrollPane = new JScrollPane(chosenMeasurement); this.add(jScrollPane); + this.parentGUI = parentGUI; } public ArrayList getChosenMeasurements(){ return measurementsDataModel.getSelectedMeasurements(chosenMeasurement.getSelectedIndices()); } + @Override + public void valueChanged(ListSelectionEvent e) { + if (e.getSource().equals(chosenMeasurement)){ + parentGUI.activateOkayButton(); + } + } + public enum AvailableMeasurements{ AVERAGE("Average"), STD_DEV("Standard Deviation"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 8f42bd5..838d7c7 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -38,15 +38,11 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o ArrayList dimensions = firstSim.getN5Dimensions(); if (dataReduction){ dataReductionGUI = new DataReductionGUI(filesToOpen, dimensions.get(2), dimensions.get(3), dimensions.get(4)); - DataReductionGUI.DataReductionSubmission submission = dataReductionGUI.displayGUI(); - if (submission != null){ - DataReductionWriter.createDataReductionProcess(submission); - } } else { rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); } } - boolean dataReductionOkay = dataReduction && dataReductionGUI.mainGUIReturnValue == JOptionPane.OK_OPTION && dataReductionGUI.fileChooserReturnValue == JFileChooser.APPROVE_OPTION; + boolean dataReductionOkay = dataReduction && dataReductionGUI.shouldContinueWithProcess(); if (dataReductionOkay || !dataReduction){ controlButtonsPanel.allowCancel(true); MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); From 585926d365d1da01e12e7e59b1980f846de9d8dd Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 15 Nov 2024 11:03:24 -0500 Subject: [PATCH 31/44] Implement New Button Context System --- .../java/org/vcell/N5/N5ImageHandler.java | 5 +- .../org/vcell/N5/UI/ControlButtonsPanel.java | 119 +++++++++++++----- .../java/org/vcell/N5/UI/N5ExportTable.java | 12 +- .../java/org/vcell/N5/UI/RangeSelector.java | 2 +- .../vcell/N5/reduction/DataReductionGUI.java | 5 +- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java index c62b6e4..09ef90e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/N5ImageHandler.java @@ -40,7 +40,7 @@ public void run() { initializeLogService(); loadingManager = new LoadingManager(); exportTable = new MainPanel(); - MainPanel.controlButtonsPanel.enableCriticalButtons(false); + MainPanel.controlButtonsPanel.setStateToInitializing(true); setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); Thread thread = new Thread(() -> { @@ -48,7 +48,8 @@ public void run() { // So create one upon initialization, while the user is focused on the GUI // and by the time they open an Image it's already loaded. SimResultsLoader.s3ClientBuilder = AmazonS3ClientBuilder.standard(); - MainPanel.controlButtonsPanel.enableCriticalButtons(true); + MainPanel.controlButtonsPanel.setStateToInitializing(false); + MainPanel.n5ExportTable.valueChanged(null); }); thread.start(); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java index e733783..ebbc9fb 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ControlButtonsPanel.java @@ -13,7 +13,12 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private static JButton openOrCancel; + private final String openButtonText = "Open Virtual Stack"; + private final String cancelButtonText = "Cancel"; + private final JButton dataReduction; + private final String runScriptButtonText = "Run Measurement Script"; + private final String cancelScriptButtonText = "Cancel Measurement Script"; // private final JButton openLocal = new JButton("Open N5 Local"); private final JButton questionMark; @@ -23,7 +28,7 @@ public class ControlButtonsPanel extends JPanel implements ActionListener { private N5ExportTable n5ExportTable; private RemoteFileSelection remoteFileSelection; public final AdvancedFeatures advancedFeatures = new AdvancedFeatures(); - private boolean allowButtons = true; + private PanelState panelState = PanelState.NOTHING_OR_LOADING_IMAGE; public ControlButtonsPanel(){ includeExampleExports = new JCheckBox("Show Example Exports"); @@ -32,7 +37,7 @@ public ControlButtonsPanel(){ displayAdvancedFeatures = new JCheckBox("Advanced Features"); openOrCancel = new JButton("Open Virtual Stack"); - dataReduction = new JButton("Run Measurement Script"); + dataReduction = new JButton(runScriptButtonText); questionMark = new JButton("?"); questionMark.setPreferredSize(new Dimension(20, 20)); @@ -64,10 +69,6 @@ public ControlButtonsPanel(){ // buttonsPanel.add(questionMark); - - - - int paneWidth = 800; this.setPreferredSize(new Dimension(paneWidth, 110)); this.setLayout(new BorderLayout()); @@ -104,14 +105,25 @@ public void initialize(N5ExportTable n5ExportTable, RemoteFileSelection remoteFi @Override public void actionPerformed(ActionEvent e) { boolean inMemory = e.getSource().equals(advancedFeatures.openInMemory); - boolean performDataReduction = e.getSource().equals(dataReduction); - if(e.getSource().equals(openOrCancel) || inMemory || performDataReduction){ - if (openOrCancel.getText().equals("Cancel")){ + if(e.getSource().equals(openOrCancel) || inMemory){ + panelState = PanelState.NOTHING_OR_LOADING_IMAGE; + if (openOrCancel.getText().equals(cancelButtonText)){ n5ExportTable.stopSelectedImageFromLoading(); + updateButtonsToMatchState(false); } else { - SimResultsLoader.OpenTag openTag = performDataReduction ? SimResultsLoader.OpenTag.DATA_REDUCTION : SimResultsLoader.OpenTag.VIEW; - n5ExportTable.openSelectedRows(inMemory, performDataReduction, openTag); + n5ExportTable.openSelectedRows(inMemory, false, SimResultsLoader.OpenTag.VIEW); + updateButtonsToMatchState(true); + } + } else if (e.getSource().equals(dataReduction)) { + if (dataReduction.getText().equals(cancelScriptButtonText)){ + panelState = PanelState.NOTHING_OR_LOADING_IMAGE; + N5ImageHandler.loadingManager.stopAllImagesAndAnalysis(); + } else{ + panelState = PanelState.PERFORMING_ANALYSIS; + setButtonsToCancelReduction(); + n5ExportTable.openSelectedRows(false, true, SimResultsLoader.OpenTag.DATA_REDUCTION); } + updateButtonsToMatchState(); } else if (e.getSource().equals(advancedFeatures.copyLink)) { n5ExportTable.copySelectedRowLink(); } else if (e.getSource().equals(questionMark)) { @@ -125,38 +137,79 @@ public void actionPerformed(ActionEvent e) { } } - public void allowCancel(boolean allow){ - if (allowButtons){ - openOrCancel.setEnabled(true); - advancedFeatures.copyLink.setEnabled(true); - advancedFeatures.useN5Link.setEnabled(true); - remoteFileSelection.submitS3Info.setEnabled(true); - dataReduction.setEnabled(!allow); - advancedFeatures.openInMemory.setEnabled(!allow); - if (allow){ - openOrCancel.setText("Cancel"); - } else { - openOrCancel.setText("Open Virtual Stack"); - } - } + public void updateButtonsToMatchState(){ + updateButtonsToMatchState(false); + } + + public void updateButtonsToMatchState(boolean rowIsLoadingImage){ + updateButtonsToMatchState(rowIsLoadingImage, panelState); } - public void enableRowContextDependentButtons(boolean enable){ - if (allowButtons){ - openOrCancel.setEnabled(enable); - advancedFeatures.copyLink.setEnabled(enable); - dataReduction.setEnabled(enable); - advancedFeatures.openInMemory.setEnabled(enable); + public void setStateToInitializing(boolean isInitializing){ + panelState = isInitializing ? PanelState.INITIALIZING : PanelState.NOTHING_OR_LOADING_IMAGE; + } + + public void updateButtonsToMatchState(boolean rowIsLoadingImage, PanelState newPanelState){ + switch (newPanelState){ + case NOTHING_OR_LOADING_IMAGE: + if (rowIsLoadingImage){ + allowCancel(); + } else { + enableAllButtons(true); + } + break; + case PERFORMING_ANALYSIS: + setButtonsToCancelReduction(); + break; + case INITIALIZING: + enableAllButtons(false); + break; } + panelState = newPanelState; + } + + public void setButtonsToCancelReduction(){ + openOrCancel.setText(openButtonText); + openOrCancel.setEnabled(false); + advancedFeatures.useN5Link.setEnabled(false); + advancedFeatures.openInMemory.setEnabled(false); + + advancedFeatures.copyLink.setEnabled(true); + dataReduction.setText(cancelScriptButtonText); + } + + private void allowCancel(){ + openOrCancel.setEnabled(true); + advancedFeatures.copyLink.setEnabled(true); + advancedFeatures.useN5Link.setEnabled(true); + remoteFileSelection.submitS3Info.setEnabled(true); + dataReduction.setEnabled(false); + advancedFeatures.openInMemory.setEnabled(false); + openOrCancel.setText(cancelButtonText); + } + + public void disableAllContextDependentButtons(){ + openOrCancel.setEnabled(false); + advancedFeatures.copyLink.setEnabled(false); + dataReduction.setEnabled(false); + advancedFeatures.openInMemory.setEnabled(false); } - public void enableCriticalButtons(boolean enable){ + public void enableAllButtons(boolean enable){ + openOrCancel.setText(openButtonText); + dataReduction.setText(runScriptButtonText); + advancedFeatures.useN5Link.setEnabled(enable); openOrCancel.setEnabled(enable); advancedFeatures.copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); dataReduction.setEnabled(enable); advancedFeatures.openInMemory.setEnabled(enable); - allowButtons = enable; + } + + public enum PanelState { + PERFORMING_ANALYSIS, + NOTHING_OR_LOADING_IMAGE, + INITIALIZING } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index 9202e9e..d10199b 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -195,30 +195,30 @@ public void valueChanged(ListSelectionEvent e) { int row = exportListTable.getSelectedRow(); exportDetailsPanel.resetExportDetails(); if (row > exportListTable.getRowCount() || row < 0){ - controlPanel.enableRowContextDependentButtons(false); + controlPanel.disableAllContextDependentButtons(); return; } - controlPanel.enableRowContextDependentButtons(true); MainPanel.setEnableParentAndChild(exportDetailsPanel, true); ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); exportDetailsPanel.addExportDetailEntries("Variables: " + rowData.variables, rowData.differentParameterValues); int loadingRow = loadingRowsJobID.containsKey(row) ? findLoadingRow(row, row) : -1; - controlPanel.allowCancel(loadingRow != -1); + controlPanel.updateButtonsToMatchState(loadingRow != -1); } public void stopSelectedImageFromLoading(){ int row = exportListTable.getSelectedRow(); - N5ImageHandler.loadingManager.stopOpeningSimulation(n5ExportTableModel.tableData.get(row).jobID); + N5ImageHandler.loadingManager.stopLoadingImage(n5ExportTableModel.tableData.get(row).jobID); loadingRowsJobID.remove(row); exportListTable.repaint(); } public void removeSpecificRowFromLoadingRows(int rowNumber){ + int realRowNumber = findLoadingRow(rowNumber, rowNumber); loadingRowsJobID.remove(rowNumber); int selected = exportListTable.getSelectedRow(); - if (selected == rowNumber){ - controlPanel.allowCancel(false); + if (selected == realRowNumber){ + controlPanel.updateButtonsToMatchState(false); exportListTable.repaint(); } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java index 4fc1ddd..8605a70 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/RangeSelector.java @@ -118,7 +118,7 @@ public void actionPerformed(ActionEvent e) { else if (e.getSource().equals(cancelButton)) { MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); + controlButtonsPanel.enableAllButtons(true); cancel = true; this.setVisible(false); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java index 6dd8265..6e4fa5b 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java @@ -3,6 +3,7 @@ import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; +import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.retrieving.SimResultsLoader; @@ -150,12 +151,12 @@ public void actionPerformed(ActionEvent e) { fileChooserReturnValue = saveToFile.showDialog(this, "Save Results To File"); if (fileChooserReturnValue == JFileChooser.APPROVE_OPTION){ chosenFile = saveToFile.getSelectedFile(); - MainPanel.controlButtonsPanel.enableCriticalButtons(false); - DataReductionWriter.createDataReductionProcess(createSubmission()); + MainPanel.controlButtonsPanel.updateButtonsToMatchState(); continueWithProcess = true; jDialog.dispose(); } } else if (e.getSource().equals(cancelButton)) { + MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); jDialog.dispose(); } } From 609cebe1f156a8775699f0558e8ff00385048f35 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 15 Nov 2024 11:04:49 -0500 Subject: [PATCH 32/44] Ability to Cancel Data Reduction Process --- .../N5/reduction/DataReductionWriter.java | 71 ++++++++++++++++--- .../N5/reduction/ReductionCalculations.java | 12 ++-- .../vcell/N5/retrieving/LoadingManager.java | 35 ++++++--- .../reduction/ReductionCalculationsTest.java | 3 +- 4 files changed, 97 insertions(+), 24 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 294612f..ec0fefa 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -1,11 +1,14 @@ package org.vcell.N5.reduction; +import com.amazonaws.AbortedException; import com.google.gson.internal.LinkedTreeMap; import com.opencsv.CSVWriter; import ij.ImagePlus; +import ij.WindowManager; import ij.gui.Roi; import org.vcell.N5.ExportDataRepresentation; import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.reduction.DTO.RangeOfImage; @@ -17,6 +20,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; public class DataReductionWriter implements SimLoadingListener { private final ArrayList arrayOfSimRois; @@ -34,6 +39,9 @@ public class DataReductionWriter implements SimLoadingListener { private final ArrayList> standardDivMatrix = new ArrayList<>(); private final ArrayList> metaDataSheet = new ArrayList<>(); + private final ConcurrentHashMap threadPool = new ConcurrentHashMap<>(); + private final Object threadPoolLock = new Object(); + private final HashMap>> sheetsAvailable = new HashMap>>(){{ put(SelectMeasurements.AvailableMeasurements.AVERAGE, averageMatrix); put(SelectMeasurements.AvailableMeasurements.STD_DEV, standardDivMatrix); @@ -61,10 +69,6 @@ public ReducedData(int rowLen, int colLen, SelectMeasurements.AvailableMeasureme // Initialize Sheet and Lab results // ///////////////////////////////////// - public static void createDataReductionProcess(DataReductionGUI.DataReductionSubmission submission){ - new DataReductionWriter(submission); - } - public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ N5ImageHandler.loadingManager.addSimLoadingListener(this); this.submission = submission; @@ -83,8 +87,15 @@ public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ Thread processLabResults = new Thread(() -> { calculateAndAddResults(submission.labResults, submission.experiementNormRange, submission.experimentImageRange, - submission.arrayOfLabRois, null); + submission.arrayOfLabRois, null, "Lab"); + synchronized (threadPoolLock){ + threadPool.remove("Lab"); + } }, "Processing Lab Image"); + ThreadStruct threadStruct = new ThreadStruct(null, new AtomicBoolean(true), processLabResults); + synchronized (threadPoolLock){ + threadPool.put("Lab", threadStruct); + } processLabResults.start(); } @@ -137,7 +148,8 @@ private void initializeDataSheets(){ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, RangeOfImage imageRange, ArrayList rois, - LinkedTreeMap> channelInfo){ + LinkedTreeMap> channelInfo, + String threadName){ HashMap normValue = null; if (submission.normalizeMeasurementsBool){ normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); @@ -153,9 +165,12 @@ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, reducedDataArrayList.add(reducedData); calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); } - calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange); + AtomicBoolean continueOperation = threadPool.get(threadName).continueOperation; + calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange, continueOperation); for (ReducedData reducedData: reducedDataArrayList){ - addValuesToCSVMatrix(reducedData); + if (continueOperation.get()){ + addValuesToCSVMatrix(reducedData); + } } } @@ -248,8 +263,26 @@ private void writeCSVMatrix(){ throw new RuntimeException(e); } finally { N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); - MainPanel.controlButtonsPanel.enableCriticalButtons(true); + MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); + } + } + + public void stopAllThreads(){ + synchronized (threadPoolLock){ + for (String threadName: threadPool.keySet()){ + ThreadStruct threadStruct = threadPool.get(threadName); + threadStruct.continueOperation.set(false); + // Experiment image is in thread pool, so trying to retrieve a results loader for it would not work + if (threadStruct.simResultsLoader != null){ + SimResultsLoader loadedResults = threadStruct.simResultsLoader; + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); + WindowManager.getImage(loadedResults.getImagePlus().getID()).close(); + } + threadPool.remove(threadName); + } } + N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); + MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); } @@ -266,14 +299,32 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { imagePlus.show(); addMetaData(loadedResults); calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, - submission.arrayOfSimRois, loadedResults.getChannelInfo()); + submission.arrayOfSimRois, loadedResults.getChannelInfo(), loadedResults.exportID); MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); imagePlus.close(); + synchronized (threadPoolLock){ + threadPool.remove(loadedResults.exportID); + } }, "Processing Image: " + loadedResults.userSetFileName); + ThreadStruct threadStruct = new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); + synchronized (threadPoolLock){ + threadPool.put(loadedResults.exportID, threadStruct); + } imageProcessingThread.start(); } } + static class ThreadStruct { + public final SimResultsLoader simResultsLoader; + public final AtomicBoolean continueOperation; + public final Thread thread; + public ThreadStruct(SimResultsLoader simResultsLoader, AtomicBoolean continueOperation, Thread thread){ + this.simResultsLoader = simResultsLoader; + this.continueOperation = continueOperation; + this.thread = thread; + } + } + } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index b553351..7924ad1 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.atomic.AtomicBoolean; class ReductionCalculations { private final boolean normalize; @@ -37,9 +38,9 @@ public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, R * @param rangeOfImage */ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, - HashMap normalizationValue, - ArrayList reducedDataArrayList, - RangeOfImage rangeOfImage){ + HashMap normalizationValue, + ArrayList reducedDataArrayList, + RangeOfImage rangeOfImage, AtomicBoolean continueOperation){ int roiCounter = 0; for (Roi roi: roiList) { imagePlus.setRoi(roi); @@ -48,6 +49,9 @@ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ int channelSize = rangeOfImage.channelEnd - rangeOfImage.channelStart + 1; + if (!continueOperation.get()){ + return; + } imagePlus.setPosition(c, z, t); double calculatedValue; for (DataReductionWriter.ReducedData reducedData : reducedDataArrayList){ @@ -61,7 +65,7 @@ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, default: throw new RuntimeException("Unknown measurement type selected."); } - if (normalize && reducedData.measurementType == SelectMeasurements.AvailableMeasurements.AVERAGE){ + if (normalize){ calculatedValue = calculatedValue / normalizationValue.get(roi.getName() + c); } reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = calculatedValue; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 838d7c7..52ec335 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -1,7 +1,6 @@ package org.vcell.N5.retrieving; import com.amazonaws.AbortedException; -import com.amazonaws.http.timers.client.SdkInterruptedException; import ij.ImagePlus; import org.scijava.log.Logger; import org.vcell.N5.N5ImageHandler; @@ -26,6 +25,7 @@ public class LoadingManager implements SimLoadingEventCreator { private final HashMap openingSimulations = new HashMap<>(); private final Object openSimulationsLock = new Object(); + private DataReductionWriter dataReductionWriter = null; private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); @@ -38,13 +38,13 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o ArrayList dimensions = firstSim.getN5Dimensions(); if (dataReduction){ dataReductionGUI = new DataReductionGUI(filesToOpen, dimensions.get(2), dimensions.get(3), dimensions.get(4)); + dataReductionWriter = dataReductionGUI.shouldContinueWithProcess() ? new DataReductionWriter(dataReductionGUI.createSubmission()) : null; } else { rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); } } boolean dataReductionOkay = dataReduction && dataReductionGUI.shouldContinueWithProcess(); if (dataReductionOkay || !dataReduction){ - controlButtonsPanel.allowCancel(true); MainPanel.changeCursor(new Cursor(Cursor.WAIT_CURSOR)); for (int i = 0; i < filesToOpen.size(); i++){ SimResultsLoader simResultsLoader = filesToOpen.get(i); @@ -64,6 +64,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } catch (RuntimeException e) { simResultsLoader.setTagToCanceled(); + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(simResultsLoader.rowNumber); if (e instanceof AbortedException){ logger.debug("Simulation stopped loading"); } else { @@ -75,8 +76,6 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o synchronized (openSimulationsLock){ openingSimulations.remove(simResultsLoader.exportID); } - controlButtonsPanel.enableRowContextDependentButtons(true); - MainPanel.controlButtonsPanel.allowCancel(false); } }); openThread.setName("Opening sim number: " + i + ". With id: " + simResultsLoader.exportID); @@ -88,18 +87,36 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o } } - public void stopOpeningSimulation(String exportID){ + public void stopAllImagesAndAnalysis(){ + Thread stopEverything = new Thread(() -> { + synchronized (openSimulationsLock){ + for (String threadName : openingSimulations.keySet()){ + openingSimulations.get(threadName).interrupt(); + openingSimulations.remove(threadName); + } + } + if (dataReductionWriter != null){ + dataReductionWriter.stopAllThreads(); + } + }); + stopEverything.start(); + } + + + public void stopLoadingImage(String exportID){ Thread stopOtherThread = new Thread(() -> { synchronized (openSimulationsLock){ - openingSimulations.get(exportID).interrupt(); - openingSimulations.remove(exportID); + if (openingSimulations.containsKey(exportID)){ + openingSimulations.get(exportID).interrupt(); + openingSimulations.remove(exportID); + } } }); stopOtherThread.start(); } public void openLocalN5FS(ArrayList filesToOpen){ - controlButtonsPanel.enableCriticalButtons(true); + controlButtonsPanel.enableAllButtons(true); JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setAcceptAllFileFilterUsed(false); @@ -121,7 +138,7 @@ public void openLocalN5FS(ArrayList filesToOpen){ @Override public void run() { MainPanel.changeCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - controlButtonsPanel.enableCriticalButtons(true); + controlButtonsPanel.enableAllButtons(true); } }); } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 9c183b1..556b72f 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -17,6 +17,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.atomic.AtomicBoolean; public class ReductionCalculationsTest { // First two are SimROI, last two are LabROI @@ -55,7 +56,7 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi reducedDataArrayList.add(reducedData); HashMap norms = reductionCalculations.calculateNormalValue(imagePlus, normRange, roiList, entireRange); - reductionCalculations.calculateStatistics(imagePlus, roiList, norms, reducedDataArrayList, entireRange); + reductionCalculations.calculateStatistics(imagePlus, roiList, norms, reducedDataArrayList, entireRange, new AtomicBoolean(true)); for (int r = 0; r < expectedResults.length; r++){ for (int c = 0; c < expectedResults[r].length; c++){ Assert.assertEquals(expectedResults[r][c], reducedData.data[r][c], 0.0009); From 1b4557daa67c26595716eacb9a99da5ff30e31a2 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 18 Nov 2024 10:42:54 -0500 Subject: [PATCH 33/44] Introduce Padding to Wide Table Export Allow uneven images to be exported and still retain their correct position within the data matrix. --- .../N5/reduction/DataReductionWriter.java | 107 +++++++++++++----- .../N5/reduction/ReductionCalculations.java | 2 +- .../reduction/ReductionCalculationsTest.java | 2 +- 3 files changed, 80 insertions(+), 31 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index ec0fefa..4279b5c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -1,6 +1,5 @@ package org.vcell.N5.reduction; -import com.amazonaws.AbortedException; import com.google.gson.internal.LinkedTreeMap; import com.opencsv.CSVWriter; import ij.ImagePlus; @@ -30,7 +29,7 @@ public class DataReductionWriter implements SimLoadingListener { private final Object metaDataLock = new Object(); private final File file; - private int numOfImagesToBeOpened; + private int numOfCalculationsTimesNumImages; private final ReductionCalculations calculations; public final DataReductionGUI.DataReductionSubmission submission; @@ -53,15 +52,24 @@ public class DataReductionWriter implements SimLoadingListener { private final ArrayList selectedMeasurements; + private int maxZ; + private int maxT; + // Per Image static class ReducedData{ public final double[][] data; public final ArrayList columnHeaders; public final SelectMeasurements.AvailableMeasurements measurementType; - public ReducedData(int rowLen, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ - data = new double[rowLen][colLen]; + public final RangeOfImage rangeOfImage; + public final int colLen; + public ReducedData(RangeOfImage rangeOfImage, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ + int nFrames = rangeOfImage.timeEnd - rangeOfImage.timeStart + 1; + int nSlices = rangeOfImage.zEnd - rangeOfImage.zStart + 1; + data = new double[nFrames * nSlices][colLen]; // row - col columnHeaders = new ArrayList<>(); this.measurementType = measurementType; + this.colLen = colLen; + this.rangeOfImage = rangeOfImage; } } @@ -73,13 +81,9 @@ public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ N5ImageHandler.loadingManager.addSimLoadingListener(this); this.submission = submission; this.selectedMeasurements = submission.selectedMeasurements; - synchronized (csvMatrixLock){ - synchronized (metaDataLock){ - initializeDataSheets(); - } - } + this.arrayOfSimRois = submission.arrayOfSimRois; - this.numOfImagesToBeOpened = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image + this.numOfCalculationsTimesNumImages = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image this.file = submission.fileToSaveResultsTo; this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); @@ -92,16 +96,15 @@ public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ threadPool.remove("Lab"); } }, "Processing Lab Image"); - ThreadStruct threadStruct = new ThreadStruct(null, new AtomicBoolean(true), processLabResults); + ThreadStruct threadStruct = new ThreadStruct(submission.labResults, new AtomicBoolean(true), processLabResults); synchronized (threadPoolLock){ threadPool.put("Lab", threadStruct); } - processLabResults.start(); } private void initializeDataSheets(){ ArrayList headers = new ArrayList(){{add("Time Frame");}}; - boolean is3D = submission.labResults.getNSlices() > 1; + boolean is3D = maxZ > 1; if (is3D){ headers.add("Z Index"); } @@ -129,8 +132,8 @@ private void initializeDataSheets(){ for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ ArrayList> dataSheet = sheetsAvailable.get(measurement); - for (int t = submission.experimentImageRange.timeStart; t <= submission.experimentImageRange.timeEnd; t++){ - for (int z = submission.experimentImageRange.zStart; z <= submission.experimentImageRange.zEnd; z++){ + for (int t = 1; t <= maxT; t++){ + for (int z = 1; z <= maxZ; z++){ ArrayList pointRow = new ArrayList<>(); pointRow.add(0, String.valueOf(t)); if (is3D){ @@ -155,13 +158,11 @@ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); } - int nFrames = imageRange.timeEnd - imageRange.timeStart + 1; - int nSlices = imageRange.zEnd - imageRange.zStart + 1; int nChannels = imageRange.channelEnd - imageRange.channelStart + 1; ArrayList reducedDataArrayList = new ArrayList<>(); for (SelectMeasurements.AvailableMeasurements measurement : submission.selectedMeasurements){ - ReducedData reducedData = new ReducedData(nFrames * nSlices, nChannels * arrayOfSimRois.size(), measurement); + ReducedData reducedData = new ReducedData(imageRange, nChannels * arrayOfSimRois.size(), measurement); reducedDataArrayList.add(reducedData); calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); } @@ -169,12 +170,12 @@ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange, continueOperation); for (ReducedData reducedData: reducedDataArrayList){ if (continueOperation.get()){ - addValuesToCSVMatrix(reducedData); + addValuesToWideCSVMatrix(reducedData); } } } - private void addValuesToCSVMatrix(ReducedData reducedData){ + private void addValuesToWideCSVMatrix(ReducedData reducedData){ synchronized (csvMatrixLock){ ArrayList> dataSheet = sheetsAvailable.get(reducedData.measurementType); int colIndex = columnsForSheets.get(reducedData.measurementType); @@ -182,18 +183,28 @@ private void addValuesToCSVMatrix(ReducedData reducedData){ for (int c = 0; c < reducedData.columnHeaders.size(); c++){ dataSheet.get(0).add(colIndex, reducedData.columnHeaders.get(c)); } - for (int i = 0; i < reducedData.data.length; i++){ - for (int c = 0; c < reducedData.data[i].length; c++){ - ArrayList row = dataSheet.get(i + 1); + RangeOfImage rangeOfImage = reducedData.rangeOfImage; + int tzCounter = 1; + for (int t = 1; t <= maxT; t++){ + for (int z = 1; z <= maxZ; z++){ + boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; + boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; + ArrayList row = dataSheet.get(tzCounter); fillWithEmptySpace(row, colIndex); - double mean = reducedData.data[i][c]; - row.add(String.valueOf(mean)); + for (int c = 0; c < reducedData.colLen; c++){ + if (inBetweenTime && inBetweenZ){ + int dataRow = ((t - rangeOfImage.timeStart) * (z - rangeOfImage.zStart)) + (z - rangeOfImage.zStart); + double mean = reducedData.data[dataRow][c]; + row.add(String.valueOf(mean)); + } + } + tzCounter += 1; } } - numOfImagesToBeOpened -= 1; + numOfCalculationsTimesNumImages -= 1; colIndex += 1 + reducedData.data[0].length; columnsForSheets.replace(reducedData.measurementType, colIndex); - if (numOfImagesToBeOpened == 0){ + if (numOfCalculationsTimesNumImages == 0){ writeCSVMatrix(); } } @@ -237,6 +248,19 @@ private void fillWithEmptySpace(ArrayList arrayList, int col){ } } +// // Z changes the fastest +// private ArrayList> fillWithEmptySpace(ReducedData reducedData){ +// int t = 1; +// int z = 1; +// ArrayList> paddedInfo = new ArrayList<>(); +// while (reducedData.numFrames != t){ +// while (reducedData.numSlices != z){ +// +// } +// t += 1; +// } +// } + private void writeCSVMatrix(){ try { @@ -276,7 +300,10 @@ public void stopAllThreads(){ if (threadStruct.simResultsLoader != null){ SimResultsLoader loadedResults = threadStruct.simResultsLoader; MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); - WindowManager.getImage(loadedResults.getImagePlus().getID()).close(); + ImagePlus openImage = WindowManager.getImage(loadedResults.getImagePlus().getID()); + if (openImage != null){ + openImage.close(); + } } threadPool.remove(threadName); } @@ -309,19 +336,41 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { ThreadStruct threadStruct = new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); synchronized (threadPoolLock){ threadPool.put(loadedResults.exportID, threadStruct); + if (threadPool.size() == (submission.numOfSimImages + 1)){ + maxZ = 0; + maxT = 0; + for (String threadName : threadPool.keySet()){ + int curZ = threadPool.get(threadName).imagePlus.getNSlices(); + int curT = threadPool.get(threadName).imagePlus.getNFrames(); + maxZ = Math.max(curZ, maxZ); + maxT = Math.max(curT, maxT); + } + initializeDataSheets(); + for (String threadName : threadPool.keySet()){ + threadPool.get(threadName).thread.start(); + } + } } - imageProcessingThread.start(); } } static class ThreadStruct { public final SimResultsLoader simResultsLoader; + public final ImagePlus imagePlus; public final AtomicBoolean continueOperation; public final Thread thread; public ThreadStruct(SimResultsLoader simResultsLoader, AtomicBoolean continueOperation, Thread thread){ this.simResultsLoader = simResultsLoader; this.continueOperation = continueOperation; this.thread = thread; + this.imagePlus = simResultsLoader.getImagePlus(); + } + + public ThreadStruct(ImagePlus imagePlus, AtomicBoolean continueOperation, Thread thread){ + this.imagePlus = imagePlus; + this.simResultsLoader = null; + this.continueOperation = continueOperation; + this.thread = thread; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index 7924ad1..dd6e57d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -23,7 +23,7 @@ public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, R for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable String stringC = String.valueOf(c - 1); String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); - reducedData.columnHeaders.add(imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + reducedData.columnHeaders.add(0, imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); } } } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 556b72f..68c4fbf 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -49,9 +49,9 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi boolean normalizeMeasurementsBool){ ReductionCalculations reductionCalculations = new ReductionCalculations(normalizeMeasurementsBool); - DataReductionWriter.ReducedData reducedData = new DataReductionWriter.ReducedData(imagePlus.getNFrames() * imagePlus.getNSlices(), imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); RangeOfImage entireRange = new RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), 1, imagePlus.getNChannels()); RangeOfImage normRange = new RangeOfImage(1, 1); + DataReductionWriter.ReducedData reducedData = new DataReductionWriter.ReducedData(entireRange, imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); ArrayList reducedDataArrayList = new ArrayList<>(); reducedDataArrayList.add(reducedData); From 62bbb617226d5bb1f06a4ebc0ef389192a588ab7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 18 Nov 2024 13:00:51 -0500 Subject: [PATCH 34/44] Refactor Data Reduction Manager into It's Own Class --- .../N5/reduction/DataReductionManager.java | 200 +++++++++++++ .../N5/reduction/DataReductionWriter.java | 278 +++--------------- .../N5/reduction/ReductionCalculations.java | 7 +- .../vcell/N5/retrieving/LoadingManager.java | 5 +- .../reduction/ReductionCalculationsTest.java | 5 +- 5 files changed, 255 insertions(+), 240 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java new file mode 100644 index 0000000..70385e6 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java @@ -0,0 +1,200 @@ +package org.vcell.N5.reduction; + +import com.google.gson.internal.LinkedTreeMap; +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.Roi; +import org.vcell.N5.N5ImageHandler; +import org.vcell.N5.UI.ControlButtonsPanel; +import org.vcell.N5.UI.MainPanel; +import org.vcell.N5.reduction.DTO.RangeOfImage; +import org.vcell.N5.retrieving.SimLoadingListener; +import org.vcell.N5.retrieving.SimResultsLoader; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +public class DataReductionManager implements SimLoadingListener { + private final ArrayList arrayOfSimRois; + private final Object csvMatrixLock = new Object(); + + private int numOfCalculationsTimesNumImages; + private final ReductionCalculations calculations; + + public final DataReductionGUI.DataReductionSubmission submission; + + private final ConcurrentHashMap threadPool = new ConcurrentHashMap<>(); + private final Object threadPoolLock = new Object(); + + private DataReductionWriter dataReductionWriter; + + + // Per Image + public static class ReducedData{ + public final double[][] data; + public final ArrayList columnHeaders; + public final SelectMeasurements.AvailableMeasurements measurementType; + public final RangeOfImage rangeOfImage; + public final int colLen; + public ReducedData(RangeOfImage rangeOfImage, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ + int nFrames = rangeOfImage.timeEnd - rangeOfImage.timeStart + 1; + int nSlices = rangeOfImage.zEnd - rangeOfImage.zStart + 1; + data = new double[nFrames * nSlices][colLen]; // row - col + columnHeaders = new ArrayList<>(); + this.measurementType = measurementType; + this.colLen = colLen; + this.rangeOfImage = rangeOfImage; + } + } + + public DataReductionManager(DataReductionGUI.DataReductionSubmission submission){ + N5ImageHandler.loadingManager.addSimLoadingListener(this); + this.submission = submission; + + this.arrayOfSimRois = submission.arrayOfSimRois; + this.numOfCalculationsTimesNumImages = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image + this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); + + Thread processLabResults = new Thread(() -> { + calculateAndAddResults(submission.labResults, submission.experiementNormRange, submission.experimentImageRange, + submission.arrayOfLabRois, null, "Lab"); + synchronized (threadPoolLock){ + threadPool.remove("Lab"); + } + }, "Processing Lab Image"); + ThreadStruct threadStruct = new ThreadStruct(submission.labResults, new AtomicBoolean(true), processLabResults); + synchronized (threadPoolLock){ + threadPool.put("Lab", threadStruct); + } + } + + //////////////////////// + // General Functions // + ////////////////////// + + private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, + RangeOfImage imageRange, ArrayList rois, + LinkedTreeMap> channelInfo, + String threadName){ + HashMap normValue = null; + if (submission.normalizeMeasurementsBool){ + normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); + } + + int nChannels = imageRange.channelEnd - imageRange.channelStart + 1; + + ArrayList reducedDataArrayList = new ArrayList<>(); + for (SelectMeasurements.AvailableMeasurements measurement : submission.selectedMeasurements){ + ReducedData reducedData = new ReducedData(imageRange, nChannels * arrayOfSimRois.size(), measurement); + reducedDataArrayList.add(reducedData); + calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); + } + AtomicBoolean continueOperation = threadPool.get(threadName).continueOperation; + calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange, continueOperation); + for (ReducedData reducedData: reducedDataArrayList){ + if (continueOperation.get()){ + synchronized (csvMatrixLock){ + dataReductionWriter.addValuesToWideCSVMatrix(reducedData); + numOfCalculationsTimesNumImages -= 1; + } + } + } + if (numOfCalculationsTimesNumImages == 0){ + try{ + dataReductionWriter.writeCSVMatrix(); + } catch (IOException ioException){ + throw new RuntimeException(ioException); + } finally { + N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); + MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); + } + } + } + + public void stopAllThreads(){ + synchronized (threadPoolLock){ + for (String threadName: threadPool.keySet()){ + ThreadStruct threadStruct = threadPool.get(threadName); + threadStruct.continueOperation.set(false); + // Experiment image is in thread pool, so trying to retrieve a results loader for it would not work + if (threadStruct.simResultsLoader != null){ + SimResultsLoader loadedResults = threadStruct.simResultsLoader; + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); + ImagePlus openImage = WindowManager.getImage(loadedResults.getImagePlus().getID()); + if (openImage != null){ + openImage.close(); + } + } + threadPool.remove(threadName); + } + } + N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); + MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); + } + + + @Override + public void simIsLoading(int itemRow, String exportID) { + + } + + @Override + public void simFinishedLoading(SimResultsLoader loadedResults) { + if (loadedResults.openTag == SimResultsLoader.OpenTag.DATA_REDUCTION){ + Thread imageProcessingThread = new Thread(() -> { + ImagePlus imagePlus = loadedResults.getImagePlus(); + imagePlus.show(); + dataReductionWriter.addMetaData(loadedResults); + calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, + submission.arrayOfSimRois, loadedResults.getChannelInfo(), loadedResults.exportID); + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); + imagePlus.close(); + synchronized (threadPoolLock){ + threadPool.remove(loadedResults.exportID); + } + }, "Processing Image: " + loadedResults.userSetFileName); + ThreadStruct threadStruct = new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); + synchronized (threadPoolLock){ + threadPool.put(loadedResults.exportID, threadStruct); + if (threadPool.size() == (submission.numOfSimImages + 1)){ + int maxZ = 0; + int maxT = 0; + for (String threadName : threadPool.keySet()){ + int curZ = threadPool.get(threadName).imagePlus.getNSlices(); + int curT = threadPool.get(threadName).imagePlus.getNFrames(); + maxZ = Math.max(curZ, maxZ); + maxT = Math.max(curT, maxT); + } + dataReductionWriter = new DataReductionWriter(submission, maxT, maxZ); + dataReductionWriter.initializeDataSheets(); + for (String threadName : threadPool.keySet()){ + threadPool.get(threadName).thread.start(); + } + } + } + } + } + + static class ThreadStruct { + public final SimResultsLoader simResultsLoader; + public final ImagePlus imagePlus; + public final AtomicBoolean continueOperation; + public final Thread thread; + public ThreadStruct(SimResultsLoader simResultsLoader, AtomicBoolean continueOperation, Thread thread){ + this.simResultsLoader = simResultsLoader; + this.continueOperation = continueOperation; + this.thread = thread; + this.imagePlus = simResultsLoader.getImagePlus(); + } + + public ThreadStruct(ImagePlus imagePlus, AtomicBoolean continueOperation, Thread thread){ + this.imagePlus = imagePlus; + this.simResultsLoader = null; + this.continueOperation = continueOperation; + this.thread = thread; + } + } +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 4279b5c..1d92edb 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -1,17 +1,11 @@ package org.vcell.N5.reduction; -import com.google.gson.internal.LinkedTreeMap; import com.opencsv.CSVWriter; -import ij.ImagePlus; -import ij.WindowManager; -import ij.gui.Roi; import org.vcell.N5.ExportDataRepresentation; -import org.vcell.N5.N5ImageHandler; -import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.reduction.DTO.RangeOfImage; -import org.vcell.N5.retrieving.SimLoadingListener; +import org.vcell.N5.reduction.DataReductionManager.ReducedData; import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; @@ -19,27 +13,17 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -public class DataReductionWriter implements SimLoadingListener { - private final ArrayList arrayOfSimRois; - - private final Object csvMatrixLock = new Object(); +public class DataReductionWriter{ private final Object metaDataLock = new Object(); private final File file; - private int numOfCalculationsTimesNumImages; - private final ReductionCalculations calculations; - public final DataReductionGUI.DataReductionSubmission submission; private final ArrayList> averageMatrix = new ArrayList<>(); private final ArrayList> standardDivMatrix = new ArrayList<>(); private final ArrayList> metaDataSheet = new ArrayList<>(); - private final ConcurrentHashMap threadPool = new ConcurrentHashMap<>(); - private final Object threadPoolLock = new Object(); private final HashMap>> sheetsAvailable = new HashMap>>(){{ put(SelectMeasurements.AvailableMeasurements.AVERAGE, averageMatrix); @@ -52,57 +36,22 @@ public class DataReductionWriter implements SimLoadingListener { private final ArrayList selectedMeasurements; - private int maxZ; - private int maxT; - - // Per Image - static class ReducedData{ - public final double[][] data; - public final ArrayList columnHeaders; - public final SelectMeasurements.AvailableMeasurements measurementType; - public final RangeOfImage rangeOfImage; - public final int colLen; - public ReducedData(RangeOfImage rangeOfImage, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ - int nFrames = rangeOfImage.timeEnd - rangeOfImage.timeStart + 1; - int nSlices = rangeOfImage.zEnd - rangeOfImage.zStart + 1; - data = new double[nFrames * nSlices][colLen]; // row - col - columnHeaders = new ArrayList<>(); - this.measurementType = measurementType; - this.colLen = colLen; - this.rangeOfImage = rangeOfImage; - } - } + private final int maxZ; + private final int maxT; /////////////////////////////////////// // Initialize Sheet and Lab results // ///////////////////////////////////// - public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission){ - N5ImageHandler.loadingManager.addSimLoadingListener(this); + public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission, int maxT, int maxZ){ this.submission = submission; this.selectedMeasurements = submission.selectedMeasurements; - - this.arrayOfSimRois = submission.arrayOfSimRois; - this.numOfCalculationsTimesNumImages = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image this.file = submission.fileToSaveResultsTo; - this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); - - - - Thread processLabResults = new Thread(() -> { - calculateAndAddResults(submission.labResults, submission.experiementNormRange, submission.experimentImageRange, - submission.arrayOfLabRois, null, "Lab"); - synchronized (threadPoolLock){ - threadPool.remove("Lab"); - } - }, "Processing Lab Image"); - ThreadStruct threadStruct = new ThreadStruct(submission.labResults, new AtomicBoolean(true), processLabResults); - synchronized (threadPoolLock){ - threadPool.put("Lab", threadStruct); - } + this.maxZ = maxZ; + this.maxT = maxT; } - private void initializeDataSheets(){ + public void initializeDataSheets(){ ArrayList headers = new ArrayList(){{add("Time Frame");}}; boolean is3D = maxZ > 1; if (is3D){ @@ -149,69 +98,37 @@ private void initializeDataSheets(){ // General Functions // ////////////////////// - private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, - RangeOfImage imageRange, ArrayList rois, - LinkedTreeMap> channelInfo, - String threadName){ - HashMap normValue = null; - if (submission.normalizeMeasurementsBool){ - normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); - } - - int nChannels = imageRange.channelEnd - imageRange.channelStart + 1; - - ArrayList reducedDataArrayList = new ArrayList<>(); - for (SelectMeasurements.AvailableMeasurements measurement : submission.selectedMeasurements){ - ReducedData reducedData = new ReducedData(imageRange, nChannels * arrayOfSimRois.size(), measurement); - reducedDataArrayList.add(reducedData); - calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); - } - AtomicBoolean continueOperation = threadPool.get(threadName).continueOperation; - calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange, continueOperation); - for (ReducedData reducedData: reducedDataArrayList){ - if (continueOperation.get()){ - addValuesToWideCSVMatrix(reducedData); - } - } - } - - private void addValuesToWideCSVMatrix(ReducedData reducedData){ - synchronized (csvMatrixLock){ - ArrayList> dataSheet = sheetsAvailable.get(reducedData.measurementType); - int colIndex = columnsForSheets.get(reducedData.measurementType); - fillWithEmptySpace(dataSheet.get(0), colIndex); - for (int c = 0; c < reducedData.columnHeaders.size(); c++){ - dataSheet.get(0).add(colIndex, reducedData.columnHeaders.get(c)); - } - RangeOfImage rangeOfImage = reducedData.rangeOfImage; - int tzCounter = 1; - for (int t = 1; t <= maxT; t++){ - for (int z = 1; z <= maxZ; z++){ - boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; - boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; - ArrayList row = dataSheet.get(tzCounter); - fillWithEmptySpace(row, colIndex); - for (int c = 0; c < reducedData.colLen; c++){ - if (inBetweenTime && inBetweenZ){ - int dataRow = ((t - rangeOfImage.timeStart) * (z - rangeOfImage.zStart)) + (z - rangeOfImage.zStart); - double mean = reducedData.data[dataRow][c]; - row.add(String.valueOf(mean)); - } + public void addValuesToWideCSVMatrix(ReducedData reducedData){ + ArrayList> dataSheet = sheetsAvailable.get(reducedData.measurementType); + int colIndex = columnsForSheets.get(reducedData.measurementType); + fillWithEmptySpace(dataSheet.get(0), colIndex); + for (int c = 0; c < reducedData.columnHeaders.size(); c++){ + dataSheet.get(0).add(colIndex, reducedData.columnHeaders.get(c)); + } + RangeOfImage rangeOfImage = reducedData.rangeOfImage; + int tzCounter = 1; + for (int t = 1; t <= maxT; t++){ + for (int z = 1; z <= maxZ; z++){ + boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; + boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; + ArrayList row = dataSheet.get(tzCounter); + fillWithEmptySpace(row, colIndex); + for (int c = 0; c < reducedData.colLen; c++){ + if (inBetweenTime && inBetweenZ){ + int dataRow = ((t - rangeOfImage.timeStart) * (z - rangeOfImage.zStart)) + (z - rangeOfImage.zStart); + double mean = reducedData.data[dataRow][c]; + row.add(String.valueOf(mean)); } - tzCounter += 1; } - } - numOfCalculationsTimesNumImages -= 1; - colIndex += 1 + reducedData.data[0].length; - columnsForSheets.replace(reducedData.measurementType, colIndex); - if (numOfCalculationsTimesNumImages == 0){ - writeCSVMatrix(); + tzCounter += 1; } } + colIndex += 1 + reducedData.data[0].length; + columnsForSheets.replace(reducedData.measurementType, colIndex); } // If parameter is not in list of parameters, add new column. If simulation does not have parameter say "not-present" - private void addMetaData(SimResultsLoader loadedResults){ + public void addMetaData(SimResultsLoader loadedResults){ synchronized (metaDataLock){ N5ExportTable n5ExportTable = MainPanel.n5ExportTable; ExportDataRepresentation.SimulationExportDataRepresentation data = n5ExportTable.n5ExportTableModel.getRowData(loadedResults.rowNumber); @@ -248,132 +165,27 @@ private void fillWithEmptySpace(ArrayList arrayList, int col){ } } -// // Z changes the fastest -// private ArrayList> fillWithEmptySpace(ReducedData reducedData){ -// int t = 1; -// int z = 1; -// ArrayList> paddedInfo = new ArrayList<>(); -// while (reducedData.numFrames != t){ -// while (reducedData.numSlices != z){ -// -// } -// t += 1; -// } -// } - - private void writeCSVMatrix(){ - try { - for (SelectMeasurements.AvailableMeasurements measurements : sheetsAvailable.keySet()){ - if (!sheetsAvailable.get(measurements).isEmpty()){ - File currentFile = new File(file.getAbsolutePath() + "-" + measurements.publicName + ".csv"); - try (FileWriter fileWriter = new FileWriter(currentFile)){ - CSVWriter csvWriter = new CSVWriter(fileWriter); - for (ArrayList row : sheetsAvailable.get(measurements)){ - csvWriter.writeNext(row.toArray(new String[0])); - } + public void writeCSVMatrix() throws IOException { + for (SelectMeasurements.AvailableMeasurements measurements : sheetsAvailable.keySet()){ + if (!sheetsAvailable.get(measurements).isEmpty()){ + File currentFile = new File(file.getAbsolutePath() + "-" + measurements.publicName + ".csv"); + try (FileWriter fileWriter = new FileWriter(currentFile)){ + CSVWriter csvWriter = new CSVWriter(fileWriter); + for (ArrayList row : sheetsAvailable.get(measurements)){ + csvWriter.writeNext(row.toArray(new String[0])); } } } - File currentFile = new File(file.getAbsolutePath() + "-Metadata.csv"); - try (FileWriter fileWriter = new FileWriter(currentFile)){ - CSVWriter csvWriter = new CSVWriter(fileWriter); - for (ArrayList row : metaDataSheet){ - csvWriter.writeNext(row.toArray(new String[0])); - } - } - - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); - MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); - } - } - - public void stopAllThreads(){ - synchronized (threadPoolLock){ - for (String threadName: threadPool.keySet()){ - ThreadStruct threadStruct = threadPool.get(threadName); - threadStruct.continueOperation.set(false); - // Experiment image is in thread pool, so trying to retrieve a results loader for it would not work - if (threadStruct.simResultsLoader != null){ - SimResultsLoader loadedResults = threadStruct.simResultsLoader; - MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); - ImagePlus openImage = WindowManager.getImage(loadedResults.getImagePlus().getID()); - if (openImage != null){ - openImage.close(); - } - } - threadPool.remove(threadName); - } } - N5ImageHandler.loadingManager.removeFromSimLoadingListener(this); - MainPanel.controlButtonsPanel.updateButtonsToMatchState(false, ControlButtonsPanel.PanelState.NOTHING_OR_LOADING_IMAGE); - } - - - @Override - public void simIsLoading(int itemRow, String exportID) { - - } - - @Override - public void simFinishedLoading(SimResultsLoader loadedResults) { - if (loadedResults.openTag == SimResultsLoader.OpenTag.DATA_REDUCTION){ - Thread imageProcessingThread = new Thread(() -> { - ImagePlus imagePlus = loadedResults.getImagePlus(); - imagePlus.show(); - addMetaData(loadedResults); - calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, - submission.arrayOfSimRois, loadedResults.getChannelInfo(), loadedResults.exportID); - MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); - imagePlus.close(); - synchronized (threadPoolLock){ - threadPool.remove(loadedResults.exportID); - } - }, "Processing Image: " + loadedResults.userSetFileName); - ThreadStruct threadStruct = new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); - synchronized (threadPoolLock){ - threadPool.put(loadedResults.exportID, threadStruct); - if (threadPool.size() == (submission.numOfSimImages + 1)){ - maxZ = 0; - maxT = 0; - for (String threadName : threadPool.keySet()){ - int curZ = threadPool.get(threadName).imagePlus.getNSlices(); - int curT = threadPool.get(threadName).imagePlus.getNFrames(); - maxZ = Math.max(curZ, maxZ); - maxT = Math.max(curT, maxT); - } - initializeDataSheets(); - for (String threadName : threadPool.keySet()){ - threadPool.get(threadName).thread.start(); - } - } + File currentFile = new File(file.getAbsolutePath() + "-Metadata.csv"); + try (FileWriter fileWriter = new FileWriter(currentFile)){ + CSVWriter csvWriter = new CSVWriter(fileWriter); + for (ArrayList row : metaDataSheet){ + csvWriter.writeNext(row.toArray(new String[0])); } } } - - static class ThreadStruct { - public final SimResultsLoader simResultsLoader; - public final ImagePlus imagePlus; - public final AtomicBoolean continueOperation; - public final Thread thread; - public ThreadStruct(SimResultsLoader simResultsLoader, AtomicBoolean continueOperation, Thread thread){ - this.simResultsLoader = simResultsLoader; - this.continueOperation = continueOperation; - this.thread = thread; - this.imagePlus = simResultsLoader.getImagePlus(); - } - - public ThreadStruct(ImagePlus imagePlus, AtomicBoolean continueOperation, Thread thread){ - this.imagePlus = imagePlus; - this.simResultsLoader = null; - this.continueOperation = continueOperation; - this.thread = thread; - } - } - } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index dd6e57d..5b66008 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -4,6 +4,7 @@ import ij.ImagePlus; import ij.gui.Roi; import org.vcell.N5.reduction.DTO.RangeOfImage; +import org.vcell.N5.reduction.DataReductionManager.ReducedData; import java.util.ArrayList; import java.util.HashMap; @@ -17,7 +18,7 @@ public ReductionCalculations(boolean normalize){ } public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, RangeOfImage rangeOfImage, - DataReductionWriter.ReducedData reducedData, + ReducedData reducedData, LinkedTreeMap> channelInfo){ for (Roi roi: roiList){ for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable @@ -39,7 +40,7 @@ public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, R */ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, HashMap normalizationValue, - ArrayList reducedDataArrayList, + ArrayList reducedDataArrayList, RangeOfImage rangeOfImage, AtomicBoolean continueOperation){ int roiCounter = 0; for (Roi roi: roiList) { @@ -54,7 +55,7 @@ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, } imagePlus.setPosition(c, z, t); double calculatedValue; - for (DataReductionWriter.ReducedData reducedData : reducedDataArrayList){ + for (ReducedData reducedData : reducedDataArrayList){ switch (reducedData.measurementType){ case AVERAGE: calculatedValue = imagePlus.getStatistics().mean; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 52ec335..6ee6990 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -8,6 +8,7 @@ import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.reduction.DataReductionGUI; +import org.vcell.N5.reduction.DataReductionManager; import org.vcell.N5.reduction.DataReductionWriter; import javax.swing.*; @@ -25,7 +26,7 @@ public class LoadingManager implements SimLoadingEventCreator { private final HashMap openingSimulations = new HashMap<>(); private final Object openSimulationsLock = new Object(); - private DataReductionWriter dataReductionWriter = null; + private DataReductionManager dataReductionWriter = null; private static final Logger logger = N5ImageHandler.getLogger(RangeSelector.class); @@ -38,7 +39,7 @@ public void openN5FileDataset(ArrayList filesToOpen, boolean o ArrayList dimensions = firstSim.getN5Dimensions(); if (dataReduction){ dataReductionGUI = new DataReductionGUI(filesToOpen, dimensions.get(2), dimensions.get(3), dimensions.get(4)); - dataReductionWriter = dataReductionGUI.shouldContinueWithProcess() ? new DataReductionWriter(dataReductionGUI.createSubmission()) : null; + dataReductionWriter = dataReductionGUI.shouldContinueWithProcess() ? new DataReductionManager(dataReductionGUI.createSubmission()) : null; } else { rangeSelector.displayRangeMenu(dimensions.get(2), dimensions.get(3), dimensions.get(4)); } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 68c4fbf..6c1ff2f 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -11,6 +11,7 @@ import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; +import org.vcell.N5.reduction.DataReductionManager.ReducedData; import java.io.File; import java.net.URISyntaxException; @@ -51,8 +52,8 @@ private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roi RangeOfImage entireRange = new RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), 1, imagePlus.getNChannels()); RangeOfImage normRange = new RangeOfImage(1, 1); - DataReductionWriter.ReducedData reducedData = new DataReductionWriter.ReducedData(entireRange, imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - ArrayList reducedDataArrayList = new ArrayList<>(); + ReducedData reducedData = new ReducedData(entireRange, imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); + ArrayList reducedDataArrayList = new ArrayList<>(); reducedDataArrayList.add(reducedData); HashMap norms = reductionCalculations.calculateNormalValue(imagePlus, normRange, roiList, entireRange); From 0ebb4ec572a91261ccd6b8a8e4d644948ad1027a Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 20 Nov 2024 11:15:05 -0500 Subject: [PATCH 35/44] Add Tall Table Writer and Implement Opinionated Data Retrieval Have a writer function which allows for tall tables, and make data retrieval from reduced data be through an opinionated method. --- .../vcell/N5/reduction/DTO/RangeOfImage.java | 12 ++ .../vcell/N5/reduction/DTO/ReducedData.java | 47 ++++++ .../N5/reduction/DataReductionManager.java | 52 ++---- .../N5/reduction/DataReductionWriter.java | 156 ++++++++++++------ .../N5/reduction/ReductionCalculations.java | 33 ++-- .../org/vcell/N5/reduction/RoiSelection.java | 2 +- .../N5/reduction/SelectMeasurements.java | 2 +- .../reduction/ReductionCalculationsTest.java | 32 ++-- 8 files changed, 221 insertions(+), 115 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java index 1613c24..fe23c90 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/RangeOfImage.java @@ -17,6 +17,18 @@ public RangeOfImage(int timeStart, int timeEnd, int zStart, int zEnd, int channe this.channelEnd = channelEnd; } + public int getNChannels(){ + return this.channelEnd - this.channelStart + 1; + } + + public int getNFrames(){ + return this.timeEnd - this.timeStart + 1; + } + + public int getNSlices(){ + return this.zEnd - this.zStart + 1; + } + /** * Only regards time for range, and is used for normalization. * @param timeStart diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java new file mode 100644 index 0000000..42466d8 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java @@ -0,0 +1,47 @@ +package org.vcell.N5.reduction.DTO; + +import org.vcell.N5.reduction.SelectMeasurements; + +import java.util.ArrayList; +import java.util.HashMap; + +// Per Image, contain all ROI data +// Shape: [time * z][channel * roi] +public class ReducedData { + private final int nChannels; + private final int nSlices; + private final HashMap dataMap = new HashMap<>(); + + public final ArrayList measurements; + public final RangeOfImage rangeOfImage; + public final int nROIs; + public final HashMap roiNames = new HashMap<>(); + public final HashMap channelNames = new HashMap<>(); + public final String imageName; + public ReducedData(String imageName, RangeOfImage rangeOfImage, int nROIs, ArrayList measurements){ + int nFrames = rangeOfImage.timeEnd - rangeOfImage.timeStart + 1; + nSlices = rangeOfImage.zEnd - rangeOfImage.zStart + 1; + this.measurements = measurements; + this.nChannels = rangeOfImage.getNChannels(); + this.nROIs = nROIs; + this.rangeOfImage = rangeOfImage; + this.imageName = imageName; + + for (SelectMeasurements.AvailableMeasurements measurement: measurements){ + dataMap.put(measurement, new double[nFrames * nSlices][nChannels * nROIs]); + } + } + + public void putDataPoint(double data,int time, int z, int channel, int roi, SelectMeasurements.AvailableMeasurements measurementType){ + dataMap.get(measurementType)[(time * nSlices) + z][(roi * nChannels) + channel] = data; + } + + public double getDataPoint(int time, int z, int channel, int roi, SelectMeasurements.AvailableMeasurements measurementType){ + return dataMap.get(measurementType)[(time * nSlices) + z][(roi * nChannels) + channel]; + } + + public String getWideTableHeader(int r, int c){ + return imageName + ":" + roiNames.get(r) + ":" + channelNames.get(c); + } + +} diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java index 70385e6..656d744 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java @@ -8,6 +8,7 @@ import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.MainPanel; import org.vcell.N5.reduction.DTO.RangeOfImage; +import org.vcell.N5.reduction.DTO.ReducedData; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; @@ -21,7 +22,7 @@ public class DataReductionManager implements SimLoadingListener { private final ArrayList arrayOfSimRois; private final Object csvMatrixLock = new Object(); - private int numOfCalculationsTimesNumImages; + private int numOfImagesToOpen; private final ReductionCalculations calculations; public final DataReductionGUI.DataReductionSubmission submission; @@ -31,31 +32,12 @@ public class DataReductionManager implements SimLoadingListener { private DataReductionWriter dataReductionWriter; - - // Per Image - public static class ReducedData{ - public final double[][] data; - public final ArrayList columnHeaders; - public final SelectMeasurements.AvailableMeasurements measurementType; - public final RangeOfImage rangeOfImage; - public final int colLen; - public ReducedData(RangeOfImage rangeOfImage, int colLen, SelectMeasurements.AvailableMeasurements measurementType){ - int nFrames = rangeOfImage.timeEnd - rangeOfImage.timeStart + 1; - int nSlices = rangeOfImage.zEnd - rangeOfImage.zStart + 1; - data = new double[nFrames * nSlices][colLen]; // row - col - columnHeaders = new ArrayList<>(); - this.measurementType = measurementType; - this.colLen = colLen; - this.rangeOfImage = rangeOfImage; - } - } - public DataReductionManager(DataReductionGUI.DataReductionSubmission submission){ N5ImageHandler.loadingManager.addSimLoadingListener(this); this.submission = submission; this.arrayOfSimRois = submission.arrayOfSimRois; - this.numOfCalculationsTimesNumImages = (submission.numOfSimImages + 1) * submission.selectedMeasurements.size(); // Plus one for the lab image + this.numOfImagesToOpen = submission.numOfSimImages + 1; // Plus one for the lab image this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); Thread processLabResults = new Thread(() -> { @@ -84,27 +66,25 @@ private void calculateAndAddResults(ImagePlus imagePlus, RangeOfImage normRange, normValue = calculations.calculateNormalValue(imagePlus, normRange, rois, imageRange); } - int nChannels = imageRange.channelEnd - imageRange.channelStart + 1; + ReducedData reducedData = new ReducedData(imagePlus.getTitle(), imageRange, arrayOfSimRois.size(), submission.selectedMeasurements); + calculations.addAppropriateHeaders(rois, imageRange, reducedData, channelInfo); - ArrayList reducedDataArrayList = new ArrayList<>(); - for (SelectMeasurements.AvailableMeasurements measurement : submission.selectedMeasurements){ - ReducedData reducedData = new ReducedData(imageRange, nChannels * arrayOfSimRois.size(), measurement); - reducedDataArrayList.add(reducedData); - calculations.addAppropriateHeaders(imagePlus, rois, imageRange, reducedData, channelInfo); - } AtomicBoolean continueOperation = threadPool.get(threadName).continueOperation; - calculations.calculateStatistics(imagePlus, rois, normValue, reducedDataArrayList, imageRange, continueOperation); - for (ReducedData reducedData: reducedDataArrayList){ - if (continueOperation.get()){ - synchronized (csvMatrixLock){ - dataReductionWriter.addValuesToWideCSVMatrix(reducedData); - numOfCalculationsTimesNumImages -= 1; + calculations.calculateStatistics(imagePlus, rois, normValue, reducedData, imageRange, continueOperation); + if (continueOperation.get()){ + synchronized (csvMatrixLock){ + try { + dataReductionWriter.consumeNewData(reducedData); + } catch (IOException e) { + stopAllThreads(); + throw new RuntimeException(e); } + numOfImagesToOpen -= 1; } } - if (numOfCalculationsTimesNumImages == 0){ + if (numOfImagesToOpen == 0 && continueOperation.get()){ try{ - dataReductionWriter.writeCSVMatrix(); + dataReductionWriter.close(); } catch (IOException ioException){ throw new RuntimeException(ioException); } finally { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 1d92edb..4858895 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -5,13 +5,14 @@ import org.vcell.N5.UI.MainPanel; import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.reduction.DTO.RangeOfImage; -import org.vcell.N5.reduction.DataReductionManager.ReducedData; +import org.vcell.N5.reduction.DTO.ReducedData; import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; public class DataReductionWriter{ @@ -39,6 +40,8 @@ public class DataReductionWriter{ private final int maxZ; private final int maxT; + private final boolean wideTable = true; + /////////////////////////////////////// // Initialize Sheet and Lab results // ///////////////////////////////////// @@ -51,12 +54,23 @@ public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission, this.maxT = maxT; } + public void consumeNewData(ReducedData reducedData) throws IOException { + if (wideTable){ + addValuesToWideCSVMatrix(reducedData); + } else { + appendAndWriteTallTable(reducedData); + } + } + + public void close() throws IOException { + if (wideTable){ + writeWideTableCSVMatrix(); + } + } + public void initializeDataSheets(){ ArrayList headers = new ArrayList(){{add("Time Frame");}}; boolean is3D = maxZ > 1; - if (is3D){ - headers.add("Z Index"); - } // Add Time and Z-Index Columns for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ @@ -77,54 +91,40 @@ public void initializeDataSheets(){ metaDataSheet.get(0).add("Simulation Name"); metaDataSheet.get(0).add("N5 URL"); - // Fill in Time and Z-Index Columns with selected range - - for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ - ArrayList> dataSheet = sheetsAvailable.get(measurement); - for (int t = 1; t <= maxT; t++){ - for (int z = 1; z <= maxZ; z++){ - ArrayList pointRow = new ArrayList<>(); - pointRow.add(0, String.valueOf(t)); - if (is3D){ - pointRow.add(1, String.valueOf(z)); - } - dataSheet.add(pointRow); - } + if (wideTable){ + // Fill in Time and Z-Index Columns with selected range + if (is3D){ + headers.add("Z Index"); } - } - } - - //////////////////////// - // General Functions // - ////////////////////// - - public void addValuesToWideCSVMatrix(ReducedData reducedData){ - ArrayList> dataSheet = sheetsAvailable.get(reducedData.measurementType); - int colIndex = columnsForSheets.get(reducedData.measurementType); - fillWithEmptySpace(dataSheet.get(0), colIndex); - for (int c = 0; c < reducedData.columnHeaders.size(); c++){ - dataSheet.get(0).add(colIndex, reducedData.columnHeaders.get(c)); - } - RangeOfImage rangeOfImage = reducedData.rangeOfImage; - int tzCounter = 1; - for (int t = 1; t <= maxT; t++){ - for (int z = 1; z <= maxZ; z++){ - boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; - boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; - ArrayList row = dataSheet.get(tzCounter); - fillWithEmptySpace(row, colIndex); - for (int c = 0; c < reducedData.colLen; c++){ - if (inBetweenTime && inBetweenZ){ - int dataRow = ((t - rangeOfImage.timeStart) * (z - rangeOfImage.zStart)) + (z - rangeOfImage.zStart); - double mean = reducedData.data[dataRow][c]; - row.add(String.valueOf(mean)); + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ + ArrayList> dataSheet = sheetsAvailable.get(measurement); + for (int t = 1; t <= maxT; t++){ + for (int z = 1; z <= maxZ; z++){ + ArrayList pointRow = new ArrayList<>(); + pointRow.add(0, String.valueOf(t)); + if (is3D){ + pointRow.add(1, String.valueOf(z)); + } + dataSheet.add(pointRow); } } - tzCounter += 1; + } + } else { + headers.add(1, "Z Index"); + headers.add("Image Name"); + headers.add("ROI Name"); + headers.add("Channel Name"); + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ + headers.add(measurement.publicName); + } + File file = new File(this.file.getAbsolutePath() + ".csv"); + try(FileWriter fileWriter = new FileWriter(file)) { + CSVWriter csvWriter = new CSVWriter(fileWriter); + csvWriter.writeNext(headers.toArray(new String[0])); + } catch (IOException ioException){ + throw new RuntimeException("Can't write to CSV file.", ioException); } } - colIndex += 1 + reducedData.data[0].length; - columnsForSheets.replace(reducedData.measurementType, colIndex); } // If parameter is not in list of parameters, add new column. If simulation does not have parameter say "not-present" @@ -158,6 +158,42 @@ public void addMetaData(SimResultsLoader loadedResults){ } } + //////////////////////// + // Private Functions // + ////////////////////// + + private void addValuesToWideCSVMatrix(ReducedData reducedData){ + for (SelectMeasurements.AvailableMeasurements measurement: reducedData.measurements){ + ArrayList> dataSheet = sheetsAvailable.get(measurement); + int colIndex = columnsForSheets.get(measurement); + fillWithEmptySpace(dataSheet.get(0), colIndex); + RangeOfImage rangeOfImage = reducedData.rangeOfImage; + for (int c = 0; c < rangeOfImage.getNChannels(); c++){ + for (int r = 0; r < reducedData.nROIs; r++){ + dataSheet.get(0).add(colIndex, reducedData.getWideTableHeader(r, c)); + int tzCounter = 1; + for (int t = 1; t <= maxT; t++){ + for (int z = 1; z <= maxZ; z++){ + boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; + boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; + ArrayList row = dataSheet.get(tzCounter); + fillWithEmptySpace(row, colIndex); + if (inBetweenTime && inBetweenZ){ + int nt = t - rangeOfImage.timeStart; + int nz = z - rangeOfImage.zStart; + row.add(String.valueOf(reducedData.getDataPoint(nt, nz, c, r, measurement))); + } + tzCounter += 1; + } + } + colIndex += 1; + } + } + colIndex += 1; + columnsForSheets.replace(measurement, colIndex); + } + } + // If specific entry to be added isn't in array list length, add empty space until it is private void fillWithEmptySpace(ArrayList arrayList, int col){ while (arrayList.size() < col){ @@ -165,8 +201,32 @@ private void fillWithEmptySpace(ArrayList arrayList, int col){ } } + // Each reduced data is a different measurement type + private void appendAndWriteTallTable(ReducedData reducedData) throws IOException { + RangeOfImage rangeOfImage = reducedData.rangeOfImage; + for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++) { + for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++) { + for (int channel = 0; channel < rangeOfImage.getNChannels(); channel++){ + for(int roi= 0; roi < reducedData.nROIs; roi++){ + File file = new File(this.file.getAbsolutePath() + ".csv"); + ArrayList newRow = new ArrayList<>(Arrays.asList(String.valueOf(t), String.valueOf(z), + reducedData.imageName, reducedData.roiNames.get(roi), reducedData.channelNames.get(channel))); + for (SelectMeasurements.AvailableMeasurements measurement : reducedData.measurements){ + int nt = t - rangeOfImage.timeStart; + int nz = z - rangeOfImage.zStart; + newRow.add(String.valueOf(reducedData.getDataPoint(nt, nz, channel, roi, measurement))); + } + try (FileWriter fileWriter = new FileWriter(file, true)) { + CSVWriter csvWriter = new CSVWriter(fileWriter); + csvWriter.writeNext(newRow.toArray(new String[0])); + } + } + } + } + } + } - public void writeCSVMatrix() throws IOException { + private void writeWideTableCSVMatrix() throws IOException { for (SelectMeasurements.AvailableMeasurements measurements : sheetsAvailable.keySet()){ if (!sheetsAvailable.get(measurements).isEmpty()){ File currentFile = new File(file.getAbsolutePath() + "-" + measurements.publicName + ".csv"); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index 5b66008..4ee879d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -4,12 +4,13 @@ import ij.ImagePlus; import ij.gui.Roi; import org.vcell.N5.reduction.DTO.RangeOfImage; -import org.vcell.N5.reduction.DataReductionManager.ReducedData; +import org.vcell.N5.reduction.DTO.ReducedData; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; + class ReductionCalculations { private final boolean normalize; @@ -17,14 +18,15 @@ public ReductionCalculations(boolean normalize){ this.normalize = normalize; } - public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, RangeOfImage rangeOfImage, + public void addAppropriateHeaders(ArrayList roiList, RangeOfImage rangeOfImage, ReducedData reducedData, LinkedTreeMap> channelInfo){ - for (Roi roi: roiList){ + for (int r = 0; r < roiList.size(); r++){ for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ //Last channel is domain channel, not variable String stringC = String.valueOf(c - 1); String channelName = channelInfo != null && channelInfo.containsKey(stringC) ? channelInfo.get(stringC).get("Name") : String.valueOf(c); - reducedData.columnHeaders.add(0, imagePlus.getTitle() + ":" + roi.getName() + ":" + channelName); + reducedData.channelNames.put(c - 1, channelName); + reducedData.roiNames.put(r, roiList.get(r).getName()); } } } @@ -35,28 +37,27 @@ public void addAppropriateHeaders(ImagePlus imagePlus, ArrayList roiList, R * @param imagePlus * @param roiList * @param normalizationValue - * @param reducedDataArrayList * @param rangeOfImage */ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, HashMap normalizationValue, - ArrayList reducedDataArrayList, + ReducedData reducedData, RangeOfImage rangeOfImage, AtomicBoolean continueOperation){ - int roiCounter = 0; - for (Roi roi: roiList) { - imagePlus.setRoi(roi); - int tzCounter = 0; + for (int roi = 0; roi < roiList.size(); roi++) { + imagePlus.setRoi(roiList.get(roi)); for (int t = rangeOfImage.timeStart; t <= rangeOfImage.timeEnd; t++){ for (int z = rangeOfImage.zStart; z <= rangeOfImage.zEnd; z++){ for (int c = rangeOfImage.channelStart; c <= rangeOfImage.channelEnd; c++){ - int channelSize = rangeOfImage.channelEnd - rangeOfImage.channelStart + 1; if (!continueOperation.get()){ return; } imagePlus.setPosition(c, z, t); + int nT = t - rangeOfImage.timeStart; + int nZ = z - rangeOfImage.zStart; + int nC = c - rangeOfImage.channelStart; double calculatedValue; - for (ReducedData reducedData : reducedDataArrayList){ - switch (reducedData.measurementType){ + for (SelectMeasurements.AvailableMeasurements measurement : reducedData.measurements){ + switch (measurement){ case AVERAGE: calculatedValue = imagePlus.getStatistics().mean; break; @@ -67,15 +68,13 @@ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, throw new RuntimeException("Unknown measurement type selected."); } if (normalize){ - calculatedValue = calculatedValue / normalizationValue.get(roi.getName() + c); + calculatedValue = calculatedValue / normalizationValue.get(roiList.get(roi).getName() + c); } - reducedData.data[tzCounter][c - 1 + (roiCounter * channelSize)] = calculatedValue; + reducedData.putDataPoint(calculatedValue, nT, nZ, nC, roi, measurement); } } - tzCounter += 1; } } - roiCounter += 1; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java index 6f1072f..cfe3d82 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java @@ -25,7 +25,7 @@ public RoiSelection(DataReductionGUI parentGUI){ JList simROITable = new JList<>(simTableModel); JFileChooser simROIFileChooser = new JFileChooser(); this.add(createROIInput(simROITable, simTableModel, simROIFileChooser, "Sim")); - this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "ROI Files")); + this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "2D ROI Files")); this.parentGUI = parentGUI; } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java index 1579f08..970457c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java @@ -6,7 +6,7 @@ import java.awt.*; import java.util.ArrayList; -class SelectMeasurements extends JPanel implements ListSelectionListener { +public class SelectMeasurements extends JPanel implements ListSelectionListener { private final JList chosenMeasurement; private final MeasurementsDataModel measurementsDataModel = new MeasurementsDataModel(); private final DataReductionGUI parentGUI; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 6c1ff2f..39e2e71 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -9,14 +9,15 @@ import org.junit.Test; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.reduction.DTO.RangeOfImage; +import org.vcell.N5.reduction.DTO.ReducedData; import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; -import org.vcell.N5.reduction.DataReductionManager.ReducedData; import java.io.File; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -47,20 +48,24 @@ public static void init(){ } private void compareExpectedCalculations(ImagePlus imagePlus, ArrayList roiList, double[][] expectedResults, - boolean normalizeMeasurementsBool){ + boolean normalizeMeasurementsBool, int nz, int nt, int nc){ ReductionCalculations reductionCalculations = new ReductionCalculations(normalizeMeasurementsBool); RangeOfImage entireRange = new RangeOfImage(1, imagePlus.getNFrames(), 1, imagePlus.getNSlices(), 1, imagePlus.getNChannels()); RangeOfImage normRange = new RangeOfImage(1, 1); - ReducedData reducedData = new ReducedData(entireRange, imagePlus.getNChannels() * roiList.size(), SelectMeasurements.AvailableMeasurements.AVERAGE); - ArrayList reducedDataArrayList = new ArrayList<>(); - reducedDataArrayList.add(reducedData); + ReducedData reducedData = new ReducedData("", entireRange, roiList.size(), new ArrayList<>(Collections.singletonList(SelectMeasurements.AvailableMeasurements.AVERAGE))); HashMap norms = reductionCalculations.calculateNormalValue(imagePlus, normRange, roiList, entireRange); - reductionCalculations.calculateStatistics(imagePlus, roiList, norms, reducedDataArrayList, entireRange, new AtomicBoolean(true)); - for (int r = 0; r < expectedResults.length; r++){ - for (int c = 0; c < expectedResults[r].length; c++){ - Assert.assertEquals(expectedResults[r][c], reducedData.data[r][c], 0.0009); + reductionCalculations.calculateStatistics(imagePlus, roiList, norms, reducedData, entireRange, new AtomicBoolean(true)); + for (int c = 0; c < nc; c++){ + for (int r = 0; r < roiList.size(); r++){ + for (int t = 0; t < nt; t++){ + for (int z = 0; z < nz; z++){ + int row = (t * nz) + z; + int col = (r * nc) + c; + Assert.assertEquals(expectedResults[row][col], reducedData.getDataPoint(t, z, c, r, SelectMeasurements.AvailableMeasurements.AVERAGE), 0.0009); + } + } } } } @@ -74,7 +79,8 @@ public void testMean2DCalculation(){ Roi labRoi = RoiDecoder.open(getTestResourceFiles("ROIs/Lab ROI.roi").getAbsolutePath()); Roi simROI = RoiDecoder.open(getTestResourceFiles("ROIs/Sim ROI.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(labRoi); add(simROI);}}; - compareExpectedCalculations(labResultImage2D, roiList, labMeans2D, false); + compareExpectedCalculations(labResultImage2D, roiList, labMeans2D, false, + 1, 3, 2); } @Test @@ -82,7 +88,8 @@ public void testMean3DCalculation(){ ImagePlus mitosis = new ImagePlus(getTestResourceFiles("mitosis.tif").getAbsolutePath()); Roi mitosisROI = RoiDecoder.open(getTestResourceFiles("ROIs/Mitosis Center.roi").getAbsolutePath()); ArrayList roiList = new ArrayList(){{add(mitosisROI);}}; - compareExpectedCalculations(mitosis, roiList, threeDMeans, false); + compareExpectedCalculations(mitosis, roiList, threeDMeans, false, + 5, 1, 2); } @Test @@ -111,6 +118,7 @@ public void testMeanAndNormalization2DCalculation(){ } } - compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, true); + compareExpectedCalculations(labResultImage2D, roiList, normalizedValues, true, + 1, 3, 2); } } From 755b94eaacfffc764e45a5d6cf44f42b255f5cf0 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 21 Nov 2024 12:27:52 -0500 Subject: [PATCH 36/44] Treat 3D Simulations Restricted to One Z Slice as 2D --- .../N5/reduction/DataReductionManager.java | 3 +++ .../N5/reduction/DataReductionWriter.java | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java index 656d744..0b2a549 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java @@ -145,6 +145,9 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { for (String threadName : threadPool.keySet()){ int curZ = threadPool.get(threadName).imagePlus.getNSlices(); int curT = threadPool.get(threadName).imagePlus.getNFrames(); + if (!threadName.equals("Lab") && submission.simImageRange.zEnd - submission.simImageRange.zStart == 0){ + curZ = 1; + } maxZ = Math.max(curZ, maxZ); maxT = Math.max(curT, maxT); } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 4858895..41e1e4d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -73,16 +73,7 @@ public void initializeDataSheets(){ boolean is3D = maxZ > 1; // Add Time and Z-Index Columns - for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ - ArrayList> dataSheet = sheetsAvailable.get(measurement); - dataSheet.add(new ArrayList<>()); - ArrayList headerRow = dataSheet.get(0); - for (int i = 0; i < headers.size(); i++){ - headerRow.add(i, headers.get(i)); - } - columnsForSheets.put(measurement, headers.size() + 1); - } metaDataSheet.add(new ArrayList<>()); metaDataSheet.get(0).add(""); @@ -96,6 +87,17 @@ public void initializeDataSheets(){ if (is3D){ headers.add("Z Index"); } + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ + ArrayList> dataSheet = sheetsAvailable.get(measurement); + dataSheet.add(new ArrayList<>()); + ArrayList headerRow = dataSheet.get(0); + + for (int i = 0; i < headers.size(); i++){ + headerRow.add(i, headers.get(i)); + } + columnsForSheets.put(measurement, headers.size() + 1); + } + for (SelectMeasurements.AvailableMeasurements measurement : selectedMeasurements){ ArrayList> dataSheet = sheetsAvailable.get(measurement); for (int t = 1; t <= maxT; t++){ @@ -175,12 +177,13 @@ private void addValuesToWideCSVMatrix(ReducedData reducedData){ for (int t = 1; t <= maxT; t++){ for (int z = 1; z <= maxZ; z++){ boolean inBetweenTime = t <= rangeOfImage.timeEnd && rangeOfImage.timeStart <= t; - boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z; + boolean onlyOneZ = rangeOfImage.zEnd - rangeOfImage.zStart == 0 && maxZ == 1; + boolean inBetweenZ = z <= rangeOfImage.zEnd && rangeOfImage.zStart <= z || onlyOneZ; ArrayList row = dataSheet.get(tzCounter); fillWithEmptySpace(row, colIndex); if (inBetweenTime && inBetweenZ){ int nt = t - rangeOfImage.timeStart; - int nz = z - rangeOfImage.zStart; + int nz = onlyOneZ ? 0 : z - rangeOfImage.zStart; row.add(String.valueOf(reducedData.getDataPoint(nt, nz, c, r, measurement))); } tzCounter += 1; From 1cfee1d3686aa77bc6019aec515d6dd9e7c8752d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 27 Nov 2024 08:27:25 -0500 Subject: [PATCH 37/44] Add Ability to Select Tall Table in GUI --- .../vcell/N5/reduction/DataReductionGUI.java | 20 +++++++++++-- .../N5/reduction/DataReductionWriter.java | 3 +- .../vcell/N5/reduction/SelectTableFormat.java | 29 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java index 6e4fa5b..a5110b4 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java @@ -22,6 +22,7 @@ public class DataReductionGUI extends JPanel implements ActionListener { private JComboBox chosenImage; private final JCheckBox selectRangeOfMeasurement = new JCheckBox("Select Measurement Range: "); private final JCheckBox normalizeMeasurement = new JCheckBox("Normalize Measurement: "); + private final JCheckBox choseCSVTableFormat = new JCheckBox("Choose CSV Format: "); private final JDialog jDialog = new JDialog(MainPanel.exportTableDialog, true); private final JButton okayButton = new JButton("Okay"); @@ -36,6 +37,7 @@ public class DataReductionGUI extends JPanel implements ActionListener { private final RoiSelection roiSelection; private final NormalizeGUI normalizeGUI; private final SelectMeasurements selectMeasurements; + private final SelectTableFormat selectTableFormat; private boolean continueWithProcess = false; @@ -51,6 +53,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize roiSelection = new RoiSelection(this); normalizeGUI = new NormalizeGUI(jDialog, simTSize); selectMeasurements = new SelectMeasurements(this); + selectTableFormat = new SelectTableFormat(); JPanel imagesToMeasurePanel = new JPanel(); imagesToMeasurePanel.setLayout(new BoxLayout(imagesToMeasurePanel, BoxLayout.Y_AXIS)); @@ -62,6 +65,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize add(roiSelection); add(selectMeasurements); add(displayOptionsPanel()); + add(selectTableFormat); add(normalizeGUI); add(selectSimRange); add(okayCancelPanel()); @@ -72,6 +76,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize cancelButton.addActionListener(this); normalizeMeasurement.addActionListener(this); selectRangeOfMeasurement.addActionListener(this); + choseCSVTableFormat.addActionListener(this); this.setBorder(new EmptyBorder(15, 12, 15, 12)); @@ -90,7 +95,7 @@ public DataReductionSubmission createSubmission(){ roiSelection.getSimROIList(), roiSelection.getImageROIList(), WindowManager.getImage((String) chosenImage.getSelectedItem()), simRange[0], simRange[1], labRange[0], labRange[1], filesToOpen.size(), chosenFile, - selectSimRange.getRangeOfSim(), selectMeasurements.getChosenMeasurements()); + selectSimRange.getRangeOfSim(), selectMeasurements.getChosenMeasurements(), selectTableFormat.isWideTableSelected()); } private JPanel okayCancelPanel(){ @@ -129,6 +134,7 @@ private JPanel displayOptionsPanel(){ jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.X_AXIS)); jPanel.add(normalizeMeasurement); jPanel.add(selectRangeOfMeasurement); + jPanel.add(choseCSVTableFormat); return jPanel; } @@ -145,6 +151,13 @@ public void actionPerformed(ActionEvent e) { normalizeGUI.setVisible(normalizeMeasurement.isSelected()); } else if (e.getSource().equals(selectRangeOfMeasurement)){ selectSimRange.setVisible(selectRangeOfMeasurement.isSelected()); + } else if (e.getSource().equals(choseCSVTableFormat)) { + selectTableFormat.setVisible(choseCSVTableFormat.isSelected()); + selectTableFormat.revalidate(); + selectTableFormat.repaint(); + jDialog.revalidate(); + jDialog.repaint(); + jDialog.pack(); } else if (e.getSource().equals(okayButton)) { JFileChooser saveToFile = new JFileChooser(); saveToFile.setFileSelectionMode(JFileChooser.FILES_ONLY); @@ -180,10 +193,12 @@ public static class DataReductionSubmission{ public final RangeOfImage simImageRange; public final ArrayList selectedMeasurements; + public final boolean wideTable; + public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList arrayOfSimRois, ArrayList arrayOfLabRois, ImagePlus labResults, int simStartPointNorm, int simEndPointNorm, int imageStartPointNorm, int imageEndPointNorm, int numOfSimImages, File fileToSaveResultsTo, - RangeOfImage simRange, ArrayList selectedMeasurements){ + RangeOfImage simRange, ArrayList selectedMeasurements, boolean wideTable){ this.normalizeMeasurementsBool = normalizeMeasurementsBool; this.arrayOfLabRois = arrayOfLabRois; this.arrayOfSimRois = arrayOfSimRois; @@ -198,6 +213,7 @@ public DataReductionSubmission(boolean normalizeMeasurementsBool, ArrayList 1, labResults.getNSlices(), 1, labResults.getNChannels()); this.simImageRange = simRange; this.selectedMeasurements = selectedMeasurements; + this.wideTable = wideTable; } } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 41e1e4d..676de5a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -40,7 +40,7 @@ public class DataReductionWriter{ private final int maxZ; private final int maxT; - private final boolean wideTable = true; + private final boolean wideTable; /////////////////////////////////////// // Initialize Sheet and Lab results // @@ -52,6 +52,7 @@ public DataReductionWriter(DataReductionGUI.DataReductionSubmission submission, this.file = submission.fileToSaveResultsTo; this.maxZ = maxZ; this.maxT = maxT; + this.wideTable = submission.wideTable; } public void consumeNewData(ReducedData reducedData) throws IOException { diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java new file mode 100644 index 0000000..904cd03 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java @@ -0,0 +1,29 @@ +package org.vcell.N5.reduction; + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import java.awt.*; + +public class SelectTableFormat extends JPanel { + private final JRadioButton wideTable = new JRadioButton("Wide (Best for manual input)"); + + public SelectTableFormat(){ + this.setLayout(new GridLayout(1,1)); + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(wideTable); + JRadioButton tallTable = new JRadioButton("Tall (Best for scripts)"); + buttonGroup.add(tallTable); + this.add(wideTable); + this.add(tallTable); + this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Select CSV Table Format:")); + wideTable.setSelected(true); + this.setVisible(false); + } + + + public boolean isWideTableSelected(){ + return wideTable.isSelected(); + } + + +} From 85524720767b86544aa6d2c329ee6e0c8a8189a2 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 27 Nov 2024 09:48:23 -0500 Subject: [PATCH 38/44] Refactor GUI Into Separate Package --- .../src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java | 2 +- .../main/java/org/vcell/N5/reduction/DataReductionManager.java | 1 + .../main/java/org/vcell/N5/reduction/DataReductionWriter.java | 2 ++ .../org/vcell/N5/reduction/{ => GUI}/DataReductionGUI.java | 2 +- .../java/org/vcell/N5/reduction/{ => GUI}/NormalizeGUI.java | 2 +- .../java/org/vcell/N5/reduction/{ => GUI}/RoiSelection.java | 2 +- .../org/vcell/N5/reduction/{ => GUI}/SelectMeasurements.java | 2 +- .../java/org/vcell/N5/reduction/{ => GUI}/SelectSimRange.java | 2 +- .../org/vcell/N5/reduction/{ => GUI}/SelectTableFormat.java | 2 +- .../java/org/vcell/N5/reduction/ReductionCalculations.java | 1 + .../src/main/java/org/vcell/N5/retrieving/LoadingManager.java | 3 +-- .../java/org/vcell/N5/reduction/ReductionCalculationsTest.java | 1 + 12 files changed, 13 insertions(+), 9 deletions(-) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/DataReductionGUI.java (99%) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/NormalizeGUI.java (98%) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/RoiSelection.java (99%) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/SelectMeasurements.java (98%) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/SelectSimRange.java (98%) rename view-simulation-results/src/main/java/org/vcell/N5/reduction/{ => GUI}/SelectTableFormat.java (96%) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java index 42466d8..2984c9f 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DTO/ReducedData.java @@ -1,6 +1,6 @@ package org.vcell.N5.reduction.DTO; -import org.vcell.N5.reduction.SelectMeasurements; +import org.vcell.N5.reduction.GUI.SelectMeasurements; import java.util.ArrayList; import java.util.HashMap; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java index 0b2a549..964beb6 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java @@ -9,6 +9,7 @@ import org.vcell.N5.UI.MainPanel; import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.reduction.DTO.ReducedData; +import org.vcell.N5.reduction.GUI.DataReductionGUI; import org.vcell.N5.retrieving.SimLoadingListener; import org.vcell.N5.retrieving.SimResultsLoader; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 676de5a..fd596c6 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -6,6 +6,8 @@ import org.vcell.N5.UI.N5ExportTable; import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.reduction.DTO.ReducedData; +import org.vcell.N5.reduction.GUI.DataReductionGUI; +import org.vcell.N5.reduction.GUI.SelectMeasurements; import org.vcell.N5.retrieving.SimResultsLoader; import java.io.File; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java similarity index 99% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java index a5110b4..bdbf6c1 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import ij.ImagePlus; import ij.WindowManager; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/NormalizeGUI.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/NormalizeGUI.java index 46c9b10..4072d8d 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/NormalizeGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/NormalizeGUI.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import org.vcell.N5.UI.HintTextField; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java similarity index 99% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java index cfe3d82..3b0022e 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import ij.gui.Roi; import ij.io.RoiDecoder; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java index 970457c..a052aaf 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectMeasurements.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import javax.swing.*; import javax.swing.event.ListSelectionEvent; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java similarity index 98% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java index db40f65..290bbb4 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectSimRange.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import org.vcell.N5.UI.HintTextField; import org.vcell.N5.reduction.DTO.RangeOfImage; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java similarity index 96% rename from view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java rename to view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java index 904cd03..8637f6a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/SelectTableFormat.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java @@ -1,4 +1,4 @@ -package org.vcell.N5.reduction; +package org.vcell.N5.reduction.GUI; import javax.swing.*; import javax.swing.border.EtchedBorder; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index 4ee879d..d541372 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -5,6 +5,7 @@ import ij.gui.Roi; import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.reduction.DTO.ReducedData; +import org.vcell.N5.reduction.GUI.SelectMeasurements; import java.util.ArrayList; import java.util.HashMap; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java index 6ee6990..c44ccac 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/retrieving/LoadingManager.java @@ -7,9 +7,8 @@ import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.RangeSelector; import org.vcell.N5.UI.MainPanel; -import org.vcell.N5.reduction.DataReductionGUI; +import org.vcell.N5.reduction.GUI.DataReductionGUI; import org.vcell.N5.reduction.DataReductionManager; -import org.vcell.N5.reduction.DataReductionWriter; import javax.swing.*; import javax.swing.event.EventListenerList; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java index 39e2e71..314c356 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/reduction/ReductionCalculationsTest.java @@ -10,6 +10,7 @@ import org.vcell.N5.N5ImageHandler; import org.vcell.N5.reduction.DTO.RangeOfImage; import org.vcell.N5.reduction.DTO.ReducedData; +import org.vcell.N5.reduction.GUI.SelectMeasurements; import org.vcell.N5.retrieving.LoadingManager; import org.vcell.N5.retrieving.SimResultsLoader; From 46d1a79474644abb4940b4559415e38d35556d5d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 27 Nov 2024 10:09:03 -0500 Subject: [PATCH 39/44] Add Max and Min Intensity Options --- .../java/org/vcell/N5/reduction/DataReductionWriter.java | 4 ++++ .../org/vcell/N5/reduction/GUI/SelectMeasurements.java | 7 +++++-- .../java/org/vcell/N5/reduction/ReductionCalculations.java | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index fd596c6..44199d5 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -25,12 +25,16 @@ public class DataReductionWriter{ private final ArrayList> averageMatrix = new ArrayList<>(); private final ArrayList> standardDivMatrix = new ArrayList<>(); + private final ArrayList> maxIntensityMatrix = new ArrayList<>(); + private final ArrayList> minIntensityMatrix = new ArrayList<>(); private final ArrayList> metaDataSheet = new ArrayList<>(); private final HashMap>> sheetsAvailable = new HashMap>>(){{ put(SelectMeasurements.AvailableMeasurements.AVERAGE, averageMatrix); put(SelectMeasurements.AvailableMeasurements.STD_DEV, standardDivMatrix); + put(SelectMeasurements.AvailableMeasurements.MAX_INTENSITY, maxIntensityMatrix); + put(SelectMeasurements.AvailableMeasurements.MIN_INTENSITY, minIntensityMatrix); }}; private final HashMap columnsForSheets = new HashMap<>(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java index a052aaf..782ca42 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectMeasurements.java @@ -35,7 +35,9 @@ public void valueChanged(ListSelectionEvent e) { public enum AvailableMeasurements{ AVERAGE("Average"), - STD_DEV("Standard Deviation"); + STD_DEV("Standard Deviation"), + MAX_INTENSITY("Max Intensity"), + MIN_INTENSITY("Minimum Intensity"); public final String publicName; AvailableMeasurements(String publicName){ @@ -44,7 +46,8 @@ public enum AvailableMeasurements{ } static class MeasurementsDataModel extends AbstractListModel{ - private final AvailableMeasurements[] availableMeasurements = new AvailableMeasurements[]{AvailableMeasurements.AVERAGE, AvailableMeasurements.STD_DEV}; + private final AvailableMeasurements[] availableMeasurements = new AvailableMeasurements[]{ + AvailableMeasurements.AVERAGE, AvailableMeasurements.STD_DEV, AvailableMeasurements.MAX_INTENSITY, AvailableMeasurements.MIN_INTENSITY}; public ArrayList getSelectedMeasurements(int[] indices){ ArrayList selected = new ArrayList<>(); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java index d541372..8580906 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/ReductionCalculations.java @@ -65,6 +65,12 @@ void calculateStatistics(ImagePlus imagePlus, ArrayList roiList, case STD_DEV: calculatedValue = imagePlus.getStatistics().stdDev; break; + case MAX_INTENSITY: + calculatedValue = imagePlus.getStatistics().max; + break; + case MIN_INTENSITY: + calculatedValue = imagePlus.getStatistics().min; + break; default: throw new RuntimeException("Unknown measurement type selected."); } From 88be5b5b7674e37b326bf761b3b4280eaa9e2a31 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 27 Nov 2024 10:15:53 -0500 Subject: [PATCH 40/44] Have Metadata Be Written For Tall Tables Too --- .../main/java/org/vcell/N5/reduction/DataReductionWriter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java index 44199d5..65c5509 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionWriter.java @@ -73,6 +73,7 @@ public void close() throws IOException { if (wideTable){ writeWideTableCSVMatrix(); } + writeMetaDataTable(); } public void initializeDataSheets(){ @@ -248,6 +249,9 @@ private void writeWideTableCSVMatrix() throws IOException { } } } + } + + private void writeMetaDataTable() throws IOException { File currentFile = new File(file.getAbsolutePath() + "-Metadata.csv"); try (FileWriter fileWriter = new FileWriter(currentFile)){ CSVWriter csvWriter = new CSVWriter(fileWriter); From 1a107cb8c819efb7ce361959f2ca0c9ac8ec41d1 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 4 Dec 2024 07:37:35 -0500 Subject: [PATCH 41/44] Remove Normalize From GUI --- .../java/org/vcell/N5/reduction/GUI/DataReductionGUI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java index bdbf6c1..0c03a58 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java @@ -66,7 +66,7 @@ public DataReductionGUI(ArrayList filesToOpen, double simCSize add(selectMeasurements); add(displayOptionsPanel()); add(selectTableFormat); - add(normalizeGUI); +// add(normalizeGUI); add(selectSimRange); add(okayCancelPanel()); @@ -132,7 +132,7 @@ private JPanel selectedImagesToOpenPanel(){ private JPanel displayOptionsPanel(){ JPanel jPanel = new JPanel(); jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.X_AXIS)); - jPanel.add(normalizeMeasurement); +// jPanel.add(normalizeMeasurement); jPanel.add(selectRangeOfMeasurement); jPanel.add(choseCSVTableFormat); return jPanel; From c3010b353c5afe3433be8f57a1784a3344940d8a Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 4 Dec 2024 09:26:37 -0500 Subject: [PATCH 42/44] Let Users Specify No ROI If the user doesn't specify a ROI, then it does the entire image. --- .../N5/reduction/DataReductionManager.java | 46 +++++++++++++------ .../N5/reduction/GUI/DataReductionGUI.java | 4 +- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java index 964beb6..1bce13a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/DataReductionManager.java @@ -4,6 +4,7 @@ import ij.ImagePlus; import ij.WindowManager; import ij.gui.Roi; +import org.jetbrains.annotations.NotNull; import org.vcell.N5.N5ImageHandler; import org.vcell.N5.UI.ControlButtonsPanel; import org.vcell.N5.UI.MainPanel; @@ -42,6 +43,13 @@ public DataReductionManager(DataReductionGUI.DataReductionSubmission submission) this.calculations = new ReductionCalculations(submission.normalizeMeasurementsBool); Thread processLabResults = new Thread(() -> { + if (submission.arrayOfLabRois.isEmpty()){ + int height = submission.labResults.getHeight(); + int width = submission.labResults.getWidth(); + Roi roi = new Roi(0, 0, width, height); + roi.setName("Entire Image"); + submission.arrayOfLabRois.add(roi); + } calculateAndAddResults(submission.labResults, submission.experiementNormRange, submission.experimentImageRange, submission.arrayOfLabRois, null, "Lab"); synchronized (threadPoolLock){ @@ -125,24 +133,20 @@ public void simIsLoading(int itemRow, String exportID) { @Override public void simFinishedLoading(SimResultsLoader loadedResults) { if (loadedResults.openTag == SimResultsLoader.OpenTag.DATA_REDUCTION){ - Thread imageProcessingThread = new Thread(() -> { - ImagePlus imagePlus = loadedResults.getImagePlus(); - imagePlus.show(); - dataReductionWriter.addMetaData(loadedResults); - calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, - submission.arrayOfSimRois, loadedResults.getChannelInfo(), loadedResults.exportID); - MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); - imagePlus.close(); - synchronized (threadPoolLock){ - threadPool.remove(loadedResults.exportID); - } - }, "Processing Image: " + loadedResults.userSetFileName); - ThreadStruct threadStruct = new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); + ThreadStruct threadStruct = getThreadStruct(loadedResults); synchronized (threadPoolLock){ threadPool.put(loadedResults.exportID, threadStruct); if (threadPool.size() == (submission.numOfSimImages + 1)){ int maxZ = 0; int maxT = 0; + // + if (arrayOfSimRois.isEmpty() && !threadStruct.thread.getName().equals("Lab")){ + int height = loadedResults.getImagePlus().getHeight(); + int width = loadedResults.getImagePlus().getWidth(); + Roi roi = new Roi(0, 0, width, height); + roi.setName("Entire Image"); + arrayOfSimRois.add(roi); + } for (String threadName : threadPool.keySet()){ int curZ = threadPool.get(threadName).imagePlus.getNSlices(); int curT = threadPool.get(threadName).imagePlus.getNFrames(); @@ -162,6 +166,22 @@ public void simFinishedLoading(SimResultsLoader loadedResults) { } } + private @NotNull ThreadStruct getThreadStruct(SimResultsLoader loadedResults) { + Thread imageProcessingThread = new Thread(() -> { + ImagePlus imagePlus = loadedResults.getImagePlus(); + imagePlus.show(); + dataReductionWriter.addMetaData(loadedResults); + calculateAndAddResults(imagePlus, submission.simNormRange, submission.simImageRange, + submission.arrayOfSimRois, loadedResults.getChannelInfo(), loadedResults.exportID); + MainPanel.n5ExportTable.removeSpecificRowFromLoadingRows(loadedResults.rowNumber); + imagePlus.close(); + synchronized (threadPoolLock){ + threadPool.remove(loadedResults.exportID); + } + }, "Processing Image: " + loadedResults.userSetFileName); + return new ThreadStruct(loadedResults, new AtomicBoolean(true), imageProcessingThread); + } + static class ThreadStruct { public final SimResultsLoader simResultsLoader; public final ImagePlus imagePlus; diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java index 0c03a58..7be7adf 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/DataReductionGUI.java @@ -141,8 +141,8 @@ private JPanel displayOptionsPanel(){ public void activateOkayButton(){ boolean selectedAMeasurement = !selectMeasurements.getChosenMeasurements().isEmpty(); boolean chosenExperimentImage = chosenImage.getSelectedItem() != null; - boolean roisIsSelected = !roiSelection.getImageROIList().isEmpty() && !roiSelection.getSimROIList().isEmpty(); - okayButton.setEnabled(selectedAMeasurement && chosenExperimentImage && roisIsSelected); +// boolean roisIsSelected = !roiSelection.getImageROIList().isEmpty() && !roiSelection.getSimROIList().isEmpty(); + okayButton.setEnabled(selectedAMeasurement && chosenExperimentImage); } @Override From 5d931aed33828c65b390bf7e25e2641ed5b83d3c Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 4 Dec 2024 11:04:50 -0500 Subject: [PATCH 43/44] Small Changes to the GUI Text --- .../src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java | 2 +- .../main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java | 2 +- .../main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java index 3b0022e..731ded8 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/RoiSelection.java @@ -25,7 +25,7 @@ public RoiSelection(DataReductionGUI parentGUI){ JList simROITable = new JList<>(simTableModel); JFileChooser simROIFileChooser = new JFileChooser(); this.add(createROIInput(simROITable, simTableModel, simROIFileChooser, "Sim")); - this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "2D ROI Files")); + this.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Apply 2D ROI Files")); this.parentGUI = parentGUI; } diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java index 290bbb4..600b57c 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectSimRange.java @@ -40,7 +40,7 @@ public SelectSimRange(JDialog jDialog, double simCSize, double simZSize, double zRange.add(zEnd); JPanel tRange = new JPanel(new GridLayout()); - tRange.add(new JLabel("Time Range: ")); + tRange.add(new JLabel("Time Frame's: ")); tRange.add(tStart); tRange.add(new JLabel("to")); tRange.add(tEnd); diff --git a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java index 8637f6a..e90076a 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/reduction/GUI/SelectTableFormat.java @@ -5,7 +5,7 @@ import java.awt.*; public class SelectTableFormat extends JPanel { - private final JRadioButton wideTable = new JRadioButton("Wide (Best for manual input)"); + private final JRadioButton wideTable = new JRadioButton("Wide (Best for manual analysis)"); public SelectTableFormat(){ this.setLayout(new GridLayout(1,1)); From 8b043df25a6951b14d5100887cecb2f17692b8c8 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 4 Dec 2024 11:07:43 -0500 Subject: [PATCH 44/44] Table Updating is More Responsive Updating which row is loading is more responsive, and no longer relies on the row being updated to be selected. --- .../src/main/java/org/vcell/N5/UI/N5ExportTable.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java index d10199b..ca79296 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/N5ExportTable.java @@ -215,12 +215,9 @@ public void stopSelectedImageFromLoading(){ public void removeSpecificRowFromLoadingRows(int rowNumber){ int realRowNumber = findLoadingRow(rowNumber, rowNumber); - loadingRowsJobID.remove(rowNumber); - int selected = exportListTable.getSelectedRow(); - if (selected == realRowNumber){ - controlPanel.updateButtonsToMatchState(false); - exportListTable.repaint(); - } + loadingRowsJobID.remove(realRowNumber); + controlPanel.updateButtonsToMatchState(false); + exportListTable.repaint(); } @Override