<div dir="ltr">ImageJ1 has built-in support for non-uniform x/y/z units via Calibration's getX/Y/ZUnit() and setX/Y/ZUnit(). At my company, we look a good amount of "raw" image data that naturally has time as one unit and detectors as the other unit, so our raw file reader makes use of this functionality. I found that some parts of ImageJ don't seem to look for X/Y/Z units, instead using getUnit/s() without checking for non-uniform units.<div>

<br></div><div>So, I have put together a patch to improve a couple of key functions. I based the patch on the 2014.06.23 (1.40c20) snapshot on <a href="https://github.com/imagej/imagej1.git">https://github.com/imagej/imagej1.git</a>. I don't see any pull requests for that project, so not sure how the IJ team would want this patch? For now, it is inline, below. But I'm happy to push it to the correct spot ... perhaps I should be asking <a href="http://wiki.imagej.net/ImageJA">http://wiki.imagej.net/ImageJA</a> for a pull request?</div>

<div><br></div><div>Thanks,</div><div>Alan</div><div><br></div><div><br></div><div><div>From ad1add8f9dcdfd1ba42436a225a0c41e80353be6 Mon Sep 17 00:00:00 2001</div><div>From: Alan Brooks <<a href="mailto:alancbrooks@gmail.com">alancbrooks@gmail.com</a>></div>

<div>Date: Wed, 25 Jun 2014 12:21:48 -0500</div><div>Subject: [PATCH] Show correct non-matching x & y units on surface plot.</div><div><br></div><div>---</div><div> ij/plugin/SurfacePlotter.java | 7 +++++--</div><div>

 1 file changed, 5 insertions(+), 2 deletions(-)</div><div><br></div><div>diff --git a/ij/plugin/SurfacePlotter.java b/ij/plugin/SurfacePlotter.java</div><div>index 011754e..9789155 100644</div><div>--- a/ij/plugin/SurfacePlotter.java</div>

<div>+++ b/ij/plugin/SurfacePlotter.java</div><div>@@ -306,12 +306,15 @@ public class SurfacePlotter implements PlugIn {</div><div> <span class="" style="white-space:pre">            </span>ip2.drawString(s, (int) p1x-18-w, (int) p1y +h/2);</div>

<div> <span class="" style="white-space:pre">          </span></div><div> <span class="" style="white-space:pre">         </span>//x-axis</div><div>-<span class="" style="white-space:pre">          </span>s = (double) Math.round(roi.height*cal.pixelHeight*10)/10+" "+cal.getUnits();</div>

<div>+<span class="" style="white-space:pre">           </span>boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit());</div><div>+<span class="" style="white-space:pre">               </span>String xunits = unitsMatch ? cal.getUnits() : cal.getYUnit(); // why swapped?</div>

<div>+<span class="" style="white-space:pre">           </span>s = (double) Math.round(roi.height*cal.pixelHeight*10)/10+" "+xunits;</div><div> <span class="" style="white-space:pre">          </span>w =  ip2.getFontMetrics().stringWidth(s);</div>

<div> <span class="" style="white-space:pre">          </span>drawAxis(ip2, (int) p1x, (int) p1y, (int) p2x, (int) p2y, s, 10, -1, 1, 1);</div><div> </div><div> <span class="" style="white-space:pre">             </span>//y-axis</div><div>
-<span class="" style="white-space:pre">              </span>s =  (double) Math.round(roi.width*cal.pixelWidth*10)/10+" "+cal.getUnits();</div>
<div>+<span class="" style="white-space:pre">           </span>String yunits = unitsMatch ? cal.getUnits() : cal.getXUnit(); // why swapped?</div><div>+<span class="" style="white-space:pre">             </span>s =  (double) Math.round(roi.width*cal.pixelWidth*10)/10+" "+yunits;</div>

<div> <span class="" style="white-space:pre">          </span>w =  ip2.getFontMetrics().stringWidth(s);</div><div> <span class="" style="white-space:pre">               </span>//drawAxis(ip2, (int) p2x, (int) p2y, (int) p3x, (int) p3y, s, 10, 1 , 1, -1);</div>

<div> <span class="" style="white-space:pre">          </span>drawAxis(ip2, (int) p2x, (int) p2y, (int) p3x, (int) p3y, s, 10, 1, -1, 1);</div><div>-- </div><div>1.8.4.msysgit.0</div><div><br></div><div>From 70df4ea5619a010caa8732c764ea2ab897dab448 Mon Sep 17 00:00:00 2001</div>

<div>From: Alan Brooks <<a href="mailto:alancbrooks@gmail.com">alancbrooks@gmail.com</a>></div><div>Date: Wed, 25 Jun 2014 12:20:54 -0500</div><div>Subject: [PATCH] Show correct non-matching x & y units when specifying an ROI</div>

<div> selection.</div><div><br></div><div>---</div><div> ij/plugin/SpecifyROI.java | 4 +++-</div><div> 1 file changed, 3 insertions(+), 1 deletion(-)</div><div><br></div><div>diff --git a/ij/plugin/SpecifyROI.java b/ij/plugin/SpecifyROI.java</div>

<div>index bb48b24..db71ac3 100644</div><div>--- a/ij/plugin/SpecifyROI.java</div><div>+++ b/ij/plugin/SpecifyROI.java</div><div>@@ -111,8 +111,10 @@ public class SpecifyROI implements PlugIn, DialogListener {</div><div>
 <span class="" style="white-space:pre">             </span>gd.addCheckbox("Oval", oval);</div>
<div> <span class="" style="white-space:pre">          </span>gd.addCheckbox("Constrain square/circle", square);</div><div> <span class="" style="white-space:pre">             </span>gd.addCheckbox("Centered",centered);</div>

<div>+<span class="" style="white-space:pre">           </span>boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit());</div><div>+<span class="" style="white-space:pre">               </span>String units = unitsMatch ? cal.getUnits() : cal.getXUnit()+" x "+cal.getYUnit();</div>

<div> <span class="" style="white-space:pre">          </span>if (cal.scaled())</div><div>-<span class="" style="white-space:pre">                 </span>gd.addCheckbox("Scaled units ("+cal.getUnits()+")", scaledUnits);</div>

<div>+<span class="" style="white-space:pre">                   </span>gd.addCheckbox("Scaled units ("+units+")", scaledUnits);</div><div> <span class="" style="white-space:pre">             </span>fields = gd.getNumericFields();</div>

<div> <span class="" style="white-space:pre">          </span>gd.addDialogListener(this);</div><div> <span class="" style="white-space:pre">              </span>gd.showDialog();</div><div>-- </div><div>1.8.4.msysgit.0</div><div><br></div><div>

>From c8717cd7146dae5e54f6b93ba529632f828ce5ef Mon Sep 17 00:00:00 2001</div><div>From: Alan Brooks <<a href="mailto:alancbrooks@gmail.com">alancbrooks@gmail.com</a>></div><div>Date: Wed, 25 Jun 2014 12:18:12 -0500</div>

<div>Subject: [PATCH] Update Transformer so that Rotate Right and Rotate Left</div><div> commands preserve non-matching x & y units.</div><div><br></div><div>---</div><div> ij/plugin/filter/Transformer.java | 3 +++</div>

<div> 1 file changed, 3 insertions(+)</div><div><br></div><div>diff --git a/ij/plugin/filter/Transformer.java b/ij/plugin/filter/Transformer.java</div><div>index 26a1e96..5a6aa88 100644</div><div>--- a/ij/plugin/filter/Transformer.java</div>

<div>+++ b/ij/plugin/filter/Transformer.java</div><div>@@ -62,6 +62,9 @@ public class Transformer implements PlugInFilter {</div><div> <span class="" style="white-space:pre"> </span>    <span class="" style="white-space:pre">    </span>double pixelWidth = cal.pixelWidth;</div>

<div> <span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">    </span>cal.pixelWidth = cal.pixelHeight;</div><div> <span class="" style="white-space:pre">        </span>    <span class="" style="white-space:pre">    </span>cal.pixelHeight = pixelWidth;</div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>String xUnit = cal.getXUnit();</div><div>+<span class="" style="white-space:pre">    </span>        cal.setXUnit(cal.getYUnit());</div>

<div>+<span class="" style="white-space:pre">   </span>        cal.setYUnit(xUnit);</div><div> <span class="" style="white-space:pre">                 </span>return;</div><div> <span class="" style="white-space:pre">          </span>}</div><div>

 <span class="" style="white-space:pre">     </span>}</div><div>-- </div><div>1.8.4.msysgit.0</div><div><br></div><div>From bc4a026a612559b77be7dfc2120886be3529d092 Mon Sep 17 00:00:00 2001</div><div>From: Alan Brooks <<a href="mailto:alancbrooks@gmail.com">alancbrooks@gmail.com</a>></div>

<div>Date: Wed, 25 Jun 2014 12:16:43 -0500</div><div>Subject: [PATCH] Improve ImageWindow's subtitle to handle non-matching x & y</div><div> units. Useful when working with raw data files.</div><div><br></div><div>

---</div><div> ij/gui/ImageWindow.java | 12 ++++++++++--</div><div> 1 file changed, 10 insertions(+), 2 deletions(-)</div><div><br></div><div>diff --git a/ij/gui/ImageWindow.java b/ij/gui/ImageWindow.java</div><div>index a81ebe3..ee853d9 100644</div>

<div>--- a/ij/gui/ImageWindow.java</div><div>+++ b/ij/gui/ImageWindow.java</div><div>@@ -301,8 +301,16 @@ public class ImageWindow extends Frame implements FocusListener, WindowListener,</div><div>     <span class="" style="white-space:pre">        </span>int type = imp.getType();</div>

<div>     <span class="" style="white-space:pre">    </span>Calibration cal = imp.getCalibration();</div><div>     <span class="" style="white-space:pre">    </span>if (cal.scaled()) {</div><div>-    <span class="" style="white-space:pre">         </span>s += IJ.d2s(imp.getWidth()*cal.pixelWidth,2) + "x" + IJ.d2s(imp.getHeight()*cal.pixelHeight,2)</div>

<div>- <span class="" style="white-space:pre">                  </span>+ " " + cal.getUnits() + " (" + imp.getWidth() + "x" + imp.getHeight() + "); ";</div><div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit());</div>

<div>+    <span class="" style="white-space:pre">             </span>if (unitsMatch) {</div><div>+<span class="" style="white-space:pre"> </span>    <span class="" style="white-space:pre">            </span>s += IJ.d2s(imp.getWidth()*cal.pixelWidth,2) + "x" </div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">            </span>   + IJ.d2s(imp.getHeight()*cal.pixelHeight,2) + " " + cal.getUnits()</div><div>+<span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">            </span>   + " (" + imp.getWidth() + "x" + imp.getHeight() + "); ";</div>

<div>+<span class="" style="white-space:pre">   </span> <span class="" style="white-space:pre">         </span>} else {</div><div>+<span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">            </span>s += IJ.d2s(imp.getWidth()*cal.pixelWidth,2) + cal.getXUnit() + " x "</div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">            </span>   + IJ.d2s(imp.getHeight()*cal.pixelHeight,2) + cal.getYUnit()</div><div>+<span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">            </span>   + " (" + imp.getWidth() + "x" + imp.getHeight() + "); ";</div>

<div>+<span class="" style="white-space:pre">   </span> <span class="" style="white-space:pre">         </span>}</div><div>     <span class="" style="white-space:pre">  </span>} else</div><div>     <span class="" style="white-space:pre">             </span>s += imp.getWidth() + "x" + imp.getHeight() + " pixels; ";</div>

<div> <span class="" style="white-space:pre">          </span>double size = ((double)imp.getWidth()*imp.getHeight()*imp.getStackSize())/1024.0;</div><div>-- </div><div>1.8.4.msysgit.0</div><div><br></div><div>From cb0e1dd0f81ca526cc17de90acc13f1569e06584 Mon Sep 17 00:00:00 2001</div>

<div>From: Alan Brooks <<a href="mailto:alancbrooks@gmail.com">alancbrooks@gmail.com</a>></div><div>Date: Wed, 25 Jun 2014 12:07:30 -0500</div><div>Subject: [PATCH] Respect X/Y/Z units when showing file information. Useful for</div>

<div> displaying details about raw data collect files where x-y-z units are often</div><div> different.</div><div><br></div><div>---</div><div> ij/plugin/filter/Info.java | 59 +++++++++++++++++++++++-----------------------</div>

<div> 1 file changed, 30 insertions(+), 29 deletions(-)</div><div><br></div><div>diff --git a/ij/plugin/filter/Info.java b/ij/plugin/filter/Info.java</div><div>index 9ce1ac2..99fdcf8 100644</div><div>--- a/ij/plugin/filter/Info.java</div>

<div>+++ b/ij/plugin/filter/Info.java</div><div>@@ -85,36 +85,37 @@ public class Info implements PlugInFilter {</div><div> <span class="" style="white-space:pre">     </span>}</div><div> </div><div> <span class="" style="white-space:pre">       </span>String getInfo(ImagePlus imp, ImageProcessor ip) {</div>

<div>-<span class="" style="white-space:pre">           </span>String s = new String("\n");</div><div>-<span class="" style="white-space:pre">            </span>s += "Title: " + imp.getTitle() + "\n";</div><div>

-<span class="" style="white-space:pre">              </span>Calibration cal = imp.getCalibration();</div><div>-    <span class="" style="white-space:pre">     </span>int stackSize = imp.getStackSize();</div><div>-    <span class="" style="white-space:pre"> </span>int channels = imp.getNChannels();</div>

<div>-    <span class="" style="white-space:pre">     </span>int slices = imp.getNSlices();</div><div>-    <span class="" style="white-space:pre">      </span>int frames = imp.getNFrames();</div><div>-<span class="" style="white-space:pre">            </span>int digits = imp.getBitDepth()==32?4:0;</div>

<div>-<span class="" style="white-space:pre">           </span>int dp, dp2;</div><div>-<span class="" style="white-space:pre">              </span>if (cal.scaled()) {</div><div>-<span class="" style="white-space:pre">                       </span>String unit = cal.getUnit();</div>

<div>-<span class="" style="white-space:pre">                   </span>String units = cal.getUnits();</div><div>-<span class="" style="white-space:pre">                    </span>double pw = imp.getWidth()*cal.pixelWidth;</div><div>-<span class="" style="white-space:pre">                        </span>double ph = imp.getHeight()*cal.pixelHeight;</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>dp = Tools.getDecimalPlaces(pw, ph);</div><div>-<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">    </span>s += "Width:  "+IJ.d2s(pw,dp)+" " + units+" ("+imp.getWidth()+")\n";</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Height:  "+IJ.d2s(ph,dp)+" " + units+" ("+imp.getHeight()+")\n";</div>
<div>
-<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">    </span>if (slices>1) {</div><div>-<span class="" style="white-space:pre">                                </span>double pd = slices*cal.pixelDepth;</div><div>

-<span class="" style="white-space:pre">                              </span>dp = Tools.getDecimalPlaces(pw, pd);</div><div>-<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">            </span>s += "Depth:  "+IJ.d2s(pd,dp)+" " + units+" ("+slices+")\n";</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>}</div><div>+            String s = new String("\n");</div><div>+            s += "Title: " + imp.getTitle() + "\n";</div>

<div>+            Calibration cal = imp.getCalibration();</div><div>+            int stackSize = imp.getStackSize();</div><div>+            int channels = imp.getNChannels();</div><div>+            int slices = imp.getNSlices();</div>

<div>+            int frames = imp.getNFrames();</div><div>+            int digits = imp.getBitDepth()==32?4:0;</div><div>+            int dp, dp2;</div><div>+            String xunit = cal.getXUnit();</div><div>+            String yunit = cal.getYUnit();</div>

<div>+            String zunit = cal.getZUnit();</div><div>+            if (cal.scaled()) {</div><div>+                double pw = imp.getWidth()*cal.pixelWidth;</div><div>+                double ph = imp.getHeight()*cal.pixelHeight;</div>

<div>+                dp = Tools.getDecimalPlaces(pw, ph);</div><div>+                s += "Width:  "+IJ.d2s(pw,dp)+" " + xunit +"s ("+imp.getWidth()+")\n";</div><div>+                s += "Height:  "+IJ.d2s(ph,dp)+" " + yunit +"s ("+imp.getHeight()+")\n";</div>

<div>+                if (slices>1) {</div><div>+                                double pd = slices*cal.pixelDepth;</div><div>+                                dp = Tools.getDecimalPlaces(pw, pd);</div><div>+                        s += "Depth:  "+IJ.d2s(pd,dp)+" " + zunit +"s ("+slices+")\n";</div>

<div>+                }</div><div> <span class="" style="white-space:pre"> </span>    <span class="" style="white-space:pre">    </span>double xResolution = 1.0/cal.pixelWidth;</div><div> <span class="" style="white-space:pre"> </span>    <span class="" style="white-space:pre">    </span>double yResolution = 1.0/cal.pixelHeight;</div>

<div> <span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">    </span>int places = Tools.getDecimalPlaces(xResolution, yResolution);</div><div> <span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>if (xResolution==yResolution)</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">            </span>s += "Resolution:  "+IJ.d2s(xResolution,places) + " pixels per "+unit+"\n";</div><div>

+<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">            </span>s += "Resolution:  "+IJ.d2s(xResolution,places) + " pixels per "+xunit+"\n";</div><div> <span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">    </span>else {</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">            </span>s += "X Resolution:  "+IJ.d2s(xResolution,places) + " pixels per "+unit+"\n";</div><div>

-<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">            </span>s += "Y Resolution:  "+IJ.d2s(yResolution,places) + " pixels per "+unit+"\n";</div><div>+<span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">            </span>s += "X Resolution:  "+IJ.d2s(xResolution,places) + " pixels per "+xunit+"\n";</div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">            </span>s += "Y Resolution:  "+IJ.d2s(yResolution,places) + " pixels per "+yunit+"\n";</div><div>

 <span class="" style="white-space:pre">     </span>    <span class="" style="white-space:pre">    </span>}</div><div> <span class="" style="white-space:pre">        </span>    } else {</div><div> <span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Width:  " + imp.getWidth() + " pixels\n";</div>

<div>@@ -122,19 +123,19 @@ public class Info implements PlugInFilter {</div><div> <span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">    </span>if (stackSize>1)</div><div> <span class="" style="white-space:pre">      </span>    <span class="" style="white-space:pre">            </span>s += "Depth:  " + slices + " pixels\n";</div>

<div> <span class="" style="white-space:pre">  </span>    }</div><div>-    <span class="" style="white-space:pre">     </span>if (stackSize>1) {</div><div>+            if (stackSize>1) {</div><div> <span class="" style="white-space:pre">     </span>    <span class="" style="white-space:pre">    </span>dp = Tools.getDecimalPlaces(cal.pixelWidth, cal.pixelDepth);</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Voxel size: "+IJ.d2s(cal.pixelWidth,dp)+"x"+IJ.d2s(cal.pixelHeight,dp)+"x"+IJ.d2s(cal.pixelDepth,dp)+" "+cal.getUnit()+"\n";</div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Voxel size: "+IJ.d2s(cal.pixelWidth,dp)+"x"+IJ.d2s(cal.pixelHeight,dp)+"x"+IJ.d2s(cal.pixelDepth,dp)+" ("+xunit+" x "+yunit+" x "+zunit+")\n";</div>

<div> <span class="" style="white-space:pre">  </span>    } else {</div><div> <span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>dp = Tools.getDecimalPlaces(cal.pixelWidth, cal.pixelHeight);</div>

<div>-<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Pixel size: "+IJ.d2s(cal.pixelWidth,dp)+"x"+IJ.d2s(cal.pixelHeight,dp)+" "+cal.getUnit()+"\n";</div>

<div>+<span class="" style="white-space:pre">   </span>    <span class="" style="white-space:pre">    </span>s += "Pixel size: "+IJ.d2s(cal.pixelWidth,dp)+"x"+IJ.d2s(cal.pixelHeight,dp)+" ("+xunit+" x "+yunit+")\n";</div>

<div> <span class="" style="white-space:pre">  </span>    }</div><div> </div><div> <span class="" style="white-space:pre"> </span>    s += "ID: "+imp.getID()+"\n";</div><div> <span class="" style="white-space:pre">  </span>    String zOrigin = stackSize>1||cal.zOrigin!=0.0?","+d2s(cal.zOrigin):"";</div>

<div> <span class="" style="white-space:pre">  </span>    s += "Coordinate origin:  " + d2s(cal.xOrigin)+","+d2s(cal.yOrigin)+zOrigin+"\n";</div><div> <span class="" style="white-space:pre">   </span>    int type = imp.getType();</div>

<div>-    <span class="" style="white-space:pre">     </span>switch (type) {</div><div>+            switch (type) {</div><div> <span class="" style="white-space:pre"> </span>    <span class="" style="white-space:pre">    </span>case ImagePlus.GRAY8:</div>

<div> <span class="" style="white-space:pre">  </span>    <span class="" style="white-space:pre">            </span>s += "Bits per pixel: 8 ";</div><div> <span class="" style="white-space:pre">     </span>    <span class="" style="white-space:pre">            </span>String lut = "LUT";</div>

<div>-- </div><div>1.8.4.msysgit.0</div><div><br></div></div></div>