Next: Use Outside of a Up: Converting Between Multiple Coordinate Previous: Converting Between Multiple Coordinate

### Basic Use

A `CoordTransform` object is most commonly used by attaching it to a `CoordinateSystem` via one of the latter's `attachTransform()` methods. This causes the `CoordinateSystem` to automatically apply the transform everytime positions are requested from the system. For example, suppose we have a `CoordinateSystem` that calculates positions in some space that is defined by a reference point:

    CoordinateSystem csys;
    ...
    Metadata md = csys.getMetadata();
    System.out.println( "reference point for first axis: " +
    	            md.getMetadata("Axes[0].refposition"));
    /*
     * OUTPUT:
     * reference point for first axis: 7.0
     */

    double[] datapos = { 1.0, 2.5, 5.0 };
    CoordPos cpos = csys.getCoordPos(datavox);
    System.out.println( cpos.getValueString(0) )

    /*
     * OUTPUT:
     * 7.0
     */

Suppose further that we would like the positions that are printed out to be relative to the reference point, rather than absolute positions. We can think of this as transforming the positions to a new coordinate system; that is, we will convert them from from an absolute system to a relative system. To do this we can apply the `AbsToRelCoordTransform` to the `CoordinateSystem`:

    // we want to convert positions along 3 of the axes
    CoordTransform conversion = new AbsToRelCoordTransform(3);

    // attach the transform to the coordinate system
    try{
        csys.attachTransform(conversion);
    }
    catch (IllegalTransformException ex) {
        System.err.println("Unable to attach transform: " + ex.getMessage());
    }

    // the transform get automatically applied
    datapos = { 1.0, 2.5, 5.0 };
    cpos = csys.getCoordPos(datavox);
    System.out.println( cpos.getValueString(0) )

    /*
     * OUTPUT:
     * -6.0
     */

When the tranform object `conversion` in this example was ``attached'' to the coordinate system, it took a peek into the system's metadata to find out what its native reference position was and then adjusted its own internal parameters so that it can properly perform the conversion to relative coordinates.

Now suppose we no longer want to positions relative to the system's native reference point, but rather relative to some other point:

    // First remove the previous transform we just applied
    csys.popTransform();

    // Create a new transform using our reference point.  The third
    // argument to the constructor tells the transform not to use
    // the native reference position when it is attached to a coordinate
    // system (see API for details).
    //
    double[] refpos = { 5.5, 1.98, 10 };    // our referenct point
    conversion = new AbsToRelCoordTransform(3, refpos, false);

    // attach new transform
    try{
        csys.attachTransform(conversion);
    }
    catch (IllegalTransformException ex) {
        System.err.println("Unable to attach transform: " + ex.getMessage());
    }

    // now the new transform will be used
    datapos = { 1.0, 2.5, 5.0 };
    cpos = csys.getCoordPos(datavox);
    System.out.println( cpos.getValueString(0) )

    /*
     * OUTPUT:
     * -4.5
     */

In the above example, the transform applies (by default) itself to (at most) the first three axes of the system. However, sometimes the desired application of a transform is a little more complicated. Consider for example a 3-dimensional astronomical image whose axes are frequency, right ascension, and declination:

    Viewable astroimage;
    ...
    CoordinateSystem csys = astroimage.getCoordinateSystem();

    // display coordinates of the dataset origin
    double origin = {0.0, 0.0, 0.0};
    CoordPos cpos = csys.getCoordPos(origin);
    System.out.prinln( cpos.getAxisLabel(0) + ": " + cpos.getValueString(0) );
    System.out.prinln( cpos.getAxisLabel(1) + ": " + cpos.getValueString(1) );
    System.out.prinln( cpos.getAxisLabel(2) + ": " + cpos.getValueString(2) );

    /*
     * OUTPUT:
     * Frequency: 115.98 GHz
     * Right Ascension: 14:32:42.05
     * Declination: 27:02:13.3
     */

Suppose now that instead of right ascension and declination, we would like positions in terms of Galactic longitude and latitude. We might do the following:

    CoordTransform conversion = new CelToGalCoordTransform();

    // attach the transform to the coordinate system
    try{
        csys.attachTransform(conversion);
    }
    catch (IllegalTransformException ex) {
        System.err.println("Unable to attach transform: " + ex.getMessage());
    }

    // now the new transform will be used
    CoordPos cpos = csys.getCoordPos(origin);
    System.out.prinln( cpos.getAxisLabel(0) + ": " + cpos.getValueString(0) );
    System.out.prinln( cpos.getAxisLabel(1) + ": " + cpos.getValueString(1) );
    System.out.prinln( cpos.getAxisLabel(2) + ": " + cpos.getValueString(2) );

    /*
     * OUTPUT:
     * Frequency: 115.98 GHz
     * Galactic Longitude: 38.123513
     * Galactic Latitude: 66.984528
     */

The transform object did more than just convert right ascension and declination into Galactic longitude and latidute, updating the labels appropriately. When it was attached, it actually had to figure out which axes were the ones it needed to operate on. That is, the transform knows that converts between celestial coordinates and galactic coordinates, and therefore looked for axes named ``Right Ascension'' and ``Declination'' (by examining the `CoordinateSystem`'s metadata); if it did not find them, a `IllegalTransformException` would have been thrown during attachment.

What if the coordinate system was already in terms of Galactic longitude and latitude and you wanted to convert positions to celestial coordinates? One can attach `CoordTransform` objects backwards to have the reverse transform applied. For example:

    // attach the transform to the coordinate system; the second argument
    // tells the system to attach the transform in the reverse direction.
    try{
        csys.attachTransform(conversion, false);
    }
    catch (IllegalTransformException ex) {
        System.err.println("Unable to attach transform: " + ex.getMessage());
    }

Instead of having the `CoordTransform` figure out how it is suppose to be applied, you can give explicit instructions via the `CoordTransformConstraints` class. This class can provide the two basic pieces of information needed, namely the direction the transform should be applied and something referred to as the Axis Index List which indicates which axes should be transformed and the order in which they should be interpreted.

To understand the Axis Index List, consider our example above converting celestial coordinates to galactic coordinates. The `CelToGalCoordTransform` by default expects that its first axis (axis # 0) will be a right ascension axis and the second axis (axis # 1) will be declination. That of course is not the order in which they actually appear in our data set. The `CoordTransformConstraints` class allows us to indicate that the axis that our transform expects at position 0 is actually at position 1:

    // Create a CoordTransformConstraint to describe how to apply the
    // transform:
    CoordTransformConstraint constraints = new CoordTransformConstraint();

    // the transform will be attached in the forward direction
    constraints.forward = true;

    // The transform by default wants the right ascension axis at axis
    // position 0;  indicate that instead this axis will be at position 1.
    constraints.setAxisAt(0, 1);

    // The transform by default wants the declination axis at axis
    // position 1;  indicate that instead this axis will be at position 2.
    constraints.setAxisAt(1, 2);

    // Now attach our transform
    csys.attachTransform(conversion, constraints);

Note that when we attach a tranform using a `CoordTransformConstraints` object, we do not need to be prepared to catch an `IllegalTransformException`. With the constraints, the `CoordTransform` does not need to check the system's metadata; thus, we have essentially ``forced'' the transform onto the system.

Next: Use Outside of a Up: Converting Between Multiple Coordinate Previous: Converting Between Multiple Coordinate