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. 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(); - } - } -} diff --git a/view-simulation-results/pom.xml b/view-simulation-results/pom.xml index 875ddd4..9b27f8b 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,10 @@ gson 2.10.1 - + + software.amazon.awssdk + s3 + 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..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 @@ -33,11 +33,13 @@ 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() { exportTable = new N5ExportTable(); initializeLogService(); + setExampleJSONData(); // N5ImageHandler.logService.setLevel(LogService.DEBUG); exportTable.displayExportTable(); } @@ -56,51 +58,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 { - try(BufferedInputStream remoteJSONFile = new BufferedInputStream(new URL("https://api.npoint.io/b85bb21076bf422a7d93").openStream())){ + private static void setExampleJSONData(){ + try(BufferedInputStream remoteJSONFile = new BufferedInputStream(new URL("https://api.npoint.io/6de0febb887fdc4c2fa0").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/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 00f0359..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 @@ -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,10 @@ 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.N5Exception; import org.janelia.saalfeldlab.n5.N5FSReader; import org.janelia.saalfeldlab.n5.N5KeyValueReader; import org.janelia.saalfeldlab.n5.N5Reader; @@ -22,6 +28,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 +38,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; @@ -40,22 +52,51 @@ 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){ - logger.debug("Creating S3 Client"); + logger.debug("Creating S3 Client with url: " + url); AmazonS3ClientBuilder s3ClientBuilder = AmazonS3ClientBuilder.standard(); URI uri = URI.create(url); @@ -86,6 +127,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]; @@ -96,19 +155,7 @@ public void createS3Client(String url, HashMap credentials, Hash 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 @@ -126,14 +173,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); @@ -142,27 +182,40 @@ 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"); - ImagePlus imagePlus = ImageJFunctions.wrap((CachedCellImg) N5Utils.open(n5AmazonS3Reader, dataSetChosen), userSetFileName); + if (userSetFileName == null || userSetFileName.isEmpty()){ + userSetFileName = n5AmazonS3Reader.getAttribute(dataSetChosen, "name", String.class); + } + + + SimCacheLoader simCacheLoader = SimCacheLoader.factoryDefault(n5AmazonS3Reader, dataSetChosen); + CachedCellImg cachedCellImg = simCacheLoader.createCachedCellImage(); + ImagePlus imagePlus = ImageJFunctions.wrap(cachedCellImg, userSetFileName); + 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)); + 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); + 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."); } } - public void setDataSetChosen(String dataSetChosen) { - this.dataSetChosen = dataSetChosen; - } public static void openN5FileDataset(ArrayList filesToOpen, boolean openInMemory){ N5ExportTable.enableCriticalButtons(false); 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 dda9cc0..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 @@ -11,6 +11,8 @@ 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; @@ -19,10 +21,9 @@ 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.*; +import java.util.concurrent.TimeUnit; public class N5ExportTable implements ActionListener, ListSelectionListener { public static JDialog exportTableDialog; @@ -31,6 +32,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; @@ -38,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; @@ -58,64 +58,117 @@ 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) + || !formatExportData.simulationDataMap.containsKey(mostRecentTableEntry.jobID))){ + break; + } + isUpdated = n5ExportTableModel.prependRowData(formatExportData.simulationDataMap.get(currentJob), oldestTimeAllowed()); + } + if(isUpdated){ + n5ExportTableModel.fireTableDataChanged(); + tableScrollPane.updateUI(); + } + } + Thread.sleep(TimeUnit.SECONDS.toMillis(2)); + } + } catch (FileNotFoundException e) { + throw new RuntimeException("Problem Loading Export JSON",e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + refreshTableThread.start(); + } + 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(); + if(!N5ImageHandler.exportedDataExists()){ + updateExampleExportsToTable(); + } + else{ + initalizeTableData(); + } + automaticRefresh(); } @@ -140,10 +193,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 +207,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)); + tableScrollPane.setBorder(BorderFactory.createTitledBorder(lowerEtchedBorder, "Export Table")); + exportListTable.getSelectionModel().addListSelectionListener(this); + return tableScrollPane; } @@ -163,9 +221,11 @@ 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"); - 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(); @@ -175,24 +235,17 @@ 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); + gridBagConstraints.gridx = 3; + topRow.add(questionMark, gridBagConstraints); JPanel bottomRow = new JPanel(new GridBagLayout()); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; + bottomRow.add(includeExampleExports, gridBagConstraints); + gridBagConstraints.gridx = 1; bottomRow.add(openInMemory, gridBagConstraints); @@ -201,8 +254,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); @@ -221,7 +272,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); @@ -241,7 +292,15 @@ 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()){ + b.nextElement().addActionListener(this); + } + + open.setEnabled(false); + copyLink.setEnabled(false); return topBar; } @@ -252,7 +311,29 @@ 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){ + 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 @@ -275,9 +356,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(); } } @@ -286,8 +376,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); @@ -361,15 +459,15 @@ 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"); }}; - private List tableData = new ArrayList<>(); + private LinkedList tableData = new LinkedList<>(); public N5ExportTableModel(){ } @@ -392,11 +490,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; @@ -412,11 +510,28 @@ 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 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); } 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..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 @@ -3,23 +3,28 @@ import java.util.HashMap; public class N5DataSetFile { - public String uri; - public String[] variables; - public HashMap mask; - public double[][] histMax; - 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; } +// https://vcell-dev.cam.uchc.edu/n5Data/ezequiel23/c607b779af9481f.n5?dataSetName=4130889219 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/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, @@ -29,9 +34,32 @@ 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, + new double[]{170.94880000000251,313.05120000000511}); - return new N5DataSetFile[]{frapSimulationResultsMasked}; + 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[][]{ + {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} + }, + 143301.0176, + 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 ee7d496..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 @@ -1,18 +1,21 @@ package org.vcell.N5; -import com.amazonaws.regions.Regions; +import com.google.gson.internal.LinkedTreeMap; import ij.ImagePlus; import ij.io.Opener; import ij.plugin.Duplicator; import ij.plugin.ImageCalculator; -import org.junit.*; +import ij.process.ImageProcessor; +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.HashMap; +import java.util.Map; /* @@ -65,37 +68,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(); @@ -118,15 +90,128 @@ 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); + } + } + + 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(); + + boolean threeD = imagePlus.getNSlices() > 1; + if (threeD){ + 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.0001); + + imagePlus.setPosition(imagePlus.getNChannels(), 1, 1); + ImageProcessor imageProcessor = imagePlus.getProcessor(); + + for(int domain: n5DataSetFile.mask.keySet()){ + totalArea = 0; + + 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; + } + } + } + } + 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("Domain: " + domain + ", Total Area: " + totalArea, + n5DataSetFile.testDomainArea[domain], totalArea, 0.000001); + } } } + 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 (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; + } + } + } + + } + return (total / totalVolume ); + } + public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, stats testType){ double[][] controlData = {{}}; - imagePlus.setPosition(1, 0, 10); switch (testType){ case HISTMAX: controlData = n5DataSetFile.histMax; @@ -137,31 +222,59 @@ public void alphaStatsTest(ImagePlus imagePlus, N5DataSetFile n5DataSetFile, sta case HISTAVERAGE: controlData = n5DataSetFile.histAverage; } - for(int k = 1; k < controlData.length; k++){ - for (int i = 0; i < controlData[k].length; i++){ - imagePlus.setPosition(k, 0, i+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(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); } } } - private void setImageMask(ImagePlus imagePlus){ - ImagePlus maskImagePlus = imagePlus.createImagePlus(); - maskImagePlus.setPosition(0, 0, 0); - imagePlus.getProcessor().setMask(maskImagePlus.createRoiMask()); + private ImagePlus setImageMask(ImagePlus imagePlus){ + ImagePlus maskImagePlus = imagePlus.duplicate(); + 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 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; }