use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class TemplateTree method renameType.
/**
* Rename a TemplateThing type from @param old_name to @param new_name.
* If such a new_name already exists, the renaming will not occur and returns false.
*/
public boolean renameType(final String old_name, String new_name) {
// to lower case!
new_name = new_name.toLowerCase();
Project project = root.getProject();
if (new_name.equals(old_name)) {
return true;
} else if (project.typeExists(new_name)) {
Utils.logAll("Type '" + new_name + "' exists already!");
return false;
}
// process name change in all TemplateThing instances that have it
ArrayList<TemplateThing> al = root.collectAllChildren(new ArrayList<TemplateThing>());
al.add(root);
for (final TemplateThing tet : al) {
// Utils.log("\tchecking " + tet.getType() + " " + tet.getId());
if (tet.getType().equals(old_name))
tet.rename(new_name);
}
// and update the ProjectThing objects in the tree and its dependant Displayable objects in the open Displays
project.getRootProjectThing().updateType(new_name, old_name);
// tell the project about it
project.updateTypeName(old_name, new_name);
// repaint both trees (will update the type names)
updateUILater();
project.getProjectTree().updateUILater();
return true;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Search method createCoordinate.
private Coordinate<Displayable> createCoordinate(final Displayable d) {
Rectangle r = d.getBoundingBox();
Layer la = d instanceof ZDisplayable ? ((ZDisplayable) d).getFirstLayer() : d.getLayer();
if (null == la) {
Display display = Display.getFront(d.getProject());
if (null == display)
la = d.getProject().getRootLayerSet().getLayer(0);
else
la = display.getLayer();
}
return new Coordinate<Displayable>(r.x + r.width / 2, r.y + r.height / 2, la, d);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Project method getParentTitle.
/**
* Returns the title of the enclosing abstract node in the ProjectTree.
*/
public String getParentTitle(final Displayable d) {
try {
ProjectThing thing = findProjectThing(d);
ProjectThing parent = (ProjectThing) thing.getParent();
if (d instanceof Profile) {
// skip the profile_list
parent = (ProjectThing) parent.getParent();
}
if (null == parent)
Utils.log2("null parent for " + d);
if (null != parent && null == parent.getObject()) {
Utils.log2("null ob for parent " + parent + " of " + d);
}
// the abstract thing should be enclosing a String object
return parent.getObject().toString();
} catch (Exception e) {
IJError.print(e);
return null;
}
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class AreaList method exportAsLabels.
/**
* Export all given AreaLists as one per pixel value, what is called a "labels" file; a file dialog is offered to save the image as a tiff stack.
*/
public static void exportAsLabels(final List<Displayable> listToPaint, final ij.gui.Roi roi, final float scale, int first_layer, int last_layer, final boolean visible_only, final boolean to_file, final boolean as_amira_labels) {
// survive everything:
if (null == listToPaint || 0 == listToPaint.size()) {
Utils.log("Null or empty list.");
return;
}
if (scale < 0 || scale > 1) {
Utils.log("Improper scale value. Must be 0 < scale <= 1");
return;
}
// Select the subset to paint
final ArrayList<AreaList> list = new ArrayList<AreaList>();
for (final Displayable d : listToPaint) {
if (visible_only && !d.isVisible())
continue;
if (d instanceof AreaList)
list.add((AreaList) d);
}
Utils.log2("exportAsLabels: list.size() is " + list.size());
// Current AmiraMeshEncoder supports ByteProcessor only: 256 labels max, including background at zero.
if (as_amira_labels && list.size() > 255) {
Utils.log("Saving ONLY first 255 AreaLists!\nDiscarded:");
final StringBuilder sb = new StringBuilder();
for (final Displayable d : list.subList(255, list.size())) {
sb.append(" ").append(d.getProject().getShortMeaningfulTitle(d)).append('\n');
}
Utils.log(sb.toString());
final ArrayList<AreaList> li = new ArrayList<AreaList>(list);
list.clear();
list.addAll(li.subList(0, 255));
}
String path = null;
if (to_file) {
final String ext = as_amira_labels ? ".am" : ".tif";
final File f = Utils.chooseFile("labels", ext);
if (null == f)
return;
path = f.getAbsolutePath().replace('\\', '/');
}
final LayerSet layer_set = list.get(0).getLayerSet();
if (first_layer > last_layer) {
final int tmp = first_layer;
first_layer = last_layer;
last_layer = tmp;
if (first_layer < 0)
first_layer = 0;
if (last_layer >= layer_set.size())
last_layer = layer_set.size() - 1;
}
// Create image according to roi and scale
final int width, height;
final Rectangle broi;
if (null == roi) {
broi = null;
width = (int) (layer_set.getLayerWidth() * scale);
height = (int) (layer_set.getLayerHeight() * scale);
} else {
broi = roi.getBounds();
width = (int) (broi.width * scale);
height = (int) (broi.height * scale);
}
// Compute highest label value, which affects of course the stack image type
final TreeSet<Integer> label_values = new TreeSet<Integer>();
for (final Displayable d : list) {
final String label = d.getProperty("label");
if (null != label)
label_values.add(Integer.parseInt(label));
}
int lowest = 0, highest = 0;
if (label_values.size() > 0) {
lowest = label_values.first();
highest = label_values.last();
}
final int n_non_labeled = list.size() - label_values.size();
final int max_label_value = highest + n_non_labeled;
int type_ = ImagePlus.GRAY8;
if (max_label_value > 255) {
type_ = ImagePlus.GRAY16;
if (max_label_value > 65535) {
type_ = ImagePlus.GRAY32;
}
}
final int type = type_;
final ImageStack stack = new ImageStack(width, height);
final Calibration cal = layer_set.getCalibration();
String amira_params = null;
if (as_amira_labels) {
final StringBuilder sb = new StringBuilder("CoordType \"uniform\"\nMaterials {\nExterior {\n Id 0,\nColor 0 0 0\n}\n");
final float[] c = new float[3];
int value = 0;
for (final Displayable d : list) {
// 0 is background
value++;
d.getColor().getRGBColorComponents(c);
String s = d.getProject().getShortMeaningfulTitle(d);
s = s.replace('-', '_').replaceAll(" #", " id");
sb.append(Utils.makeValidIdentifier(s)).append(" {\n").append("Id ").append(value).append(",\n").append("Color ").append(c[0]).append(' ').append(c[1]).append(' ').append(c[2]).append("\n}\n");
}
sb.append("}\n");
amira_params = sb.toString();
}
final float len = last_layer - first_layer + 1;
// Assign labels
final HashMap<AreaList, Integer> labels = new HashMap<AreaList, Integer>();
for (final AreaList d : list) {
final String slabel = d.getProperty("label");
int label;
if (null != slabel) {
label = Integer.parseInt(slabel);
} else {
// 0 is background
label = (++highest);
}
labels.put(d, label);
}
final ExecutorService exec = Utils.newFixedThreadPool("labels");
final Map<Integer, ImageProcessor> slices = Collections.synchronizedMap(new TreeMap<Integer, ImageProcessor>());
final List<Future<?>> fus = new ArrayList<Future<?>>();
final List<Layer> layers = layer_set.getLayers().subList(first_layer, last_layer + 1);
for (int k = 0; k < layers.size(); k++) {
final Layer la = layers.get(k);
final int slice = k;
fus.add(exec.submit(new Runnable() {
@Override
public void run() {
Utils.showProgress(slice / len);
final ImageProcessor ip;
if (ImagePlus.GRAY8 == type) {
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
final Graphics2D g = bi.createGraphics();
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty())
continue;
// Transform: the scale and the roi
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To roi coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
g.setTransform(aff);
final int label = labels.get(ali);
g.setColor(new Color(label, label, label));
g.fill(area);
}
g.dispose();
ip = new ByteProcessor(bi);
bi.flush();
} else if (ImagePlus.GRAY16 == type) {
final USHORTPaint paint = new USHORTPaint((short) 0);
final BufferedImage bi = new BufferedImage(paint.getComponentColorModel(), paint.getComponentColorModel().createCompatibleWritableRaster(width, height), false, null);
final Graphics2D g = bi.createGraphics();
// final ColorSpace ugray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int painted = 0;
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty())
continue;
// Transform: the scale and the roi
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To roi coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
// Fill
g.setTransform(aff);
// The color doesn't work: paints in a stretched 8-bit mode
// g.setColor(new Color(ugray, new float[]{((float)labels.get(d)) / range}, 1));
Utils.log2("value: " + labels.get(ali).shortValue());
paint.setValue(labels.get(ali).shortValue());
g.setPaint(paint);
// .createTransformedArea(aff));
g.fill(area);
painted += 1;
}
g.dispose();
ip = new ShortProcessor(bi);
bi.flush();
Utils.log2("painted: " + painted);
} else {
// Option 1: could use the same as above, but shifted by 65536, so that 65537 is 1, 65538 is 2, etc.
// and keep doing it until no more need to be shifted.
// The PROBLEM: cannot keep the order without complicated gymnastics to remember
// which label in which image has to be merged to the final image, which prevent
// a simple one-pass blitter.
//
// Option 2: paint each arealist, extract the image, use it as a mask for filling:
final FloatProcessor fp = new FloatProcessor(width, height);
final float[] fpix = (float[]) fp.getPixels();
ip = fp;
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
final Graphics2D gbi = bi.createGraphics();
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty()) {
continue;
}
// Transform: the scale and the roi
// reverse order of transformations:
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To ROI coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
final Area s = area.createTransformedArea(aff);
final Rectangle sBounds = s.getBounds();
// Need to paint at all?
if (0 == sBounds.width || 0 == sBounds.height || !sBounds.intersects(0, 0, width, height))
continue;
// Paint shape
gbi.setColor(Color.white);
gbi.fill(s);
// Read out painted region
final int x0 = Math.max(0, sBounds.x);
final int y0 = Math.max(0, sBounds.y);
final int xN = Math.min(width, sBounds.x + sBounds.width);
final int yN = Math.min(height, sBounds.y + sBounds.height);
// Get the array
final byte[] bpix = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
final float value = labels.get(ali);
// For every non-black pixel, set a 'value' pixel in the FloatProcessor
for (int y = y0; y < yN; ++y) {
for (int x = x0; x < xN; ++x) {
final int pos = y * width + x;
// black
if (0 == bpix[pos])
continue;
fpix[pos] = value;
}
}
// Clear image region
gbi.setColor(Color.black);
gbi.fill(s);
}
gbi.dispose();
bi.flush();
}
slices.put(slice, ip);
}
}));
}
Utils.wait(fus);
exec.shutdownNow();
for (final Map.Entry<Integer, ImageProcessor> e : slices.entrySet()) {
final Layer la = layers.get(e.getKey());
stack.addSlice(la.getZ() * cal.pixelWidth + "", e.getValue());
if (ImagePlus.GRAY8 != type) {
e.getValue().setMinAndMax(lowest, highest);
}
}
Utils.showProgress(1);
// Save via file dialog:
final ImagePlus imp = new ImagePlus("Labels", stack);
if (as_amira_labels)
imp.setProperty("Info", amira_params);
imp.setCalibration(layer_set.getCalibrationCopy());
if (to_file) {
if (as_amira_labels) {
final AmiraMeshEncoder ame = new AmiraMeshEncoder(path);
if (!ame.open()) {
Utils.log("Could not write to file " + path);
return;
}
if (!ame.write(imp)) {
Utils.log("Error in writing Amira file!");
return;
}
} else {
new FileSaver(imp).saveAsTiff(path);
}
} else
imp.show();
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Graph method extractAndShowGraph.
/**
* Shows a dialog to pick which classes is one interested in.
*/
public static final void extractAndShowGraph(final LayerSet ls) {
GenericDialog gd = new GenericDialog("Graph elements");
Class<Displayable>[] c = new Class[] { AreaList.class, AreaTree.class, Ball.class, Connector.class, Patch.class, Pipe.class, Polyline.class, Profile.class, DLabel.class, Treeline.class };
String[] types = new String[] { "AreaList", "AreaTree", "Ball", "Connector", "Image", "Pipe", "Polyline", "Profile", "Text", "Treeline" };
boolean[] states = new boolean[] { true, true, false, false, false, false, true, true, false, true };
assert (c.length == types.length && types.length == states.length);
for (int i = 0; i < c.length; i++) {
if (ZDisplayable.class.isAssignableFrom(c[i])) {
if (!ls.contains(c[i]))
states[i] = false;
} else if (!ls.containsDisplayable(c[i]))
states[i] = false;
}
gd.addCheckboxGroup(types.length, 1, types, states, new String[] { "Include only:" });
gd.showDialog();
if (gd.wasCanceled())
return;
HashSet<Class<Displayable>> only = new HashSet<Class<Displayable>>();
for (int i = 0; i < types.length; i++) {
if (gd.getNextBoolean())
only.add(c[i]);
}
Graph.extractAndShowGraph(ls, only);
}
Aggregations