use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Render method accumulate.
/**
* Recursive; returns the last added profile.
*/
private Profile accumulate(final HashSet<Profile> hs_done, final ArrayList<Profile> al, final Profile step, int z_trend) {
final HashSet<Displayable> hs_linked = step.getLinked(Profile.class);
if (al.size() > 1 && hs_linked.size() > 2) {
// base found
return step;
}
double step_z = step.getLayer().getZ();
Profile next_step = null;
boolean started = false;
for (final Displayable ob : hs_linked) {
// loop only one cycle, to move only in one direction
if (al.contains(ob) || started || hs_done.contains(ob))
continue;
started = true;
next_step = (Profile) ob;
double next_z = next_step.getLayer().getZ();
if (0 == z_trend) {
// define trend
if (next_z > step_z) {
z_trend = 1;
} else {
z_trend = -1;
}
// add!
al.add(next_step);
} else {
// if the z trend is broken, finish
if ((next_z > step_z && 1 == z_trend) || (next_z < step_z && -1 == z_trend)) {
// z trend continues
al.add(next_step);
} else {
// z trend broken
next_step = null;
}
}
}
Profile last = step;
// Utils.log2("next_step is " + next_step);
if (null != next_step) {
hs_done.add(next_step);
last = accumulate(hs_done, al, next_step, z_trend);
}
// Utils.log2("returning last " + last);
return last;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Search method executeSearch.
private void executeSearch() {
final Project project = Project.getProjects().get(projects.getSelectedIndex());
if (null == project) {
// Should not happen
return;
}
Bureaucrat.createAndStart(new Worker.Task("Searching") {
public void exec() {
String pattern = search_field.getText();
if (null == pattern || 0 == pattern.length()) {
return;
}
// fix pattern
final String typed_pattern = pattern;
// I hate java
final StringBuilder sb = new StringBuilder();
if (!pattern.startsWith("^"))
sb.append("^.*");
for (int i = 0; i < pattern.length(); i++) {
sb.append(pattern.charAt(i));
}
if (!pattern.endsWith("$"))
sb.append(".*$");
pattern = sb.toString();
final Pattern pat = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// Utils.log2("pattern after: " + pattern);
final ArrayList<DBObject> al = new ArrayList<DBObject>();
// Utils.log("types[pulldown] = " +
// types[pulldown.getSelectedIndex()]);
find(project.getRootLayerSet(), al, types[pulldown.getSelectedIndex()]);
// Utils.log2("found labels: " + al.size());
if (0 == al.size())
return;
final Vector<DBObject> v_obs = new Vector<DBObject>();
final Vector<String> v_txt = new Vector<String>();
final Vector<Coordinate<?>> v_co = new Vector<Coordinate<?>>();
Coordinate<?> co = null;
for (final DBObject dbo : al) {
if (Thread.currentThread().isInterrupted()) {
return;
}
boolean matched = false;
// Search in its title
Displayable d = null;
if (dbo instanceof Displayable) {
d = (Displayable) dbo;
}
String txt;
String meaningful_title = null;
if (null == d || Patch.class == d.getClass())
txt = dbo.getTitle();
else {
txt = meaningful_title = dbo.getProject().getMeaningfulTitle(d);
}
if (null == txt || 0 == txt.trim().length())
continue;
matched = pat.matcher(txt).matches();
if (!matched && null != d) {
// Search also in its annotation
txt = d.getAnnotation();
if (null != txt)
matched = pat.matcher(txt).matches();
}
if (!matched) {
// Search also in its toString()
txt = dbo.toString();
matched = pat.matcher(txt).matches();
}
if (!matched) {
// Search also in its id
txt = Long.toString(dbo.getId());
matched = pat.matcher(txt).matches();
if (matched)
txt = "id: #" + txt;
}
if (!matched && null != d) {
// Search also in its properties
Map<String, String> props = d.getProperties();
if (null != props) {
for (final Map.Entry<String, String> e : props.entrySet()) {
if (pat.matcher(e.getKey()).matches() || pat.matcher(e.getValue()).matches()) {
matched = true;
txt = e.getKey() + " => " + e.getValue() + " [property]";
break;
}
}
}
if (!matched) {
Map<Displayable, Map<String, String>> linked_props = ((Displayable) dbo).getLinkedProperties();
if (null != linked_props) {
for (final Map.Entry<Displayable, Map<String, String>> e : linked_props.entrySet()) {
for (final Map.Entry<String, String> ee : e.getValue().entrySet()) {
if (pat.matcher(ee.getKey()).matches() || pat.matcher(ee.getValue()).matches()) {
matched = true;
txt = ee.getKey() + " => " + e.getValue() + " [linked property]";
break;
}
}
}
}
}
}
if (!matched && dbo instanceof Tree<?>) {
// search Node tags
Node<?> root = ((Tree<?>) dbo).getRoot();
if (null == root)
continue;
for (final Node<?> nd : root.getSubtreeNodes()) {
Set<Tag> tags = nd.getTags();
if (null == tags)
continue;
for (final Tag tag : tags) {
if (pat.matcher(tag.toString()).matches()) {
v_obs.add(dbo);
v_txt.add(new StringBuilder(tag.toString()).append(" (").append(null == meaningful_title ? dbo.toString() : meaningful_title).append(')').toString());
v_co.add(createCoordinate((Tree<?>) dbo, nd));
}
}
}
// all added if any
continue;
}
if (!matched)
continue;
// txt = txt.length() > 30 ? txt.substring(0, 27) + "..." :
// txt;
v_obs.add(dbo);
v_txt.add(txt);
v_co.add(co);
}
if (0 == v_obs.size()) {
Utils.showMessage("Nothing found.");
return;
}
final JPanel result = new JPanel();
GridBagLayout gb = new GridBagLayout();
result.setLayout(gb);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(5, 10, 5, 10);
String xml = "";
if (project.getLoader() instanceof FSLoader) {
String path = ((FSLoader) project.getLoader()).getProjectXMLPath();
if (null != path) {
xml = " [" + new File(path).getName() + "]";
}
}
JLabel projectTitle = new JLabel(project.getTitle() + xml);
gb.setConstraints(projectTitle, c);
result.add(projectTitle);
c.insets = new Insets(0, 0, 0, 0);
JPanel padding = new JPanel();
c.weightx = 1;
gb.setConstraints(padding, c);
result.add(padding);
c.gridy = 1;
c.gridwidth = 2;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
JScrollPane jsp = makeTable(new DisplayableTableModel(v_obs, v_txt, v_co), project);
gb.setConstraints(jsp, c);
result.add(jsp);
search_tabs.addTab(typed_pattern, result);
search_tabs.setSelectedComponent(result);
synchronized (tabMap) {
List<JPanel> cs = tabMap.get(project);
if (null == cs) {
cs = new ArrayList<JPanel>();
tabMap.put(project, cs);
}
cs.add(result);
}
}
}, project);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Merger method makeGUI.
private static void makeGUI(final Project p1, final Project p2, HashSet<ZDisplayable> empty1, HashSet<ZDisplayable> empty2, HashMap<Displayable, List<Change>> matched, HashSet<ZDisplayable> unmatched1, HashSet<ZDisplayable> unmatched2) {
final ArrayList<Row> rows = new ArrayList<Row>();
for (Map.Entry<Displayable, List<Change>> e : matched.entrySet()) {
for (Change c : e.getValue()) {
rows.add(new Row(c));
}
if (e.getValue().size() > 1) {
Utils.log("More than one assigned to " + e.getKey());
}
}
JTabbedPane tabs = new JTabbedPane();
final Table table = new Table();
tabs.addTab("Matched", new JScrollPane(table));
JTable tu1 = createTable(unmatched1, "Unmatched 1", p1, p2);
JTable tu2 = createTable(unmatched2, "Unmatched 2", p1, p2);
JTable tu3 = createTable(empty1, "Empty 1", p1, p2);
JTable tu4 = createTable(empty2, "Empty 2", p1, p2);
tabs.addTab("Unmatched 1", new JScrollPane(tu1));
tabs.addTab("Unmatched 2", new JScrollPane(tu2));
tabs.addTab("Empty 1", new JScrollPane(tu3));
tabs.addTab("Empty 2", new JScrollPane(tu4));
for (int i = 0; i < tabs.getTabCount(); i++) {
if (null == tabs.getTabComponentAt(i)) {
Utils.log2("null at " + i);
continue;
}
tabs.getTabComponentAt(i).setPreferredSize(new Dimension(1024, 768));
}
String xml1 = new File(((FSLoader) p1.getLoader()).getProjectXMLPath()).getName();
String xml2 = new File(((FSLoader) p2.getLoader()).getProjectXMLPath()).getName();
JFrame frame = new JFrame("1: " + xml1 + " || 2: " + xml2);
tabs.setPreferredSize(new Dimension(1024, 768));
frame.getContentPane().add(tabs);
frame.pack();
frame.setVisible(true);
// so the bullshit starts: any other way to set the model fails, because it tries to render it while setting it
SwingUtilities.invokeLater(new Runnable() {
public void run() {
table.setModel(new Model(rows));
CustomCellRenderer cc = new CustomCellRenderer();
for (int i = 0; i < Row.COLUMNS; i++) {
table.setDefaultRenderer(table.getColumnClass(i), cc);
}
}
});
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class AreaUtils method generateTriangles.
/**
* Expects areas in local coordinates to the Displayable @param d.
* @param d
* @param scale The scaling of the entire universe, to limit the overall box
* @param resample_ The optimization parameter for marching cubes (i.e. a value of 2 will scale down to half, then apply marching cubes, then scale up by 2 the vertices coordinates).
* @param areas
* @return The List of triangles involved, specified as three consecutive vertices. A list of Point3f vertices.
*/
public static List<Point3f> generateTriangles(final Displayable d, final double scale, final int resample_, final Map<Layer, Area> areas) {
// in the LayerSet, layers are ordered by Z already.
try {
int n = areas.size();
if (0 == n)
return null;
final int resample;
if (resample_ <= 0) {
resample = 1;
Utils.log2("Fixing zero or negative resampling value to 1.");
} else
resample = resample_;
final LayerSet layer_set = d.getLayerSet();
final AffineTransform aff = d.getAffineTransformCopy();
final Rectangle r = d.getBoundingBox(null);
// remove translation from a copy of the Displayable's AffineTransform
final AffineTransform at_translate = new AffineTransform();
at_translate.translate(-r.x, -r.y);
aff.preConcatenate(at_translate);
// incorporate resampling scaling into the transform
final AffineTransform atK = new AffineTransform();
// Utils.log("resample: " + resample + " scale: " + scale);
// 'scale' is there to limit gigantic universes
final double K = (1.0 / resample) * scale;
atK.scale(K, K);
aff.preConcatenate(atK);
final Calibration cal = layer_set.getCalibrationCopy();
// Find first layer, compute depth, and fill in the depth vs area map
Layer first_layer = null, last_layer = null;
final int w = (int) Math.ceil(r.width * K);
final int h = (int) Math.ceil(r.height * K);
int depth = 0;
final Map<Integer, Area> ma = new HashMap<Integer, Area>();
for (final Layer la : layer_set.getLayers()) {
// layers sorted by Z ASC
final Area area = areas.get(la);
if (null != area) {
ma.put(depth, area);
if (null == first_layer) {
first_layer = la;
}
// Utils.log("area at depth " + depth + " for layer " + la);
depth++;
n--;
} else if (0 != depth) {
// Utils.log("Empty area at depth " + depth);
// an empty layer
depth++;
}
if (0 == n) {
last_layer = la;
// no more areas to paint
break;
}
}
if (0 == depth) {
Utils.log("ERROR could not find any areas for " + d);
return null;
}
if (0 != n) {
Utils.log("WARNING could not find all areas for " + d);
}
// No zero-padding: Marching Cubes now can handle edges
final ShapeList<ByteType> shapeList = new ShapeListCached<ByteType>(new int[] { w, h, depth }, new ByteType(), 32);
final Image<ByteType> shapeListImage = new Image<ByteType>(shapeList, shapeList.getBackground(), "ShapeListContainer");
// 255 or -1 don't work !? So, giving the highest value (127) that is both a byte and an int.
final ByteType intensity = new ByteType((byte) 127);
for (final Map.Entry<Integer, Area> e : ma.entrySet()) {
Area a = e.getValue();
if (!aff.isIdentity()) {
a = M.areaInIntsByRounding(a.createTransformedArea(aff));
}
shapeList.addShape(a, intensity, new int[] { e.getKey() });
}
// debug:
// ImagePlus imp = ImageJFunctions.displayAsVirtualStack(shapeListImage);
// imp.getProcessor().setMinAndMax( 0, 255 );
// imp.show();
// Utils.log2("Using imglib Shape List Image Container");
// Now marching cubes
// origins at 0,0,0: uncalibrated
final List<Point3f> list = new MCTriangulator().getTriangles(shapeListImage, 1, new float[3]);
// The list of triangles has coordinates:
// - in x,y: in pixels, scaled by K = (1 / resample) * scale,
// translated by r.x, r.y (the top-left coordinate of this AreaList bounding box)
// - in z: in stack slice indices
// So all x,y,z must be corrected in x,y and z of the proper layer
// final double offset = first_layer.getZ();
final int i_first_layer = layer_set.indexOf(first_layer);
// The x,y translation to correct each point by:
final float dx = (float) (r.x * scale * cal.pixelWidth);
final float dy = (float) (r.y * scale * cal.pixelHeight);
// Correct x,y by resampling and calibration, but not scale
// scale is already in the pixel coordinates
final float rsw = (float) (resample * cal.pixelWidth);
final float rsh = (float) (resample * cal.pixelHeight);
// no resampling in Z. and Uses pixelWidth, not pixelDepth.
final double sz = scale * cal.pixelWidth;
// debug:
/*
// which p.z types exist?
final TreeSet<Float> ts = new TreeSet<Float>();
for (final Iterator it = list.iterator(); it.hasNext(); ) {
ts.add(((Point3f)it.next()).z);
}
for (final Float pz : ts) Utils.log2("A z: " + pz);
*/
// debug: How many different Z?
/*
HashSet<Float> zs = new HashSet<Float>();
for (Point3f p : list) {
zs.add(p.z);
}
ArrayList<Float> a = new ArrayList<Float>(zs);
java.util.Collections.sort(a);
for (Float f : a) {
Utils.log("f: " + f);
}
*/
// Utils.log2("Number of slices: " + imp.getNSlices());
// Fix all points:
// Read from list, modify and put into verts
// and don't modify it if the verts already has it (it's just coincident)
final Point3f[] verts = new Point3f[list.size()];
// Utils.log("number of verts: " + verts.length + " mod 3: " + (verts.length % 3));
final TreeMap<Integer, Point3f> output = new TreeMap<Integer, Point3f>();
// The first section generates vertices at -1 and 0
// The last section generates them at last_section_index and last_section_index +1
// Capture from -1 to 0
fix3DPoints(list, output, verts, first_layer.getZ(), 0, -1, dx, dy, rsw, rsh, sz, 1);
int slice_index = 0;
for (final Layer la : layer_set.getLayers().subList(i_first_layer, i_first_layer + depth)) {
// If layer is empty, continue
/* // YEAH don't! At least the immediate next layer would have points, like the extra Z level after last layer, to account for the thickness of the layer!
if (empty_layers.contains(la)) {
slice_index++;
continue;
}
*/
fix3DPoints(list, output, verts, la.getZ(), la.getThickness(), slice_index, dx, dy, rsw, rsh, sz, 1);
slice_index++;
}
// Do the last layer again. The last layer has two Z planes in which it has pixels:
try {
// Capture from last_section_index to last_section_index+1, inclusive
fix3DPoints(list, output, verts, last_layer.getZ() + last_layer.getThickness(), 0, slice_index, dx, dy, rsw, rsh, sz, 2);
} catch (final Exception ee) {
IJError.print(ee);
}
// Handle potential errors:
if (0 != list.size() - output.size()) {
Utils.log2("Unprocessed/unused points: " + (list.size() - output.size()));
for (int i = 0; i < verts.length; i++) {
if (null == verts[i]) {
final Point3f p = (Point3f) list.get(i);
Utils.log2("verts[" + i + "] = " + p.x + ", " + p.y + ", " + p.z + " p.z as int: " + ((int) (p.z + 0.05f)));
}
}
return new ArrayList<Point3f>(output.values());
} else {
return java.util.Arrays.asList(verts);
}
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class StitchingTEM method montageWithPhaseCorrelation.
/**
* @param layers
* @param worker Optional, the {@link Worker} running this task.
*/
public static void montageWithPhaseCorrelation(final List<Layer> layers, final Worker worker) {
final PhaseCorrelationParam param = new PhaseCorrelationParam();
final Collection<Displayable> col = layers.get(0).getDisplayables(Patch.class);
if (!param.setup(col.size() > 0 ? (Patch) col.iterator().next() : null)) {
return;
}
final int i = 1;
for (final Layer la : layers) {
if (Thread.currentThread().isInterrupted() || (null != worker && worker.hasQuitted()))
return;
if (null != worker)
worker.setTaskName("Montage layer " + i + "/" + layers.size());
final Collection<Patch> patches = (Collection<Patch>) (Collection) la.getDisplayables(Patch.class);
AlignTask.transformPatchesAndVectorData(patches, new Runnable() {
@Override
public void run() {
montageWithPhaseCorrelation(patches, param);
}
});
}
}
Aggregations