From ab2b4d1f7f81cd905cb9d6d39241f2027bb89f0b Mon Sep 17 00:00:00 2001
From: Ezequiel Valencia
Date: Wed, 18 Sep 2024 12:47:20 -0400
Subject: [PATCH 1/5] Enhanced Image Into Memory
---
.../java/org/vcell/N5/SimResultsLoader.java | 59 +++---
.../java/org/vcell/N5/UI/ImageIntoMemory.java | 185 ++++++++++++++++++
.../java/org/vcell/N5/N5ImageHandlerTest.java | 6 +-
3 files changed, 210 insertions(+), 40 deletions(-)
create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
index f0804dc..bdd5635 100644
--- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
+++ b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
@@ -9,7 +9,6 @@
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.google.gson.GsonBuilder;
import ij.ImagePlus;
-import ij.plugin.Duplicator;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.img.display.imagej.ImageJFunctions;
import net.imglib2.type.numeric.real.DoubleType;
@@ -24,6 +23,7 @@
import org.janelia.saalfeldlab.n5.s3.N5AmazonS3Reader;
import org.scijava.log.Logger;
import org.vcell.N5.UI.N5ExportTable;
+import org.vcell.N5.UI.ImageIntoMemory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
@@ -70,10 +70,8 @@ public SimResultsLoader(String stringURI, String userSetFileName){
}
}
- void createS3Client(){
+ void createS3ClientAndReader(){
logger.debug("Creating S3 Client with url: " + uri);
- AmazonS3ClientBuilder s3ClientBuilder = AmazonS3ClientBuilder.standard();
-
if (uri.getHost().equals("minikube.remote") || uri.getHost().equals("minikube.island")){
SSLContext sslContext = null;
try {
@@ -104,6 +102,8 @@ public boolean verify(String hostname, SSLSession session) {
s3ClientBuilder.withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()));
s3ClientBuilder.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(uri.getScheme() + "://" + uri.getAuthority(), defaultS3Region));
this.s3Client = s3ClientBuilder.build();
+ S3KeyValueAccess amazonS3KeyValueAccess = new S3KeyValueAccess(s3Client, bucketName, false);
+ n5AmazonS3Reader = new N5KeyValueReader(amazonS3KeyValueAccess, s3ObjectKey, new GsonBuilder(), false);
}
/**
@@ -112,9 +112,7 @@ 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.
*/
- ImagePlus getImgPlusFromN5File() throws IOException {
- S3KeyValueAccess amazonS3KeyValueAccess = new S3KeyValueAccess(s3Client, bucketName, false);
- N5KeyValueReader n5AmazonS3Reader = new N5KeyValueReader(amazonS3KeyValueAccess, s3ObjectKey, new GsonBuilder(), false);
+ public ImagePlus getImgPlusFromN5File() throws IOException {
// N5AmazonS3Reader n5AmazonS3Reader = new N5AmazonS3Reader(s3Client, bucketName, "/" + s3ObjectKey);
long start = System.currentTimeMillis();
@@ -155,23 +153,10 @@ private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){
}
}
-// private static ImagePlus getSetOfImage(ImagePlus imagePlus){
-// int startZ = 0, startTime = 0, startChannel = 0;
-// int endZ = 5, endTime = 2, endChannel = 1;
-// ImagePlus newImage = IJ.createHyperStack(imagePlus.getTitle() + " In Memory", imagePlus.getWidth(),
-// imagePlus.getHeight(), endChannel, endZ, endTime, imagePlus.getBitDepth());
-// for (startChannel = startChannel; startChannel < endChannel; startChannel++){
-// for (startZ = startZ; startZ < endZ; startZ++){
-// for (startTime = startTime; startTime < endTime; startTime++){
-// int index = imagePlus.getStackIndex(startChannel, startZ, startTime);
-// newImage.getImageStack().addSlice("" + startTime + "" + startChannel + "" + startZ,
-// imagePlus.getStack().getProcessor(index), index);
-// }
-// }
-// }
-// newImage.setDimensions(endChannel, endZ, endTime);
-// return newImage;
-// }
+ public ArrayList getN5Dimensions(){
+ return n5AmazonS3Reader.getAttribute(dataSetChosen, "dimensions", ArrayList.class);
+ }
+
public static void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){
N5ExportTable.enableCriticalButtons(false);
@@ -179,28 +164,28 @@ public static void openN5FileDataset(ArrayList filesToOpen, bo
Thread openN5FileDataset = new Thread(() -> {
try{
for(SimResultsLoader simResultsLoader: filesToOpen){
- simResultsLoader.createS3Client();
- ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
- if(openInMemory){
- long start = System.currentTimeMillis();
- logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory");
-
- imagePlus = new Duplicator().run(imagePlus);
-// imagePlus = SimResultsLoader.getSetOfImage(imagePlus);
- long end = System.currentTimeMillis();
- imagePlus.show();
- logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s");
+ simResultsLoader.createS3ClientAndReader();
+ ImageIntoMemory imageIntoMemory;
+ if (openInMemory){
+ ArrayList dimensions = simResultsLoader.getN5Dimensions();
+ imageIntoMemory = new ImageIntoMemory(dimensions.get(2), dimensions.get(3), dimensions.get(4), simResultsLoader);
+ imageIntoMemory.displayRangeMenu();
} else{
+ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
imagePlus.show();
}
+
}
- } catch (IOException ex) {
+ } catch (Exception ex) {
+ N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
throw new RuntimeException(ex);
} finally {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ if (!openInMemory) {
+ N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
N5ExportTable.enableCriticalButtons(true);
}
});
diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
new file mode 100644
index 0000000..fe54f27
--- /dev/null
+++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
@@ -0,0 +1,185 @@
+package org.vcell.N5.UI;
+
+import ij.ImagePlus;
+import ij.plugin.Duplicator;
+import org.scijava.log.Logger;
+import org.vcell.N5.N5ImageHandler;
+import org.vcell.N5.SimResultsLoader;
+
+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;
+import java.io.IOException;
+
+public class ImageIntoMemory extends EventListenerList implements ActionListener {
+ public int startC;
+ public int endC;
+ public int startT;
+ public int endT;
+ 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 final JButton okayButton;
+ private final JButton cancelButton;
+ private final JFrame frame;
+ private final SimResultsLoader simResultsLoader;
+
+ private static final Logger logger = N5ImageHandler.getLogger(ImageIntoMemory.class);
+
+ public ImageIntoMemory(double cDim, double tDim, double zDim, SimResultsLoader simResultsLoader){
+ this.simResultsLoader = simResultsLoader;
+ channelStartTextField = new HintTextField("1");
+ channelEndTextField = new HintTextField("" + (int) cDim);
+
+ timeStartTextField = new HintTextField("1");
+ timeEndTextField = new HintTextField("" + (int) tDim);
+
+ zStartTextField = new HintTextField("1");
+ zEndTextField = new HintTextField("" + (int) zDim);
+
+ // Create the frame
+ frame = new JFrame("Select " + simResultsLoader.userSetFileName + " Dimensions");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(400, 200);
+
+ // Create a panel to hold the input boxes and buttons
+ JPanel panel = new JPanel();
+ panel.setLayout(new GridLayout(4, 4, 10, 10)); // 4 rows: 3 for input, 1 for buttons
+
+ panel.add(new JLabel("Channel Start: "));
+ panel.add(channelStartTextField);
+ panel.add(new JLabel("Channel End: "));
+ panel.add(channelEndTextField);
+
+ panel.add(new JLabel("Z-Slice Start: "));
+ panel.add(zStartTextField);
+ panel.add(new JLabel("Z-Slice End: "));
+ panel.add(zEndTextField);
+
+ panel.add(new JLabel("Time Start: "));
+ panel.add(timeStartTextField);
+ panel.add(new JLabel("Time End: "));
+ panel.add(timeEndTextField);
+
+
+ // Create the "Okay" and "Cancel" buttons
+ panel.add(new JLabel());
+ okayButton = new JButton("Okay");
+ cancelButton = new JButton("Cancel");
+
+ // Add action listeners to the buttons
+ okayButton.addActionListener(this);
+
+ cancelButton.addActionListener(this);
+
+ // Add the buttons to the panel
+ panel.add(okayButton);
+ panel.add(cancelButton);
+
+ // Add the panel to the frame
+ frame.add(panel);
+ }
+
+ public void displayRangeMenu(){
+ // Make the window visible
+ frame.setVisible(true);
+ }
+
+ public static void usePopUp(){
+
+ }
+
+ public static void useExistingParameters(int startC, int endC, int startT, int endT, int startZ, int endZ){
+
+ }
+
+ public static void main(String[] args) {
+ ImageIntoMemory inMemoryPopUp = new ImageIntoMemory(1, 2, 3, null);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource().equals(okayButton)){
+ frame.dispose();
+// N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR));
+
+ startC = Integer.parseInt(channelStartTextField.getText()) - 1;
+ endC = Integer.parseInt(channelEndTextField.getText()) - 1;
+ startT = Integer.parseInt(timeStartTextField.getText()) - 1;
+ endT = Integer.parseInt(timeEndTextField.getText()) - 1;
+ startZ = Integer.parseInt(zStartTextField.getText()) - 1;
+ endZ = Integer.parseInt(zEndTextField.getText()) - 1;
+
+ try {
+ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
+ long start = System.currentTimeMillis();
+ logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory");
+ imagePlus = new Duplicator().run(imagePlus, startC, endC, startZ,
+ endZ, startT, endT);
+ long end = System.currentTimeMillis();
+ logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s");
+ imagePlus.show();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ } else if (e.getSource().equals(cancelButton)) {
+ N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ frame.dispose();
+ }
+ }
+
+ 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/test/java/org/vcell/N5/N5ImageHandlerTest.java b/view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java
index 42e0f4c..30faa06 100644
--- a/view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java
+++ b/view-simulation-results/src/test/java/org/vcell/N5/N5ImageHandlerTest.java
@@ -73,7 +73,7 @@ public void testS3AlphaInstance() throws IOException{
N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles();
for(N5DataSetFile n5DataSetFile : n5DataSetFiles) {
SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "");
- simResultsLoader.createS3Client();
+ simResultsLoader.createS3ClientAndReader();
ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
//stats that have been preemptively calculated within VCell
@@ -88,7 +88,7 @@ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException {
N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles();
for(N5DataSetFile n5DataSetFile : n5DataSetFiles) {
SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "");
- simResultsLoader.createS3Client();
+ simResultsLoader.createS3ClientAndReader();
ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
ImagePlus inMemory = new Duplicator().run(imagePlus);
for (Object property : imagePlus.getProperties().keySet()){
@@ -109,7 +109,7 @@ public void testUnits() throws IOException {
N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles();
for (N5DataSetFile n5DataSetFile: n5DataSetFiles){
SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, "");
- simResultsLoader.createS3Client();
+ simResultsLoader.createS3ClientAndReader();
ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
double areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1);
double totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight();
From 94cea4f73c7022ff02ea4b08a99fc4aaabb50d00 Mon Sep 17 00:00:00 2001
From: Ezequiel Valencia
Date: Wed, 18 Sep 2024 12:52:07 -0400
Subject: [PATCH 2/5] Create Amazon S3 Builder upon Initalization
S3 Client builder takes approximately 3 seconds to create every time. Instead of having it be built every time someone open's a file, upfront the build cost on initialization.
---
.../src/main/java/org/vcell/N5/N5ImageHandler.java | 8 ++++++++
.../src/main/java/org/vcell/N5/SimResultsLoader.java | 4 +++-
2 files changed, 11 insertions(+), 1 deletion(-)
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 82d8bd8..3a9a14e 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
@@ -1,6 +1,7 @@
package org.vcell.N5;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.scijava.command.Command;
@@ -42,6 +43,13 @@ public void run() {
setExampleJSONData();
// N5ImageHandler.logService.setLevel(LogService.DEBUG);
exportTable.displayExportTable();
+ Thread thread = new Thread(() -> {
+ // For some reason getting a standard client takes three seconds.
+ // 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();
+ });
+ thread.start();
}
public static Logger getLogger(Class classToLog){
diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
index bdd5635..1925a74 100644
--- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
+++ b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
@@ -49,10 +49,12 @@ public class SimResultsLoader {
private String s3ObjectKey;
private URI uri;
private String dataSetChosen;
- private String userSetFileName = null;
+ public String userSetFileName = null;
private static final String defaultS3Region = "site2-low";
+ private N5Reader n5AmazonS3Reader;
private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class);
+ public static AmazonS3ClientBuilder s3ClientBuilder;
public SimResultsLoader(){
From 5f902f0bf56eaed58318f2d1767cc50162cc96e1 Mon Sep 17 00:00:00 2001
From: Ezequiel Valencia
Date: Wed, 18 Sep 2024 13:11:44 -0400
Subject: [PATCH 3/5] Open Image into Memory In Separate Thread
---
.../java/org/vcell/N5/SimResultsLoader.java | 3 +-
.../java/org/vcell/N5/UI/ImageIntoMemory.java | 40 +++++++++++--------
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
index 1925a74..f7d21d0 100644
--- a/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
+++ b/view-simulation-results/src/main/java/org/vcell/N5/SimResultsLoader.java
@@ -180,6 +180,7 @@ public static void openN5FileDataset(ArrayList filesToOpen, bo
}
} catch (Exception ex) {
N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ N5ExportTable.enableCriticalButtons(true);
throw new RuntimeException(ex);
} finally {
SwingUtilities.invokeLater(new Runnable() {
@@ -187,8 +188,8 @@ public static void openN5FileDataset(ArrayList filesToOpen, bo
public void run() {
if (!openInMemory) {
N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ N5ExportTable.enableCriticalButtons(true);
}
- N5ExportTable.enableCriticalButtons(true);
}
});
}
diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
index fe54f27..3cd4c42 100644
--- a/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
+++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/ImageIntoMemory.java
@@ -112,7 +112,6 @@ public static void main(String[] args) {
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(okayButton)){
frame.dispose();
-// N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR));
startC = Integer.parseInt(channelStartTextField.getText()) - 1;
endC = Integer.parseInt(channelEndTextField.getText()) - 1;
@@ -121,23 +120,30 @@ public void actionPerformed(ActionEvent e) {
startZ = Integer.parseInt(zStartTextField.getText()) - 1;
endZ = Integer.parseInt(zEndTextField.getText()) - 1;
- try {
- ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
- long start = System.currentTimeMillis();
- logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory");
- imagePlus = new Duplicator().run(imagePlus, startC, endC, startZ,
- endZ, startT, endT);
- long end = System.currentTimeMillis();
- logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s");
- imagePlus.show();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- } finally {
- N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
- }
-
- } else if (e.getSource().equals(cancelButton)) {
+ Thread openInMemory = new Thread(() -> {
+ try {
+ ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File();
+ long start = System.currentTimeMillis();
+ logger.debug("Loading Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory");
+ imagePlus = new Duplicator().run(imagePlus, startC, endC, startZ,
+ endZ, startT, endT);
+ long end = System.currentTimeMillis();
+ logger.debug("Loaded Virtual N5 File " + simResultsLoader.userSetFileName + " Into Memory taking: " + ((end - start)/ 1000) + "s");
+ imagePlus.show();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ N5ExportTable.enableCriticalButtons(true);
+ }
+ });
+ openInMemory.setName("Open N5 Image in Memory");
+ openInMemory.start();
+ }
+
+ else if (e.getSource().equals(cancelButton)) {
N5ExportTable.exportTableDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ N5ExportTable.enableCriticalButtons(true);
frame.dispose();
}
}
From c9aecef9e28146e778a57299f3b03e05ec7f6191 Mon Sep 17 00:00:00 2001
From: Ezequiel Valencia
Date: Thu, 19 Sep 2024 09:01:50 -0400
Subject: [PATCH 4/5] Improved Help Text
---
.../src/main/resources/Help.html | 40 ++++++++++---------
1 file changed, 22 insertions(+), 18 deletions(-)
diff --git a/view-simulation-results/src/main/resources/Help.html b/view-simulation-results/src/main/resources/Help.html
index d1bfa4a..cfc7e34 100644
--- a/view-simulation-results/src/main/resources/Help.html
+++ b/view-simulation-results/src/main/resources/Help.html
@@ -7,33 +7,37 @@ Intro
stored remotely on VCell servers, allowing applications such as ImageJ
to directly access the results of these simulations and perform analyses.
- VCell Spatial Simulation
+ Export Visualization
- Simulation solvers generating 2- or 3-dimensional spatial
- domains can be visualized in ImageJ using this plugin.
- Spatial dimensions and time directly correspond to fields within an ImageJ
- image. The image's channels depict different variables within a simulation.
+ Virtual Cell has special techniques for spatial simulation results so that they are visually compelling while accurate to their
+ source data. Those automatic techniques are not implemented within this plugin, so if an export is visually different
+ from VCell's please go to Image -> Adjust -> Brightness/Contrast, and adjust it to a point where it is similar.
- N5 and Datasets
-
- Each N5 store is a direct mapping to a VCell simulation, and contains one or more
- datasets. Each dataset holds numerical data and metadata corresponding to an Image in ImageJ.
- Each N5 store is fully identified through its N5 URL which can be shared and opened by other applications
- which support the N5 format.
-
- Accessing Simulation Results
- For VCell exports generated from your local VCell installation:
+ Dimension Properties
-
-
Either, Click the recent export button.
+ XYZ: The XYZ dimensions directly correspond to the simulations XYZ.
+
+
+ -
+
Channel: The different channels represent the variables exported,
+ and the last channel always represents the geometric domains for your spatial export.
+
+
-
-
Or, Open the export table and view all past exports with their affiliated metadata.
+ Time: Time directly corresponds to the simulations time.
+
+
+ Accessing Simulation Results
+ For VCell exports generated from your local VCell installation:
+
From N5 URL (VCell Install Not Required):
- - Click the 'Remote Files' button, paste the N5 URL,
- then select dataset from list.
+ - Click the 'Remote Files' button, paste the N5 URL, and click open.