1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
package ij.util;
import ij.*;
import ij.process.*;
import ij.plugin.DICOM;
/** DICOM utilities */
public class DicomTools {
private static final int MAX_DIGITS = 5;
private static String[] sliceLabels;
/** Sorts a DICOM stack by image number. */
public static ImageStack sort(ImageStack stack) {
if (IJ.debugMode) IJ.log("Sorting by DICOM image number");
if (stack.getSize()==1) return stack;
String[] strings = getSortStrings(stack, "0020,0013");
if (strings==null) return stack;
StringSorter.sort(strings);
ImageStack stack2 = null;
if (stack.isVirtual())
stack2 = ((VirtualStack)stack).sortDicom(strings, sliceLabels, MAX_DIGITS);
else
stack2 = sortStack(stack, strings);
return stack2!=null?stack2:stack;
}
private static ImageStack sortStack(ImageStack stack, String[] strings) {
ImageProcessor ip = stack.getProcessor(1);
ImageStack stack2 = new ImageStack(ip.getWidth(), ip.getHeight(), ip.getColorModel());
for (int i=0; i<stack.getSize(); i++) {
int slice = (int)Tools.parseDouble(strings[i].substring(strings[i].length()-MAX_DIGITS), 0.0);
if (slice==0) return null;
stack2.addSlice(sliceLabels[slice-1], stack.getPixels(slice));
}
stack2.update(stack.getProcessor(1));
return stack2;
}
private static String[] getSortStrings(ImageStack stack, String tag) {
double series = getSeriesNumber(getSliceLabel(stack,1));
int n = stack.getSize();
String[] values = new String[n];
sliceLabels = new String[n];
for (int i=1; i<=n; i++) {
String tags = getSliceLabel(stack,i);
if (tags==null) return null;
sliceLabels[i-1] = tags;
double value = getNumericTag(tags, tag);
if (Double.isNaN(value)) {
if (IJ.debugMode) IJ.log(" "+tag+" tag missing in slice "+i);
return null;
}
if (getSeriesNumber(tags)!=series) {
if (IJ.debugMode) IJ.log(" all slices must be part of the same series");
return null;
}
values[i-1] = toString(value, MAX_DIGITS) + toString(i, MAX_DIGITS);
}
return values;
}
private static String toString(double value, int width) {
String s = " " + IJ.d2s(value,0);
return s.substring(s.length()-MAX_DIGITS);
}
private static String getSliceLabel(ImageStack stack, int n) {
String info = stack.getSliceLabel(n);
if ((info==null || info.length()<100) && stack.isVirtual()) {
String dir = ((VirtualStack)stack).getDirectory();
String name = ((VirtualStack)stack).getFileName(n);
DICOM reader = new DICOM();
info = reader.getInfo(dir+name);
if (info!=null)
info = name + "\n" + info;
}
return info;
}
/** Calculates the voxel depth of the specified DICOM stack based
on the distance between the first and last slices. */
public static double getVoxelDepth(ImageStack stack) {
if (stack.isVirtual()) stack.getProcessor(1);
String pos0 = getTag(stack.getSliceLabel(1), "0020,0032");
String posn = null;
double voxelDepth = -1.0;
if (pos0!=null) {
String[] xyz = pos0.split("\\\\");
if (xyz.length!=3) return voxelDepth;
double z0 = Double.parseDouble(xyz[2]);
if (stack.isVirtual()) stack.getProcessor(stack.getSize());
posn = getTag(stack.getSliceLabel(stack.getSize()), "0020,0032");
if (posn==null) return voxelDepth;
xyz = posn.split("\\\\");
if (xyz.length!=3) return voxelDepth;
double zn = Double.parseDouble(xyz[2]);
voxelDepth = Math.abs((zn - z0) / (stack.getSize() - 1));
}
if (IJ.debugMode) IJ.log("DicomTools.getVoxelDepth: "+voxelDepth+" "+pos0+" "+posn);
return voxelDepth;
}
/** Returns the value (as a string) of the specified DICOM tag id (in the form "0018,0050")
of the specified image or stack slice. Returns null if the tag id is not found. */
public static String getTag(ImagePlus imp, String id) {
String metadata = null;
if (imp.getStackSize()>1) {
ImageStack stack = imp.getStack();
String label = stack.getSliceLabel(imp.getCurrentSlice());
if (label!=null && label.indexOf('\n')>0) metadata = label;
}
if (metadata==null)
metadata = (String)imp.getProperty("Info");
return getTag(metadata, id);
}
private static double getSeriesNumber(String tags) {
double series = getNumericTag(tags, "0020,0011");
if (Double.isNaN(series)) series = 0;
return series;
}
private static double getNumericTag(String hdr, String tag) {
String value = getTag(hdr, tag);
if (value==null) return Double.NaN;
int index3 = value.indexOf("\\");
if (index3>0)
value = value.substring(0, index3);
return Tools.parseDouble(value);
}
private static String getTag(String hdr, String tag) {
if (hdr==null) return null;
int index1 = hdr.indexOf(tag);
if (index1==-1) return null;
//IJ.log(hdr.charAt(index1+11)+" "+hdr.substring(index1,index1+20));
if (hdr.charAt(index1+11)=='>') {
// ignore tags in sequences
index1 = hdr.indexOf(tag, index1+10);
if (index1==-1) return null;
}
index1 = hdr.indexOf(":", index1);
if (index1==-1) return null;
int index2 = hdr.indexOf("\n", index1);
String value = hdr.substring(index1+1, index2);
return value;
}
}
|