id,summary,reporter,owner,description,type,status,priority,milestone,component,version,severity,resolution,keywords,cc,blockedby,blocking
2012,Support general text specified axis class,bdezonia,bdezonia,"There are good reasons to support one kind of axis that has it's equation defined by a string. I have mocked up a class below. This is not a simple endeavor but would eliminate a lot of (sometimes redundant) concrete CalibratedAxis implementations. See notes in code below for pointers.
{{{
package net.imglib2.meta.axis;
import net.imglib2.meta.AxisType;
/**
* A very general text driven axis class.
*
* @author Barry DeZonia
*/
public class UberAsciiAxis extends VariableAxis {
// I might be getting carried away but think it would be nice to define axes
// by equation alone. IJ1 has lots of one off definitions in CurveFitter that
// have offsets or not or powers or not. I've generalized some of this by
// always having an offset that can be 0. But really we'd like the flexibility
// of not needing a new concrete axis class every time someone comes up with a
// new formula. This class would parse the equation and build an appropriate
// function that can scale coords as needed. The nice thing here is that the
// parsed axis can be queried for variables and then a curve fitting algo can
// determine appropriate variable values. Curtis' idea of the EditAxes plugin
// directly tweaking the variables of a displayed equation is correct. There
// remains the trick of determining when an axis is linear. This can be done
// by testing that an axis.equals(some general linear axis string) as noted
// below.
// TODO - bad name: Equation is more general than our 1d case
private interface Equation {
// This might be involved to determine but it would be fun to write!
Equation inverse(); // if doesn't exist we will return a NullEquation
double eval(double input);
// TODO - maybe one String method rather than two.
String generalEquation();
String particularEquation(); // likely in an abstract class
}
// equation string can be things like:
// y = m*x + b
// y = 74*x + b
// y = q*sin(slope*x+19.4)^(33*power)+fred (here only x & y are predefined)
// constants and vars automatically detected
private final String equationString;
private final Equation eqn;
private final Equation eqnInverse;
public UberAsciiAxis(AxisType type, String unit, String equationString) {
super(type, unit);
this.eqn = parse(equationString);
this.eqnInverse = eqn.inverse();
this.equationString = equationString;
}
public UberAsciiAxis(AxisType type, String unit, Equation equation) {
super(type, unit);
this.eqn = equation;
this.eqnInverse = eqn.inverse();
this.equationString = equation.generalEquation(); // or particular?
}
@Override
public double calibratedValue(double rawValue) {
return eqn.eval(rawValue);
}
@Override
public double rawValue(double calibratedValue) {
return eqnInverse.eval(calibratedValue);
}
@Override
public String generalEquation() {
return equationString;
}
@Override
public UberAsciiAxis copy() {
return new UberAsciiAxis(type(), unit(), equationString);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof UberAsciiAxis)) return false;
UberAsciiAxis other = (UberAsciiAxis) o;
// TODO: do something really cool. compare syntax trees and variables of the
// two UberAxes. Even trickier: detect when vars of two eqns are the same
// due to coeffs being 1 or 0. For example y = 1*x + 0 is same as y = x
// though they would have different syntax trees.
// TEMP: only equal to self
return other == this;
}
// For generality and reuse elsewhere maybe make parser return multidim
// equation. We'd need to test that it has a single dim of input to qualify as
// a valid axis equation
private Equation parse(String equationString) {
// TODO
return new NullEquation();
}
// return one of these as an Equation::inverse() when it is not invertible
private class NullEquation implements Equation {
@Override
public double eval(double input) {
return Double.NaN;
}
@Override
public Equation inverse() {
return this;
}
@Override
public String generalEquation() {
return ""y = NaN"";
}
@Override
public String particularEquation() {
return ""y = NaN"";
}
}
}
}}}
",defect,closed,major,imagej-2.0.0,ImgLib2,,serious,moved,,,,1400