EleFits  4.0.0
A modern C++ API on top of CFitsIO

Which types to use?

Indices

Indices in the Fits namespace are 0-based longs. Here is why.

There is no way to make everybody happy:

Following the C++ Core Guidelines, we've opted for signed integers, and precisely for long's. To reduce the noise, we did not create a custom type like "index", "length" or "size". We do not rely on ptrdiff_t as suggested in the Guidelines, because it would create issues when interfacing internally with CFitsIO. Using longs conveys the following message: trying to use something larger than the max of long won't work.

Having signed indices also enables backard indexing, where -1 means the last index. This is supported, for example, by the Raster::at() and Column::at() methods.

Since indices in std::vectors are 0-based, and we use a lot of std::vectors, we follow the same convention to provide a fully consistent API. This way, the user code only copes with 0-based indices.

Data types

As shown in the CFitsIO type mapping table, handling data types right with CFitsIO can be very cumbersome. EleFits aims at carrying the boilerplate internally, so that the user doesn't need to know the underlying architecture or CFitsIO implementation. Template functions and methods are provided to simply let the user set the desired type, e.g.:

auto raster = ext.readRaster<float>();

When possible, conversions are performed internally when the template type does not correspond to the file type.

Integers

Integer types are numerous. There are two main categories: fixed-size integers (e.g. std::int32_t) and C integers (e.g. int). It is strongly recommended to use fixed-size integers to avoid bad surprises when changing the system. Indeed, if an image of pixel type int is written on a system where it is encoded as a 64-bit integers, and read on a system where it is encoded as a 32-bit integer, values will be corrupted. This is avoided by using std::int32_t instead.

The Fits format doesn't natively support unsigned integers or signed bytes. Yet, CFitsIO and EleFits rely on the scaling mechanism to support them: an unsigned integer value will be internally offset to get a signed integer in the file. The offset is written in the file as a BZERO (image HDU) or TZERO (binary table HDU) keyword record, used to correctly recover the value at reading.

String

Strings are represented as std::string and not const char* in general. Yet, a few sevices are overloaded with const char* for convenience.

VariantValue

In addition to CFitsIO data types, EleFits provides some of the services for VariantValue (e.g., to read records). In this case, the underlying type is wrapped in a VariantValue object, which can be cast later.

Development efforts have been put to allow the user to get whatever compatible type from the VariantValue object. For example, assume some unsigned long record value is read as a VariantValue. The library will allow the user casting to long long because this is a mathematically valid conversion, where std::any_cast<long long>() and the likes would throw an exception.