use of mpicbg.models.SimilarityModel2D in project TrakEM2 by trakem2.
the class MovingLeastSquaresTransform2 method init.
@Override
public final void init(final String data) throws NumberFormatException {
final String[] fields = data.split("\\s+");
if (fields.length > 3) {
final int n = Integer.parseInt(fields[1]);
if ((fields.length - 3) % (2 * n + 1) == 0) {
final int l = (fields.length - 3) / (2 * n + 1);
if (n == 2) {
if (fields[0].equals("translation"))
model = new TranslationModel2D();
else if (fields[0].equals("rigid"))
model = new RigidModel2D();
else if (fields[0].equals("similarity"))
model = new SimilarityModel2D();
else if (fields[0].equals("affine"))
model = new AffineModel2D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else if (n == 3) {
if (fields[0].equals("affine"))
model = new AffineModel3D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
alpha = Float.parseFloat(fields[2]);
p = new float[n][l];
q = new float[n][l];
w = new float[l];
int i = 2, j = 0;
while (i < fields.length - 1) {
for (int d = 0; d < n; ++d) p[d][j] = Float.parseFloat(fields[++i]);
for (int d = 0; d < n; ++d) q[d][j] = Float.parseFloat(fields[++i]);
w[j] = Float.parseFloat(fields[++i]);
++j;
}
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
}
use of mpicbg.models.SimilarityModel2D in project TrakEM2 by trakem2.
the class ManualAlignMode method apply.
@Override
public boolean apply() {
// Check there's more than one layer
if (m.size() < 2) {
Utils.showMessage("Need more than one layer to align!");
return false;
}
// Check that the current layer is one of the layers with landmarks.
// Will be used as reference
final Layer ref_layer = display.getLayer();
if (null == m.get(ref_layer)) {
Utils.showMessage("Please scroll to a layer with landmarks,\nto be used as reference.");
return false;
}
// Check that all layers have the same number of landmarks
int n_landmarks = -1;
for (final Map.Entry<Layer, Landmarks> e : m.entrySet()) {
final Landmarks lm = e.getValue();
if (-1 == n_landmarks) {
n_landmarks = lm.points.size();
continue;
}
if (n_landmarks != lm.points.size()) {
Utils.showMessage("Can't apply: there are different amounts of landmarks per layer.\nSee the log window.");
for (final Map.Entry<Layer, Landmarks> ee : m.entrySet()) {
Utils.log(ee.getValue().points.size() + " landmarks in layer " + ee.getKey());
}
return false;
}
}
// Sort Layers by Z
final TreeMap<Layer, Landmarks> sorted = new TreeMap<Layer, Landmarks>(new Comparator<Layer>() {
@Override
public boolean equals(final Object ob) {
return this == ob;
}
@Override
public int compare(final Layer l1, final Layer l2) {
// Ascending order
final double dz = l1.getZ() - l2.getZ();
if (dz < 0)
return -1;
else if (dz > 0)
return 1;
else
return 0;
}
});
sorted.putAll(m);
int iref = 0;
for (final Layer la : sorted.keySet()) {
if (la != ref_layer)
iref++;
else
break;
}
// Ok, now ask for a model
final GenericDialog gd = new GenericDialog("Model");
gd.addChoice("Model:", Align.Param.modelStrings, Align.Param.modelStrings[1]);
gd.addCheckbox("Propagate to first layer", 0 != iref);
((Component) gd.getCheckboxes().get(0)).setEnabled(0 != iref);
gd.addCheckbox("Propagate to last layer", sorted.size() - 1 != iref);
((Component) gd.getCheckboxes().get(1)).setEnabled(sorted.size() - 1 != iref);
gd.showDialog();
if (gd.wasCanceled())
return false;
final int model_index = gd.getNextChoiceIndex();
final boolean propagate_to_first = gd.getNextBoolean();
final boolean propagate_to_last = gd.getNextBoolean();
int min;
// Create a model as desired
final AbstractAffineModel2D<?> model;
switch(model_index) {
case 0:
min = 1;
model = new TranslationModel2D();
break;
case 1:
min = 2;
model = new RigidModel2D();
break;
case 2:
min = 2;
model = new SimilarityModel2D();
break;
case 3:
min = 3;
model = new AffineModel2D();
break;
default:
Utils.log("Unknown model index!");
return false;
}
if (n_landmarks < min) {
Utils.showMessage("Need at least " + min + " landmarks for a " + Align.Param.modelStrings[model_index] + " model");
return false;
}
Bureaucrat.createAndStart(new Worker.Task("Aligning layers with landmarks") {
@Override
public void exec() {
// Find layers with landmarks, in increasing Z.
// Match in pairs.
// So, get two submaps: from ref_layer to first, and from ref_layer to last
// strictly lower Z than ref_layer
final SortedMap<Layer, Landmarks> first_chunk_ = new TreeMap<Layer, Landmarks>(sorted.headMap(ref_layer));
// .. so add ref_layer
first_chunk_.put(ref_layer, m.get(ref_layer));
// equal or larger Z than ref_layer
final SortedMap<Layer, Landmarks> second_chunk = sorted.tailMap(ref_layer);
final SortedMap<Layer, Landmarks> first_chunk;
// Reverse order of first_chunk
if (first_chunk_.size() > 1) {
final SortedMap<Layer, Landmarks> fc = new TreeMap<Layer, Landmarks>(new Comparator<Layer>() {
@Override
public boolean equals(final Object ob) {
return this == ob;
}
@Override
public int compare(final Layer l1, final Layer l2) {
// Descending order
final double dz = l2.getZ() - l1.getZ();
if (dz < 0)
return -1;
else if (dz > 0)
return 1;
else
return 0;
}
});
fc.putAll(first_chunk_);
first_chunk = fc;
} else {
first_chunk = first_chunk_;
}
final LayerSet ls = ref_layer.getParent();
final Collection<Layer> affected_layers = new HashSet<Layer>(m.keySet());
// Gather all Patch instances that will be affected
final ArrayList<Patch> patches = new ArrayList<Patch>();
for (final Layer la : m.keySet()) patches.addAll(la.getAll(Patch.class));
if (propagate_to_first && first_chunk.size() > 1) {
final Collection<Layer> affected = ls.getLayers().subList(0, ls.indexOf(first_chunk.lastKey()));
for (final Layer la : affected) {
patches.addAll(la.getAll(Patch.class));
}
affected_layers.addAll(affected);
}
if (propagate_to_last && second_chunk.size() > 1) {
final Collection<Layer> affected = ls.getLayers().subList(ls.indexOf(second_chunk.lastKey()) + 1, ls.size());
for (final Layer la : affected) {
patches.addAll(la.getAll(Patch.class));
}
}
// Transform segmentations along with patches
AlignTask.transformPatchesAndVectorData(patches, new Runnable() {
@Override
public void run() {
// Apply!
// TODO: when adding non-linear transforms, use this single line for undo instead of all below:
// (these transforms may be non-linear as well, which alter mipmaps.)
// ls.addTransformStepWithData(affected_layers);
// Setup undo:
// Find all images in the range of affected layers,
// plus all Displayable of those layers (but Patch instances in a separate DoTransforms step,
// to avoid adding a "data" undo for them, which would recreate mipmaps when undone).
// plus all ZDisplayable that paint in those layers
final HashSet<Displayable> ds = new HashSet<Displayable>();
final ArrayList<Displayable> patches = new ArrayList<Displayable>();
for (final Layer layer : affected_layers) {
for (final Displayable d : layer.getDisplayables()) {
if (d.getClass() == Patch.class) {
patches.add(d);
} else {
ds.add(d);
}
}
}
for (final ZDisplayable zd : ls.getZDisplayables()) {
for (final Layer layer : affected_layers) {
if (zd.paintsAt(layer)) {
ds.add((Displayable) zd);
break;
}
}
}
if (ds.size() > 0) {
final Displayable.DoEdits step = ls.addTransformStepWithData(ds);
if (patches.size() > 0) {
final ArrayList<DoStep> a = new ArrayList<DoStep>();
a.add(new Displayable.DoTransforms().addAll(patches));
step.addDependents(a);
}
}
if (first_chunk.size() > 1) {
final AffineTransform aff = align(first_chunk, model);
if (propagate_to_first) {
for (final Layer la : ls.getLayers().subList(0, ls.indexOf(first_chunk.lastKey()))) {
// exclusive last
la.apply(Patch.class, aff);
}
}
}
if (second_chunk.size() > 1) {
final AffineTransform aff = align(second_chunk, model);
if (propagate_to_last) {
for (final Layer la : ls.getLayers().subList(ls.indexOf(second_chunk.lastKey()) + 1, ls.size())) {
// exclusive last
la.apply(Patch.class, aff);
}
}
}
Display.repaint();
// Store current state
if (ds.size() > 0) {
final Displayable.DoEdits step2 = ls.addTransformStepWithData(ds);
if (patches.size() > 0) {
final ArrayList<DoStep> a2 = new ArrayList<DoStep>();
a2.add(new Displayable.DoTransforms().addAll(patches));
step2.addDependents(a2);
}
}
}
});
}
}, display.getProject());
return true;
}
use of mpicbg.models.SimilarityModel2D in project TrakEM2 by trakem2.
the class NonLinearTransformMode method mousePressed.
@Override
public void mousePressed(final MouseEvent me, final int x_p, final int y_p, final double magnification) {
/* find if clicked on a point */
p_clicked = null;
double min = Double.MAX_VALUE;
final Point mouse = new Point(new double[] { x_p, y_p });
final double a = 64.0 / magnification / magnification;
for (final Point p : points) {
final double sd = Point.squareDistance(p, mouse);
if (sd < min && sd < a) {
p_clicked = p;
min = sd;
}
}
if (me.isShiftDown()) {
if (null == p_clicked) {
/* add one */
try {
if (points.size() > 0) {
/*
* Create a pseudo-invertible (TransformMesh) for the screen.
*/
final CoordinateTransform mlst = createCT();
final SimilarityModel2D toWorld = new SimilarityModel2D();
toWorld.set(1.0 / magnification, 0, srcRect.x, srcRect.y);
final SimilarityModel2D toScreen = toWorld.createInverse();
final mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform> ctl = new mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform>();
ctl.add(toWorld);
ctl.add(mlst);
ctl.add(toScreen);
final CoordinateTransformMesh ctm = new CoordinateTransformMesh(ctl, 32, (int) Math.ceil(srcRect.width * magnification), (int) Math.ceil(srcRect.height * magnification));
final double[] l = mouse.getL();
toScreen.applyInPlace(l);
ctm.applyInverseInPlace(l);
toWorld.applyInPlace(l);
}
points.add(mouse);
p_clicked = mouse;
} catch (final Exception e) {
Utils.log("Could not add point");
e.printStackTrace();
}
} else if (Utils.isControlDown(me)) {
// remove it
points.remove(p_clicked);
p_clicked = null;
}
}
}
use of mpicbg.models.SimilarityModel2D in project TrakEM2 by trakem2.
the class NonLinearTransformMode method doPainterUpdate.
@Override
protected void doPainterUpdate(final Rectangle r, final double m) {
try {
final CoordinateTransform mlst = createCT();
final SimilarityModel2D toWorld = new SimilarityModel2D();
toWorld.set(1.0 / m, 0, r.x - ScreenPatchRange.pad / m, r.y - ScreenPatchRange.pad / m);
final mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform> ctl = new mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform>();
ctl.add(toWorld);
ctl.add(mlst);
ctl.add(toWorld.createInverse());
final CoordinateTransformMesh ctm = new CoordinateTransformMesh(ctl, 32, r.width * m + 2 * ScreenPatchRange.pad, r.height * m + 2 * ScreenPatchRange.pad);
final TransformMeshMappingWithMasks<CoordinateTransformMesh> mapping = new TransformMeshMappingWithMasks<CoordinateTransformMesh>(ctm);
// keep a pointer to the current list
final HashMap<Paintable, GroupingMode.ScreenPatchRange<?>> screenPatchRanges = this.screenPatchRanges;
for (final GroupingMode.ScreenPatchRange spr : screenPatchRanges.values()) {
if (screenPatchRanges != this.screenPatchRanges) {
// TODO should it call itself: doPainterUpdate( r, m );
break;
}
spr.update(mapping);
}
} catch (final NotEnoughDataPointsException e) {
} catch (final NoninvertibleModelException e) {
} catch (final IllDefinedDataPointsException e) {
} catch (final Exception e) {
e.printStackTrace();
}
}
use of mpicbg.models.SimilarityModel2D in project TrakEM2 by trakem2.
the class MovingLeastSquaresTransform method init.
@Override
public final void init(final String data) throws NumberFormatException {
matches.clear();
final String[] fields = data.split("\\s+");
if (fields.length > 3) {
final int d = Integer.parseInt(fields[1]);
if ((fields.length - 3) % (2 * d + 1) == 0) {
if (d == 2) {
if (fields[0].equals("translation"))
model = new TranslationModel2D();
else if (fields[0].equals("rigid"))
model = new RigidModel2D();
else if (fields[0].equals("similarity"))
model = new SimilarityModel2D();
else if (fields[0].equals("affine"))
model = new AffineModel2D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else if (d == 3) {
if (fields[0].equals("affine"))
model = new AffineModel3D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
alpha = Double.parseDouble(fields[2]);
int i = 2;
while (i < fields.length - 1) {
final double[] p1 = new double[d];
for (int k = 0; k < d; ++k) p1[k] = Double.parseDouble(fields[++i]);
final double[] p2 = new double[d];
for (int k = 0; k < d; ++k) p2[k] = Double.parseDouble(fields[++i]);
final double weight = Double.parseDouble(fields[++i]);
final PointMatch m = new PointMatch(new Point(p1), new Point(p2), weight);
matches.add(m);
}
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
}
Aggregations