1 import ini
.trakem2
.Project
;
2 import ini
.trakem2
.ControlWindow
;
3 import ini
.trakem2
.persistence
.Loader
;
4 import ini
.trakem2
.persistence
.FSLoader
;
5 import ini
.trakem2
.display
.Layer
;
6 import ini
.trakem2
.display
.LayerSet
;
7 import ini
.trakem2
.display
.Patch
;
8 import ini
.trakem2
.display
.Displayable
;
9 import ini
.trakem2
.utils
.Utils
;
10 import ini
.trakem2
.imaging
.Registration
;
13 import ij
.io
.FileSaver
;
14 import ij
.plugin
.PlugIn
;
17 import java
.awt
.Rectangle
;
19 import java
.util
.ArrayList
;
20 import java
.util
.List
;
22 /** Albert Cardona 2007
25 * - the file path to a TrakEM2 XML project
26 * - the top-left 3D point of the microcube, as x1 y1 z1
27 * - the bottom-right point of the microcube, as x2 y2 z2
29 * - boolean to re-register stack
30 * - file path to tif stack to be generated (will be overwritten if it exists)
32 * (in total, 10 arguments)
34 * Layers are taken from the Z coordinates of the points.
35 * If a layer is not found for the exact given Z, it will get the nearest layer to that Z.
38 * - That the microcube stack will fit in RAM memory.
39 * - That the desired outcome is 8-bit gray
40 * - That the project is on a FSLoader
41 * - That the project may already be open
45 * $ java -Xmx1000m -classpath .:../../ij.jar:./plugins/TrakEM2_.jar Microcube_Maker /path/to/project.xml 123 456 78.9 987 654 87.0 0.5 true /path/to/stack.tif
47 * Example of usage as a plugin:
49 * java -Xmx512m -classpath /home/albert/Applications/ImageJ/ij.jar:/home/albert/Applications/ImageJ/plugins/TrakEM2_.jar -Dplugins.dir=/home/albert/Applications/ImageJ ij.ImageJ -eval "run(\"Microcube Maker\", \"/home/albert/Desktop/ministack4-mm.xml 520 300 0 1020 800 150 1.0 true /home/albert/temp/test-mc/result.tif\");"
52 public class Microcube_Maker
implements PlugIn
{
54 public void run(String arg
) {
55 if (null == arg
|| 0 == arg
.trim().length()) {
56 arg
= Macro
.getOptions();
58 p("Called as plugin with args:\n\t" + arg
);
62 static public void main(String
[] arg
) {
65 } catch (Exception e
) {
66 p("ERROR: could not create microcube stack file.");
71 static private final void makeMicrocube(final String
[] arg
) {
72 if (arg
.length
< 10) {
73 p("Example usage: java -Xmx1000m -classpath .:../../ij.jar:./plugins/TrakEM2_.jar Microcube_Maker /path/to/project.xml 123 456 78.9 987 654 87.0 0.5 true /path/to/stack.tif \nArguments are: <project path> <x1> <y1> <z1> <x2> <y2> <z2> <scale> <re-register layers: true|false> <path_to_stack>\n\n ... where x,y coords are pixel coordinates, and z are layer indices.");
77 Project project
= null;
78 boolean was_open
= false;
82 String path
= arg
[0].trim();
83 if (FSLoader
.isURL(path
)) {
84 // ok, we'll see if it an be opened
85 } else if (!new File(path
).exists()) {
86 p("Project XML file path is invalid or not found: " + path
);
93 x1
= Double
.parseDouble(arg
[1]);
94 y1
= Double
.parseDouble(arg
[2]);
95 z1
= Integer
.parseInt(arg
[3]);
96 x2
= Double
.parseDouble(arg
[4]);
97 y2
= Double
.parseDouble(arg
[5]);
98 z2
= Integer
.parseInt(arg
[6]);
99 scale
= Double
.parseDouble(arg
[7]);
101 } catch (NumberFormatException nfe
) {
102 p("Improper numerical argument for a coordinate.");
103 nfe
.printStackTrace();
106 final boolean align
= Boolean
.parseBoolean(arg
[8].trim().toLowerCase());
108 ControlWindow
.setGUIEnabled(false);
110 // check if the project is already open
111 project
= FSLoader
.getOpenProject(path
);
112 if (null == project
) {
113 project
= Project
.openFSProject(path
);
117 if (null == project
) {
118 p("Could not open TrakEM2 project at path " + path
);
122 int x
= (int)(x1
< x2 ? x1
: x2
);
123 int y
= (int)(y1
< y2 ? y1
: y2
);
124 int w
= (int)Math
.abs(x1
< x2 ? x2
- x1
: x1
- x2
);
125 int h
= (int)Math
.abs(y1
< y2 ? y2
- y1
: y1
- y2
);
126 final Rectangle roi
= new Rectangle(x
, y
, w
, h
);
127 // define first and last layer
128 LayerSet ls
= project
.getRootLayerSet();
129 Layer la1
= ls
.getLayer((int)Math
.abs(z1
)); // WARNING: Calibration
130 Layer la2
= ls
.getLayer((int)Math
.abs(z2
));
137 // Re-register, with proper enlarged sizes and subsequent crop to ensure there are no black areas in the downloaded microcube.
138 // One way to do it: BEST way, since the focus remains within the selected stack. Potential problem: if the slices don't match at all due to excessive deformations. But it's hard.
141 // - calculate enlarged box, and crop that from the original for each layer, but putting in the proper transforms.
142 // Another way to do it:
143 // - cut a bit more than will be needed
145 // - calculate enlarged box, crop that from the original - because black areas may still creep in
147 // - create a subproject from a double-side size area, centered on desired area
148 // - run the layer registration that will shift tile positions as well
149 // - bring in any other patches not originally included, to fill up any black areas
152 // Reality: need same ids for images to avoid duplicating cache and to reuse the same feature serialized files. So, hacking time:
157 ob
= ls
.grab(ls
.indexOf(la1
), ls
.indexOf(la2
), roi
, scale
, Patch
.class, 0xffffffff, Layer
.IMAGEPLUS
, ImagePlus
.GRAY8
);
159 // prepare enlarged roi: pad outwards by one tile width
160 final int padding
= (int)la1
.getDisplayables(Patch
.class).get(0).getWidth();
161 final Rectangle roi2
= (Rectangle
)roi
.clone();
164 roi2
.width
+= padding
* 2;
165 roi2
.height
+= padding
* 2;
167 p("padding: " + padding
);
170 // 1 - Make a subproject
171 Project sub
= ls
.getProject().createSubproject(roi
, la1
, la2
);
172 LayerSet sub_ls
= sub
.getRootLayerSet();
173 // 2 - register all tiles freely and optimally
174 final Layer
[] sub_la
= new Layer
[sub_ls
.size()];
175 sub_ls
.getLayers().toArray(sub_la
);
176 final Thread task
= Registration
.registerTilesSIFT(sub_la
, new boolean[]{true, false, false, false, false}, 512, 0.2499999f
);
177 if (null != task
) try { task
.join(); } catch (Exception e
) { e
.printStackTrace(); }
178 // 3 - prepare roi for cropping
181 // 4 - grab microcube
182 ob
= sub_ls
.grab(0, sub_la
.length
-1, roi
, scale
, Patch
.class, 0xffffffff, Layer
.IMAGEPLUS
, ImagePlus
.GRAY8
);
187 if (null != ob
&& ob
instanceof ImagePlus
) {
189 ImagePlus imp
= ((ImagePlus
)ob
);
191 if (imp
.getStackSize() > 1) {
192 p("Saving stack to " + arg
[9]);
193 new FileSaver(imp
).saveAsTiffStack(arg
[9]);
194 p("Stack saved to " + arg
[9]);
196 p("Saving image to " + arg
[9]);
197 new FileSaver(imp
).saveAsTiff(arg
[9]);
198 p("Image saved to: " + arg
[9]);
200 p("Microcube saved successfully to " + arg
[9]);
202 p("Could not save microcube from " + ob
);
206 } catch (Throwable e
) {
217 static private final void p(final String msg
) {
218 System
.out
.println(msg
);