diff --git a/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_1.m b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_1.m new file mode 100644 index 0000000..9f5c914 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_1.m @@ -0,0 +1,121 @@ +%% MATLAB 3D viewer demo 1 +% +% This example demonstrates how to use Miji to render a volume in 3D using +% accelerated graphics, if your computer is adequately equiped (most +% computers are, these days). We use the well known 'mri' data distributed +% with MATLAB, and render it in the ImageJ 3D viewer. + +%% Load and prepare data using MATLAB +% Load an example of 3D data from standard Matlab +load('mri.mat'); + +%% +% Make a simple 8-bit 3D image from it. There is a singleton dimension to +% remove. +I = squeeze(D); + +%% +% Ok, now this is an indexed color image (even if it is made a grays). The +% actual color mapping is contained in the 'map' variable. We will make a +% RGB image out of it. +[R G B] = ind2rgb(I, map); + +%% +% Just a short note here: we are going a complicated way to regenerate a +% color image from an indexed image and its color mapping, because this is +% the way the data is shipped to us in that MATLAB sample. It is a step +% proper to MATLAB only, and does not affect nor relate to the Miji +% framework we demonstrate here. +% We could skip this step by directly feeding the image 'I' to MIJ, instead +% of the color image 'J', using another method. The colors would not be +% right, but would be enough to demonstrate the 3D rendering. +% However, let us do things properly. + +%% +% An extra step to do: R, G and B now contains doubles (0 to 1), and we +% would like to make 3 channels of uint8 out of them. +R = uint8(255 * R); +G = uint8(255 * G); +B = uint8(255 * B); + +%% +% We now put them together into one 3D color image (that is, with 4D). To +% do so, we simply concatenate them along the 3th dimension. +J = cat(4, R,G,B); + +%% +% A note here: MIJ expects the dimensions of a 3D color image to be the +% following: [ x y z color ]; this is why we did this 'cat' operation just +% above. However, if you want to display the data in MATLAB's native +% implay, they must be in the following order: [ x y color z ]. In the +% latter case, 'permute' is your friend. + +%% Configure data volume using ImageJ objects +% Now we start the fun and new part. +% Everything so far has been only about MATLAB operations. + +%% +% First, we launch Miji. Here we use the launcher in non-interactive mode. +% The only thing that this will do is actually to set the path so that the +% subsequent commands and classes can be found by Matlab. +% We launched it with a 'false' in argument, to specify that we do not want +% to diplay the ImageJ toolbar. Indeed, this example is a command line +% example, so we choose not to display the GUI. Feel free to experiment. +Miji(false) + +%% +% The 3D viewer can only display ImagePlus. ImagePlus is the way ImageJ +% represent images. We can't feed it directly MATLAB data. Fortunately, +% that is where MIJ comes into handy. It has a function that can create an +% ImagePlus from a Matlab object. +% 1. The first argument is the name we will give to the image. +% 2. The second argument is the Matlab data +% 3. The last argument is a boolean. If true, the ImagePlus will be +% displayed as an image sequence. You might find this useful as well. +imp = MIJ.createColor('MRI data', J, false); + +%% +% Since we had a color volume (4D data), we used the createColor method. If +% we had only a grayscale volume (3D data), we could have used the +% createImage method instead, which works the same. + +%% +% Now comes a little non-mandatory tricky bit. +% By default, the 3D viewer will assume that the image voxel is square, +% that is, every voxel has a size of 1 in the X, Y and Z direction. +% However, for the MRI data we are playing with, this is incorrect, as a +% voxel is 2.5 times larger in the Z direction that in the X and Y +% direction. +% If we do not correct that, the head we are trying to display will look +% flat. +% A way to tell this to the 3D viewer is to create a Calibration object and +% set its public field pixelDepth to 2.5. Then we set this object to be the +% calibration of the ImagePlus, and the 3D viewer will be able to deal with +% it. +calibration = ij.measure.Calibration(); +calibration.pixelDepth = 2.5; +imp.setCalibration(calibration); + +%% Display the data in ImageJ 3D viewer +% Now for the display itself. +% +% We create an empty 3D viewer to start with. We do not show it yet. +universe = ij3d.Image3DUniverse(); + +%% +% Now we show the 3D viewer window. +universe.show(); + +%% +% Then we send it the data, and ask it to be displayed as a volumetric +% rendering. +c = universe.addVoltex(imp); +%% +% Et voilà! +%% +% +% <> +% +%% +% +% _Jean-Yves Tinevez \ - July 2011_ diff --git a/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_2.m b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_2.m new file mode 100644 index 0000000..f3d1ee8 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_2.m @@ -0,0 +1,134 @@ +%% MATLAB 3D viewer demo 2 +% +% In this example, we will demonstrate the surface rendering capabilities +% of the 3D viewer. +% +% Rather than using an existing dataset, we will create a dummy one, in the +% shape of multiple balls or octahedrons. The balls will be created one by +% one, from a volume where all pixels are 0, but within the object volume, +% whose location and size is set randomly. From this volume, we ask the 3D +% viewer to create an iso-surface (one for each object), and to display it +% in the 3D universe, with a random color. + +%% +% Let us define the size of our target image volume. Not too big to save +% memory. +width = 128; +height = 128; +depth = 64; + +%% +% Here we determine how many objects we want, and their mean size. We will +% generate them randomly. +nballs = 10; +radius = 20; + +%% +% We pre-allocate the image volume. +I = zeros(width, height, depth, 'uint8'); + +%% +% To simplify the object creation step, we create the grid containing each +% pixel coordinates. +[X, Y, Z] = meshgrid(1:width, 1:height, 1:depth); + +%% +% Since we want to add the objects in live mode, we need to create and show +% the universe before creating and adding the balls. So we call Miji first, +Miji(false) + +%% +% Then deal with the 3D universe. +universe = ij3d.Image3DUniverse(); +universe.show(); + +%% +% Now add the objects one by one, in a loop. +for i = 1 : nballs + + %% + % Determine the ball center and radius randomly. + x = round( width * rand ); + y = round( height * rand ); + z = round( depth * rand ); + r = round( radius * (1 + randn/2) ); + intensity = 255; + + %% + % Logical indexing: we find the pixel indices that are within the + % object's volume. + + % This gives you a ball + % index = (X-x).^2 + (Y-y).^2 + (Z-z).^2 < r^2; + + % This gives you an octaedron + index = abs(X-x) + abs(Y-y) + abs(Z-z) < r; + + %% + % Then we set the intensity of these pixels to 'intensity' (here, 255) + % and the value of pixels outside the object volume to 0. + I(~index) = 0; + I(index) = intensity; + + %% + % We now export this MATLAB volume to a new ImagePlus image, without + % displaying it. + imp = MIJ.createImage(['Ball ' int2str(i)], I, false); + + %% + % It is possible to specify the color of the iso-surface at creation, + % but the 3D viewer expects a |Color3f| object, which is part of the + % |org.scijava.vecmath package|. We determine its actual color + % randomly again. + color = org.scijava.vecmath.Color3f(rand, rand, rand); + + %% + % Finally, we add the object to the 3D universe, in the shape of an + % iso-surface. Arguments meaning is detailed below. + c = universe.addMesh(imp, ... - this is the source ImagePlus + color, ... - this is the destination color + ['Ball ' int2str(i)], ... - the name of the iso-surface + 1, ... - the threshold, see below + [true true true], ... - what channels to display + 1 ... - the resampling factor + ); + + %% + % Ok, so the meanings of the |imp|, |color| and |name| arguments are + % trivial. The |threshold| value, here set to 1, is important for this + % display mode. + % + % Isosurface rendering uses the fast marching cube algorithm, which + % assumes that there is a threshold that separates the background from + % the foreground. In our case, it is easy to determine, since pixels + % out of the ball have a 0 intensity, and inside the ball they have an + % intensity of 255. So any threshold value between these two numbers + % would have worked. + % + % The array containing the 3 boolean values is used to specify what + % channels will be included in the surface rendering, if you feed it a + % color image. In our case, we simply set them all to true and do not + % care much. Finally, the resampling factor is used to win some time + % and memory at the expense of precision. If set to more than 1, the + % image is downsampled before the marching cube algorithm is applied, + % resulting in less meshes obtained in smaller time. + + %% + % Now, this individual step is going to take some time, so it is very + % likely that you see each ball appearing one by one. That is because + % computing the surface mesh is expensive, so the rendering lags a bit + % behind the command. + +end + +%% +% That's it. Note that some of our objects might be clipped because they +% cross the boundaries of the volume we defined in the variable |I|. +% +% +% +% <> +%% +% +% _Jean-Yves Tinevez \ - July 2011_ + diff --git a/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_3.m b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_3.m new file mode 100644 index 0000000..fe4caa5 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Matlab3DViewerDemo_3.m @@ -0,0 +1,88 @@ +%% MATLAB 3D viewer demo 3 +% +% In this demo file, we will use the surface plot mode of the 3D viewer. It +% is a mode of rendering where a 3D surface mesh is created from a 2D +% image. Here, the pixel intensity of the 2D image is interpreted as the +% elevation (Z coordinates), which is enough to generate the 3D surface. +% +% It is a mode which is particularly useful for images that have indeed a +% pixel intensity that can be interpreted as elevation, such as maps. Here, +% we try to use the surface plot mode of the 3D viewer with a surface well +% known to MATLAB users. + +%% Generate elevation data in MATLAB +% This is the well known *membrane* dataset, that serves as a generator for +% the MATLAB logo. + +%% +% This will generate a 51*51 image, for which intensity should be +% interpreted as height. It is not a 3D data per se, but its rendering will +% be. +Z = membrane(1,25); + +%% +% The trouble is that Z is made of doubles, the most common MATLAB type, +% whether the 3D viewer only accepts 8-bit images. So we have do some +% conversion before rendering it. The following commands will stretch the +% range of Z to [0; 255] and cast to |uint8|. +Imin = min(Z(:)); +Imax = max(Z(:)); +I = uint8( 200 * (Z-Imin) / (Imax-Imin) ); + +%% Send data to the 3D viewer, through miji +% Launch Miji +Miji(false); + +%% +% We create an ImagePlus from the 2D image. +imp = MIJ.createImage('MATLAB peaks', I, false); + +%% +% Create and display a new 3D universe. +universe = ij3d.Image3DUniverse(); +universe.show(); + +%% +% Feed it the previous ImagePlus, but render it as a surface plot, where +% the intensity is encoded as height in a 3D space. +color = org.scijava.vecmath.Color3f(240 / 255, 120 / 255, 20 / 255); +c = universe.addSurfacePlot(imp, ... + org.scijava.vecmath.Color3f(), ... + 'Matlab Peak in 3D', ... + 1, ... + [true true true], ... + 1); + +%% +% Rotate it a little, so that it shows the same orientation that of the +% actual MATLAB logo. +universe.resetView(); +c.setColor(color); +c.setTransform([1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1]); +universe.fireContentChanged(c); +universe.centerSelected(c); +universe.rotateUniverse(org.scijava.vecmath.Vector3d(-1, -0.5, +0.2), +120 * pi / 180); + +%% +% Et voilà! A beautiful monochrome MATLAB logo, rendered in an accelerated +% 3D viewer. You can try the _Fullscreen_ option in the _View_ menu, to +% maximize your experience. +% +%% +% Note that it is monochrome: the MATLAB logo (type |logo| in the command +% window) has two colors: the close side is yellow-orange-ish and the back +% face is blueish. If you look at the |logo.m| code, you will see that +% MATLAB guys generated these colors using 2 different light source of 2 +% different colors, which you cannot do in the 3D viewer. +%% +% +% <> +% +%% +% +% _Jean-Yves Tinevez \_ +% +% _Johannes Schindelin \_ +% +% _- August 2011_ + diff --git a/src/main/resources/script_templates/MATLAB/Matlab3DViewerIntroduction.m b/src/main/resources/script_templates/MATLAB/Matlab3DViewerIntroduction.m new file mode 100644 index 0000000..f57db06 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Matlab3DViewerIntroduction.m @@ -0,0 +1,151 @@ +%% How to install Fiji, and make MATLAB aware of it. +% +% ImageJ is an image processing software, very popular in the Life-Science +% field. If you are a master student, a PhD or a postdoc in Biology, there +% is a very good chance that ImageJ is installed on your computer. +% +% *ImageJ* is developed mainly by Wayne Rasband, and is written in Java +% (see http://rsb.info.nih.gov/ij/index.html). It has a clever plugin +% system that allows users to extend it with new functionalities. +% +% *Fiji* (Fiji is Just ImageJ, http://fiji.sc/) is a _distribution_ of +% ImageJ, that includes (amongst other things) a lot of plugins, some +% useful libraries and an updater to keep everything up to date. +% +% Amongst other things, it is made to facilitate inter-operability with +% other softwares. For instance, it offers scripting facilities using +% popular languages such as Python, Ruby, Clojure, Beanshell, Javascript, +% etc. It also ships with *Miji*, a set of utilities made to ease its +% interaction with MATLAB. Since ImageJ is written in Java, it can be +% called directly from within MATLAB, and be used as a supporting image +% visualization, processing or analysis tool. +% +% In this demo bundle, we demonstrate how to use Fiji to get a very nice, +% hardware accelerated, 3D viewer in MATLAB. +% +% This is not a totally trivial example, as it requires to have the Java +% libraries for accelerated 3D rendering installed for the MATLAB Java +% Virtual Machine. Fortunately, Fiji comes with a script that automates +% the process. +% +% But you still have to install Fiji. + +%% Installing Fiji +% +% Simply go to http://fiji.sc/Downloads and download the binaries for your +% OS. You will not find an installer; you just have to unzip the Fiji +% folder to somewhere convenient for you. +% +% For demonstration purposes, let us assume you have a PC machine that +% runs a 64-bit version of Windows. You then have downloaded the matching +% Fiji version (fiji-win64-something.zip), and unzipped it in |C:\Program +% Files\| and now have a folder called |C:\Program Files\Fiji.app|. +% +% Before launching MATLAB, launch Fiji itself. You will find an executable +% in the Fiji folder that you just need to run. At startup, Fiji should +% offer you to go to the *updater*. Do that and run the update. If you are +% not proposed this, you can find the updater in the _Help > Update Fiji_ +% menu item. +% +% Close Fiji when the update is done. +% +% A side note: ImageJ and its plugin are very useful if you are interested +% in scientific Image Processing. There are a zillion things you can do +% with it. If you are interested in using Fiji as a standalone +% application, check some of the tutorials there: +% http://fiji.sc/Documentation. +% +%% Making MATLAB aware of Fiji +% +% The utilities for interaction with MATLAB can all be accessed by adding a +% single folder to the MATLAB path. They are all located in the |scripts| +% folder of the Fiji folder. +% +% So, if you have installed Fiji in |C:\Program Files\Fiji.app|, you just +% have to add |C:\Program Files\Fiji.app\scripts| to the MATLAB path, and +% that's all. +% +% By the way, it is in this folder that you will find all the m-files of +% this demo bundle. So you can launch the demos listed below simply by +% typing their name in MATLAB command window; they will be found since they +% are on the path. + +%% Installing the Java3D libraries +% +% You are done with the main installation part. You just have to do it +% once, and if some updates are made to Fiji, you just have to launch its +% updater to get them. +% +% You still have to install the *Java3D* libraries. Fortunately, this is +% done automatically with a Fiji script: +% +% * Launch MATLAB; +% * type |InstallJava3D| in the command window. +% +% If you get a message stating that the function cannot be performed, this +% is because you did not add the Fiji |scripts| folder to the MATLAB path. +% in that case, go back to the previous paragraph. +% +% The |InstallJava3D| will tell you what it does verbosely. It will check +% whether your Java Virtual Machine already has Java3D installed, and if +% the version requirement is met. If not, it will automatically download +% Java 3D and install it to the right folder. +% +% There might be some issues if you do not have write permission to the +% target folder. In that case, the script will tell you what folder to make +% writable. Then you can simply re-launch the script. +% +% Once you are done, you have to restart MATLAB, so that the new libraries +% are sourced. +% +%% What now? +% +% You are all set. +% +% You can now play with the 2 demo files |Matlab3DViewerDemo_1.m| and +% |Matlab3DViewerDemo_2.m|, that are heavily annotated and published in +% the same folder as this file. +% +% * shows how to load a 3D +% data set in MATLAB and render it in 3D (volumetric rendering); +% * shows how to create +% simple object volumes in MATLAB and make a surface rendering of them. +% * demonstrates the +% surface plot mode. A 2D image is used to generate a 3D surface, where +% pixel intensity is interpreted as elevation. +% +% *MIJ* is the low level Java class that contains static methods to +% exchange data between MATLAB and ImageJ. You can find its documentation +% there: http://bigwww.epfl.ch/sage/soft/mij/ +% +% *Miji* is the glue that facilitates the use of all these components. It +% is described in the aforementioned demo files. +% +%% Authors +% +% * ImageJ is written by Wayne Rasband and friends for the core and the +% plugins; +% * Fiji is written by a bunch of enthusiasts, under the holy auspices of +% Johannes Schindelin and friends; +% * The ImageJ 3D viewer is written by Benjamin Schmid, Mark Longair, +% Albert Cardona and Johannes Schindelin; +% * MIJ is written by Daniel Sage and Dimiter Prodanov; +% * Miji is written by Johannes Schindelin, Jacques Pécréaux and Jean-Yves +% Tinevez. +% +% It's all open source, feel free to modify, distribute, comment or +% whatever you feel like. +% +%% Version history +% +% * 26 Jul 2011: Initial release +% * 4 Aug 2011: Fix a bug in write permission detection on Windows +% platform, thanks to report by Peter Beemiller +% * 11 Aug 2011: Added a 3rd demo, demonstrating the surface plot of 2D +% image, thanks to the fix on the 3D viewer applied today by Johannes +% Schindelin. +% +% +%% +% +% _Jean-Yves Tinevez \ - July 2011_ diff --git a/src/main/resources/script_templates/MATLAB/Miji.m b/src/main/resources/script_templates/MATLAB/Miji.m new file mode 100644 index 0000000..b07bee0 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Miji.m @@ -0,0 +1,104 @@ +function [mij] = Miji(open_imagej, verbose) + %% This script sets up the classpath to Fiji and optionally starts MIJ + % Author: Jacques Pecreaux, Johannes Schindelin, Jean-Yves Tinevez + % GNU Octave compatibility added by Eric Barnhill, Jul 2016 + + if nargin < 1 + open_imagej = true; + end + + if nargin < 2 + verbose = false; + end + + %% Get the Fiji directory + fiji_directory = fileparts(fileparts(mfilename('fullpath'))); + + %% Get the Java classpath + classpath = javaclasspath('-all'); + + %% Add all libraries in jars/ and plugins/ to the classpath + + % Switch off warning + warning_state = warning('off','MATLAB:javaclasspath:jarAlreadySpecified'); + + add_to_classpath(classpath, fullfile(fiji_directory,'jars'), verbose); + add_to_classpath(classpath, fullfile(fiji_directory,'plugins'), verbose); + + % Switch warning back to initial settings + warning(warning_state) + + % Set the Fiji directory (and plugins.dir which is not Fiji.app/plugins/) + javaMethod('setProperty', 'java.lang.System', 'ij.dir', fiji_directory); + javaMethod('setProperty', 'java.lang.System', 'plugins.dir', fiji_directory); + + %% Maybe open the ImageJ window + if open_imagej + fprintf('\n\nUse MIJ.exit to end the session\n\n'); + mij = javaObject('MIJ'); + mij.start(); + else + % initialize ImageJ with the NO_SHOW flag (== 2) + ij.ImageJ([], 2); + end + + % Make sure that the scripts are found. + % Unfortunately, this causes a nasty bug with MATLAB: calling this + % static method modifies the static MATLAB java path, which is + % normally forbidden. The consequences of that are nasty: adding a + % class to the dynamic class path can be refused, because it would be + % falsy recorded in the static path. On top of that, the static + % path is fsck in a weird way, with file separator from Unix, causing a + % mess on Windows platform. + % So we give it up as now. + % % fiji.User_Plugins.installScripts(); +end + +function add_to_classpath(classpath, directory, verbose) + + isoctave = exist('octave_config_info') > 0; + + % Get all .jar files in the directory + dirData = dir(directory); + dirIndex = [dirData.isdir]; + jarlist = dir(fullfile(directory,'*.jar')); + path_= cell(0); + for i = 1:length(jarlist) + if not_yet_in_classpath(classpath, jarlist(i).name) + if verbose + disp(strcat(['Adding: ',jarlist(i).name])); + end + path_{length(path_) + 1} = fullfile(directory,jarlist(i).name); + end + end + + %% Add them to the classpath + if ~isempty(path_) + if isoctave + for n = 1:numel(path_) + err_code = javaMethod('addClassPath', 'org.octave.ClassHelper', path_{n}); + if err_code == 0 + display(['Error importing ', path_{n}]); + end + end + else + javaaddpath(path_, '-end'); + end + end + + %# Recurse over subdirectories + subDirs = {dirData(dirIndex).name}; + validIndex = ~ismember(subDirs,{'.','..'}); + + for iDir = find(validIndex) + nextDir = fullfile(directory,subDirs{iDir}); + add_to_classpath(classpath, nextDir, verbose); + end +end + +function test = not_yet_in_classpath(classpath, filename) +%% Test whether the library was already imported +expression = strcat([filesep filename '$']); +test = isempty(cell2mat(regexp(classpath, expression))); +end + diff --git a/src/main/resources/script_templates/MATLAB/Miji_Test.m b/src/main/resources/script_templates/MATLAB/Miji_Test.m new file mode 100644 index 0000000..4f4955f --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/Miji_Test.m @@ -0,0 +1,6 @@ +Miji(); +MIJ.run('Embryos (42K)'); +I=MIJ.getCurrentImage; +E = imadjust(wiener2(im2double(I(:,:,1)))); +imshow(E); +MIJ.createImage('result',E, true); diff --git a/src/main/resources/script_templates/MATLAB/copytoImagePlus.m b/src/main/resources/script_templates/MATLAB/copytoImagePlus.m new file mode 100644 index 0000000..687e95d --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/copytoImagePlus.m @@ -0,0 +1,262 @@ +function imp = copytoImagePlus(I,varargin) +% copytoImagePlus allows you to open an array I with an instance of ImageJ +% within MATLAB with a proper data type and hyperstack dimensions. +% +% +% SYNTAX +% imp = copytoImagePlus(I) +% imp = copytoImagePlus(I,dimorder) +% imp = copytoImagePlus(____,'Param',value) +% +% +% REQUIREMENTS +% ImageJ-MATLAB as part of Fiji installation +% https://imagej.net/MATLAB_Scripting +% +% ijmshow assumes a net.imagej.matlab.ImageJMATLABCommands Java object +% named 'IJM' is made available in the base Workspace by ImageJ (part of +% ImageJ-MATLAB). +% +% +% INPUT ARGUMENTS +% I uint16 | uint8 | double | single +% An array of integers to be opened with ImageJ. This array can +% have from 2 to 5 dimensions. +% +% +% dimorder char row vector made of 'XYCZT' | 'YXCZT' (default) +% +% (Optional) A char row vector composed of 'X', 'Y', 'C' for +% channels, 'Z' for slices, and 'T' for frames. dimorder is +% case insensitive. You cannot repeat any of the five letters +% in dimorder. The first two letters must be either 'X' or 'Y'. +% The length of dimorder must be 5 or match the number of +% dimensions of the array specified by I. The third to the +% fifth letters must be chosen from 'C', 'Z', and 'T'. +% +% The default is set 'YXCZT' rather than 'XYZCT', because the X +% and Y axes of an MATLAB array is flipped over in ImageJ by +% IJM.show(). +% +% +% OPTIONAL PARAMETER/VALUE PAIRS +% NewName char row vector | 'new' (default) +% The window title of the new image in ImageJ +% +% FrameInterval +% scalar +% Time frame sampling interval in seconds +% +% OUTPUT ARGUMENTS +% imp ij.ImagePlus Java object +% +% EXAMPLES +% see https://github.com/kouichi-c-nakamura/copytoImagePlus +% +% +% Written by Kouichi C. Nakamura Ph.D. +% MRC Brain Network Dynamics Unit +% University of Oxford +% kouichi.c.nakamura@gmail.com +% 03-May-2018 04:57:24 +% +% See also +% ijmshow (this requires a net.imagej.matlab.ImageJMATLABCommands object IJM) +% https://github.com/kouichi-c-nakamura/ijmshow (repository for this function) +% +% ImageJ as part of ImageJ-MATLAB (https://github.com/imagej/imagej-matlab/) +% +% net.imagej.matlab.ImageJMATLABCommands +% evalin, assignin +% https://imagej.net/MATLAB_Scripting + + +import ij.process.ShortProcessor +import ij.process.ByteProcessor +import ij.process.FloatProcessor + +p = inputParser; +p.addRequired('I',@(x) isnumeric(x)); +p.addOptional('dimorder','YXCZT',@(x) ischar(x) && isrow(x) ... + && all(arrayfun(@(y) ismember(y,'XYCZT'),upper(x))) && length(x) >=2 ... + && all(arrayfun(@(y) ismember(y,'XY'),upper(x(1:2))))... + ); +p.addParameter('NewName','new',@(x) ischar(x) && isrow(x)); +p.addParameter('FrameInterval',[],@(x) isreal(x) && x > 0); + +p.parse(I,varargin{:}); + +dimorder = upper(p.Results.dimorder); +newname = p.Results.NewName; +frameinterval = p.Results.FrameInterval; + + + +switch dimorder(1:2) + case 'XY' + order1 = [1 2]; + case 'YX' + order1 = [2 1]; +end + + +switch dimorder(3:ndims(I)) + case 'CZT' + order2 = 3:5; + case 'CTZ' + order2 = [3 5 4]; + case 'ZCT' + order2 = [4 3 5]; + case 'ZTC' + order2 = [4 5 3]; + case 'TCZ' + order2 = [5 3 4]; + case 'TZC' + order2 = [5 4 3]; + case 'CZ' + order2 = [3 4]; + case 'CT' + order2 = [3 5 4]; + case 'ZC' + order2 = [4 3]; + case 'ZT' + order2 = [5 3 4]; + case 'TC' + order2 = [4 5 3]; + case 'TZ' + order2 = [5 4 3]; + case 'C' + order2 = [3 4 5]; + case 'Z' + order2 = [4 3 5]; + case 'T' + order2 = [4 5 3]; + otherwise + order2 = 3:5; +end + + +I0 = permute(I, [order1, order2]); + +nX = int32(size(I0,1)); +nY = int32(size(I0,2)); +nC = int32(size(I0,3)); +nZ = int32(size(I0,4)); +nT = int32(size(I0,5)); + +try + switch class(I0) + case 'uint8' + bitdepth = 8; + + case 'int8' + + bitdepth = 8; + + case 'uint16' + + bitdepth = 16; + + case 'int16' + + bitdepth = 8; + + case 'uint32' + + bitdepth = 32; + + case 'int32' + + bitdepth = 32; + + case 'uint64' + error('MATLAB:copytoImg:UnsupportedType', ... + 'uint64 is not supported.'); + case 'int64' + error('MATLAB:copytoImg:UnsupportedType', ... + 'uint64 is not supported.'); + case 'single' + + bitdepth = 32; + + case 'double' + + bitdepth = 32; + + case 'logical' + + bitdepth = 8; + + otherwise + error('MATLAB:copytoImg:UnsupportedType', ... + '%s is not supported.', class(I0)); + + end + +catch merr + if strcmp(merr.identifier, 'MATLAB:undefinedVarOrClass') + error('MATLAB:copytoImg:undefinedVarOrClass', ... + 'Could not find ImgLib2 on the path. Did you forget to run ''Miji(false)'' before calling this function?'); + else + rethrow(merr); + end +end + + +imp = ij.IJ.createHyperStack(newname,nX,nY,nC,nZ,nT,bitdepth); + +for t = 1:nT + imp.setT(t); + for z = 1:nZ + imp.setZ(z); + for c = 1:nC + imp.setC(c); + + XY = I0(:,:,c,z,t); + xy = XY(:)'; + + switch bitdepth + case 16 + ip = ShortProcessor(nX,nY); + ip.setPixels(xy); + imp.setProcessor(ip); + case 8 + ip = ByteProcessor(nX,nY); + ip.setPixels(xy); + imp.setProcessor(ip); + otherwise + ip = FloatProcessor(nX,nY); + ip.setPixels(single(xy)); + imp.setProcessor(ip); + end + end + end +end + +imp.setT(1); +imp.setZ(1); +imp.setC(1); +%imp.show(); +imp.setDisplayMode(ij.IJ.COLOR) %NOTE this is required to enable the next line +imp.setDisplayMode(ij.IJ.COMPOSITE) + +try + imp.resetDisplayRanges(); +catch mexc + if strcmpi(mexc.identifier,'MATLAB:UndefinedFunction') + warning('resetDisplayRanges did not work') + else + throw(mexc) + end +end + +if ~isempty(frameinterval) + + fi = imp.getFileInfo(); + fi.frameInterval = frameinterval; + imp.setFileInfo(fi); + %TODO Show Info... does not show the frameinterval +end + + +end diff --git a/src/main/resources/script_templates/MATLAB/copytoImg.m b/src/main/resources/script_templates/MATLAB/copytoImg.m new file mode 100644 index 0000000..0400006 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/copytoImg.m @@ -0,0 +1,86 @@ +function img = copytoImg(I) +%%COPYTOIMG Create a new ImgLib2 Img from a MATLAB image. +% +% img = copytoImg(I) returns a new ImgLib2 Img object, built from the +% specified MATLAB array, with the right type determined at construction. +% The target image has its X ans Y axis permuted so that both images have +% the same orientation in MATLAB and ImgLib2. +% +% This function supports all MATLAB primitive types but uint64 (unsigned +% long integers). +% +% We rely on Miji to set up classpath, so you would have to add Miji to +% your MATLAB path and call +% >> Miji(false); % or true +% prior to using this function. +% +% EXAMPLE +% +% Miji(false) +% load durer +% img = copytoImg(X); +% net.imglib2.img.display.imagej.ImageJFunctions.show(img); +% +% see also: copytoImgPlus, copytoMatlab +% Jean-Yves Tinevez - 2013 + +% Permute dim 0 and 1 (X & Y) so that we match MATLAB convention in ImgLib +I = permute(I, [2 1]); + +% Copy to ImgLib2 +try + + switch class(I) + + case 'uint8' + img = net.imglib2.img.array.ArrayImgs.unsignedBytes(I(:), size(I)); + + case 'int8' + img = net.imglib2.img.array.ArrayImgs.bytes(I(:), size(I)); + + case 'uint16' + img = net.imglib2.img.array.ArrayImgs.unsignedShorts(I(:), size(I)); + + case 'int16' + img = net.imglib2.img.array.ArrayImgs.shorts(I(:), size(I)); + + case 'uint32' + img = net.imglib2.img.array.ArrayImgs.unsignedInts(I(:), size(I)); + + case 'int32' + img = net.imglib2.img.array.ArrayImgs.ints(I(:), size(I)); + + case 'uint64' + error('MATLAB:copytoImg:UnsupportedType', ... + 'uint64 is not supported by Imglib2.'); + + case 'int64' + img = net.imglib2.img.array.ArrayImgs.shorts(I(:), size(I)); + + case 'single' + img = net.imglib2.img.array.ArrayImgs.floats(I(:), size(I)); + + case 'double' + img = net.imglib2.img.array.ArrayImgs.doubles(I(:), size(I)); + + case 'logical' + img = net.imglib2.img.array.ArrayImgs.bits(I(:), size(I)); + + otherwise + error('MATLAB:copytoImg:UnsupportedType', ... + '%s is not supported by Imglib2.', class(I)); + + end + +catch merr + + if strcmp(merr.identifier, 'MATLAB:undefinedVarOrClass') + error('MATLAB:copytoImg:undefinedVarOrClass', ... + 'Could not find ImgLib2 on the path. Did you forget to run ''Miji(false)'' before calling this function?'); + else + rethrow(merr); + end + +end + +end \ No newline at end of file diff --git a/src/main/resources/script_templates/MATLAB/copytoImgPlus.m b/src/main/resources/script_templates/MATLAB/copytoImgPlus.m new file mode 100644 index 0000000..c452dc5 --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/copytoImgPlus.m @@ -0,0 +1,138 @@ +function imgplus = copytoImgPlus(I, calibration, name, axes) +%%COPYTOIMGPLUS Create a new ImgLib2 ImgPlus from a MATLAB image. +% +% Returns a new ImgLib2 ImgPlus object, which is basically an Img with some +% metadata added. This method allows specifying the spatial calibration, +% the target image name in ImageJ, and the desired axes type. Because of +% metadata limitation in ImageJ, only 3 dimensions are allowed, and they +% must be taken from X, Y, Z, T and C. +% +% img = copytoImgPlus(I) returns a new ImgPlus built from the specified +% MATLAB array, with the right type determined at construction. The target +% image has its X ans Y axis permuted so that both images have the same +% orientation in MATLAB and ImgLib2. The default spatial calibration is +% taken to 1 pixel in all dimensions. The default name is set to be +% 'matlab' and the default axes are tken from X, Y, Z, T, C in this order. +% +% img = copytoImgPlus(I, calibration) allows specifying the spatial +% calibration for each dimension of the source array. It must be a double +% array of ndims elements where ndims is the number of dimensions of the +% array I. +% +% img = copytoImgPlus(I, calibration, name) allows specifying the name of +% the ImgPlus image. +% +% img = copytoImgPlus(I, calibration, name, axes) allows specifying axes +% types for the target multidimensional image. They must be passed as a +% cell array of strings taken from { 'X', 'Y', 'Z', 'T', 'C' }. +% +% This function supports all MATLAB primitive types but uint64 (unsigned +% long integers). +% +% We rely on Miji to set up classpath, so you would have to add Miji to +% your MATLAB path and call +% >> Miji(false); % or true +% prior to using this function. +% +% EXAMPLE +% +% Miji(false) +% load durer +% imgplus = copytoImgPlus(X, [0.2 0.7], 'Dürer', { 'Y' , 'X' }); +% net.imglib2.img.display.imagej.ImageJFunctions.show(imgplus); +% +% see also: copytoImg, copytoMatlab +% Jean-Yves Tinevez - 2013 + + +%% CONTANTS + +DEFAULT_AXES = { 'X', 'Y', 'Z', 'T', 'C' }; + +try + MATCHING_AXES = [ + net.imagej.axis.Axes.X + net.imagej.axis.Axes.Y + net.imagej.axis.Axes.Z + net.imagej.axis.Axes.TIME + net.imagej.axis.Axes.CHANNEL ]; +catch merr + if strcmp(merr.identifier, 'MATLAB:undefinedVarOrClass') + error('MATLAB:copytoImgPlus:undefinedVarOrClass', ... + 'Could not find ImgLib2 on the path. Did you forget to run ''Miji(false)'' before calling this function?'); + else + rethrow(merr); + end +end +DEFAULT_NAME = 'matlab'; + +%% Check input + +if ndims(I) > 5 + error('MATLAB:copytoImgPlus:TooManyDimensions', ... + 'Cannot deal with more that 5 dims, got %d.', ndims(I)) +end + + +if nargin < 2 + calibration = ones( ndims(I), 1); +else + if ~isfloat(calibration) + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Second argument, calibration, must be a double array. Got a %s.', ... + class(calibration)) + end + if numel(calibration) ~= ndims(I) + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Second argument, calibration, must must have one element per dimension of I. Got %d elements.', ... + numel(calibration)) + end + +end + +if nargin < 3 + name = DEFAULT_NAME; +else + if ~ischar(name) + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Third argument, name, must be a string. Got a %s.', ... + class(name)) + end +end + +if nargin < 4 + axes = DEFAULT_AXES(1 : ndims(I)); +else + if ~iscell(axes) + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Fourth argument, axes, must be a cell array of strings. Got a %s.', ... + class(axes)) + end + if numel(axes) ~= ndims(I) + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Fourth argument, axes, must must have one element per dimension of I. Got %d elements.', ... + numel(axes)) + end +end + +%% Deal with metadata + +ax(ndims(I)) = MATCHING_AXES(1); +for i = 1 : ndims(I) + index = find(strcmp(DEFAULT_AXES, axes{i}), 1); + if isempty(index) || index < 0 + error('MATLAB:copytoImgPlus:IllegalArgument', ... + 'Unkown axis type: %s. Can only deal with X, Y, Z, T & C.', axes{i}) + end + + ax(i) = MATCHING_AXES(index); + +end + +%% Generate ImgLib2 img + +img = copytoImg(I); + +imgplus = net.imagej.ImgPlus(img, name, ax, calibration); + +end \ No newline at end of file diff --git a/src/main/resources/script_templates/MATLAB/copytoMatlab.m b/src/main/resources/script_templates/MATLAB/copytoMatlab.m new file mode 100644 index 0000000..3235acd --- /dev/null +++ b/src/main/resources/script_templates/MATLAB/copytoMatlab.m @@ -0,0 +1,81 @@ +function I = copytoMatlab(img) +%%COPYTOMATLAB Copy the content of an ImgLib2 image to MATLAB. +% +% I = copytoMatlab(img) returns a MATLAB copy of the array stored in the +% specified ImgLib2 Img object. This function only works for ImgLib2 images +% that are ArrayImgs, and whose types are native real or integer ones. +% +% We rely on Miji to set up classpath, so you would have to add Miji to +% your MATLAB path and call +% >> Miji(false); % or true +% prior to using this function. +% +% see also: copytoImgPlus, copytoImg +% Jean-Yves Tinevez - 2013 + + %% CONSTANTS + + ACCEPTED_TYPES = { + 'net.imglib2.type.numeric.integer.UnsignedByteType' + 'net.imglib2.type.numeric.integer.UnsignedShortType' + 'net.imglib2.type.numeric.integer.UnsignedIntType' + 'net.imglib2.type.numeric.integer.ByteType' + 'net.imglib2.type.numeric.integer.ShortType' + 'net.imglib2.type.numeric.integer.IntType' + 'net.imglib2.type.numeric.integer.LongType' + 'net.imglib2.type.numeric.integer.LongType' + 'net.imglib2.type.numeric.real.FloatType' + 'net.imglib2.type.numeric.real.DoubleType' + }; + + %% Check input + + if ~isa(img, 'net.imglib2.img.array.ArrayImg') + error('MATLAB:copytoMatlab:IllegalArgument', ... + 'Expected argument to be an ImgLib2 ArrayImg, got a %s.', ... + class(img) ) + end + + fel = img.firstElement; + knowType = false; + for i = 1 : numel(ACCEPTED_TYPES) + if isa(fel, ACCEPTED_TYPES{i}) + knowType = true; + break + end + end + + if ~knowType + error('MATLAB:copytoMatlab:IllegalArgument', ... + 'Can only deal with native real or integer types, got a %s.', ... + class(fel) ) + end + + + + %% Operate on source image + + % Retrieve dimensions + numDims = img.numDimensions(); + sizes = NaN(1, numDims); + for i = 1 : numDims + sizes(i) = img.dimension(i-1); + end + + % Retrieve array container + J = img.update([]).getCurrentStorageArray; + + % Deal with unsigned types + if isa(fel, 'net.imglib2.type.numeric.integer.UnsignedByteType') + J = typecast(J, 'uint8'); + elseif isa(fel, 'net.imglib2.type.numeric.integer.UnsignedShortType') + J = typecast(J, 'uint16'); + elseif isa(fel, 'net.imglib2.type.numeric.integer.UnsignedIntType') + J = typecast(J, 'uint32'); + end + + % Build MATLAB array + I = reshape(J, sizes); + I = permute(I, [2 1]); + +end \ No newline at end of file diff --git a/src/scripts/update/ImageJ.m b/src/scripts/update/ImageJ.m index 0d01eb6..06c4a10 100644 --- a/src/scripts/update/ImageJ.m +++ b/src/scripts/update/ImageJ.m @@ -1,94 +1,67 @@ function ImageJ(open_imagej, verbose) - %% This script adds the ImageJ libraries to the MATLAB classpath. By default, - %% it will also start up an ImageJ instance within MATLAB. - %% Parameters: - %% open_imagej - If false, an ImageJ instance will not be launched. Default: true - %% verbose - If true, a confirmation message will be printed the first time - %% a jar is added to the MATLAB classpath. Default: false - %% Author: Jacques Pecreaux, Johannes Schindelin, Jean-Yves Tinevez, Mark Hiner - - if nargin < 1 - open_imagej = true; - end - - if nargin < 2 - verbose = false; - end - - %% Get the ImageJ directory - imagej_directory = fileparts(fileparts(mfilename('fullpath'))); - - %% Get the Java classpath - classpath = javaclasspath('-all'); - - %% Add all libraries in jars/ and plugins/ to the classpath - - % Switch off warning - warning_state = warning('off','MATLAB:javaclasspath:jarAlreadySpecified'); - - add_to_classpath(classpath, fullfile(imagej_directory,'jars'), verbose); - add_to_classpath(classpath, fullfile(imagej_directory,'plugins'), verbose); - - % Switch warning back to initial settings - warning(warning_state) - - % Set the ImageJ directory (and plugins.dir which is not ImageJ.app/plugins/) - java.lang.System.setProperty('ij.dir', imagej_directory); - java.lang.System.setProperty('plugins.dir', imagej_directory); - - %% Maybe open the ImageJ window - import net.imagej.matlab.*; - if open_imagej - ImageJMATLAB.start(verbose); - else - % initialize ImageJ with the headless flag - ImageJMATLAB.start(verbose, '--headless'); - end - - % Make sure that the scripts are found. - % Unfortunately, this causes a nasty bug with MATLAB: calling this - % static method modifies the static MATLAB java path, which is - % normally forbidden. The consequences of that are nasty: adding a - % class to the dynamic class path can be refused, because it would be - % falsy recorded in the static path. On top of that, the static - % path is fsck in a weird way, with file separator from Unix, causing a - % mess on Windows platform. - % So we give it up as now. - % % imagej.User_Plugins.installScripts(); +% This function ImageJ adds the ImageJ libraries to the MATLAB classpath. +% By default, it will also start up an ImageJ instance within MATLAB. +% +% SYNTAX +% +% ImageJ +% ImageJ(open_imagej) +% ImageJ(open_imagej,verbose) +% +% PARAMETERS +% +% open_imagej true (default) | false | 1 | 0 +% +% If false, an ImageJ instance will not be launched. +% +% verbose true | false (default) | 1 | 0 +% +% If true, a confirmation message will be printed the first time +% a jar is added to the MATLAB classpath. +% +% Author: Jacques Pecreaux, Johannes Schindelin, Jean-Yves Tinevez, Mark Hiner +% +% See also +% ImageJ_javaaddpath + + +if nargin < 1 + open_imagej = true; end -function add_to_classpath(classpath, directory, verbose) - % Get all .jar files in the directory - dirData = dir(directory); - dirIndex = [dirData.isdir]; - jarlist = dir(fullfile(directory,'*.jar')); - path_= cell(0); - for i = 1:length(jarlist) - if not_yet_in_classpath(classpath, jarlist(i).name) - if verbose - disp(strcat(['Adding: ',jarlist(i).name])); - end - path_{length(path_) + 1} = fullfile(directory,jarlist(i).name); - end - end - - %% Add them to the classpath - if ~isempty(path_) - javaaddpath(path_, '-end'); - end - - %# Recurse over subdirectories - subDirs = {dirData(dirIndex).name}; - validIndex = ~ismember(subDirs,{'.','..'}); +if nargin < 2 + verbose = false; +end - for iDir = find(validIndex) - nextDir = fullfile(directory,subDirs{iDir}); - add_to_classpath(classpath, nextDir, verbose); - end +%% Get the ImageJ directory + +ImageJ_javaaddpath(verbose); + +%% Maybe open the ImageJ window +import net.imagej.matlab.*; +if open_imagej + ImageJMATLAB.start(verbose); +else + % initialize ImageJ with the headless flag + % ImageJMATLAB.start(verbose, '--headless'); % this does not work + + % after ImageJ_javaaddpath, you have access to Java API of ImageJ + % Cant't we just call it "headless mode"? + % + % If not, what functionality is the API missing to be called as + % headless? + end -function test = not_yet_in_classpath(classpath, filename) -%% Test whether the library was already imported -expression = strcat([filesep filename '$']); -test = isempty(cell2mat(regexp(classpath, expression))); +% Make sure that the scripts are found. +% Unfortunately, this causes a nasty bug with MATLAB: calling this +% static method modifies the static MATLAB java path, which is +% normally forbidden. The consequences of that are nasty: adding a +% class to the dynamic class path can be refused, because it would be +% falsy recorded in the static path. On top of that, the static +% path is fsck in a weird way, with file separator from Unix, causing a +% mess on Windows platform. +% So we give it up as now. +% % imagej.User_Plugins.installScripts(); end + diff --git a/src/scripts/update/ImageJ_javaaddpath.m b/src/scripts/update/ImageJ_javaaddpath.m new file mode 100644 index 0000000..dc7459e --- /dev/null +++ b/src/scripts/update/ImageJ_javaaddpath.m @@ -0,0 +1,127 @@ +function ImageJ_javaaddpath(varargin) +% ImageJ_javaaddpath will add the paths for ImageJ/Fiji jar files to +% dyanamic Java class path using javaaddpath, without launching ImageJ +% instance. +% +% When you want to use Fiji/ImageJ within parfor loop for +% parallel computation, you need to add Java class paths for Fiji/ImageJ +% within parfor loop in order to change dynamic Java class path for each +% MATLAB worker. +% +% Virtually all of the code is taken from ImageJ.m. +% +% SYNTAX +% ImageJ_javaaddpath +% ImageJ_javaaddpath(verbose) +% +% INPUT ARGUMENTS +% +% verbose true | false (default) | 1 | 0 +% (Optional) true or 1 will print added java paths to the +% Command Window. +% +% +% EXAMPLE +% +% fijiscriptpath = 'D:\Fiji.app\scripts'; +% +% addpath(fijiscriptpath) +% ImageJ +% +% I = imread('corn.tif',3); % uint8 +% +% parfor i = 1:10 +% addpath(fijiscriptpath) % to make MATLAB functions for ImageJ available +% ImageJ_javaaddpath % to make ImageJ Java class available +% +% I1 = I - uint8(10*i); +% imp = copytoImagePlus(I1); +% +% disp(imp) +% +% local_saveasTIFF(imp,i) % you cannot directly access ij.IJ in parfor loop +% end +% +% % a local function is needed to access ij.IJ +% function local_saveasTIFF(imp,i) +% ij.IJ.saveAsTiff(imp,sprintf('testimage%d.tif',i)) +% end +% +% +% Written by Kouichi C. Nakamura Ph.D. +% MRC Brain Network Dynamics Unit +% University of Oxford +% kouichi.c.nakamura@gmail.com +% 14-Aug-2018 10:34:01 +% +% +% See also +% ImageJ, javaaddpath, parfor + + +p = inputParser; +p.addOptional('verbose',false,@(x) isscalar(x) && x == 1 || x == 0); +p.parse(varargin{:}); + +verbose = p.Results.verbose; + +imagej_directory = fileparts(fileparts(mfilename('fullpath'))); + +%% Get the Java classpath +classpath = javaclasspath('-all'); + +%% Add all libraries in jars/ and plugins/ to the classpath + +% Switch off warning +warning_state = warning('off'); + +add_to_classpath(classpath, fullfile(imagej_directory,'jars'), verbose); +add_to_classpath(classpath, fullfile(imagej_directory,'plugins'), verbose); + +% Switch warning back to initial settings +warning(warning_state) + +% Set the ImageJ directory (and plugins.dir which is not ImageJ.app/plugins/) +java.lang.System.setProperty('ij.dir', imagej_directory); +java.lang.System.setProperty('plugins.dir', imagej_directory); +end + +%------------------------------------------------------------------ + +function add_to_classpath(classpath, directory, verbose) +% Get all .jar files in the directory +dirData = dir(directory); +dirIndex = [dirData.isdir]; +jarlist = dir(fullfile(directory,'*.jar')); +path_= cell(0); +for i = 1:length(jarlist) + if not_yet_in_classpath(classpath, jarlist(i).name) + if verbose + disp(strcat(['Adding: ',jarlist(i).name])); + end + path_{length(path_) + 1} = fullfile(directory,jarlist(i).name); + end +end + +%% Add them to the classpath +if ~isempty(path_) + javaaddpath(path_, '-end'); +end + +%# Recurse over subdirectories +subDirs = {dirData(dirIndex).name}; +validIndex = ~ismember(subDirs,{'.','..'}); + +for iDir = find(validIndex) + nextDir = fullfile(directory,subDirs{iDir}); + add_to_classpath(classpath, nextDir, verbose); +end +end + +%------------------------------------------------------------------ + +function test = not_yet_in_classpath(classpath, filename) +%% Test whether the library was already imported +expression = strcat([filesep filename '$']); +test = isempty(cell2mat(regexp(classpath, expression))); +end \ No newline at end of file