package ij.plugin;
import ij.*;
import ij.gui.GenericDialog;
import ij.process.ImageProcessor;
import ij.process.LUT;
import java.util.ArrayList;
import java.util.List;
import java.awt.Color;
public class SubHyperstackMaker implements PlugIn {
public void run(String arg) {
ImagePlus input = WindowManager.getCurrentImage();
if (input == null) {
IJ.showMessage("No image open.");
return;
}
if (input.getStackSize() == 1) {
IJ.showMessage("Image is not a stack.");
return;
}
int cCount = input.getNChannels();
int zCount = input.getNSlices();
int tCount = input.getNFrames();
boolean hasC = cCount > 1;
boolean hasZ = zCount > 1;
boolean hasT = tCount > 1;
GenericDialog gd = new GenericDialog("Subhyperstack Maker");
gd.addMessage("Enter a range (e.g. 2-14), a range with increment\n"
+ "(e.g. 1-100-2) or a list (e.g. 7,9,25,27)", null, Color.darkGray);
if (hasC) gd.addStringField("Channels:", "1-" + cCount, 40);
if (hasZ) gd.addStringField("Slices:", "1-" + zCount, 40);
if (hasT) gd.addStringField("Frames:", "1-" + tCount, 40);
gd.showDialog();
if (gd.wasCanceled()) return;
String cString = hasC ? gd.getNextString() : "1";
String zString = hasZ ? gd.getNextString() : "1";
String tString = hasT ? gd.getNextString() : "1";
ImagePlus output = makeSubhyperstack(input, cString, zString, tString);
output.show();
}
public static ImagePlus makeSubhyperstack(ImagePlus input, String cString, String zString, String tString) {
ArrayList<Integer> cList = parseList(cString, input.getNChannels());
ArrayList<Integer> zList = parseList(zString, input.getNSlices());
ArrayList<Integer> tList = parseList(tString, input.getNFrames());
return makeSubhyperstack(input, cList, zList, tList);
}
public static ImagePlus makeSubhyperstack(ImagePlus input, List<Integer> cList, List<Integer> zList, List<Integer> tList) {
if (cList.size() == 0)
throw new IllegalArgumentException("Must specify at least one channel");
if (zList.size() == 0)
throw new IllegalArgumentException("Must specify at least one slice");
if (tList.size() == 0)
throw new IllegalArgumentException("Must specify at least one frame");
ImageStack inputStack = input.getImageStack();
int cCount = input.getNChannels();
int zCount = input.getNSlices();
int tCount = input.getNFrames();
for (int c : cList)
check("C", c, cCount);
for (int z : zList)
check("Z", z, zCount);
for (int t : tList)
check("T", t, tCount);
String title = WindowManager.getUniqueName(input.getTitle());
ImagePlus output = IJ.createHyperStack(title, input.getWidth(), input.getHeight(), cList.size(), zList.size(), tList.size(), input.getBitDepth());
ImageStack outputStack = output.getImageStack();
int oc = 0, oz, ot;
for (int c : cList) {
oc++;
oz = 0;
for (int z : zList) {
oz++;
ot = 0;
for (int t : tList) {
ot++;
int i = input.getStackIndex(c, z, t);
int oi = output.getStackIndex(oc, oz, ot);
String label = inputStack.getSliceLabel(i);
ImageProcessor ip = inputStack.getProcessor(i);
outputStack.setSliceLabel(label, oi);
outputStack.setPixels(ip.getPixels(), oi);
}
}
}
output.setStack(outputStack);
if (input instanceof CompositeImage) {
CompositeImage compositeInput = (CompositeImage) input;
CompositeImage compositeOutput =
new CompositeImage(output, compositeInput.getMode());
oc = 0;
for (int c : cList) {
oc++;
LUT table = compositeInput.getChannelLut(c);
compositeOutput.setChannelLut(table, oc);
compositeOutput.setPositionWithoutUpdate(oc, 1, 1);
compositeInput.setPositionWithoutUpdate(c, 1, 1);
double min = compositeInput.getDisplayRangeMin();
double max = compositeInput.getDisplayRangeMax();
compositeOutput.setDisplayRange(min, max);
}
output = compositeOutput;
}
output.setCalibration(input.getCalibration());
return output;
}
private static void check(String name, int index, int count) {
if (index < 1 || index > count) {
throw new IllegalArgumentException("Invalid " + name + " index: " +
index);
}
}
private static ArrayList<Integer> parseList(String planeString, int count) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (String token : planeString.split("\\s*,\\s*")) {
int dash1 = token.indexOf("-");
int dash2 = token.lastIndexOf("-");
if (dash1 < 0) {
int index;
try {
index = Integer.parseInt(token);
} catch (NumberFormatException exc) {
throw new IllegalArgumentException("Invalid number: " + token);
}
if (index < 1 || index > count)
throw new IllegalArgumentException("Invalid number: " + token);
list.add(Integer.parseInt(token));
} else {
int min, max, step;
try {
min = Integer.parseInt(token.substring(0, dash1));
if (dash1 == dash2) {
max = Integer.parseInt(token.substring(dash1 + 1));
step = 1;
} else {
max = Integer.parseInt(token.substring(dash1 + 1, dash2));
step = Integer.parseInt(token.substring(dash2 + 1));
}
} catch (NumberFormatException exc) {
throw new IllegalArgumentException("Invalid range: " + token);
}
if (min < 1 || min > max || max > count || step < 1)
throw new IllegalArgumentException("Invalid range: " + token);
for (int index = min; index <= max; index += step)
list.add(index);
}
}
return list;
}
}