From e511f5c82c000e02ea005d78d4454c813cbb0905 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 15 Jul 2024 12:16:11 -0400 Subject: [PATCH 01/18] Remove Ricky's Code --- ricky/src/org/vcell/Ricky/BaseImport.java | 431 ------------------ ricky/src/org/vcell/Ricky/Main.java | 7 - .../src/org/vcell/Ricky/OnlineImageLoad.java | 179 -------- .../org/vcell/Ricky/OnlineModelSearch.java | 55 --- ricky/src/org/vcell/Ricky/WebSearch.java | 422 ----------------- 5 files changed, 1094 deletions(-) delete mode 100644 ricky/src/org/vcell/Ricky/BaseImport.java delete mode 100644 ricky/src/org/vcell/Ricky/Main.java delete mode 100644 ricky/src/org/vcell/Ricky/OnlineImageLoad.java delete mode 100644 ricky/src/org/vcell/Ricky/OnlineModelSearch.java delete mode 100644 ricky/src/org/vcell/Ricky/WebSearch.java diff --git a/ricky/src/org/vcell/Ricky/BaseImport.java b/ricky/src/org/vcell/Ricky/BaseImport.java deleted file mode 100644 index af882f1..0000000 --- a/ricky/src/org/vcell/Ricky/BaseImport.java +++ /dev/null @@ -1,431 +0,0 @@ -package org.vcell.Ricky; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.nodes.TextNode; -import org.jsoup.select.Elements; -import org.jsoup.nodes.Node; - -import java.io.IOException; -import java.net.URL; - -import org.scijava.command.ContextCommand; -import org.scijava.plugin.Parameter; -import org.scijava.plugin.Plugin; -import org.scijava.ui.UIService; - -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; - -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.net.URI; -import java.net.URISyntaxException; -import ij.gui.GenericDialog; -import net.imagej.ImageJ; - -import javax.swing.text.html.HTMLDocument; -import javax.swing.text.html.HTMLFrameHyperlinkEvent; - -//@SuppressWarnings("unused") -@Plugin(type = ContextCommand.class, menuPath = "Plugins>VCell> Base Version") -public class BaseImport extends ContextCommand { - @Parameter - private UIService uiService; - - public static void main(String[] args) { - final ImageJ ij = new ImageJ(); - ij.ui().showUI(); - } - - public void loadWebsite(String url, JEditorPane editorPane) { - try { - editorPane.setPage(new URL(url)); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private static void handleTableLinkClick(JTable table) { - table.addMouseMotionListener(new MouseAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - JTable table = (JTable) e.getSource(); - Point point = e.getPoint(); - int row = table.rowAtPoint(point); - int column = table.columnAtPoint(point); - Object value = table.getValueAt(row, column); - - if (value != null && value.toString().contains(" elements - if (headerCells.isEmpty()) { - // Create a default format with empty strings - for (int i = 0; i < format.length; i++) { - format[i] = ""; - } - } else { - // Extract the format from the elements - for (int i = 0; i < headerCells.size(); i++) { - format[i] = headerCells.get(i).text(); - } - } - return format; - } - - private static class TableData { - String text; - String linkUrl; - - TableData(String text, String linkUrl) { - this.text = text; - this.linkUrl = linkUrl; - } - } - - private static TableData processTableCell(Element cell) { - StringBuilder sb = new StringBuilder(); - String linkUrl = ""; - - for (Node child : cell.childNodes()) { - if (child instanceof TextNode) { - sb.append(((TextNode) child).text()); - } else if (child instanceof Element && ((Element) child).tagName().equals("a")) { - Element link = (Element) child; - String linkText = link.text(); - linkUrl = link.attr("abs:href"); - sb.append(linkText); - } - } - - return new TableData(sb.toString(), linkUrl); - } - - private static String[][] extractTableData(Element table) { - Elements rows = table.select("tr"); - String[][] data = new String[rows.size()][]; - - for (int i = 0; i < rows.size(); i++) { - Elements cells = rows.get(i).select("td"); - data[i] = new String[cells.size()]; - - for (int j = 0; j < cells.size(); j++) { - Element cell = cells.get(j); - TableData tableData = processTableCell(cell); - data[i][j] = tableData.text; - } - } - - return data; - } - - private static void handleTableLinkClick(JTable table, int row, int column) throws IOException { - String value = (String) table.getValueAt(row, column); - if (value != null && value.contains(" { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - if (e instanceof HTMLFrameHyperlinkEvent) { - HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; - HTMLDocument doc1 = (HTMLDocument) editorPane.getDocument(); - doc1.processHTMLFrameHyperlinkEvent(evt); - } else { - try { - Desktop.getDesktop().browse(e.getURL().toURI()); - } catch (IOException | URISyntaxException ex) { - ex.printStackTrace(); - } - } - } - }); - - JScrollPane scrollPane = new JScrollPane(editorPane); - scrollPane.setPreferredSize(new Dimension(800, 600)); - JOptionPane.showMessageDialog(null, scrollPane, "Link", JOptionPane.PLAIN_MESSAGE); - } - } - - - @SuppressWarnings("serial") - private class JTextAreaCellRenderer extends JTextArea implements TableCellRenderer { - public JTextAreaCellRenderer() { - setLineWrap(true); - setWrapStyleWord(true); - setOpaque(true); - setBorder(BorderFactory.createEmptyBorder()); - FontMetrics fm = getFontMetrics(getFont()); - int lineHeight = fm.getHeight(); - int ascent = fm.getAscent(); - int descent = fm.getDescent(); - int leading = fm.getLeading(); - int adjustedLineHeight = lineHeight - leading + descent; - setLineHeight(adjustedLineHeight); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - setText(value != null ? value.toString() : ""); - setSize(table.getColumnModel().getColumn(column).getWidth(), getPreferredSize().height); - if (isSelected) { - setBackground(table.getSelectionBackground()); - setForeground(table.getSelectionForeground()); - } else { - setBackground(table.getBackground()); - setForeground(table.getForeground()); - } - return this; - } - - private void setLineHeight(int lineHeight) { - String html = "%s"; - setText(String.format(html, getText())); - } - } - - private static void adjustRowHeight(JTable table) { - for (int row = 0; row < table.getRowCount(); row++) { - int rowHeight = table.getRowHeight(); - for (int column = 0; column < table.getColumnCount(); column++) { - TableCellRenderer renderer = table.getCellRenderer(row, column); - Component comp = table.prepareRenderer(renderer, row, column); - rowHeight = Math.max(rowHeight, comp.getPreferredSize().height); - } - table.setRowHeight(row, rowHeight); - } - } - - @SuppressWarnings("serial") - private static class QuotationCellRenderer extends JEditorPane implements TableCellRenderer { - public QuotationCellRenderer() { - setContentType("text/html"); - setEditable(false); - setOpaque(true); - setBorder(BorderFactory.createEmptyBorder()); - setForeground(Color.BLUE); - addHyperlinkListener(e -> { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - if (e instanceof HTMLFrameHyperlinkEvent) { - HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; - HTMLDocument doc = (HTMLDocument) getDocument(); - doc.processHTMLFrameHyperlinkEvent(evt); - } else { - try { - Desktop.getDesktop().browse(e.getURL().toURI()); - } catch (IOException | URISyntaxException ex) { - ex.printStackTrace(); - } - } - } - }); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - if (value instanceof String) { - String text = (String) value; - setText(text); - } else { - setText(""); - } - - adjustWidth(table, column); - adjustHeight(table, row, column); - - if (isSelected) { - setBackground(table.getSelectionBackground()); - setForeground(table.getSelectionForeground()); - } else { - setBackground(table.getBackground()); - setForeground(table.getForeground()); - } - - return this; - } - - private void adjustWidth(JTable table, int column) { - TableColumn tableColumn = table.getColumnModel().getColumn(column); - setSize(tableColumn.getWidth(), getPreferredSize().height); - } - - private void adjustHeight(JTable table, int row, int column) { - int rowHeight = table.getRowHeight(row); - int columnWidth = table.getColumnModel().getColumn(column).getWidth(); - - setSize(columnWidth, Short.MAX_VALUE); - int preferredHeight = getPreferredSize().height; - if (preferredHeight > rowHeight) { - rowHeight = preferredHeight; - table.setRowHeight(row, rowHeight); - } - } - } - - @SuppressWarnings("serial") - private static class QuotationCellEditor extends DefaultCellEditor { - private JTextArea textArea; - - public QuotationCellEditor() { - super(new JTextField()); - textArea = new JTextArea(); - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - textArea.setBorder(BorderFactory.createEmptyBorder()); - textArea.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_TAB) { - e.consume(); - } - } - }); - setClickCountToStart(0); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - textArea.setText(value != null ? value.toString() : ""); - adjustTextAreaWidth(table, column); - return new JScrollPane(textArea); - } - - @Override - public Object getCellEditorValue() { - return textArea.getText(); - } - - private void adjustTextAreaWidth(JTable table, int column) { - int tableWidth = table.getColumnModel().getColumn(column).getWidth(); - int textWidth = textArea.getPreferredSize().width; - if (textWidth < tableWidth) { - textArea.setSize(tableWidth, textArea.getPreferredSize().height); - } - } - } - - public void run() { - try { - String string = new String(); - String url = new String(); - JFrame ui = new JFrame(); - - GenericDialog box = new GenericDialog("Web Model Search"); - - box.addStringField("Model Name:", string, 45); - box.addStringField("Model ID:", string, 45); - box.addStringField("Model Owner:", string, 45); - box.addStringField("Begin Date:", string, 45); - box.addStringField("End Date:", string, 45); - box.showDialog(); - - boolean shouldContinue = true; - - while (shouldContinue) { - if (box.wasCanceled() && !box.isVisible()) { - shouldContinue = false; - break; - } - - if (box.wasOKed()) { - String modelName = box.getNextString(); - String modelID = box.getNextString(); - String modelOwner = box.getNextString(); - String beginDate = box.getNextString(); - String endDate = box.getNextString(); - - JFrame frame = new JFrame("Search Results"); - - url = "https://vcellapi-beta.cam.uchc.edu:8080/biomodel?bmName=" + modelName + "&bmId=" + modelID - + "&category=all" + "&owner=" + modelOwner + "&savedLow=&savedHigh=&startRow=1&maxRows=100&orderBy=date_desc"; - - try { - Document doc = Jsoup.connect(url).get(); - doc.select("tbody").first().remove(); - - String[][] tableData = extractTableData(doc); - String[] columns = extractFormat(doc); - - DefaultTableModel finalFormat = new DefaultTableModel(tableData, columns); - - JTable table = new JTable(finalFormat); - adjustRowHeight(table); - table.setDefaultRenderer(Object.class, new QuotationCellRenderer()); - table.setDefaultEditor(Object.class, null); - table.getColumnModel().getColumn(3).setCellRenderer(new QuotationCellRenderer()); - - table.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - int row = table.rowAtPoint(e.getPoint()); - int col = table.columnAtPoint(e.getPoint()); - try { - handleTableLinkClick(table, row, col); - } catch (IOException e1) { - e1.printStackTrace(); - } - } - }); - - JScrollPane panel = new JScrollPane(table); - panel.setPreferredSize(new Dimension(1500, 500)); - - frame.add(panel); - frame.pack(); - frame.setVisible(true); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - ui.add(box); - ui.pack(); - ui.setVisible(true); - } catch (ArrayIndexOutOfBoundsException e) { - e.printStackTrace(); - } - } -} diff --git a/ricky/src/org/vcell/Ricky/Main.java b/ricky/src/org/vcell/Ricky/Main.java deleted file mode 100644 index b1d7242..0000000 --- a/ricky/src/org/vcell/Ricky/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.vcell.Ricky; - -public class Main { - public static void main(String[] args) { - System.out.printf("Hello and welcome!"); - } -} \ No newline at end of file diff --git a/ricky/src/org/vcell/Ricky/OnlineImageLoad.java b/ricky/src/org/vcell/Ricky/OnlineImageLoad.java deleted file mode 100644 index 3d160b7..0000000 --- a/ricky/src/org/vcell/Ricky/OnlineImageLoad.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * To the extent possible under law, the ImageJ developers have waived - * all copyright and related or neighboring rights to this tutorial code. - * - * See the CC0 1.0 Universal license for details: - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - - -package org.vcell.Ricky; -import java.awt.*; -import java.io.*; -import java.net.URL; -import java.util.*; -import ij.*; -import ij.io.*; -import ij.gui.*; -import ij.plugin.MacroInstaller; -import ij.plugin.PluginInstaller; -import ij.plugin.URLOpener; -import ij.plugin.frame.*; -import java.awt.Color; - -import org.scijava.command.ContextCommand; - -import org.scijava.plugin.Plugin; - -import ij.IJ; -import ij.ImagePlus; -import ij.WindowManager; -import java.io.File; -import java.io.IOException; - - -@Plugin(type = ContextCommand.class, menuPath = "Plugins>VCell> Load Web Image") -public class OnlineImageLoad extends ContextCommand { - private static String url = null; - - /** If 'urlOrName' is a URL, opens the image at that URL. If it is - a file name, opens the image with that name from the 'images.location' - URL in IJ_Props.txt. If it is blank, prompts for an image - URL and open the specified image. */ - public void run() { - GenericDialog box = new GenericDialog("Web Image Load"); - box.setInsets(10, 32, 0); - box.addMessage("Enter Model ID", null, Color.darkGray); - box.addStringField("ID:", url, 45); - box.showDialog(); - if (box.wasCanceled()) - return; - url = box.getNextString(); - url = url.trim(); - url = "https://vcellapi-beta.cam.uchc.edu:8080/biomodel/" + url + "/diagram"; - /* if (url.endsWith("/")) - IJ.runPlugIn("ij.plugin.BrowserLauncher", url.substring(0, url.length()-1)); */ - /* else if (url.endsWith(".html") || url.endsWith(".htm") || url.endsWith(".pdf") || url.indexOf(".html#")>0 || noExtension(url)) - IJ.runPlugIn("ij.plugin.BrowserLauncher", url); */ - if (url.endsWith(".txt")||url.endsWith(".ijm")||url.endsWith(".js")||url.endsWith(".java")) - openTextFile(url, false); - else if (url.endsWith(".jar")||url.endsWith(".class")) - IJ.open(url); - else { - IJ.showStatus("Opening: " + url); - double startTime = System.currentTimeMillis(); - ImagePlus imp = new ImagePlus(url); - WindowManager.checkForDuplicateName = true; - FileInfo fi = imp.getOriginalFileInfo(); - if (fi!=null && fi.fileType==FileInfo.RGB48) - imp = new CompositeImage(imp, IJ.COMPOSITE); - else if (imp.getNChannels()>1 && fi!=null && fi.description!=null && fi.description.indexOf("mode=")!=-1) { - int mode = IJ.COLOR; - if (fi.description.indexOf("mode=composite")!=-1) - mode = IJ.COMPOSITE; - else if (fi.description.indexOf("mode=gray")!=-1) - mode = IJ.GRAYSCALE; - imp = new CompositeImage(imp, mode); - } - if (fi!=null && (fi.url==null || fi.url.length()==0)) { - fi.url = url; - imp.setFileInfo(fi); - } - imp.show(Opener.getLoadRate(startTime,imp)); - } - IJ.register(URLOpener.class); - } - - boolean noExtension(String url) { - int lastSlash = url.lastIndexOf("/"); - if (lastSlash==-1) lastSlash = 0; - int lastDot = url.lastIndexOf("."); - if (lastDot==-1 || lastDot6) - return true; - else - return false; - } - - void openTextFile(String urlString, boolean install) { - StringBuffer sb = null; - try { - URL url = new URL(urlString); - InputStream in = url.openStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - sb = new StringBuffer() ; - String line; - while ((line=br.readLine()) != null) - sb.append (line + "\n"); - in.close (); - } catch (IOException e) { - if (!(install&&urlString.endsWith("StartupMacros.txt"))) - IJ.error("URL Opener", ""+e); - sb = null; - } - if (sb!=null) { - if (install) - (new MacroInstaller()).install(new String(sb)); - else { - int index = urlString.lastIndexOf("/"); - if (index!=-1 && index<=urlString.length()-1) - urlString = urlString.substring(index+1); - (new Editor()).create(urlString, new String(sb)); - } - } - } - - private void cacheSampleImages() { - String[] names = getSampleImageNames(); - int n = names.length; - if (n==0) return; - String dir = IJ.getDirectory("imagej")+"samples"; - File f = new File(dir); - if (!f.exists()) { - boolean ok = f.mkdir(); - if (!ok) { - IJ.error("Unable to create directory:\n \n"+dir); - return; - } - } - IJ.resetEscape(); - for (int i=0; i list = new ArrayList<>(); - Hashtable commands = Menus.getCommands(); - Menu samplesMenu = Menus.getImageJMenu("File>Open Samples"); - if (samplesMenu==null) - return new String[0]; - for (int i=0; i" + linkedContent + ""); - - JScrollPane linkPanel = new JScrollPane(editorPane); - linkFrame.add(linkPanel); - linkFrame.setPreferredSize(new Dimension(1500, 600)); - linkFrame.pack(); - linkFrame.setVisible(true); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } - }); - } - - private static String formatLinkedContent(Document linkedDoc) { - Elements rows = linkedDoc.select("tr"); - StringBuilder tableContent = new StringBuilder(""); - - for (Element row : rows) { - Elements cells = row.select("td"); - tableContent.append(""); - - for (Element cell : cells) { - tableContent.append(""); - } - - tableContent.append(""); - } - - tableContent.append("
").append(cell.html()).append("
"); - return tableContent.toString(); - } - - - - private static String[] extractFormat(Element table) { - Elements headerCells = table.select("th"); - String[] format = new String[headerCells.size()]; - - if (headerCells.isEmpty()) { - for (int i = 0; i < format.length; i++) { - format[i] = ""; - } - } else { - for (int i = 0; i < headerCells.size(); i++) { - format[i] = headerCells.get(i).text(); - } - } - return format; - } - - private static String[][] extractTableData(Element table) { - Elements rows = table.select("tr"); - String[][] data = new String[rows.size()][]; - - for (int i = 0; i < rows.size(); i++) { - Elements cells = rows.get(i).select("td"); - data[i] = new String[cells.size()]; - - for (int j = 0; j < cells.size(); j++) { - Element cell = cells.get(j); - StringBuilder sb = new StringBuilder(); - - for (Node child : cell.childNodes()) { - if (child instanceof TextNode) { - sb.append(((TextNode) child).text()); - } else if (child instanceof Element && ((Element) child).tagName().equals("a")) { - Element link = (Element) child; - String linkText = link.text(); - String linkUrl = link.attr("abs:href"); - sb.append("
" + linkText + ""); - } - } - - data[i][j] = sb.toString(); - } - } - - return data; - } - - - @SuppressWarnings("serial") - private class JTextAreaCellRenderer extends JTextArea implements TableCellRenderer { - public JTextAreaCellRenderer() { - setLineWrap(true); - setWrapStyleWord(true); - setOpaque(true); - setBorder(BorderFactory.createEmptyBorder()); - FontMetrics fm = getFontMetrics(getFont()); - int lineHeight = fm.getHeight(); - int ascent = fm.getAscent(); - int descent = fm.getDescent(); - int leading = fm.getLeading(); - int adjustedLineHeight = lineHeight - leading + descent; - setLineHeight(adjustedLineHeight); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - setText(value != null ? value.toString() : ""); - setSize(table.getColumnModel().getColumn(column).getWidth(), getPreferredSize().height); - if (isSelected) { - setBackground(table.getSelectionBackground()); - setForeground(table.getSelectionForeground()); - } else { - setBackground(table.getBackground()); - setForeground(table.getForeground()); - } - return this; - } - - private void setLineHeight(int lineHeight) { - String html = "%s"; - setText(String.format(html, getText())); - } - } - - private static void adjustRowHeight(JTable table) { - for (int row = 0; row < table.getRowCount(); row++) { - int rowHeight = table.getRowHeight(); - for (int column = 0; column < table.getColumnCount(); column++) { - TableCellRenderer renderer = table.getCellRenderer(row, column); - Component comp = table.prepareRenderer(renderer, row, column); - rowHeight = Math.max(rowHeight, comp.getPreferredSize().height); - } - table.setRowHeight(row, rowHeight); - } - } - - @SuppressWarnings("serial") - private static class QuotationCellRenderer extends JScrollPane implements TableCellRenderer { - private JTextPane textPane; - - public QuotationCellRenderer() { - setOpaque(true); - setBorder(BorderFactory.createEmptyBorder()); - setForeground(Color.BLUE); - textPane = new JTextPane(); - textPane.setContentType("text/html"); - textPane.setEditable(false); - textPane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - if (e instanceof HTMLFrameHyperlinkEvent) { - HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; - HTMLDocument doc = (HTMLDocument) textPane.getDocument(); - doc.processHTMLFrameHyperlinkEvent(evt); - - } - } - } - }); - setViewportView(textPane); - setPreferredSize(new Dimension(300, 50)); - setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); - setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - textPane.setText(value != null ? value.toString() : ""); - adjustWidth(table, column); - adjustHeight(table, row, column); - return this; - } - - private void adjustWidth(JTable table, int column) { - TableColumn tableColumn = table.getColumnModel().getColumn(column); - textPane.setSize(tableColumn.getWidth(), textPane.getPreferredSize().height); - } - - private void adjustHeight(JTable table, int row, int column) { - int rowHeight = table.getRowHeight(row); - int columnWidth = table.getColumnModel().getColumn(column).getWidth(); - - textPane.setSize(columnWidth, Short.MAX_VALUE); - int preferredHeight = textPane.getPreferredSize().height; - if (preferredHeight > rowHeight) { - rowHeight = preferredHeight; - table.setRowHeight(row, rowHeight); - } - } - - } - - private static class HyperlinkCellRenderer extends DefaultTableCellRenderer { - public HyperlinkCellRenderer() { - setHorizontalAlignment(SwingConstants.CENTER); - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - JEditorPane editorPane = new JEditorPane(); - editorPane.setContentType("text/html"); - editorPane.setEditable(false); - editorPane.setText(value != null ? value.toString() : ""); - return editorPane; - } - } - - private int findHyperlinkColumnIndex(JTable table) { - String[] header = new String[table.getColumnCount()]; - for (int i = 0; i < header.length; i++) { - header[i] = table.getColumnName(i); - } - // Replace "Your Hyperlink Column Header" with the actual header of the hyperlink column - return IntStream.range(0, header.length) - .filter(i -> header[i].equals("Your Hyperlink Column Header")) - .findFirst() - .orElse(-1); - } - - @SuppressWarnings("serial") - private static class QuotationCellEditor extends DefaultCellEditor { - private JTextArea textArea; - - public QuotationCellEditor() { - super(new JTextField()); - textArea = new JTextArea(); - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - textArea.setBorder(BorderFactory.createEmptyBorder()); - textArea.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_TAB) { - e.consume(); - } - } - }); - setClickCountToStart(0); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - textArea.setText(value != null ? value.toString() : ""); - adjustTextAreaWidth(table, column); - return new JScrollPane(textArea); - } - - @Override - public Object getCellEditorValue() { - return textArea.getText(); - } - - private void adjustTextAreaWidth(JTable table, int column) { - int tableWidth = table.getColumnModel().getColumn(column).getWidth(); - int textWidth = textArea.getPreferredSize().width; - if (textWidth < tableWidth) { - textArea.setSize(tableWidth, textArea.getPreferredSize().height); - } - } - } - - public void run() { - try { - String string = new String(); - String url = new String(); - JFrame ui = new JFrame(); - - GenericDialog box = new GenericDialog("Web Model Search"); - - box.addStringField("Model Name:", string, 45); - box.addStringField("Model ID:", string, 45); - box.addStringField("Model Owner:", string, 45); - box.addStringField("Begin Date:", string, 45); - box.addStringField("End Date:", string, 45); - box.showDialog(); - - boolean shouldContinue = true; - - while (shouldContinue) { - if (box.wasCanceled() && !box.isVisible()) { - shouldContinue = false; - break; - } - - if (box.wasOKed()) { - String modelName = box.getNextString(); - String modelID = box.getNextString(); - String modelOwner = box.getNextString(); - String beginDate = box.getNextString(); - String endDate = box.getNextString(); - - JFrame frame = new JFrame("Search Results"); - - url = "https://vcellapi-beta.cam.uchc.edu:8080/biomodel?bmName=" + modelName + "&bmId=" + modelID - + "&category=all" + "&owner=" + modelOwner + "&savedLow=&savedHigh=&startRow=1&maxRows=100&orderBy=date_desc"; - - try { - Document doc = Jsoup.connect(url).get(); - doc.select("tbody").first().remove(); - - String[][] tableData = extractTableData(doc); - String[] columns = extractFormat(doc); - - DefaultTableModel finalFormat = new DefaultTableModel(tableData, columns); - - JTable table = new JTable(finalFormat); - adjustRowHeight(table); - table.setDefaultRenderer(Object.class, new QuotationCellRenderer()); - table.setDefaultEditor(Object.class, null); - - linkClicked(table); - - /* int hyperlinkColumnIndex = findHyperlinkColumnIndex(table); - - - for (int i = 0; i < table.getColumnCount(); i++) { - if (i != hyperlinkColumnIndex) { - table.getColumnModel().getColumn(i).setCellRenderer(new JTextAreaCellRenderer()); - } - } - - table.getColumnModel().getColumn(hyperlinkColumnIndex).setCellRenderer(new HyperlinkCellRenderer()); - - adjustRowHeight(table); */ - - JScrollPane panel = new JScrollPane(table); - panel.setPreferredSize(new Dimension(1500, 500)); - - frame.add(panel); - frame.pack(); - frame.setVisible(true); - - - } catch (IOException e) { - e.printStackTrace(); - } - } - } - ui.add(box); - ui.pack(); - ui.setVisible(true); - } catch (ArrayIndexOutOfBoundsException e) { - e.printStackTrace(); - } - } -} From fb908d5989738ffda3c308be6dcbf7a46aa52542 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Tue, 16 Jul 2024 08:46:17 -0400 Subject: [PATCH 02/18] Context Aware GUI --- .../java/org/vcell/N5/UI/N5ExportTable.java | 87 ++++++++++++++----- 1 file changed, 67 insertions(+), 20 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 dda9cc0..6ff527c 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 @@ -11,18 +11,20 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableColumn; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; import java.io.FileNotFoundException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Stack; +import java.util.*; public class N5ExportTable implements ActionListener, ListSelectionListener { public static JDialog exportTableDialog; @@ -31,6 +33,7 @@ public class N5ExportTable implements ActionListener, ListSelectionListener { private JTable parameterTable; private JTable exportListTable; private JScrollPane tableScrollPane; + private JSplitPane exportDetails; private static JButton open; private static JButton copyLink; @@ -97,24 +100,21 @@ public void initalizeTableData(){ private void initialize(){ - JPanel exportPanel = new JPanel(); + JPanel parentPanel = new JPanel(); - exportPanel.setLayout(new BorderLayout()); - exportPanel.add(topPanel(), BorderLayout.NORTH); + parentPanel.setLayout(new BorderLayout()); + parentPanel.add(topPanel(), BorderLayout.NORTH); JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,tablePanel(), exportDetailsPanel()); jSplitPane.setContinuousLayout(true); - exportPanel.add(jSplitPane, BorderLayout.CENTER); + parentPanel.add(jSplitPane, BorderLayout.CENTER); - exportPanel.setPreferredSize(new Dimension(paneWidth, 650)); - JOptionPane pane = new JOptionPane(exportPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); + parentPanel.setPreferredSize(new Dimension(paneWidth, 650)); + JOptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, 0, null, new Object[]{"Close"}); exportTableDialog = pane.createDialog("VCell Exports"); exportTableDialog.setModal(false); exportTableDialog.setResizable(true); exportTableDialog.setVisible(true); - - exportListTable.getSelectionModel().addListSelectionListener(this); - initalizeTableData(); } @@ -140,10 +140,12 @@ private JSplitPane exportDetailsPanel(){ jtextScrollPane.setPreferredSize(new Dimension(paneWidth / 2, 80)); jtextScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Variables ")); - JSplitPane exportDetails = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jtextScrollPane, parameterTableScrollPane); + exportDetails = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jtextScrollPane, parameterTableScrollPane); exportDetails.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, " Export Details ")); exportDetails.setResizeWeight(0.5); exportDetails.setContinuousLayout(true); + + setEnableParentAndChild(exportDetails, false); return exportDetails; } @@ -152,8 +154,11 @@ private JScrollPane tablePanel(){ exportListTable = new JTable(n5ExportTableModel); tableScrollPane = new JScrollPane(exportListTable); + tableScrollPane.setPreferredSize(new Dimension(500, 400)); tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, switchMainTableContext.getText().equals(optionForExampleTableButtonText) ? personalTableLabelText : exampleTableLabelText)); + exportListTable.getSelectionModel().addListSelectionListener(this); + return tableScrollPane; } @@ -243,6 +248,14 @@ private JPanel topPanel(){ useN5Link.addActionListener(this); switchMainTableContext.addActionListener(this); + Enumeration b = buttonGroup.getElements(); + while (b.hasMoreElements()){ + b.nextElement().addActionListener(this); + } + + open.setEnabled(false); + copyLink.setEnabled(false); + return topBar; } @@ -255,6 +268,29 @@ public static void enableCriticalButtons(boolean enable){ switchMainTableContext.setEnabled(enable); } + public static void setEnableParentAndChild(Container container, boolean enable){ + container.setEnabled(enable); + for (Component component : container.getComponents()){ + if (component instanceof Container){ + setEnableParentAndChild((Container) component, enable); + } + component.setEnabled(enable); + if(component instanceof JTable){ + Enumeration columns = ((JTable) component).getColumnModel().getColumns(); + while (columns.hasMoreElements()){ + columns.nextElement().setHeaderRenderer(new DefaultTableCellRenderer(){ + @Override + public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) { + Component c = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column); + c.setForeground(enable ? Color.BLACK : Color.GRAY); + return c; + } + }); + } + } + } + } + @Override public void actionPerformed(ActionEvent e) { if(e.getSource().equals(open)){ @@ -279,6 +315,9 @@ public void actionPerformed(ActionEvent e) { String currentState = switchMainTableContext.getText(); switchMainTableContext.setText(currentState.equals(optionForExampleTableButtonText) ? optionForPersonalTableButtonText : optionForExampleTableButtonText); initalizeTableData(); + } else if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) + || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { + initalizeTableData(); } } @@ -286,8 +325,16 @@ public void actionPerformed(ActionEvent e) { public void valueChanged(ListSelectionEvent e) { int row = exportListTable.getSelectedRow(); if (row > exportListTable.getRowCount() || row < 0){ + parameterTableModel.resetTableData(); + variableTextPanel.setText(""); + open.setEnabled(false); + copyLink.setEnabled(false); + setEnableParentAndChild(exportDetails, false); return; } + open.setEnabled(true); + copyLink.setEnabled(true); + setEnableParentAndChild(exportDetails, true); // AttributeSet attributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.) ExportDataRepresentation.SimulationExportDataRepresentation rowData = n5ExportTableModel.getRowData(row); variableTextPanel.setText("Variables: " + rowData.variables); @@ -311,7 +358,7 @@ static class ParameterTableModel extends AbstractTableModel{ private List> tableData = new ArrayList<>(); - private final ArrayList headers = new ArrayList(){{ + public final ArrayList headers = new ArrayList(){{ add(parameterHeader); add(defaultValueHeader); add(newValueHeader); @@ -361,9 +408,9 @@ public void resetTableData(){ static class N5ExportTableModel extends AbstractTableModel { public final ArrayList headers = new ArrayList(){{ - add("BM Name"); - add("App Name"); - add("Sim Name"); + add("BioModel"); + add("Application"); + add("Simulation"); add("Time Slice"); add("Date Exported"); add("N5 File Name"); @@ -392,11 +439,11 @@ public String getColumnName(int column) { @Override public Object getValueAt(int rowIndex, int columnIndex) { ExportDataRepresentation.SimulationExportDataRepresentation data = getRowData(rowIndex); - if (columnIndex == headers.indexOf("App Name")){ + if (columnIndex == headers.indexOf("Application")){ return data.applicationName; - } else if (columnIndex == headers.indexOf("BM Name")) { + } else if (columnIndex == headers.indexOf("BioModel")) { return data.biomodelName; - } else if (columnIndex == headers.indexOf("Sim Name")) { + } else if (columnIndex == headers.indexOf("Simulation")) { return data.simulationName; } else if (columnIndex == headers.indexOf("Time Slice")) { return data.startAndEndTime; From c81fc7dc8c0188fb391b226cd30312c1a8dd070e Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 17 Jul 2024 09:40:34 -0400 Subject: [PATCH 03/18] Context Dependent GUI Changed the GUI so that it is context dependent, and features less buttons. Also no longer is "open in memory" a default option. --- .../java/org/vcell/N5/N5ImageHandler.java | 32 ++-- .../java/org/vcell/N5/UI/N5ExportTable.java | 167 ++++++++++++------ 2 files changed, 121 insertions(+), 78 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 34c4449..75ebf1f 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 @@ -33,6 +33,7 @@ public class N5ImageHandler implements Command { public static LogService logService; public static N5ExportTable exportTable; public static String exportedMetaDataPath = System.getProperty("user.home") + "/.vcell/exportMetaData.json"; + private static ExportDataRepresentation.FormatExportDataRepresentation exampleJSONData; @Override public void run() { @@ -56,51 +57,40 @@ public static void initializeLogService(){ public static void main(String[] args) { N5ImageHandler n5ImageHandler = new N5ImageHandler(); initializeLogService(); + setExampleJSONData(); n5ImageHandler.run(); } - public static ExportDataRepresentation.SimulationExportDataRepresentation getLastJSONElement() throws FileNotFoundException { - ExportDataRepresentation jsonData = getJsonData(); - if (jsonData != null && jsonData.formatData.containsKey(N5ImageHandler.formatName)) { - ExportDataRepresentation.FormatExportDataRepresentation formatExportDataRepresentation = jsonData.formatData.get(N5ImageHandler.formatName); - Stack formatJobIDs = formatExportDataRepresentation.formatJobIDs; - String jobID = formatJobIDs.isEmpty() ? null : formatJobIDs.peek(); - - return jobID == null ? null : formatExportDataRepresentation.simulationDataMap.get(jobID); - } - return null; - } - public static boolean exportedDataExists(){ File jsonFile = new File(exportedMetaDataPath); return jsonFile.exists(); } - public static ExportDataRepresentation getJsonData() throws FileNotFoundException { + public static ExportDataRepresentation.FormatExportDataRepresentation getJsonData() throws FileNotFoundException { File jsonFile = new File(exportedMetaDataPath); if (jsonFile.exists() && jsonFile.length() != 0){ - ExportDataRepresentation jsonHashMap; Gson gson = new GsonBuilder().setPrettyPrinting().create(); - jsonHashMap = gson.fromJson(new FileReader(jsonFile.getAbsolutePath()), ExportDataRepresentation.class); - return jsonHashMap; + return gson.fromJson(new FileReader(jsonFile.getAbsolutePath()), ExportDataRepresentation.class).formatData.get(N5ImageHandler.formatName); } return null; } -// https://www.npoint.io/docs/b85bb21076bf422a7d93 - public static ExportDataRepresentation getExampleJSONData() throws FileNotFoundException { + private static void setExampleJSONData(){ try(BufferedInputStream remoteJSONFile = new BufferedInputStream(new URL("https://api.npoint.io/b85bb21076bf422a7d93").openStream())){ InputStreamReader remoteJSONFileReader = new InputStreamReader(remoteJSONFile); - ExportDataRepresentation jsonHashMap; Gson gson = new GsonBuilder().setPrettyPrinting().create(); - jsonHashMap = gson.fromJson(remoteJSONFileReader, ExportDataRepresentation.class); - return jsonHashMap; + exampleJSONData = gson.fromJson(remoteJSONFileReader, ExportDataRepresentation.class).formatData.get(N5ImageHandler.formatName); } catch (IOException e) { throw new RuntimeException(e); } } +// https://www.npoint.io/docs/b85bb21076bf422a7d93 + public static ExportDataRepresentation.FormatExportDataRepresentation getExampleJSONData() throws FileNotFoundException { + return exampleJSONData; + } + } 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 6ff527c..48aae2d 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 @@ -18,13 +18,12 @@ import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; import java.io.FileNotFoundException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.*; +import java.util.concurrent.TimeUnit; public class N5ExportTable implements ActionListener, ListSelectionListener { public static JDialog exportTableDialog; @@ -41,17 +40,15 @@ public class N5ExportTable implements ActionListener, ListSelectionListener { private static JButton useN5Link; private static JButton questionMark; public static JCheckBox openInMemory; - private static JButton switchMainTableContext; - private final String optionForExampleTableButtonText = "Show Export Examples"; - private final String optionForPersonalTableButtonText = "Show My Exports"; - private final String exampleTableLabelText = " Example Export Table "; - private final String personalTableLabelText = " Personal Export Table "; + public static JCheckBox includeExampleExports; private JCheckBox todayInterval; private JCheckBox monthInterval; private JCheckBox yearlyInterval; private JCheckBox anyInterval; + private JPanel timeFilter; private JTextPane variableTextPanel; private final Border lowerEtchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + private final Border exampleBorder = BorderFactory.createTitledBorder(lowerEtchedBorder, "Example Exports"); private static RemoteFileSelection remoteFileSelection; private final int paneWidth = 800; @@ -61,43 +58,93 @@ public N5ExportTable(){ remoteFileSelection = new RemoteFileSelection(); } + private 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 initalizeTableData(){ - ExportDataRepresentation jsonData = null; n5ExportTableModel.resetData(); + tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Personal Exports")); try { - jsonData = switchMainTableContext.getText().equals(optionForPersonalTableButtonText) ? N5ImageHandler.getExampleJSONData() : N5ImageHandler.getJsonData(); - if (jsonData != null){ - 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 - } - - ExportDataRepresentation.FormatExportDataRepresentation formatExportData = jsonData.formatData.get(N5ImageHandler.formatName); + ExportDataRepresentation.FormatExportDataRepresentation formatExportData = N5ImageHandler.getJsonData(); + if (formatExportData != null){ Stack jobStack = formatExportData.formatJobIDs; while (!jobStack.isEmpty()){ String jobID = jobStack.pop(); - DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime exportDate = LocalDateTime.parse(formatExportData.simulationDataMap.get(jobID).exportDate, dateFormat); - if (exportDate.isBefore(pastTime)){ + if (!n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(jobID), oldestTimeAllowed())){ break; } - n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(jobID)); } } n5ExportTableModel.fireTableDataChanged(); - tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, switchMainTableContext.getText().equals(optionForPersonalTableButtonText) ? exampleTableLabelText : personalTableLabelText)); tableScrollPane.updateUI(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } + private void updateExampleExportsToTable(){ + n5ExportTableModel.resetData(); + tableScrollPane.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(); + tableScrollPane.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 && !tableScrollPane.getBorder().equals(exampleBorder)){ + ExportDataRepresentation.SimulationExportDataRepresentation mostRecentTableEntry = !n5ExportTableModel.tableData.isEmpty() ? n5ExportTableModel.tableData.getFirst() : null; + Stack jobStack = formatExportData.formatJobIDs; + boolean isUpdated = false; + while (!jobStack.isEmpty()){ + String currentJob = jobStack.pop(); + if (mostRecentTableEntry != null && currentJob.equals(mostRecentTableEntry.jobID)){ + break; + } + isUpdated = n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); + } + if(isUpdated){ + n5ExportTableModel.fireTableDataChanged(); + tableScrollPane.updateUI(); + } + } + Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + } + } catch (FileNotFoundException e) { + throw new RuntimeException("Problem Loading Export JSON",e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + refreshTableThread.start(); + } + private void initialize(){ JPanel parentPanel = new JPanel(); @@ -114,8 +161,13 @@ private void initialize(){ exportTableDialog.setModal(false); exportTableDialog.setResizable(true); exportTableDialog.setVisible(true); - - initalizeTableData(); + if(!N5ImageHandler.exportedDataExists()){ + updateExampleExportsToTable(); + } + else{ + initalizeTableData(); + } + automaticRefresh(); } @@ -156,7 +208,7 @@ private JScrollPane tablePanel(){ tableScrollPane.setPreferredSize(new Dimension(500, 400)); - tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, switchMainTableContext.getText().equals(optionForExampleTableButtonText) ? personalTableLabelText : exampleTableLabelText)); + tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); exportListTable.getSelectionModel().addListSelectionListener(this); return tableScrollPane; @@ -169,8 +221,9 @@ private JPanel topPanel(){ useN5Link = new JButton("Use N5 Link"); questionMark = new JButton("?"); openInMemory = new JCheckBox("Open In Memory"); - switchMainTableContext = new JButton(N5ImageHandler.exportedDataExists() ? optionForExampleTableButtonText : optionForPersonalTableButtonText); - openInMemory.setSelected(true); + openInMemory.setSelected(false); + includeExampleExports = new JCheckBox("Show Example Exports"); + includeExampleExports.setSelected(!N5ImageHandler.exportedDataExists()); GridBagConstraints gridBagConstraints = new GridBagConstraints(); @@ -180,24 +233,15 @@ private JPanel topPanel(){ topRow.add(open, gridBagConstraints); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; - topRow.add(refreshButton, gridBagConstraints); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 0; topRow.add(copyLink, gridBagConstraints); - - JPanel midRow = new JPanel(new GridBagLayout()); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - midRow.add(useN5Link, gridBagConstraints); -// gridBagConstraints.gridx = 1; -// gridBagConstraints.gridy = 2; - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - midRow.add(switchMainTableContext, gridBagConstraints); + gridBagConstraints.gridx = 2; + topRow.add(useN5Link, gridBagConstraints); JPanel bottomRow = new JPanel(new GridBagLayout()); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; + bottomRow.add(includeExampleExports, gridBagConstraints); + gridBagConstraints.gridx = 1; bottomRow.add(openInMemory, gridBagConstraints); @@ -206,8 +250,6 @@ private JPanel topPanel(){ gridBagConstraints.gridy = 0; userButtonsPanel.add(topRow, gridBagConstraints); gridBagConstraints.gridy = 1; - userButtonsPanel.add(midRow, gridBagConstraints); - gridBagConstraints.gridy = 2; userButtonsPanel.add(bottomRow, gridBagConstraints); @@ -226,7 +268,7 @@ private JPanel topPanel(){ buttonGroup.add(yearlyInterval); buttonGroup.add(anyInterval); - JPanel timeFilter = new JPanel(); + timeFilter = new JPanel(); timeFilter.add(todayInterval); timeFilter.add(monthInterval); timeFilter.add(yearlyInterval); @@ -246,7 +288,7 @@ private JPanel topPanel(){ copyLink.addActionListener(this); questionMark.addActionListener(this); useN5Link.addActionListener(this); - switchMainTableContext.addActionListener(this); + includeExampleExports.addActionListener(this); Enumeration b = buttonGroup.getElements(); while (b.hasMoreElements()){ @@ -265,7 +307,6 @@ public static void enableCriticalButtons(boolean enable){ refreshButton.setEnabled(enable); copyLink.setEnabled(enable); remoteFileSelection.submitS3Info.setEnabled(enable); - switchMainTableContext.setEnabled(enable); } public static void setEnableParentAndChild(Container container, boolean enable){ @@ -311,12 +352,18 @@ public void actionPerformed(ActionEvent e) { new HelpExplanation().displayHelpMenu(); } else if (e.getSource().equals(useN5Link)) { remoteFileSelection.setVisible(true); - } else if (e.getSource().equals(switchMainTableContext)){ - String currentState = switchMainTableContext.getText(); - switchMainTableContext.setText(currentState.equals(optionForExampleTableButtonText) ? optionForPersonalTableButtonText : optionForExampleTableButtonText); + } else if (e.getSource().equals(includeExampleExports)){ + if(includeExampleExports.isSelected()){ + updateExampleExportsToTable(); + return; + } initalizeTableData(); } else if (e.getSource().equals(anyInterval) || e.getSource().equals(todayInterval) || e.getSource().equals(monthInterval) || e.getSource().equals(yearlyInterval)) { + if(includeExampleExports.isSelected()){ + updateExampleExportsToTable(); + return; + } initalizeTableData(); } } @@ -358,7 +405,7 @@ static class ParameterTableModel extends AbstractTableModel{ private List> tableData = new ArrayList<>(); - public final ArrayList headers = new ArrayList(){{ + private final ArrayList headers = new ArrayList(){{ add(parameterHeader); add(defaultValueHeader); add(newValueHeader); @@ -416,7 +463,7 @@ static class N5ExportTableModel extends AbstractTableModel { add("N5 File Name"); }}; - private List tableData = new ArrayList<>(); + private LinkedList tableData = new LinkedList<>(); public N5ExportTableModel(){ } @@ -459,10 +506,16 @@ public ExportDataRepresentation.SimulationExportDataRepresentation getRowData(in return tableData.get(rowIndex); } public void resetData(){ - tableData = new ArrayList<>(); + tableData = new LinkedList<>(); } - public void appendRowData(ExportDataRepresentation.SimulationExportDataRepresentation rowData){ + 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; } public ExportDataRepresentation.SimulationExportDataRepresentation getLastRowData(){ return tableData.get(0); From 854ef85dc7a1f45b4a67823149d1e9892b2a59e7 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 17 Jul 2024 10:08:33 -0400 Subject: [PATCH 04/18] Include Help --- .../src/main/java/org/vcell/N5/UI/HelpExplanation.java | 6 ++++-- .../src/main/java/org/vcell/N5/UI/N5ExportTable.java | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/view-simulation-results/src/main/java/org/vcell/N5/UI/HelpExplanation.java b/view-simulation-results/src/main/java/org/vcell/N5/UI/HelpExplanation.java index 8e65e04..2748266 100644 --- a/view-simulation-results/src/main/java/org/vcell/N5/UI/HelpExplanation.java +++ b/view-simulation-results/src/main/java/org/vcell/N5/UI/HelpExplanation.java @@ -27,14 +27,16 @@ public HelpExplanation(){ throw new RuntimeException(e); } textPane.setContentType("text/html"); - textPane.setSize(width, height); - textPane.setPreferredSize(new Dimension(width, height)); + textPane.setSize(width, 1000); + textPane.setPreferredSize(new Dimension(width, 1000)); textPane.setText(text); textPane.setEditable(false); JScrollPane scrollPane = new JScrollPane(textPane); scrollPane.setSize(width, height); + scrollPane.setPreferredSize(new Dimension(width, height)); helperPanel.setSize(width, height); + helperPanel.setPreferredSize(new Dimension(width, height)); helperPanel.add(scrollPane); 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 48aae2d..5895d41 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 @@ -220,6 +220,7 @@ private JPanel topPanel(){ copyLink = new JButton("Copy Link"); useN5Link = new JButton("Use N5 Link"); questionMark = new JButton("?"); + questionMark.setPreferredSize(new Dimension(20, 20)); openInMemory = new JCheckBox("Open In Memory"); openInMemory.setSelected(false); includeExampleExports = new JCheckBox("Show Example Exports"); @@ -236,6 +237,8 @@ private JPanel topPanel(){ topRow.add(copyLink, gridBagConstraints); gridBagConstraints.gridx = 2; topRow.add(useN5Link, gridBagConstraints); + gridBagConstraints.gridx = 3; + topRow.add(questionMark, gridBagConstraints); JPanel bottomRow = new JPanel(new GridBagLayout()); gridBagConstraints.gridx = 0; From e5e32a9f504531af43ed1482b29bc68e1845aff0 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 18 Jul 2024 21:30:39 -0400 Subject: [PATCH 05/18] Fixed Null Examples --- .../src/main/java/org/vcell/N5/N5ImageHandler.java | 1 + 1 file changed, 1 insertion(+) 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 75ebf1f..88bb4e1 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 @@ -39,6 +39,7 @@ public class N5ImageHandler implements Command { public void run() { exportTable = new N5ExportTable(); initializeLogService(); + setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); exportTable.displayExportTable(); } From 475d143b49f54c17de5a543a1033a4289eee434b Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 19 Jul 2024 08:47:13 -0400 Subject: [PATCH 06/18] Allow Self Signed Certs --- view-simulation-results/pom.xml | 23 +++++++++++++-- .../java/org/vcell/N5/SimResultsLoader.java | 29 +++++++++++++++++++ .../test/java/org/vcell/N5/N5DataSetFile.java | 2 +- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 875ddd4..5b82344 100644 --- a/view-simulation-results/pom.xml +++ b/view-simulation-results/pom.xml @@ -80,6 +80,18 @@ UTF-8 + + + + software.amazon.awssdk + bom + 2.17.290 + pom + import + + + + junit @@ -148,8 +160,6 @@ - - org.jsoup jsoup @@ -177,7 +187,14 @@ gson 2.10.1 - + + software.amazon.awssdk + apache-client + + + software.amazon.awssdk + s3 + 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 00f0359..fa14ae3 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 @@ -1,9 +1,11 @@ package org.vcell.N5; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.AnonymousAWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.http.conn.ssl.SdkTLSSocketFactory; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.AmazonS3URI; @@ -13,6 +15,9 @@ import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; import net.imglib2.type.numeric.real.DoubleType; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.ssl.SSLContexts; import org.janelia.saalfeldlab.n5.N5FSReader; import org.janelia.saalfeldlab.n5.N5KeyValueReader; import org.janelia.saalfeldlab.n5.N5Reader; @@ -22,6 +27,9 @@ import org.scijava.log.Logger; import org.vcell.N5.UI.N5ExportTable; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; import javax.swing.*; import java.awt.*; import java.io.File; @@ -29,6 +37,9 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLDecoder; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -86,6 +97,24 @@ public void createS3Client(String url, HashMap credentials, Hash // otherwise assume it is one of our URLs // http://vcell:8000/bucket/object/object2 catch (IllegalArgumentException e){ + 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); + } String[] pathSubStrings = uri.getPath().split("/", 3); this.s3ObjectKey = pathSubStrings[2]; this.bucketName = pathSubStrings[1]; diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index 2970f00..91b5d87 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -19,7 +19,7 @@ public N5DataSetFile(String uri, String[] variables, HashMap ma } public static N5DataSetFile[] alphaTestFiles(){ - N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcellapi-beta.cam.uchc.edu:8088/n5Data/ezequiel23/b5b12db07b6bc1bc15456fb59b530a19.n5?dataSetName=Plugin_Test_Frap_Masked", + N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/b5b12db07b6bc1bc15456fb59b530a19.n5?dataSetName=Plugin_Test_Frap_Masked", new String[]{"Dex"}, new HashMap(){{put(1, "Cyt"); put(0, "Ec");}}, new double[][]{{10.0, 9.990392675155721, 9.83580092714469, 9.520539931524715, 9.162150060086567, 8.82335160436397, 8.523689113752786, 8.265381795870683, 8.044751960699015, 7.856809648125466, From ae88d4d454fb7ea71df5556a3c1bc274ddb99473 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 19 Jul 2024 12:31:55 -0400 Subject: [PATCH 07/18] Fix examples URL and Deletion Bug If you deleted the most recent entry in the export table within VCell a duplication glitch would occur where all entries within the table will be duplicated indefinitely. --- .../src/main/java/org/vcell/N5/N5ImageHandler.java | 2 +- .../src/main/java/org/vcell/N5/UI/N5ExportTable.java | 3 ++- 2 files changed, 3 insertions(+), 2 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 88bb4e1..82d8bd8 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 @@ -78,7 +78,7 @@ public static ExportDataRepresentation.FormatExportDataRepresentation getJsonDat } private static void setExampleJSONData(){ - try(BufferedInputStream remoteJSONFile = new BufferedInputStream(new URL("https://api.npoint.io/b85bb21076bf422a7d93").openStream())){ + try(BufferedInputStream remoteJSONFile = new BufferedInputStream(new URL("https://api.npoint.io/6de0febb887fdc4c2fa0").openStream())){ InputStreamReader remoteJSONFileReader = new InputStreamReader(remoteJSONFile); Gson gson = new GsonBuilder().setPrettyPrinting().create(); exampleJSONData = gson.fromJson(remoteJSONFileReader, ExportDataRepresentation.class).formatData.get(N5ImageHandler.formatName); 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 5895d41..2e0443b 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 @@ -124,7 +124,8 @@ private void automaticRefresh(){ boolean isUpdated = false; while (!jobStack.isEmpty()){ String currentJob = jobStack.pop(); - if (mostRecentTableEntry != null && currentJob.equals(mostRecentTableEntry.jobID)){ + if (mostRecentTableEntry != null && (currentJob.equals(mostRecentTableEntry.jobID) + || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ break; } isUpdated = n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); From 6cd4bc52dac15df14f428089d086088fec806756 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 22 Jul 2024 09:15:54 -0400 Subject: [PATCH 08/18] New Export Tested and Updated Mask Function --- .../test/java/org/vcell/N5/N5DataSetFile.java | 4 +-- .../java/org/vcell/N5/N5ImageHandlerTest.java | 29 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index 91b5d87..c534c6f 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -6,7 +6,7 @@ public class N5DataSetFile { public String uri; public String[] variables; public HashMap mask; - public double[][] histMax; + public double[][] histMax; //channel(variable), frame for [][] public double[][] histMin; public double[][] histAverage; public N5DataSetFile(String uri, String[] variables, HashMap mask, double[][] histMax, double[][] histMin, double[][] histAverage){ @@ -19,7 +19,7 @@ public N5DataSetFile(String uri, String[] variables, HashMap ma } public static N5DataSetFile[] alphaTestFiles(){ - N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/b5b12db07b6bc1bc15456fb59b530a19.n5?dataSetName=Plugin_Test_Frap_Masked", + N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=6262029569", new String[]{"Dex"}, new HashMap(){{put(1, "Cyt"); put(0, "Ec");}}, new double[][]{{10.0, 9.990392675155721, 9.83580092714469, 9.520539931524715, 9.162150060086567, 8.82335160436397, 8.523689113752786, 8.265381795870683, 8.044751960699015, 7.856809648125466, 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 ee7d496..c3b07fd 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 @@ -5,6 +5,10 @@ import ij.io.Opener; import ij.plugin.Duplicator; import ij.plugin.ImageCalculator; +import ij.plugin.Thresholder; +import ij.process.Blitter; +import ij.process.ByteProcessor; +import ij.process.ImageProcessor; import org.junit.*; import java.io.File; @@ -126,7 +130,6 @@ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, stats testType){ double[][] controlData = {{}}; - imagePlus.setPosition(1, 0, 10); switch (testType){ case HISTMAX: controlData = n5DataSetFile.histMax; @@ -137,9 +140,9 @@ public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, sta case HISTAVERAGE: controlData = n5DataSetFile.histAverage; } - for(int k = 1; k < controlData.length; k++){ + for(int k = 0; k < controlData.length; k++){ for (int i = 0; i < controlData[k].length; i++){ - imagePlus.setPosition(k, 0, i+1); + imagePlus.setPosition(k + 1, 1, i + 1); //frame position seems to start at 1 double experimentalData = 0; switch (testType){ case HISTMAX: @@ -153,15 +156,27 @@ public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, sta setImageMask(imagePlus); experimentalData = imagePlus.getStatistics().mean; } - Assert.assertEquals(0.0, experimentalData - controlData[k][i], 0.000001); + Assert.assertEquals("Channel: " + k + " Time: " + i + " Stat: " + testType + + "\n Experiment Value: " + experimentalData + " Control Value: " + controlData[k][i] + ,0.0, experimentalData - controlData[k][i], 0.000001); } } } private void setImageMask(ImagePlus imagePlus){ - ImagePlus maskImagePlus = imagePlus.createImagePlus(); - maskImagePlus.setPosition(0, 0, 0); - imagePlus.getProcessor().setMask(maskImagePlus.createRoiMask()); + ImagePlus maskImagePlus = imagePlus.duplicate(); + maskImagePlus.setPosition(maskImagePlus.getNChannels(), 1, 1); + ImageProcessor maskProcessor = maskImagePlus.getChannelProcessor(); + int height = maskImagePlus.getHeight(); + int width = maskImagePlus.getWidth(); + for (int i = 0; i < height; i++){ + for (int k = 0; k < width; k++){ + int maskValue = maskProcessor.get(k, i); + if (maskValue == 0){ + imagePlus.getProcessor().setf(k, i, Float.NaN); + } + } + } } From 0618eb6ec1dfba5ad813ca90a2a7877dbcda8ccf Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Mon, 22 Jul 2024 12:37:17 -0400 Subject: [PATCH 09/18] Test The Units/Pixel There is a 1.3% error because of the way VCell handles the "atomic" unit of pixels (in VCell they aren't exactly atomic). It can be calculated to 0%, but this is an initial start. --- .../java/org/vcell/N5/SimResultsLoader.java | 17 +++++++ .../test/java/org/vcell/N5/N5DataSetFile.java | 22 ++++++--- .../java/org/vcell/N5/N5ImageHandlerTest.java | 49 +++++++++++++++++-- 3 files changed, 75 insertions(+), 13 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 fa14ae3..f8985de 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 @@ -11,6 +11,7 @@ import com.amazonaws.services.s3.AmazonS3URI; import com.google.gson.GsonBuilder; import ij.ImagePlus; +import ij.measure.Calibration; import ij.plugin.Duplicator; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; @@ -18,6 +19,7 @@ import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.ssl.SSLContexts; +import org.janelia.saalfeldlab.n5.N5Exception; import org.janelia.saalfeldlab.n5.N5FSReader; import org.janelia.saalfeldlab.n5.N5KeyValueReader; import org.janelia.saalfeldlab.n5.N5Reader; @@ -174,6 +176,7 @@ public ImagePlus getImgPlusFromN5File() throws IOException { ImagePlus imagePlus = ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5AmazonS3Reader, dataSetChosen), userSetFileName); long end = System.currentTimeMillis(); logger.debug("Read N5 File " + userSetFileName + " Into ImageJ taking: " + ((end - start) / 1000) + "s"); + setUnits(n5AmazonS3Reader, imagePlus); return imagePlus; } @@ -189,6 +192,20 @@ public void setURI(URI uri){ } } + private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ + try{ + double pixelWidth = n5Reader.getAttribute(dataSetChosen, "pixelWidth", double.class); + double pixelHeight = n5Reader.getAttribute(dataSetChosen, "pixelHeight", double.class); + String unit = n5Reader.getAttribute(dataSetChosen, "unit", String.class); + imagePlus.getCalibration().setUnit(unit); + imagePlus.getCalibration().pixelHeight = pixelHeight; + imagePlus.getCalibration().pixelWidth = pixelWidth; + } + catch (N5Exception n5Exception){ + logger.error("Can't read units."); + } + } + public void setDataSetChosen(String dataSetChosen) { this.dataSetChosen = dataSetChosen; } diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index c534c6f..0292683 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -3,19 +3,23 @@ import java.util.HashMap; public class N5DataSetFile { - public String uri; - public String[] variables; - public HashMap mask; - public double[][] histMax; //channel(variable), frame for [][] - public double[][] histMin; - public double[][] histAverage; - public N5DataSetFile(String uri, String[] variables, HashMap mask, double[][] histMax, double[][] histMin, double[][] histAverage){ + public final String uri; + public final String[] variables; + public final HashMap mask; + public final double[][] histMax; //channel(variable), frame for [][] + public final double[][] histMin; + public final double[][] histAverage; + public final double totalArea; + public final double testDomainArea; + public N5DataSetFile(String uri, String[] variables, HashMap mask, double[][] histMax, double[][] histMin, double[][] histAverage, double totalArea, double testDomainArea){ this.uri = uri; this.histMax = histMax; this.histMin = histMin; this.histAverage = histAverage; this.variables = variables; this.mask = mask; + this.totalArea = totalArea; + this.testDomainArea = testDomainArea; } public static N5DataSetFile[] alphaTestFiles(){ @@ -29,7 +33,9 @@ public static N5DataSetFile[] alphaTestFiles(){ 4.441933641025697, 4.752525652114409, 5.021489447662615, 5.25417298783172, 5.4553370523518065, 5.62917275251317, 5.7793451286004585, 5.909046810912881, 6.0210510711120975}}, new double[][]{{ 6.728509585652239, 6.7285095856523345, 6.728509585652324, 6.72850958565233, 6.728509585652335, 6.728509585652381, 6.728509585652381, 6.728509585652362, 6.728509585652365, - 6.728509585652356, 6.7285095856523185, 6.728509585652278, 6.7285095856522865, 6.728509585652241, 6.728509585652113, 6.728509585652124, 6.7285095856521355, 6.728509585652127, 6.728509585652108}}); + 6.728509585652356, 6.7285095856523185, 6.728509585652278, 6.7285095856522865, 6.728509585652241, 6.728509585652113, 6.728509585652124, 6.7285095856521355, 6.728509585652127, 6.728509585652108}}, + 484, + 314.64); return new N5DataSetFile[]{frapSimulationResultsMasked}; } 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 c3b07fd..4b80cec 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 @@ -1,13 +1,9 @@ package org.vcell.N5; -import com.amazonaws.regions.Regions; import ij.ImagePlus; import ij.io.Opener; import ij.plugin.Duplicator; import ij.plugin.ImageCalculator; -import ij.plugin.Thresholder; -import ij.process.Blitter; -import ij.process.ByteProcessor; import ij.process.ImageProcessor; import org.junit.*; @@ -16,7 +12,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; /* @@ -128,6 +123,50 @@ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { } } + interface PixelCalculations { + int grabEdge(int w, int h, int w1, int h1); + } + + @Test + public void testUnits() throws IOException { + N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); + for (N5DataSetFile n5DataSetFile: n5DataSetFiles){ + SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); + simResultsLoader.createS3Client(); + ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); + double areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1); + double totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight(); + Assert.assertEquals(n5DataSetFile.totalArea, totalArea, 0.0000001); + + totalArea = 0; + imagePlus.setPosition(imagePlus.getNChannels(), 1, 1); + ImageProcessor imageProcessor = imagePlus.getProcessor(); + + PixelCalculations pixelCalculations = ((w, h, w1, h1) -> { + int inBounds = (0 <= w1) && (w1 < imagePlus.getWidth()) && (0 <= h1) && (h1 < imagePlus.getHeight()) ? 2 : 1; + if (inBounds == 2 && imageProcessor.getf(w1, h1) != imageProcessor.getf(w, h)){ + return inBounds; + } + return 1; + }); + for (int h = 0; h < imagePlus.getHeight(); h++){ + for (int w = 0; w < imagePlus.getWidth(); w++){ + double sum = pixelCalculations.grabEdge(w, h, w, h -1) * + pixelCalculations.grabEdge(w, h, w, h + 1) * + pixelCalculations.grabEdge(w, h,w + 1, h) * + pixelCalculations.grabEdge(w, h,w -1, h); + if (imageProcessor.getf(w, h) != 1 && sum > 1){ + totalArea += (areaOfPixel / sum); + } + if (imageProcessor.getf(w, h) == 1){ + totalArea += areaOfPixel; + } + } + } + Assert.assertEquals(n5DataSetFile.testDomainArea, totalArea, n5DataSetFile.testDomainArea * 0.013); + } + } + public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, stats testType){ double[][] controlData = {{}}; switch (testType){ From 2a67de53098b1b7fdb11c0c31a5b1fb06b03d198 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 26 Jul 2024 09:39:38 -0400 Subject: [PATCH 10/18] Set Metadata for Images in their Properties --- .../java/org/vcell/N5/SimResultsLoader.java | 73 ++++++++++--------- 1 file changed, 37 insertions(+), 36 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 f8985de..53e18bd 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 @@ -53,18 +53,47 @@ public class SimResultsLoader { private String s3ObjectKey; private URI uri; private String dataSetChosen; - private String userSetFileName; + private String userSetFileName = null; private static final Logger logger = N5ImageHandler.getLogger(SimResultsLoader.class); public SimResultsLoader(){ } + public void createS3Client(){ + createS3Client(uri.toString(), null, null); + } + public void setDataSetChosen(String dataSetChosen) { + this.dataSetChosen = dataSetChosen; + } + + public void setSelectedLocalFile(File selectedLocalFile){ + this.selectedLocalFile = selectedLocalFile; + } + public void createS3Client(HashMap credentials, HashMap endpoint){createS3Client(uri.toString(), credentials, endpoint);} + public 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))); + } + } + public ImagePlus getImgPlusFromLocalN5File() throws IOException { + N5Reader n5Reader = new N5FSReader(selectedLocalFile.getPath()); + return ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5Reader, dataSetChosen), userSetFileName); + } public SimResultsLoader(String stringURI, String userSetFileName){ uri = URI.create(stringURI); this.userSetFileName = userSetFileName; - setURI(uri); + if(!(uri.getQuery() == null)){ + dataSetChosen = uri.getQuery().split("=")[1]; // query should be "dataSetName=name", thus splitting it by = and getting the second entry gives the name + try { + dataSetChosen = URLDecoder.decode(dataSetChosen, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } } public void createS3Client(String url, HashMap credentials, HashMap endpoint){ @@ -127,19 +156,7 @@ public boolean verify(String hostname, SSLSession session) { logger.debug("Created S3 Client With Legacy URL"); } } - //When creating client's try to make one for an Amazon link, otherwise use our custom url scheme - public void createS3Client(){ - createS3Client(uri.toString(), null, null); - } - public void createS3Client(HashMap credentials, HashMap endpoint){createS3Client(uri.toString(), credentials, endpoint);} - public 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))); - } - } public ArrayList getN5DatasetList() throws IOException { // auto closes reader @@ -157,14 +174,7 @@ public ArrayList getN5DatasetList() throws IOException { } } - public void setSelectedLocalFile(File selectedLocalFile){ - this.selectedLocalFile = selectedLocalFile; - } - public ImagePlus getImgPlusFromLocalN5File() throws IOException { - N5Reader n5Reader = new N5FSReader(selectedLocalFile.getPath()); - return ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5Reader, dataSetChosen), userSetFileName); - } public ImagePlus getImgPlusFromN5File() throws IOException { AmazonS3KeyValueAccess amazonS3KeyValueAccess = new AmazonS3KeyValueAccess(s3Client, bucketName, false); @@ -173,25 +183,19 @@ public ImagePlus getImgPlusFromN5File() throws IOException { // N5AmazonS3Reader n5AmazonS3Reader = new N5AmazonS3Reader(s3Client, bucketName, "/" + s3ObjectKey); 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); + } ImagePlus imagePlus = ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5AmazonS3Reader, dataSetChosen), userSetFileName); long end = System.currentTimeMillis(); logger.debug("Read N5 File " + userSetFileName + " Into ImageJ taking: " + ((end - start) / 1000) + "s"); + setUnits(n5AmazonS3Reader, imagePlus); + imagePlus.setProperty("channelInfo", n5AmazonS3Reader.getAttribute(dataSetChosen, "channelInfo", HashMap.class)); + imagePlus.setProperty("maskInfo", n5AmazonS3Reader.getAttribute(dataSetChosen, "maskMapping", HashMap.class)); return imagePlus; } - public void setURI(URI uri){ - this.uri = uri; - if(!(uri.getQuery() == null)){ - dataSetChosen = uri.getQuery().split("=")[1]; // query should be "dataSetName=name", thus splitting it by = and getting the second entry gives the name - try { - dataSetChosen = URLDecoder.decode(dataSetChosen, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - } - private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ try{ double pixelWidth = n5Reader.getAttribute(dataSetChosen, "pixelWidth", double.class); @@ -206,9 +210,6 @@ private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ } } - public void setDataSetChosen(String dataSetChosen) { - this.dataSetChosen = dataSetChosen; - } public static void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ N5ExportTable.enableCriticalButtons(false); From eebfd149ef09949c65ad341ba2a9fcb26ef4ce37 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 26 Jul 2024 09:40:09 -0400 Subject: [PATCH 11/18] Remove Old Test --- .../java/org/vcell/N5/N5ImageHandlerTest.java | 31 ------------------- 1 file changed, 31 deletions(-) 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 4b80cec..651b889 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 @@ -64,37 +64,6 @@ public void testGettingImgPlus() throws IOException { fiveDStackTests(imagePlus); } -// @Test -// // Create client without creds, with cred no endpoint, endpoint no creds, endpoint and creds, then test whether they can handle images as expected -// public void testS3Client() throws IOException { -// HashMap s3Endpoint = new HashMap<>(); -// HashMap credentials = new HashMap<>(); -// -// s3Endpoint.put("Endpoint", "http://127.0.0.1:4000"); -// s3Endpoint.put("Region", Regions.US_EAST_1.getName()); -// -// credentials.put("AccessKey", "jj"); -// credentials.put("SecretKey", "jj"); -// -// final String s3ProxyURI = "http://localhost:4000/" + this.n5FileName + "?datasetName=" + datasetName; -// -// SimResultsLoader simResultsLoader = new SimResultsLoader(s3ProxyURI, ""); -// -// // Environment variables are set in github actions VM -// -// simResultsLoader.createS3Client(null, null); -// this.remoteN5ImgPlusTests(simResultsLoader); -// -// simResultsLoader.createS3Client(null, s3Endpoint); -// this.remoteN5ImgPlusTests(simResultsLoader); -// -//// simResultsLoader.createS3Client(credentials, null); -//// this.remoteN5ImgPlusTests(simResultsLoader); -//// -//// simResultsLoader.createS3Client(credentials, s3Endpoint); -//// this.remoteN5ImgPlusTests(simResultsLoader); -// } - @Test public void testS3AlphaInstance() throws IOException{ N5DataSetFile[] n5DataSetFiles = N5DataSetFile.alphaTestFiles(); From 6a0cf5f3ea185be3394ffbf6df28509472a1f369 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 26 Jul 2024 09:40:49 -0400 Subject: [PATCH 12/18] Mask Setting for Tests --- .../java/org/vcell/N5/N5ImageHandlerTest.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) 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 651b889..387678c 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 @@ -171,20 +171,32 @@ public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, sta } } - private void setImageMask(ImagePlus imagePlus){ + private ImagePlus setImageMask(ImagePlus imagePlus){ ImagePlus maskImagePlus = imagePlus.duplicate(); - maskImagePlus.setPosition(maskImagePlus.getNChannels(), 1, 1); - ImageProcessor maskProcessor = maskImagePlus.getChannelProcessor(); + LinkedTreeMap> channelInfo = (LinkedTreeMap>) imagePlus.getProperty("channelInfo"); + String domainName = (String) channelInfo.get(String.valueOf(imagePlus.getChannel() - 1)).get("Domain"); + LinkedTreeMap maskInfo = (LinkedTreeMap) imagePlus.getProperty("maskInfo"); + int domainMaskValue = 0; + for (Map.Entry entry : maskInfo.entrySet()) { + if (entry.getValue().equals(domainName)) { + domainMaskValue = Integer.parseInt(entry.getKey()); + break; + } + } + + maskImagePlus.setPosition(maskImagePlus.getNChannels(), imagePlus.getSlice(), imagePlus.getFrame()); + ImageProcessor maskProcessor = maskImagePlus.getProcessor(); int height = maskImagePlus.getHeight(); int width = maskImagePlus.getWidth(); - for (int i = 0; i < height; i++){ - for (int k = 0; k < width; k++){ - int maskValue = maskProcessor.get(k, i); - if (maskValue == 0){ - imagePlus.getProcessor().setf(k, i, Float.NaN); + for (int h = 0; h < height; h++){ + for (int w = 0; w < width; w++){ + float maskValue = maskProcessor.getPixelValue(w, h); + if (maskValue != domainMaskValue){ + imagePlus.getProcessor().setf(w, h, Float.NaN); } } } + return imagePlus; } From b20a80e276ae418373e35a109a94a3acaa3d4def Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 26 Jul 2024 14:36:18 -0400 Subject: [PATCH 13/18] Calculate Mean, Min and Max for 5D Images Statistical tests that calculate the mean, min, and max for N5 files loaded into images. --- .../test/java/org/vcell/N5/N5DataSetFile.java | 31 ++++- .../java/org/vcell/N5/N5ImageHandlerTest.java | 125 ++++++++++++++---- 2 files changed, 127 insertions(+), 29 deletions(-) diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index 0292683..d6eb65a 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -10,8 +10,8 @@ public class N5DataSetFile { public final double[][] histMin; public final double[][] histAverage; public final double totalArea; - public final double testDomainArea; - public N5DataSetFile(String uri, String[] variables, HashMap mask, double[][] histMax, double[][] histMin, double[][] histAverage, double totalArea, double testDomainArea){ + public final double[] testDomainArea; + public N5DataSetFile(String uri, String[] variables, HashMap mask, double[][] histMax, double[][] histMin, double[][] histAverage, double totalArea, double[] testDomainArea){ this.uri = uri; this.histMax = histMax; this.histMin = histMin; @@ -23,7 +23,7 @@ public N5DataSetFile(String uri, String[] variables, HashMap ma } public static N5DataSetFile[] alphaTestFiles(){ - N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=6262029569", + N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=4457702594", new String[]{"Dex"}, new HashMap(){{put(1, "Cyt"); put(0, "Ec");}}, new double[][]{{10.0, 9.990392675155721, 9.83580092714469, 9.520539931524715, 9.162150060086567, 8.82335160436397, 8.523689113752786, 8.265381795870683, 8.044751960699015, 7.856809648125466, @@ -35,9 +35,30 @@ public static N5DataSetFile[] alphaTestFiles(){ 6.728509585652239, 6.7285095856523345, 6.728509585652324, 6.72850958565233, 6.728509585652335, 6.728509585652381, 6.728509585652381, 6.728509585652362, 6.728509585652365, 6.728509585652356, 6.7285095856523185, 6.728509585652278, 6.7285095856522865, 6.728509585652241, 6.728509585652113, 6.728509585652124, 6.7285095856521355, 6.728509585652127, 6.728509585652108}}, 484, - 314.64); + new double[]{0,314.64}); - return new N5DataSetFile[]{frapSimulationResultsMasked}; + N5DataSetFile anns5DTIRFSimulation = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/a530ce83268de2a.n5?dataSetName=3340371272", + new String[]{"Dark", "Flour"}, + new HashMap(){{put(0, "ec"); put(1, "cytosol"); put(2, "Nucleus");}}, + new double[][]{ + {2.2250738585072014E-308, 2.2250738585072014E-308, 2.2250738585072014E-308, 3.52810806343277, 3.67238125879494, + 0.37504412562962713, 0.1941393552238283}, + {10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0} + }, + new double[][]{ + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {10.0, 10.0, 10.0, 6.471891936567229, 6.32761874120506, 9.624955874370375, 9.805860644776171} + }, + new double[][]{ + {0.0, 0.0, 0.0, 0.007280282509686344, 0.013997372023832945, 0.013997372023832947, 0.013997372023832949}, + {9.999999999999494, 9.999999999999494, 9.999999999999494, 9.992719717489994, 9.986002627975711, + 9.98600262797569, 9.986002627975722} + }, + 143300, + new double[]{0, 14891, 3697} + ); + + return new N5DataSetFile[]{frapSimulationResultsMasked, anns5DTIRFSimulation}; } } 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 387678c..de66517 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 @@ -1,17 +1,21 @@ package org.vcell.N5; +import com.google.gson.internal.LinkedTreeMap; import ij.ImagePlus; import ij.io.Opener; import ij.plugin.Duplicator; import ij.plugin.ImageCalculator; import ij.process.ImageProcessor; -import org.junit.*; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; +import java.util.Map; /* @@ -86,9 +90,13 @@ public void testS3AlphaInstanceLoadedIntoMemory() throws IOException { SimResultsLoader simResultsLoader = new SimResultsLoader(n5DataSetFile.uri, ""); simResultsLoader.createS3Client(); ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); - alphaStatsTest(new Duplicator().run(imagePlus), n5DataSetFile, stats.HISTMAX); - alphaStatsTest(new Duplicator().run(imagePlus), n5DataSetFile, stats.HISTMIN); - alphaStatsTest(new Duplicator().run(imagePlus), n5DataSetFile, stats.HISTAVERAGE); + ImagePlus inMemory = new Duplicator().run(imagePlus); + for (Object property : imagePlus.getProperties().keySet()){ + inMemory.setProperty((String) property, imagePlus.getProperty((String) property)); + } + alphaStatsTest(inMemory, n5DataSetFile, stats.HISTMAX); + alphaStatsTest(inMemory, n5DataSetFile, stats.HISTMIN); + alphaStatsTest(inMemory, n5DataSetFile, stats.HISTAVERAGE); } } @@ -105,35 +113,100 @@ public void testUnits() throws IOException { ImagePlus imagePlus = simResultsLoader.getImgPlusFromN5File(); double areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1); double totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight(); + + boolean threeD = imagePlus.getNSlices() > 1; + if (threeD){ + areaOfPixel *= imagePlus.getCalibration().getZ(1); + totalArea *= imagePlus.getDimensions()[3]; + } Assert.assertEquals(n5DataSetFile.totalArea, totalArea, 0.0000001); - totalArea = 0; imagePlus.setPosition(imagePlus.getNChannels(), 1, 1); ImageProcessor imageProcessor = imagePlus.getProcessor(); - PixelCalculations pixelCalculations = ((w, h, w1, h1) -> { int inBounds = (0 <= w1) && (w1 < imagePlus.getWidth()) && (0 <= h1) && (h1 < imagePlus.getHeight()) ? 2 : 1; - if (inBounds == 2 && imageProcessor.getf(w1, h1) != imageProcessor.getf(w, h)){ + boolean edgeOfDomain = (inBounds == 2) && + (imageProcessor.getf(w1, h1) != imageProcessor.getf(w, h)); + if (edgeOfDomain){ return inBounds; } return 1; }); - for (int h = 0; h < imagePlus.getHeight(); h++){ - for (int w = 0; w < imagePlus.getWidth(); w++){ - double sum = pixelCalculations.grabEdge(w, h, w, h -1) * + + for(int domain: n5DataSetFile.mask.keySet()){ + totalArea = 0; + for (int h = 0; h < imagePlus.getHeight(); h++){ + for (int w = 0; w < imagePlus.getWidth(); w++){ + double sum = pixelCalculations.grabEdge(w, h, w, h -1) * pixelCalculations.grabEdge(w, h, w, h + 1) * pixelCalculations.grabEdge(w, h,w + 1, h) * pixelCalculations.grabEdge(w, h,w -1, h); - if (imageProcessor.getf(w, h) != 1 && sum > 1){ - totalArea += (areaOfPixel / sum); + if (imageProcessor.getf(w,h) != domain && sum > 1 && domain != 0){ + totalArea += (areaOfPixel / sum); + } + if (imageProcessor.getf(w, h) == domain && domain != 0){ + totalArea += areaOfPixel; + } + } + } + Assert.assertEquals(n5DataSetFile.testDomainArea[domain], totalArea, n5DataSetFile.testDomainArea[domain] * 0.013); + } + } + } + + private double alphaStatsThreeD(ImagePlus imagePlus, stats testType, int channel, int frame){ + double experimentValue = Double.NaN; + for (int z = 1; z <= imagePlus.getNSlices(); z++){ + imagePlus.setPosition(channel, z, frame); + double currentValue; + switch (testType){ + case HISTMAX: + setImageMask(imagePlus); + currentValue = imagePlus.getStatistics().max; + if (currentValue == -Double.MAX_VALUE){ + currentValue = 0; } - if (imageProcessor.getf(w, h) == 1){ - totalArea += areaOfPixel; + if (Double.isNaN(experimentValue) || experimentValue < currentValue){ + experimentValue = currentValue; + } + break; + case HISTMIN: + setImageMask(imagePlus); + currentValue = imagePlus.getStatistics().min; + if (Double.isNaN(experimentValue) || experimentValue > currentValue){ + experimentValue = currentValue; + } + break; + case HISTAVERAGE: + experimentValue = average3D(imagePlus); + } + if (testType.equals(stats.HISTAVERAGE)){ + break; + } + } + return experimentValue; + } + + private double average3D(ImagePlus imagePlus){ + double total = 0; + double voxelVolume = imagePlus.getCalibration().pixelHeight * imagePlus.getCalibration().pixelWidth * imagePlus.getCalibration().pixelDepth; + double totalVolume = 0; + for (int z = 1; z < imagePlus.getNSlices(); z++){ + imagePlus.setPosition(imagePlus.getChannel(), z, imagePlus.getFrame()); + setImageMask(imagePlus); + ImageProcessor imageProcessor = imagePlus.getProcessor(); + for (int x = 0; x < imagePlus.getWidth(); x++){ + for (int y = 0; y < imagePlus.getHeight(); y++){ + double pixelValue = imageProcessor.getValue(x, y); + if (!Double.isNaN(pixelValue)){ + total += (pixelValue * voxelVolume); + totalVolume += voxelVolume; } } } - Assert.assertEquals(n5DataSetFile.testDomainArea, totalArea, n5DataSetFile.testDomainArea * 0.013); + } + return (total / totalVolume ); } public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, stats testType){ @@ -148,25 +221,29 @@ public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, sta case HISTAVERAGE: controlData = n5DataSetFile.histAverage; } - for(int k = 0; k < controlData.length; k++){ - for (int i = 0; i < controlData[k].length; i++){ - imagePlus.setPosition(k + 1, 1, i + 1); //frame position seems to start at 1 + boolean threeD = imagePlus.getNSlices() > 1; + for(int channel = 1; channel <= controlData.length; channel++){ + for (int frame = 1; frame <= controlData[channel - 1].length; frame++){ + imagePlus.setPosition(channel, 1, frame); //frame position seems to start at 1 double experimentalData = 0; switch (testType){ case HISTMAX: - experimentalData = imagePlus.getStatistics().histMax; + experimentalData = threeD ? alphaStatsThreeD(imagePlus, testType, channel, frame) : + imagePlus.getStatistics().max; break; case HISTMIN: setImageMask(imagePlus); - experimentalData = imagePlus.getStatistics().min; + experimentalData = threeD ? alphaStatsThreeD(imagePlus, testType, channel, frame) : + imagePlus.getStatistics().min; break; case HISTAVERAGE: setImageMask(imagePlus); - experimentalData = imagePlus.getStatistics().mean; + experimentalData = threeD ? alphaStatsThreeD(imagePlus, testType, channel, frame) : + imagePlus.getStatistics().mean; } - Assert.assertEquals("Channel: " + k + " Time: " + i + " Stat: " + testType + - "\n Experiment Value: " + experimentalData + " Control Value: " + controlData[k][i] - ,0.0, experimentalData - controlData[k][i], 0.000001); + Assert.assertEquals("Channel: " + channel + " Time: " + frame + " Stat: " + testType + + "\n Experiment Value: " + experimentalData + " Control Value: " + controlData[channel - 1][frame - 1] + ,0.0, experimentalData - controlData[channel - 1][frame - 1], 0.0001); } } } From 012de0e5711d6657e8cddef5cebdb7fdc702bd24 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Wed, 7 Aug 2024 07:32:33 -0400 Subject: [PATCH 14/18] Full Test Coverage With the new method for exporting N5 files the area for each domain is exactly what is expected. --- .../java/org/vcell/N5/SimResultsLoader.java | 2 + .../test/java/org/vcell/N5/N5DataSetFile.java | 11 +++-- .../java/org/vcell/N5/N5ImageHandlerTest.java | 47 ++++++++++--------- 3 files changed, 32 insertions(+), 28 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 53e18bd..0e26e13 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 @@ -200,10 +200,12 @@ private void setUnits(N5Reader n5Reader, ImagePlus imagePlus){ try{ double pixelWidth = n5Reader.getAttribute(dataSetChosen, "pixelWidth", double.class); double pixelHeight = n5Reader.getAttribute(dataSetChosen, "pixelHeight", double.class); + double pixelDepth = n5Reader.getAttribute(dataSetChosen, "pixelDepth", double.class); String unit = n5Reader.getAttribute(dataSetChosen, "unit", String.class); imagePlus.getCalibration().setUnit(unit); imagePlus.getCalibration().pixelHeight = pixelHeight; imagePlus.getCalibration().pixelWidth = pixelWidth; + imagePlus.getCalibration().pixelDepth = pixelDepth; } catch (N5Exception n5Exception){ logger.error("Can't read units."); diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index d6eb65a..a9c0963 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -21,9 +21,10 @@ public N5DataSetFile(String uri, String[] variables, HashMap ma this.totalArea = totalArea; this.testDomainArea = testDomainArea; } +// https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=4130889219 public static N5DataSetFile[] alphaTestFiles(){ - N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=4457702594", + N5DataSetFile frapSimulationResultsMasked = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=4130889219", new String[]{"Dex"}, new HashMap(){{put(1, "Cyt"); put(0, "Ec");}}, new double[][]{{10.0, 9.990392675155721, 9.83580092714469, 9.520539931524715, 9.162150060086567, 8.82335160436397, 8.523689113752786, 8.265381795870683, 8.044751960699015, 7.856809648125466, @@ -35,9 +36,9 @@ public static N5DataSetFile[] alphaTestFiles(){ 6.728509585652239, 6.7285095856523345, 6.728509585652324, 6.72850958565233, 6.728509585652335, 6.728509585652381, 6.728509585652381, 6.728509585652362, 6.728509585652365, 6.728509585652356, 6.7285095856523185, 6.728509585652278, 6.7285095856522865, 6.728509585652241, 6.728509585652113, 6.728509585652124, 6.7285095856521355, 6.728509585652127, 6.728509585652108}}, 484, - new double[]{0,314.64}); + new double[]{170.94880000000251,313.05120000000511}); - N5DataSetFile anns5DTIRFSimulation = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/a530ce83268de2a.n5?dataSetName=3340371272", + N5DataSetFile anns5DTIRFSimulation = new N5DataSetFile("https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/a530ce83268de2a.n5?dataSetName=5371385960", new String[]{"Dark", "Flour"}, new HashMap(){{put(0, "ec"); put(1, "cytosol"); put(2, "Nucleus");}}, new double[][]{ @@ -54,8 +55,8 @@ public static N5DataSetFile[] alphaTestFiles(){ {9.999999999999494, 9.999999999999494, 9.999999999999494, 9.992719717489994, 9.986002627975711, 9.98600262797569, 9.986002627975722} }, - 143300, - new double[]{0, 14891, 3697} + 143301, + new double[]{124412.82212538144, 15317.6945829, 3570.5008917656078} ); return new N5DataSetFile[]{frapSimulationResultsMasked, anns5DTIRFSimulation}; 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 de66517..a5f25da 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 @@ -116,40 +116,41 @@ public void testUnits() throws IOException { boolean threeD = imagePlus.getNSlices() > 1; if (threeD){ - areaOfPixel *= imagePlus.getCalibration().getZ(1); - totalArea *= imagePlus.getDimensions()[3]; + areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1) * imagePlus.getCalibration().getZ(1); + totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight() * imagePlus.getNSlices(); } - Assert.assertEquals(n5DataSetFile.totalArea, totalArea, 0.0000001); + Assert.assertEquals(n5DataSetFile.totalArea, totalArea, n5DataSetFile.totalArea * 0.0001); imagePlus.setPosition(imagePlus.getNChannels(), 1, 1); ImageProcessor imageProcessor = imagePlus.getProcessor(); - PixelCalculations pixelCalculations = ((w, h, w1, h1) -> { - int inBounds = (0 <= w1) && (w1 < imagePlus.getWidth()) && (0 <= h1) && (h1 < imagePlus.getHeight()) ? 2 : 1; - boolean edgeOfDomain = (inBounds == 2) && - (imageProcessor.getf(w1, h1) != imageProcessor.getf(w, h)); - if (edgeOfDomain){ - return inBounds; - } - return 1; - }); for(int domain: n5DataSetFile.mask.keySet()){ totalArea = 0; - for (int h = 0; h < imagePlus.getHeight(); h++){ - for (int w = 0; w < imagePlus.getWidth(); w++){ - double sum = pixelCalculations.grabEdge(w, h, w, h -1) * - pixelCalculations.grabEdge(w, h, w, h + 1) * - pixelCalculations.grabEdge(w, h,w + 1, h) * - pixelCalculations.grabEdge(w, h,w -1, h); - if (imageProcessor.getf(w,h) != domain && sum > 1 && domain != 0){ - totalArea += (areaOfPixel / sum); + + if(!threeD) { + for (int h = 0; h < imagePlus.getHeight(); h++) { + for (int w = 0; w < imagePlus.getWidth(); w++) { + if (imageProcessor.getf(w, h) == domain) { + totalArea += areaOfPixel; + } } - if (imageProcessor.getf(w, h) == domain && domain != 0){ - totalArea += areaOfPixel; + } + } + else{ + for (int k = 0; k < imagePlus.getNSlices(); k++){ + imagePlus.setPosition(imagePlus.getNChannels(), k + 1, 1); + imageProcessor = imagePlus.getProcessor(); + for (int h = 0; h < imagePlus.getHeight(); h++) { + for (int w = 0; w < imagePlus.getWidth(); w++) { + if (imageProcessor.getf(w, h) == domain) { + totalArea += areaOfPixel; + } + } } } } - Assert.assertEquals(n5DataSetFile.testDomainArea[domain], totalArea, n5DataSetFile.testDomainArea[domain] * 0.013); + Assert.assertEquals("Domain: " + domain + ", Total Area: " + totalArea, + n5DataSetFile.testDomainArea[domain], totalArea, 0.000001); } } } From fbcf680f82a0d0449dae6edff433e11aab755299 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 9 Aug 2024 07:16:57 -0400 Subject: [PATCH 15/18] Update Table More Quickly --- .../main/java/org/vcell/N5/SimResultsLoader.java | 2 +- .../main/java/org/vcell/N5/UI/N5ExportTable.java | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 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 0e26e13..40ad584 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 @@ -97,7 +97,7 @@ public SimResultsLoader(String stringURI, String userSetFileName){ } public void createS3Client(String url, HashMap credentials, HashMap endpoint){ - logger.debug("Creating S3 Client"); + logger.debug("Creating S3 Client with url: " + url); AmazonS3ClientBuilder s3ClientBuilder = AmazonS3ClientBuilder.standard(); URI uri = URI.create(url); 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 2e0443b..efbbfd0 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 @@ -128,14 +128,14 @@ private void automaticRefresh(){ || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ break; } - isUpdated = n5ExportTableModel.appendRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); + isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); } if(isUpdated){ n5ExportTableModel.fireTableDataChanged(); tableScrollPane.updateUI(); } } - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + Thread.sleep(TimeUnit.SECONDS.toMillis(2)); } } catch (FileNotFoundException e) { throw new RuntimeException("Problem Loading Export JSON",e); @@ -521,6 +521,17 @@ public boolean appendRowData(ExportDataRepresentation.SimulationExportDataRepres tableData.add(rowData); return true; } + + public boolean prependRowData(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.addFirst(rowData); + return true; + } + public ExportDataRepresentation.SimulationExportDataRepresentation getLastRowData(){ return tableData.get(0); } From 4dbcd33e9a679a2cedeba90e9d0466918fa8309d Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 9 Aug 2024 07:17:05 -0400 Subject: [PATCH 16/18] ReadME --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index caef23d..224380d 100644 --- a/README.md +++ b/README.md @@ -1 +1,13 @@ -# vcell-fiji \ No newline at end of file +## VCell's Introduction to Analysing Simulation Results in Fiji + +--- + +[Virtual Cell](https://vcell.org/) is a +comprehensive platform for modeling cell biological +systems, and produces simulation results for these systems. + +As another analysis avenue we have added the new N5 +export file which takes spatial simulation results, and +allow it to be accessed remotely. This plugin can then +read these simulation results stored on our servers in +the N5 format, and open them within Fiji. From 9a9e8906823f9392ede1a673345be34d9c88507f Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Thu, 15 Aug 2024 11:49:12 -0400 Subject: [PATCH 17/18] Custom Cache Loader This custom cache loader allows us to control what occurs when read requests are executed by ImageJ. --- .../java/org/vcell/N5/SimCacheLoader.java | 78 +++++++++++++++++++ .../java/org/vcell/N5/SimResultsLoader.java | 8 +- 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java diff --git a/view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java b/view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java new file mode 100644 index 0000000..b8c24a6 --- /dev/null +++ b/view-simulation-results/src/main/java/org/vcell/N5/SimCacheLoader.java @@ -0,0 +1,78 @@ +package org.vcell.N5; + +import ij.ImagePlus; +import ij.gui.ImageWindow; +import net.imglib2.IterableInterval; +import net.imglib2.cache.Cache; +import net.imglib2.cache.LoaderCache; +import net.imglib2.cache.img.CachedCellImg; +import net.imglib2.cache.ref.SoftRefLoaderCache; +import net.imglib2.img.basictypeaccess.AccessFlags; +import net.imglib2.img.basictypeaccess.ArrayDataAccessFactory; +import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; +import net.imglib2.img.cell.Cell; +import net.imglib2.img.cell.CellGrid; +import net.imglib2.type.NativeType; +import org.janelia.saalfeldlab.n5.DatasetAttributes; +import org.janelia.saalfeldlab.n5.N5Exception; +import org.janelia.saalfeldlab.n5.N5Reader; +import org.janelia.saalfeldlab.n5.imglib2.N5CacheLoader; +import org.janelia.saalfeldlab.n5.imglib2.N5Utils; + +import java.awt.*; +import java.util.Set; +import java.util.function.Consumer; + + +public class SimCacheLoader, A extends ArrayDataAccess> extends N5CacheLoader { + + private final CellGrid cellGrid; + private final LoaderCache> loaderCache; + private final T type; + private final Set accessFlags; + private ImagePlus imagesResponsibleFor; + + + public SimCacheLoader(N5Reader n5, String dataset, CellGrid grid, T type, Set accessFlags, Consumer> blockNotFoundHandler, LoaderCache> loaderCache) throws N5Exception { + super(n5, dataset, grid, type, accessFlags, blockNotFoundHandler); + this.cellGrid = grid; + this.loaderCache = loaderCache; + this.type = type; + this.accessFlags = accessFlags; + } + + public CachedCellImg createCachedCellImage(){ + final Cache> cache = this.loaderCache.withLoader(this); + return new CachedCellImg<>(cellGrid, type, cache, ArrayDataAccessFactory.get(type, accessFlags)); + } + + public void setImagesResponsibleFor(ImagePlus imagePlus){ + imagesResponsibleFor = imagePlus; + } + + public static , A extends ArrayDataAccess> SimCacheLoader factoryDefault(N5Reader n5Reader, String dataset){ + final DatasetAttributes attributes = n5Reader.getDatasetAttributes(dataset); + final long[] dimensions = attributes.getDimensions(); + final int[] blockSize = attributes.getBlockSize(); + final CellGrid grid = new CellGrid(dimensions, blockSize); + final Set accessFlags = AccessFlags.setOf(); + final T type = N5Utils.type(n5Reader.getDatasetAttributes(dataset).getDataType()); + return new SimCacheLoader<>(n5Reader, dataset, grid, type, accessFlags, (Consumer>) img -> {}, new SoftRefLoaderCache<>()); + } + + + @Override + public Cell get(Long key) throws Exception { + ImageWindow window = imagesResponsibleFor == null ? null : imagesResponsibleFor.getWindow(); + + if (window != null){ window.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } + + Cell cell = super.get(key); + + if (window != null){ window.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } + + return cell; + } + + +} 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 40ad584..a4becb2 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 @@ -11,7 +11,6 @@ import com.amazonaws.services.s3.AmazonS3URI; import com.google.gson.GsonBuilder; import ij.ImagePlus; -import ij.measure.Calibration; import ij.plugin.Duplicator; import net.imglib2.cache.img.CachedCellImg; import net.imglib2.img.display.imagej.ImageJFunctions; @@ -186,7 +185,12 @@ public ImagePlus getImgPlusFromN5File() throws IOException { if (userSetFileName == null || userSetFileName.isEmpty()){ userSetFileName = n5AmazonS3Reader.getAttribute(dataSetChosen, "name", String.class); } - ImagePlus imagePlus = ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5AmazonS3Reader, dataSetChosen), userSetFileName); + + + SimCacheLoader simCacheLoader = SimCacheLoader.factoryDefault(n5AmazonS3Reader, dataSetChosen); + CachedCellImg cachedCellImg = simCacheLoader.createCachedCellImage(); + ImagePlus imagePlus = ImageJFunctions.wrap(cachedCellImg, userSetFileName); + simCacheLoader.setImagesResponsibleFor(imagePlus); long end = System.currentTimeMillis(); logger.debug("Read N5 File " + userSetFileName + " Into ImageJ taking: " + ((end - start) / 1000) + "s"); From c07547a9df1828d88fff447e53456388a8f3c9b4 Mon Sep 17 00:00:00 2001 From: Ezequiel Valencia Date: Fri, 16 Aug 2024 08:23:10 -0400 Subject: [PATCH 18/18] Final Touches --- view-simulation-results/pom.xml | 4 ---- .../src/main/java/org/vcell/N5/SimResultsLoader.java | 2 +- .../src/test/java/org/vcell/N5/N5DataSetFile.java | 2 +- .../src/test/java/org/vcell/N5/N5ImageHandlerTest.java | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 5b82344..9b27f8b 100644 --- a/view-simulation-results/pom.xml +++ b/view-simulation-results/pom.xml @@ -187,10 +187,6 @@ gson 2.10.1 - - software.amazon.awssdk - apache-client - software.amazon.awssdk s3 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 a4becb2..00834b8 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 @@ -192,7 +192,7 @@ public ImagePlus getImgPlusFromN5File() throws IOException { ImagePlus imagePlus = ImageJFunctions.wrap(cachedCellImg, userSetFileName); simCacheLoader.setImagesResponsibleFor(imagePlus); long end = System.currentTimeMillis(); - logger.debug("Read N5 File " + userSetFileName + " Into ImageJ taking: " + ((end - start) / 1000) + "s"); + 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)); diff --git a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java index a9c0963..2a0ab36 100644 --- a/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java +++ b/view-simulation-results/src/test/java/org/vcell/N5/N5DataSetFile.java @@ -55,7 +55,7 @@ public static N5DataSetFile[] alphaTestFiles(){ {9.999999999999494, 9.999999999999494, 9.999999999999494, 9.992719717489994, 9.986002627975711, 9.98600262797569, 9.986002627975722} }, - 143301, + 143301.0176, new double[]{124412.82212538144, 15317.6945829, 3570.5008917656078} ); 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 a5f25da..42e0f4c 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 @@ -119,7 +119,7 @@ public void testUnits() throws IOException { areaOfPixel = imagePlus.getCalibration().getX(1) * imagePlus.getCalibration().getY(1) * imagePlus.getCalibration().getZ(1); totalArea = areaOfPixel * imagePlus.getWidth() * imagePlus.getHeight() * imagePlus.getNSlices(); } - Assert.assertEquals(n5DataSetFile.totalArea, totalArea, n5DataSetFile.totalArea * 0.0001); + Assert.assertEquals(n5DataSetFile.totalArea, totalArea, 0.0001); imagePlus.setPosition(imagePlus.getNChannels(), 1, 1); ImageProcessor imageProcessor = imagePlus.getProcessor();