astshim

A C++ and Python shim around a subset of Starlink AST a library for handling world coordinate systems in astronomy.

For detailed documentation of AST see http://starlink.eao.hawaii.edu/devdocs/sun211.htx/sun211.html.

The focus of astshim is on support for spatial mappings for use by LSST. Thus few of AST's functions that support time, spectra and tables have yet been wrapped. The python wrapper uses pybind11.

## Differences between this and Starlink AST

• Most functions in AST are classes or methods in this shim.
• New class FrameDict which is a FrameSet that can reference frames by domain name.
• Mapping::applyForward and Mapping::applyInverse methods transform single points or lists of points. These replace AST's astTran<X> functions and no invert flag is supported. There are three versions of each method:
• Accept a std::vector<double> and return a new std::vector<double>. This is the simplest version to use if you wish to transorm a single point.
• Accept a 2-dimensional ndarray and return a newly allocated 2-dimensional ndarray.
• Accept a 2-dimensional ndarray and fill a pre-allocated 2-dimensional ndarray.
• Mappings may not be inverted in place. Instead call Mapping::inverted to get an inverse mapping, and Mapping::isInverted to find out if a mapping is inverted.
• Compound mappings and frames have a few minor changes:
• Exceptions are raised on errors, leaving AST in a normal (non-error) state:
• Where practical, the wrapper checks arguments and throws std::invalid_argument before calling AST code.
• After calling AST code the wrapper checks AST's error state and if invalid, the wrapper resets the AST status code and throws std::runtime_error.
• The AST functions set, set<X> and get<X> are hidden; instead each class has explicit accessors for its attributes, such as Object::getID. Mappings are mostly immutable, so they have getters, but no setters beyond a few generic setters from Object. SlaMap and TimeMap both violate immutability by having add methods; if this is a problem we can replace the add methods with constructor arguments. Frames are mutable, so all frame-specific attributes have setters as well as getters.
• Channels are constructed with a Stream; subclasses are available for files and strings, and it is easy (in C++, but not Python) to construct a Stream to use standard in and/or out.
• astshim manages memory using C++ smart pointers. Thus the following AST functions are not wrapped: astAnnul, astBegin, astClone, astDelete, astEnd, and astExport.
• Methods that output floating point data have AST__BAD replaced with nan.

### Smaller differences (not a complete list):

• Methods such as Object::set and the attributes argument of constructors do not support printf formatting and extra arguments (and this may cause warnings in some compilers).
• Object::show prints its output to a provided output stream or returns a string, rather than printing to stdout.
• Get the class name using Object::getClassName() instead of getClass() because the latter sounds like a class, not a string, and Python doesn't allow class as a property name.
• FrameSet::addAxes and FrameSet::addFrame implement AST's astAddFrame(AST__ALLFRAMES, map, frame) function, because the AST function does two very different things.
• FitsChan does not offer methods for getting or setting complex integers (astGetFitsCI and astSetFitsCI), because that data type is not supported by standard C++.
• KeyMap has several differences:
• Methods get<X> and put<X> work with both scalars and vectors (implementing astMapGet0<X>, astMapGet1<X>, astMapPut0<X> and astMapPut1<X>).
• Methods append and replace are used to alter values in existing entries (implementing astMapPutElem...<X>).
• PolyMap has two separate constructors, one that takes foward and inverse coefficients, one that takes only forward coefficients. Neither provides an iterative inverse by default.

## Missing Functionality

Many portions of AST have not yet been wrapped. Here are some highlights:

• Rebinning and resampling (astRebin<X>, astRebinSeq<X> and astResample<X>
• astDBSPecFrame
• astFluxFrame
• astRegion, astRemoveRegions and other region support
• astPlot and other plotting support
• astSpecFluxFrame
• astStcsChan
• astTable and other table support
• "astIsA<Class>". I don't think we need these (one can always use rtti or call Object::getClassName) but if they are needed then it probably makes sense to wrap these as isInstance(Object const & obj) static methods on all classes.
• and astTuneC.

The Python interface could present a more dict-like view of KeyMap and FitsChan, as pyast does.