diff --git a/.gitignore b/.gitignore index ea8c4bf..1f05272 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +.gradle +build diff --git a/Readme.md b/Readme.md index 96ffb3c..5516b88 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,9 @@ ImageJ plugin for reading and writing HDF5 files. - +For 3D datasets an individual slice can be selected for visualization. +Also, especially for very big datasets only every x-th slice can be selected +for visualization. This can be done by either specifying a number, e.g. `10` (for the slice 10) or a number with a preceding %, e.g. `%10` (for every 10th image). Indexing starts at 0. # Usage diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..23e1e15 --- /dev/null +++ b/build.gradle @@ -0,0 +1,30 @@ +apply plugin: 'java' +apply plugin: 'maven' + +group = 'ch.psi' +version = '0.8.0' + +description = """""" + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 + + + +repositories { + mavenCentral() + maven { url "http://slsyoke4.psi.ch:8081/artifactory/libs-releases" } +} +dependencies { + compile group: 'hdf5', name: 'hdf', version:'2.10.0' + compile group: 'hdf5', name: 'hdfobj', version:'2.10.0' + compile group: 'hdf5', name: 'hdf5', version:'2.10.0' + compile group: 'hdf5', name: 'hdf5obj', version:'2.10.0' + compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.6' + testCompile group: 'junit', name: 'junit', version:'4.11' + compile(group: 'gov.nih.imagej', name: 'imagej', version:'1.46') { + /* This dependency was originally in the Maven provided scope, but the project was not of type war. + This behavior is not yet supported by Gradle, so this dependency has been converted to a compile dependency. + Please review and delete this closure when resolved. */ + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..085a1cd Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..4e86dd9 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Apr 14 08:25:23 CEST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/ch/psi/imagej/hdf5/SelectedDatasets.java b/src/main/java/ch/psi/imagej/hdf5/DatasetSelection.java similarity index 57% rename from src/main/java/ch/psi/imagej/hdf5/SelectedDatasets.java rename to src/main/java/ch/psi/imagej/hdf5/DatasetSelection.java index f0e6695..7baf3cd 100644 --- a/src/main/java/ch/psi/imagej/hdf5/SelectedDatasets.java +++ b/src/main/java/ch/psi/imagej/hdf5/DatasetSelection.java @@ -5,10 +5,13 @@ import java.util.List; import ncsa.hdf.object.Dataset; -public class SelectedDatasets { +public class DatasetSelection { private List datasets = new ArrayList(); private boolean group = false; + private Integer slice; + // Intervall to read images + private Integer modulo; public List getDatasets() { return datasets; @@ -22,5 +25,16 @@ public class SelectedDatasets { public void setGroup(boolean group) { this.group = group; } - + public void setSlice(Integer slice) { + this.slice = slice; + } + public Integer getSlice() { + return slice; + } + public void setModulo(Integer modulo) { + this.modulo = modulo; + } + public Integer getModulo() { + return modulo; + } } diff --git a/src/main/java/ch/psi/imagej/hdf5/HDF5Reader.java b/src/main/java/ch/psi/imagej/hdf5/HDF5Reader.java index d9b0d81..a9e435b 100644 --- a/src/main/java/ch/psi/imagej/hdf5/HDF5Reader.java +++ b/src/main/java/ch/psi/imagej/hdf5/HDF5Reader.java @@ -10,20 +10,9 @@ import ij.plugin.PlugIn; import java.io.File; import java.lang.reflect.Array; -import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import java.awt.*; - -import javax.swing.BoxLayout; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.ScrollPaneConstants; import ncsa.hdf.object.*; import ncsa.hdf.object.h5.*; @@ -68,7 +57,7 @@ public class HDF5Reader implements PlugIn { file.open(); List datasets = HDF5Utilities.getDatasets(file); - SelectedDatasets selectedDatasets = selectDatasets(datasets); + DatasetSelection selectedDatasets = selectDatasets(datasets); // TODO Remove @@ -217,19 +206,67 @@ public class HDF5Reader implements PlugIn { } else if (numberOfDimensions == 3) { logger.info("3D Image"); - // Select what to readout - long[] selected = var.getSelectedDims(); - selected[0] = dimensions[0]; - selected[1] = dimensions[1]; - selected[2] = dimensions[2]; + ImageStack stack; + + if(selectedDatasets.getSlice()!=null){ + + // Select what to readout + long[] selected = var.getSelectedDims(); + selected[0] = 1; + selected[1] = dimensions[1]; + selected[2] = dimensions[2]; + + long[] start = var.getStartDims(); + start[0] = selectedDatasets.getSlice(); - Object wholeDataset = var.read(); + Object wholeDataset = var.read(); + + stack = new ImageStack((int) dimensions[2], (int) dimensions[1]); + int size = (int) (dimensions[1] * dimensions[2]); + +// int startIdx = selectedDatasets.getSlice() * size; + addSlice(stack, wholeDataset, 0, size); + } + else if(selectedDatasets.getModulo()!=null){ + logger.info("Read every "+selectedDatasets.getModulo()+" image"); + // Select what to readout + + stack = new ImageStack((int) dimensions[2], (int) dimensions[1]); + + for(int indexToRead=0;indexToRead datasets) throws HDF5Exception { + private DatasetSelection selectDatasets(List datasets) throws HDF5Exception { GenericDialog gd = new GenericDialog("Variable Name Selection"); gd.addMessage("Please select variables to be loaded.\n"); - // Filter datasets that are not potential images / that cannot be displayed - List fdatasets = new ArrayList(); - for(Dataset d: datasets){ - if(d.getRank()>=2 && d.getRank()<=5){ - fdatasets.add(d); - } - } - - JList list = new JList<>(fdatasets.toArray(new Dataset[fdatasets.size()])); - list.setCellRenderer(new DefaultListCellRenderer() { - private static final long serialVersionUID = 1L; - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - final Dataset d = ((Dataset) value); - label.setText(d.getFullName()+" ("+d.getRank()+"D)"); - return label; - - } - }); - - JScrollPane scroll = new JScrollPane(list); - scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS)); - panel.add(scroll); - JCheckBox checkbox = new JCheckBox("Group Datasets (2D datasets only)"); - panel.add(checkbox); + SelectionPanel panel = new SelectionPanel(datasets); gd = new GenericDialog("Variable Name Selection"); gd.add(panel); @@ -319,10 +329,12 @@ public class HDF5Reader implements PlugIn { gd.pack(); gd.showDialog(); - SelectedDatasets selectedDatasets = new SelectedDatasets(); + DatasetSelection selectedDatasets = new DatasetSelection(); if (!gd.wasCanceled()) { - selectedDatasets.setDatasets(list.getSelectedValuesList()); - selectedDatasets.setGroup(checkbox.isSelected()); + selectedDatasets.setDatasets(panel.getSelectedValues()); + selectedDatasets.setGroup(panel.groupValues()); + selectedDatasets.setSlice(panel.getSlice()); + selectedDatasets.setModulo(panel.getModulo()); } return selectedDatasets; diff --git a/src/main/java/ch/psi/imagej/hdf5/SelectionPanel.java b/src/main/java/ch/psi/imagej/hdf5/SelectionPanel.java new file mode 100644 index 0000000..e0c8c21 --- /dev/null +++ b/src/main/java/ch/psi/imagej/hdf5/SelectionPanel.java @@ -0,0 +1,105 @@ +package ch.psi.imagej.hdf5; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BoxLayout; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; + +import ncsa.hdf.object.Dataset; +import javax.swing.JTextField; +import java.awt.FlowLayout; + +public class SelectionPanel extends JPanel { + + private static final long serialVersionUID = 1L; + + private final JList list; + private JCheckBox checkbox; + private JCheckBox chckbxNewCheckBox; + private JLabel lblSlice; + private JPanel panel; + private JTextField textField; + + public SelectionPanel(){ + this(new ArrayList()); + } + + public SelectionPanel(List datasets){ + // Filter datasets that are not potential images / that cannot be displayed + List fdatasets = new ArrayList(); + for(Dataset d: datasets){ + if(d.getRank()>=2 && d.getRank()<=5){ + fdatasets.add(d); + } + } + + list = new JList<>(new DefaultListModel()); + list.setListData(fdatasets.toArray(new Dataset[fdatasets.size()])); + list.setCellRenderer(new DefaultListCellRenderer() { + private static final long serialVersionUID = 1L; + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + final Dataset d = ((Dataset) value); + label.setText(d.getFullName()+" ("+d.getRank()+"D)"); + return label; + + } + }); + + JScrollPane scroll = new JScrollPane(list); + scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); + add(scroll); + checkbox = new JCheckBox("Group Datasets (2D datasets only)"); + add(checkbox); + + chckbxNewCheckBox = new JCheckBox("Virtual Stack"); + add(chckbxNewCheckBox); + + panel = new JPanel(); + FlowLayout flowLayout = (FlowLayout) panel.getLayout(); + flowLayout.setAlignment(FlowLayout.LEFT); + add(panel); + + lblSlice = new JLabel("Slice (3D only):"); + panel.add(lblSlice); + + textField = new JTextField(); + panel.add(textField); + textField.setColumns(10); + } + + public List getSelectedValues(){ + return list.getSelectedValuesList(); + } + + public boolean groupValues(){ + return checkbox.isSelected(); + } + + public Integer getSlice(){ + String text = textField.getText(); + if(text.matches("^[0-9]+$")){ + return new Integer(text); + } + return null; + } + + public Integer getModulo(){ + String text = textField.getText(); + if(text.matches("^%[0-9]+$")){ + return new Integer(text.replace("%", "")); + } + return null; + } +}