The actual computations converting pixel to world are carried out with the WCS library.
All absolute pixels coordinates are zero relative.
Matrix<Double> xform(2,2); // 1 xform = 0.0; xform.diagonal() = 1.0; // 2 DirectionCoordinate radec(MDirection::J2000, // 3 Projection(Projection::SIN), // 4 135*C::pi/180.0, 60*C::pi/180.0, // 5 -1*C::pi/180.0, 1*C::pi/180, // 6 xform, // 7 128, 128); // 8
In this example is is more convenient to change the units to degrees. This can be accomplished as follows:
Vector<String> units(2); units = "deg"; // 9 radec.setWorldAxisUnits(units); // 10The increment and reference value are updated appropriately.
Set up a couple of vectors to use the world and pixel coordinate values.
Vector<Double> world(2), pixel(2); // 11 pixel = 138.0; // 12We use 138 as an arbitrary pixel position which is near the reference pixel so we can tell if the answers look foolish or not. We can actually perform a transformation like this as follows. If it succeeds we print the value of the world coordinate.
Bool ok = radec.toWorld(world, pixel); // 13 if (!ok) { // 14 cout << "Error: " << radec.errorMessage() << endl; // 15 return 1; // 16 } // 17 cout << world << " <--- " << pixel << endl; // 18There is an overloaded "toWorld" function that produces an MDirection in case you want to, e.g., find out what the position in B1950 coordinates would be.
The reverse transformation takes place similarly:
ok = radec.toPixel(pixel, world); // 19
Matrix
But note that the constructor will have converted the native units
of the DirectionCoordinate to radians. So the Double-based toWorld and
toPixel functions will be in terms of radians. If you want the native
units to be degrees, then again you can use
Define the DirectionCoordinate transformation. refLong and
refLat will normally the the RA/DEC of the pixel described by
refX/refY. incLat/incLong
are the increments per pixel (RA is usually negative), and the xform
matrix is usually the unit diagonal matrix unless you have a rotation or
some other linear transformation between the pixel and world axes.
Note that the units are radians initially. You can change it to degrees
or something else with the setWorldAxisUnits method later if you want.
longPole and latPole are defined by Calabretta and Greisen (these
are reference points not at the native pole). In general
you can leave these out and the default values will cause them
to be computed appropriately. However, when reading from FITS
the LONPOLE and LATPOLE keywords are passed along here.
Create DirectionCoordinate with Quantum-based interface.
Parameters are the same as above.
Regardless of the units of the quanta, the initial units
of the DirectionCoordinate will be converted radians.
You can change it to degrees or something else with the
setWorldAxisUnits method later if you want.
longPole and latPole are defined by Calabretta and Greisen (these
are reference points not at the native pole). In general
you can leave these out and the default values will cause them
to be computed appropriately. However, when reading from FITS
the LONPOLE and LATPOLE keywords are passed along here.
To get the default the 999.0 value should be used (units
are irrelevant in that case)
Copy constructor (copy semantics)
Assignment (copy semantics).
Destructor
Return Coordinate::DIRECTION
Always returns the String "Direction".
Always returns 2.
Set extra conversion type. Whenever a conversion from pixel to world is done,
the world value is then further converted to this MDirection::Types value.
For example, your DirectionCoordinate may be defined in J2000.
You can use this to get the world values out in say GALACTIC.
Similarly, whenever you convert from world to pixel, the world
value is assumed to be that appropriate to the conversionDirectionType.
It is first converted to the MDirection::Types with which the
DirectionCoordinate was constructed and from there to pixel.
If you don't call this function, or you set the same type
for which the DirectionCoordinate was constructed, no extra
conversions occur. Some conversions will fail. These are the
ones that require extra frame information (epoch, position) such
as to AZEL from J2000 etc. This will be added later.
In the mixed pixel/world conversion routine toMix
the implementation is only partial. See the comments for this
function below.
Convert a pixel position to a world position or vice versa. Returns True
if the conversion succeeds, otherwise it returns False and method
errorMessage returns an error message. The output
vectors are appropriately resized.
Mixed pixel/world coordinate conversion.
worldIn and worldAxes are of length
nWorldAxes.
pixelIn and pixelAxes are of length nPixelAxes.
worldAxes(i)=True specifies you have given a world
value in worldIn(i) to convert to pixel.
pixelAxes(i)=True specifies you have given a pixel
value in pixelIn(i) to convert to world.
You cannot specify the same axis via worldAxes
and pixelAxes.
Values in pixelIn are converted to world and
put into worldOut in the appropriate world axis
location. Values in worldIn are copied to
worldOut.
Values in worldIn are converted to pixel and
put into pixelOut in the appropriate pixel axis
location. Values in pixelIn are copied to
pixelOut.
worldMin and worldMax specify the range of the world
coordinate (in the world axis units of that world axis
in the CoordinateSystem) being solved for in a mixed calculation
for each world axis. Some mixed solutions can be degenerate, whereupon you
you must say which one you want. Use functions setWorldMixRanges
and worldMixMin, worldMixMax to set these ranges,
If you don't know, use the defaults (function setDefaultWorldMixRanges.
Removed axes are handled (for example, a removed pixel
axis with remaining corresponding world axis will
correctly be converted to world using the replacement
value).
Returns True if the conversion succeeds, otherwise it returns False and
errorMessage() contains an error message. The output vectors
are resized.
If you actually request a pure pixel to world or world to pixel
via toMix, then the functions toWorld or toPixel
will be invoked directly (see above) and the extra conversion layer
invoked through function setReferenceConversion will be active.
However, if you request a true mixed pixel/world conversion,
the extra conversion layer is not activated (because of the nature of mixed
conversions). This situation may change in the future
with a partial implementation added.
Compute and retrieve the world min and max ranges, for use in function toMix,
for a lattice of the given shape (for this coordinate). Using these
ranges in toMix should speed it up and help avoid ambiguity.
If the shape is negative, that indicates that the shape is unknown
for that axis. The default range is used for that axis. This situation
arises in a CoordinateSystem for which a pixel, but not a world axis
has been removed.
The output vectors are resized. Returns False if fails (and
then setDefaultWorldMixRanges generates the ranges)
with a reason in errorMessage().
The setDefaultWorldMixRanges function
just gives you [-90->90], [-180,180] (in appropriate units)
Non-virtual function. When which is T, use the
world value as the center for the mix world range.
A convenient way to turn the world vector into an MDirection or MVDirection
for further processing in the Measures system.
We could improve the performance of this if it would be useful, however I
expect that normally you would just call this once to get a template
MDirection, and then call the vector versions.
Batch up a lot of transformations. The first (most rapidly varying) axis
of the matrices contain the coordinates. Returns False if any conversion
failed and errorMessage() will hold a message.
The failures array is the length of the number of conversions
(True for failure, False for success)
Make absolute world coordinates relative and vice-versa (relative to
the reference value). Note that these functions are independent
of the MDirection::Types (set either at construction or by function
setReferenceConversion). The vectors must be
of length nWorldAxes or memory access errors will occur
Make absolute coordinates relative and vice versa with respect
to the given reference value. Add the other functions in this grouping
as needed.
Recover the requested attribute.
Set the value of the requested attribute. Note that these just
change the internal values, they do not cause any recomputation.
Change the world axis units. Adjust the increment and
reference value by the ratio of the old and new units.
The units must be compatible with
angle. The units are initially "rad" (radians).
Return canonical axis names for the given MDirection type,
giving FITS names if desired.
BEG think this should be in the MDirection class, but WNB
disagrees. Leave it here for now.
Comparison function. Any private Double data members are compared
with the specified fractional tolerance. Don't compare on the specified
axes in the Coordinate. If the comparison returns False, method
errorMessage returns a message about why.
Format a DirectionCoordinate coordinate world value nicely through the
common format interface. See Coordinate
for basics.
Formatting types that are allowed are
Coordinate::SCIENTIFIC, Coordinate::FIXED, Coordinate::TIME
If you ask for format type Coordinate::DEFAULT then the
selected format depends upon what the value of the enum
MDirection::GlobalTypes is for this DirectionCoordinate.
For example, if it is GRADEC or GHADEC you would
get Coordinate::TIME style formatting (DD:MM:SS.SS), otherwise
you would get Coordinate::FIXED formatting by default.
axis says which axis in this Coordinate we are formatting.
We have to know this because we may format Longitude and Latitude differently.
For Coordinate::TIME style formatting, precision
refers to the places after the decimal in the SS field.
If you leave units empty, then it makes up a nice unit for you.
Fix cylindrical coordinates to put the longitude in [-180,180] range.
If False returned, it failed an an error is in errorMessage
This fix is not done automatically internally because of the dependence
on the image shape. It should be called for any foreign image
(such as FITS) that is imported
Find the Coordinate for when we Fourier Transform ourselves. This pointer
must be deleted by the caller. Axes specifies which axes of the Coordinate
you wish to transform. Shape specifies the shape of the image
associated with all the axes of the Coordinate. Currently the
output reference pixel is always shape/2.
Save the DirectionCoordinate into the supplied record using the supplied field name.
The field must not exist, otherwise False is returned.
Recover the DirectionCoordinate from a record.
A null pointer means that the restoration did not succeed.
Make a copy of the DirectionCoordinate using new. The caller
is responsible for calling delete.
Fish out the ref and non-native poles (refLong, refLat, longPole, latPole)
Not for general use. Units are degrees.
Interconvert between degrees and the current angular unit.
Check formatting types.
Format a latitude.
Mixed pixel/world coordinate conversion. Vector in must
be length nWorldAxes (2). Specify whether longitude
(in(0)) or latitude (in(1)) is the world coordinate . It is
assumed that the other value is the pixel coordinate.
Helper functions interfacing to WCS.
Convert PC cards to xform format (required by DC and LinearXform constructors)
Helper functions interfacing to WCS.
Set up conversion machine
Convert from type_p -> conversionType_p
Convert from conversionType_p -> type_p
Set up the offset coordinate rotation matrix. Units
of long and lat are current world units
Vector<String> units(2); units = "deg";
radec.setWorldAxisUnits(units);
and thereafter degrees are the native units.
Motivation
Directions in the sky are fundamental to astronomy.
Thrown Exceptions
To Do
Member Description
DirectionCoordinate()
The default constructor creates a J2000 DirectionCoordinate with a
CARtesion projection with longitude,latitude 0,0 at pixel 0,0 and an
increment of +1 radian per pixel on both axes.
DirectionCoordinate(MDirection::Types directionType, const Projection &projection, Double refLong, Double refLat, Double incLong, Double incLat, const Projection<Double> &xform, Double refX, Double refY, Double longPole=999.0, Double latPole=999.0)
DirectionCoordinate(MDirection::Types directionType, const directionType &projection, const Quantum<Double>& refLong, const Quantum<Double>& refLat, const Quantum<Double>& incLong, const Quantum<Double>& incLat, const Matrix<Double> &xform, Double refX, Double refY, const Quantum<Double>& longPole=Quantum<Double>(999.0,Matrix("rad")), const Quantum<Double>& latPole=Quantum<Double>(999.0,Matrix("rad")))
DirectionCoordinate(const DirectionCoordinate &other)
DirectionCoordinate &operator=(const DirectionCoordinate &other)
virtual ~DirectionCoordinate()
virtual Coordinate::Type type() const
virtual String showType() const
virtual uInt nPixelAxes() const
virtual uInt nWorldAxes() const
void setReferenceConversion (MDirection::Types type)
void getReferenceConversion (MDirection::Types& type) const
virtual Bool toWorld(Vector<Double> &world, const Vector<Double> &pixel) const
virtual Bool toPixel(Vector<Double> &pixel, const Vector<Double> &world) const
virtual Bool toMix(Vector<Double>& worldOut, Vector<Double>& pixelOut, const Vector<Double>& worldIn, const Vector<Double>& pixelIn, const Vector<Bool>& worldAxes, const Vector<Bool>& pixelAxes, const Vector<Double>& worldMin, const Vector<Double>& worldMax) const
virtual Bool setWorldMixRanges (const IPosition& shape)
virtual void setDefaultWorldMixRanges ()
virtual Vector<Double> worldMixMin () const
virtual Vector<Double> worldMixMax () const
void setWorldMixRanges (const Vector<Bool>& which, const Vector<Double>& world)
Bool toWorld(MDirection &world, const Vector<Double> &pixel) const
Bool toPixel(Vector<Double> &pixel, const MDirection &world) const
Bool toWorld(MVDirection &world, const Vector<Double> &pixel) const
Bool toPixel(Vector<Double> &pixel, const MVDirection &world) const
virtual Bool toWorldMany(Matrix<Double> &world, const Matrix<Double> &pixel, Vector<Bool> &failures) const
virtual Bool toPixelMany(Matrix<Double> &pixel, const Matrix<Double> &world, Vector<Bool> &failures) const
virtual void makeWorldRelative (Vector<Double>& world) const
virtual void makeWorldRelative (MDirection& world) const
virtual void makeWorldAbsolute (Vector<Double>& world) const
virtual void makeWorldAbsolute (MDirection& world) const
virtual void makeWorldAbsoluteRef (Vector<Double>& world, const Vector<Double>& refVal) const
MDirection::Types directionType() const
Projection projection() const
virtual Vector<String> worldAxisNames() const
virtual Vector<String> worldAxisUnits() const
virtual Vector<Double> referenceValue() const
virtual Vector<Double> increment() const
virtual Matrix<Double> linearTransform() const
virtual Vector<Double> referencePixel() const
virtual Bool setWorldAxisNames(const Vector<String> &names)
virtual Bool setReferencePixel(const Vector<Double> &refPix)
virtual Bool setLinearTransform(const Matrix<Double> &xform)
virtual Bool setIncrement(const Vector<Double> &inc)
virtual Bool setReferenceValue(const Vector<Double> &refval)
virtual Bool setWorldAxisUnits(const Vector<String> &units)
static Vector<String> axisNames(MDirection::Types type, Bool FITSName = False)
virtual Bool near(const Coordinate& other, Double tol=1e-6) const
virtual Bool near(const Coordinate& other, const Vector<Int>& excludeAxes, Double tol=1e-6) const
virtual void getPrecision (Int& precision, Coordinate::formatType& format, Bool showAsAbsolute, Int defPrecScientific, Int defPrecFixed, Int defPrecTime) const
virtual String format(String& units, Coordinate::formatType format, Double worldValue, uInt axis, Bool isAbsolute, Bool showAsAbsolute, Int precision=-1)
Bool cylindricalFix (Int shapeLong, Int shapeLat)
virtual Coordinate* makeFourierCoordinate (const Vector<Bool>& axes, const Vector<Int>& shape) const
virtual Bool save(RecordInterface &container, const String &fieldName) const
static DirectionCoordinate *restore(const RecordInterface &container, const String &fieldName)
virtual Coordinate *clone() const
Vector<Double> longLatPoles() const
void toDegrees(Vector<Double> &other) const
void toOther(Vector<Double> °rees) const
void checkFormat(Coordinate::formatType& format, Bool absolute) const
String formatLatitude (String& units, MVAngle& mVA, Bool absolute, Coordinate::formatType form, Int prec) const
String formatLongitude (String& units, MVAngle& mVA, MDirection::GlobalTypes gtype, Bool absolute, Coordinate::Coordinate form, Int prec) const
Format a longitude.
Bool toMix2(Vector<Double>& out, const Vector<Double>& in, const Vector<Double>& minWorld, const Vector<Double>& maxWorld, Bool longIsWorld) const
void pcToXform (Matrix<Double>& xForm, const wcsprm& wcs) const
void makeDirectionCoordinate(Double refLong, Double refLat, Double incLong, Double incLat, const Matrix<Double> &xform, Double refX, Double refY, Double longPole, Double latPole)
void makeWCS(wcsprm& wcs, const Matrix<Double>& xform, const Matrix& proj, Projection::Types directionType, Double refPixLong, Double refPixLat, Double refLong, Double refLat, Double incLong, Double incLat, Double longPole, Double latPole)
void xFormToPC (wcsprm& wcs, const Matrix<Double>& xForm) const
Double putLongInPiRange (Double lon, const String& unit) const
void makeConversionMachines()
void convertTo (Vector<Double>& world) const
void convertToMany (Matrix<Double>& world) const
void convertFrom (Vector<Double>& world) const
void convertFromMany (Matrix<Double>& world) const
void setRotationMatrix ()
void setRotationMatrix (RotMatrix& rot, Double lon, Double lat) const