use of org.scijava.vecmath.Tuple3d in project TrakEM2 by trakem2.
the class Compare method transferVectorStrings.
/**
* Transform all points of all VectorString3D in vs using a Moving Least Squares Transform defined by the pairing of points in source to those in target.
* In short, bring source into target.
*/
public static List<VectorString3D> transferVectorStrings(final List<VectorString3D> vs, final List<Tuple3d> source, final List<Tuple3d> target, final Class<AffineModel3D> model_class) throws Exception {
if (source.size() != target.size()) {
Utils.log2("Could not generate a MovingLeastSquaresTransform: different number of source and target points.");
return null;
}
if (source.size() < 1 || target.size() < 1) {
Utils.log2("Cannot transform with less than one point correspondence!");
return null;
}
// 1 - Create the MovingLeastSquaresTransform from the point matches
final ArrayList<PointMatch> pm = new ArrayList<PointMatch>();
for (final Iterator<Tuple3d> si = source.iterator(), ti = target.iterator(); si.hasNext(); ) {
final Tuple3d sp = si.next();
final Tuple3d tp = ti.next();
pm.add(new PointMatch(new mpicbg.models.Point(new double[] { sp.x, sp.y, sp.z }), new mpicbg.models.Point(new double[] { tp.x, tp.y, tp.z }), 1));
}
final MovingLeastSquaresTransform mls = new MovingLeastSquaresTransform();
mls.setModel(model_class);
mls.setMatches(pm);
final double[] point = new double[3];
// 1.1 - Test: transfer source points
/*
for (final Iterator<Tuple3d> si = source.iterator(), ti = target.iterator(); si.hasNext(); ) {
Tuple3d sp = si.next();
point[0] = (double) sp.x;
point[1] = (double) sp.y;
point[2] = (double) sp.z;
mls.applyInPlace(point);
Tuple3d tp = ti.next();
Utils.log2("== target: " + (double)tp.x + ", " + (double)tp.y + ", " + (double)tp.z +
"\n o source: " + (double)sp.x + ", " + (double)sp.y + ", " + (double)sp.z +
"\n source: " + point[0] + ", " + point[1] + ", " + point[2]);
}
*/
// 2 - Transfer each VectorString3D in vs with mls
final List<VectorString3D> vt = new ArrayList<VectorString3D>();
for (final VectorString3D vi : vs) {
// The points of the VectorString3D:
final double[] x = vi.getPoints(0);
final double[] y = vi.getPoints(1);
final double[] z = vi.getPoints(2);
// Empty arrays to fill with the points to transfer:
final double[] tx = new double[x.length];
final double[] ty = new double[x.length];
final double[] tz = new double[x.length];
// Transfer point by point:
for (int i = 0; i < x.length; i++) {
point[0] = x[i];
point[1] = y[i];
point[2] = z[i];
mls.applyInPlace(point);
tx[i] = point[0];
ty[i] = point[1];
tz[i] = point[2];
}
try {
vt.add(new VectorString3D(tx, ty, tz, vi.isClosed()));
} catch (final Exception e) {
}
}
return vt;
}
use of org.scijava.vecmath.Tuple3d in project TrakEM2 by trakem2.
the class Compare method extractMatches.
/**
* Filer both maps, looking for matches, and put them into empty lists so and ta.
*/
private static boolean extractMatches(final Map<String, Tuple3d> source, final Map<String, Tuple3d> target, final List<Tuple3d> so, final List<Tuple3d> ta) {
if (null == source || null == target || null == so || null == ta)
return false;
so.clear();
ta.clear();
for (final Map.Entry<String, Tuple3d> e : target.entrySet()) {
final Tuple3d point = source.get(e.getKey());
if (null != point) {
so.add(point);
ta.add(e.getValue());
}
}
if (0 == so.size()) {
Utils.log2("No points in common!");
return false;
}
return true;
}
use of org.scijava.vecmath.Tuple3d in project TrakEM2 by trakem2.
the class Compare method gatherChains.
/**
* Gather chains for all projects considering the cp.regex, and transforms all relative to the reference Project p[0].
* Will ignore any for which a match exists in @param ignore.
*/
public static final Object[] gatherChains(final Project[] p, final CATAParameters cp, final String[] ignore) throws Exception {
String regex_exclude = null;
if (null != ignore) {
final StringBuilder sb = new StringBuilder();
for (final String ig : ignore) {
sb.append("(.*").append(ig).append(".*)|");
}
sb.setLength(sb.length() - 1);
regex_exclude = sb.toString();
}
Utils.logAll("Compare/gatherChains: using ignore string: " + regex_exclude);
Utils.logAll("Compare/gatherChains: using regex: " + cp.regex);
// gather all chains
// to keep track of each project's chains
final ArrayList[] p_chains = new ArrayList[p.length];
final ArrayList<Chain> chains = new ArrayList<Chain>();
for (int i = 0; i < p.length; i++) {
// for each project:
if (null == cp.regex) {
p_chains[i] = createPipeChains(p[i].getRootProjectThing(), p[i].getRootLayerSet(), regex_exclude);
} else {
// Search (shallow) for cp.regex matches
for (final ProjectThing pt : p[i].getRootProjectThing().findChildren(cp.regex, regex_exclude, true)) {
final ArrayList<Chain> ac = createPipeChains(pt, p[i].getRootLayerSet(), regex_exclude);
if (null == p_chains[i])
p_chains[i] = ac;
else
p_chains[i].addAll(ac);
}
// empty
if (null == p_chains[i])
p_chains[i] = new ArrayList<Chain>();
}
chains.addAll(p_chains[i]);
// calibrate
final Calibration cal = p[i].getRootLayerSet().getCalibrationCopy();
for (final Chain chain : (ArrayList<Chain>) p_chains[i]) chain.vs.calibrate(cal);
}
final int n_chains = chains.size();
// register all, or relative
if (4 == cp.transform_type) {
// compute global average delta
if (0 == cp.delta) {
for (final Chain chain : chains) {
cp.delta += (chain.vs.getAverageDelta() / n_chains);
}
}
Utils.log2("Using delta: " + cp.delta);
for (final Chain chain : chains) {
// BEFORE making it relative
chain.vs.resample(cp.delta, cp.with_source);
chain.vs.relative();
}
} else {
if (3 == cp.transform_type) {
// '3' means moving least squares computed from 3D landmarks
Utils.log2("Moving Least Squares Registration based on common fiducial points");
// Find fiducial points, if any
final HashMap<Project, Map<String, Tuple3d>> fiducials = new HashMap<Project, Map<String, Tuple3d>>();
for (final Project pr : p) {
final Set<ProjectThing> fids = pr.getRootProjectThing().findChildrenOfTypeR("fiducial_points");
if (null == fids || 0 == fids.size()) {
Utils.log("No fiducial points found in project: " + pr);
} else {
// the first fiducial group
fiducials.put(pr, Compare.extractPoints(fids.iterator().next()));
}
}
if (!fiducials.isEmpty()) {
// Register all VectorString3D relative to the first project:
final List<VectorString3D> lvs = new ArrayList<VectorString3D>();
final Calibration cal2 = p[0].getRootLayerSet().getCalibrationCopy();
for (final Chain chain : chains) {
final Project pr = chain.pipes.get(0).getProject();
// first project is reference, no need to transform.
if (pr == p[0])
continue;
lvs.clear();
lvs.add(chain.vs);
chain.vs = transferVectorStrings(lvs, fiducials.get(pr), fiducials.get(p[0])).get(0);
// Set (but do not apply!) the calibration of the reference project
chain.vs.setCalibration(cal2);
}
}
} else if (cp.transform_type < 3) {
// '0', '1' and '2' involve a 3D affine computed from the 3 axes
// no need //VectorString3D[][] vs_axes = new VectorString3D[p.length][];
Vector3d[][] o = new Vector3d[p.length][];
for (int i = 0; i < p.length; i++) {
// 1 - find pipes to work as axes for each project
final ArrayList<ZDisplayable> pipes = p[i].getRootLayerSet().getZDisplayables(Line3D.class, true);
final String[] pipe_names = new String[pipes.size()];
for (int k = 0; k < pipes.size(); k++) {
pipe_names[k] = p[i].getMeaningfulTitle(pipes.get(k));
}
final int[] s = findFirstXYZAxes(cp.preset, pipes, pipe_names);
// if axes are -1, forget it: not found
if (-1 == s[0] || -1 == s[1] || -1 == s[2]) {
Utils.log("Can't find axes for project " + p[i]);
o = null;
return null;
}
// obtain axes and origin
final Object[] pack = obtainOrigin(new Line3D[] { (Line3D) pipes.get(s[0]), (Line3D) pipes.get(s[1]), (Line3D) pipes.get(s[2]) }, cp.transform_type, // will be null for the first, which will then be non-null and act as the reference for the others.
o[0]);
// no need //vs_axes[i] = (VectorString3D[])pack[0];
o[i] = (Vector3d[]) pack[1];
}
/* // OLD WAY
// match the scales to make the largest be 1.0
final double scaling_factor = VectorString3D.matchOrigins(o, transform_type);
Utils.log2("matchOrigins scaling factor: " + scaling_factor + " for transform_type " + transform_type);
*/
// transform all except the first (which acts as reference)
final Transform3D M_ref = Compare.createTransform(o[0]);
for (int i = 1; i < p.length; i++) {
final Vector3d trans = new Vector3d(-o[i][3].x, -o[i][3].y, -o[i][3].z);
final Transform3D M_query = Compare.createTransform(o[i]);
// The transfer T transform: from query space to reference space.
final Transform3D T = new Transform3D(M_ref);
T.mulInverse(M_query);
for (final Chain chain : (ArrayList<Chain>) p_chains[i]) {
// in place
chain.vs.transform(T);
}
}
}
// compute global average delta, after correcting calibration and transformation
if (0 == cp.delta) {
for (final Chain chain : chains) {
cp.delta += (chain.vs.getAverageDelta() / n_chains);
}
}
Utils.log2("Using delta: " + cp.delta);
// After calibration and transformation, resample all to the same delta
for (final Chain chain : chains) chain.vs.resample(cp.delta, cp.with_source);
}
return new Object[] { chains, p_chains };
}
use of org.scijava.vecmath.Tuple3d in project TrakEM2 by trakem2.
the class Compare method extractPoints.
/**
* Extracts the list of fiduciary points from the fiducial parent and, if their name is different than "ball", adds their title as key and their first ball as a fiduciary point value of the returned map. The map is never null but could be empty.
* The values are calibrated.
*/
public static Map<String, Tuple3d> extractPoints(final ProjectThing fiducial) {
if (!fiducial.getType().equals("fiducial_points")) {
Utils.log("Can only extract points from 'fiducial_points' type.");
return null;
}
final ArrayList<ProjectThing> fiducials = fiducial.getChildren();
if (null == fiducials || 0 == fiducials.size()) {
Utils.log("No fiducial points can be extracted from " + fiducial);
return null;
}
final Map<String, Tuple3d> fide = new HashMap<String, Tuple3d>();
for (final ProjectThing child : fiducials) {
final Ball ball;
final String title;
if (child.getType().equals("ball")) {
// Method 1: use the ball title as the fiducial type
ball = (Ball) child.getObject();
title = ball.getTitle();
} else {
// Method 2: use the ball's parent type as the fiducial type
final ArrayList<ProjectThing> balls = child.findChildrenOfType("ball");
if (null == balls || 0 == balls.size()) {
Utils.log2("Ignoring empty fiducial " + child);
continue;
}
// pick the first one only
ball = (Ball) balls.get(0).getObject();
title = child.getType();
}
// calibrated
final double[][] b = ball.getWorldBalls();
if (b.length > 0) {
// get the first one only
fide.put(title.toLowerCase(), new Point3d(b[0][0], b[0][1], b[0][2]));
Utils.log2("Found fiducial point " + title.toLowerCase());
}
}
return fide;
}
use of org.scijava.vecmath.Tuple3d in project TrakEM2 by trakem2.
the class Compare method transferVectorStrings.
/**
* Transfer vs via a moving least squares transform by matching source named points into equally named target named points.
* If no points in common, returns null.
*/
public static List<VectorString3D> transferVectorStrings(final List<VectorString3D> vs, final Map<String, Tuple3d> source, final Map<String, Tuple3d> target) throws Exception {
if (null == source || null == target)
return null;
final List<Tuple3d> so = new ArrayList<Tuple3d>();
final List<Tuple3d> ta = new ArrayList<Tuple3d>();
for (final Map.Entry<String, Tuple3d> e : target.entrySet()) {
final Tuple3d point = source.get(e.getKey());
if (null != point) {
so.add(point);
ta.add(e.getValue());
}
}
if (0 == so.size()) {
Utils.log2("No points in common!");
return null;
}
Utils.log2("Found points in common: " + so.size());
return transferVectorStrings(vs, so, ta, AffineModel3D.class);
}
Aggregations