LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
fitsCompression.h
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2#ifndef LSST_AFW_fitsCompression_h_INCLUDED
3#define LSST_AFW_fitsCompression_h_INCLUDED
4
5#include <string>
6#include <limits>
7
8#include "boost/cstdfloat.hpp"
9
10#include "lsst/pex/exceptions.h"
11#include "lsst/daf/base.h"
12#include "ndarray.h"
13#include "ndarray/eigen.h"
14
16#include "lsst/afw/image/Mask.h"
17
18namespace lsst {
19namespace afw {
20namespace fits {
21
22// Forward declarations
23class Fits;
24
25namespace detail {
26
28template <typename T>
29struct Bitpix;
30
31template <>
32struct Bitpix<std::uint8_t> {
33 static int const value = 8;
34};
35template <>
36struct Bitpix<std::int16_t> {
37 static int const value = 16;
38};
39template <>
40struct Bitpix<std::int32_t> {
41 static int const value = 32;
42};
43template <>
44struct Bitpix<std::int64_t> {
45 static int const value = 64;
46};
47template <>
48struct Bitpix<std::uint16_t> {
49 static int const value = 16;
50};
51template <>
52struct Bitpix<std::uint32_t> {
53 static int const value = 32;
54};
55template <>
56struct Bitpix<std::uint64_t> {
57 static int const value = 64;
58};
59template <>
60struct Bitpix<float> {
61 static int const value = -32;
62};
63template <>
64struct Bitpix<double> {
65 static int const value = -64;
66};
67
76public:
77 virtual ~PixelArrayBase() {}
78
80 virtual void const* getData() const = 0;
81
83 std::size_t getNumElements() const { return _num; }
84
85protected:
86 PixelArrayBase(std::size_t num) : _num(num) {}
87
88private:
89 std::size_t _num; // Number of pixel values
90};
91
93template <typename T>
94class PixelArray : public PixelArrayBase {
95public:
96 PixelArray() = delete;
97 PixelArray(PixelArray const&) = delete;
98
102 PixelArray(ndarray::Array<T, 1, 1> const& array)
104 _pixels(array.getData()),
105 _manager(array.getManager()) {}
106
110 template <typename U>
111 PixelArray(ndarray::Array<U, 1, 1> const& array) : PixelArrayBase(array.getNumElements()) {
112 auto mem = ndarray::SimpleManager<U>::allocate(getNumElements());
113 _manager = mem.first;
114 _pixels = mem.second;
115 std::copy(array.begin(), array.end(),
116 const_cast<typename std::remove_const<T>::type*>(reinterpret_cast<T const*>(_pixels)));
117 }
118
119 ~PixelArray() override {}
120
121 void const* getData() const override { return _pixels; }
122
123private:
124 void const* _pixels; // The data
125 ndarray::Manager::Ptr _manager; // Memory manager; holds onto the data while we use it
126};
127
133template <typename T>
134std::shared_ptr<PixelArrayBase> makePixelArray(int bitpix, ndarray::Array<T, 1, 1> const& array) {
135 switch (bitpix) {
136 case 0:
137 return std::make_shared<PixelArray<T>>(array);
138 case 8:
139 return std::make_shared<PixelArray<std::uint8_t>>(array);
140 case 16:
141 return std::make_shared<PixelArray<std::int16_t>>(array);
142 case 32:
143 return std::make_shared<PixelArray<std::int32_t>>(array);
144 case 64:
145 return std::make_shared<PixelArray<std::int64_t>>(array);
146 case -32:
147 return std::make_shared<PixelArray<boost::float32_t>>(array);
148 case -64:
149 return std::make_shared<PixelArray<boost::float64_t>>(array);
150 default:
152 os << "Unrecognized bitpix: " << bitpix;
154 }
155}
156
157} // namespace detail
158
193 };
194 using Tiles = ndarray::Array<long, 1, 1>;
195
199
202 float quantizeLevel_ = 0.0)
203 : algorithm(algorithm_), tiles(ndarray::copy(tiles_)), quantizeLevel(quantizeLevel_) {}
204
206 float quantizeLevel_ = 0.0)
207 : algorithm(algorithm_), tiles(ndarray::allocate(tiles_.size())), quantizeLevel(quantizeLevel_) {
208 std::copy(tiles_.cbegin(), tiles_.cend(), tiles.begin());
209 }
210
216 explicit ImageCompressionOptions(CompressionAlgorithm algorithm_, int rows = 1,
217 float quantizeLevel_ = 0.0);
218
223 template <typename T>
225 : ImageCompressionOptions(image.getBBox().getArea() > 0 ? NONE : NONE) {}
226 template <typename T>
228 : ImageCompressionOptions(mask.getBBox().getArea() > 0 ? NONE : NONE) {}
229
230 // Disable compression for int64: cfitsio won't compress them
238};
239
242
245
248
251
263 int bitpix;
264 double bscale;
265 double bzero;
266 long blank;
267
276 ImageScale(int bitpix_, double bscale_, double bzero_)
277 : bitpix(bitpix_),
278 bscale(bscale_),
279 bzero(std::floor(bzero_ / bscale_ + 0.5) * bscale_),
280 blank(bitpix > 0 ? (bitpix == 8 ? 255 : (1L << (bitpix - 1)) - 1) : 0) {}
281
292 template <typename T>
294 ndarray::Array<T const, 2, 2> const& image, bool forceNonfiniteRemoval, bool fuzz = true,
295 ndarray::Array<long, 1> const& tiles = ndarray::Array<long, 1, 1>(), int seed = 1) const;
296
302 template <typename T>
303 ndarray::Array<T, 2, 2> fromFits(ndarray::Array<T, 2, 2> const& image) const;
304};
305
356public:
364 };
366 int bitpix;
367 bool fuzz;
368 int seed;
372 double bscale;
373 double bzero;
374
381
393 ImageScalingOptions(ScalingAlgorithm algorithm_, int bitpix_,
394 std::vector<std::string> const& maskPlanes_ = {}, int seed_ = 1,
395 float quantizeLevel_ = 4.0, float quantizePad_ = 5.0, bool fuzz_ = true,
396 double bscale_ = 1.0, double bzero_ = 0.0);
397
403 ImageScalingOptions(int bitpix_, double bscale_ = 1.0, double bzero_ = 0.0)
404 : ImageScalingOptions(MANUAL, bitpix_, {}, 1, 4.0, 5.0, false, bscale_, bzero_) {}
405
407
411 template <typename T>
413 image::Mask<image::MaskPixel> const * mask = nullptr) const {
414 auto const arrays = _toArray(image, mask);
415 return determine(arrays.first, arrays.second);
416 }
417
418 template <typename T>
419 [[deprecated("Replaced by a non-shared_ptr overload. Will be removed after v25.")]]
422 return determine(image, mask.get());
423 }
424
425 template <typename T, int N>
426 ImageScale determine(ndarray::Array<T const, N, N> const& image,
427 ndarray::Array<bool, N, N> const& mask) const;
429
430private:
432 template <typename T>
433 std::pair<ndarray::Array<T const, 2, 2>, ndarray::Array<bool, 2, 2>> _toArray(
435 image::Mask<image::MaskPixel> const * mask = nullptr) const {
436 if (mask && image.getDimensions() != mask->getDimensions()) {
438 os << "Size mismatch between image and mask: ";
439 os << image.getWidth() << "x" << image.getHeight();
440 os << " vs ";
441 os << mask->getWidth() << "x" << mask->getHeight();
443 }
444 ndarray::Array<T const, 2, 2> imageArray = ndarray::dynamic_dimension_cast<2>(image.getArray());
445 if (imageArray.empty()) imageArray = ndarray::copy(image.getArray());
446 ndarray::Array<bool, 2, 2> maskArray = ndarray::allocate(imageArray.getShape());
447 if (mask) {
448 maskArray.deep() = (mask->getArray() & mask->getPlaneBitMask(maskPlanes));
449 } else {
450 maskArray.deep() = false;
451 }
452 return std::make_pair(imageArray, maskArray);
453 }
454
461 template <typename T, int N>
462 ImageScale determineFromRange(ndarray::Array<T const, N, N> const& image,
463 ndarray::Array<bool, N, N> const& mask, bool isUnsigned = false,
464 bool cfitsioPadding = true) const;
465
472 template <typename T, int N>
473 ImageScale determineFromStdev(ndarray::Array<T const, N, N> const& image,
474 ndarray::Array<bool, N, N> const& mask, bool isUnsigned = false,
475 bool cfitsioPadding = true) const;
476};
477
480
483
484} // namespace fits
485} // namespace afw
486} // namespace lsst
487
488#endif // ifndef LSST_AFW_fitsCompression_h_INCLUDED
table::Key< std::string > name
Definition: Amplifier.cc:116
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Fits * fits
Definition: FitsWriter.cc:90
afw::table::Key< afw::table::Array< MaskPixelT > > mask
std::ostream * os
Definition: Schema.cc:557
ArrayKeyVector arrays
T cbegin(T... args)
Options for scaling image pixels.
ImageScale determine(image::ImageBase< T > const &image, std::shared_ptr< image::Mask< image::MaskPixel > const > mask) const
ScalingAlgorithm algorithm
Scaling algorithm to use.
float quantizeLevel
Divisor of the standard deviation for STDEV_* scaling.
@ STDEV_NEGATIVE
Scale based on the standard deviation, dynamic range negative.
@ STDEV_POSITIVE
Scale based on the standard deviation. dynamic range positive.
@ STDEV_BOTH
Scale based on the standard deviation, dynamic range positive+negative.
@ RANGE
Scale to preserve dynamic range.
ImageScalingOptions(int bitpix_, double bscale_=1.0, double bzero_=0.0)
Manual scaling Ctor.
bool fuzz
Fuzz the values when quantising floating-point values?
ImageScale determine(image::ImageBase< T > const &image, image::Mask< image::MaskPixel > const *mask=nullptr) const
Determine the scaling for a particular image.
float quantizePad
Number of stdev to allow on the low/high side (for STDEV_POSITIVE/NEGATIVE)
int bitpix
Bits per pixel (0, 8,16,32,64,-32,-64)
double bscale
Manually specified BSCALE (for MANUAL scaling)
ImageScale determine(ndarray::Array< T const, N, N > const &image, ndarray::Array< bool, N, N > const &mask) const
std::vector< std::string > maskPlanes
Mask planes to ignore when doing statistics.
int seed
Seed for random number generator when fuzzing.
double bzero
Manually specified BZERO (for MANUAL scaling)
Abstract base class for an array of pixel values.
std::size_t getNumElements() const
Return the number of pixels.
virtual void const * getData() const =0
Return a void* array of the pixels.
Typed array of pixel values.
void const * getData() const override
Return a void* array of the pixels.
PixelArray(PixelArray const &)=delete
PixelArray(ndarray::Array< U, 1, 1 > const &array)
Construct from an ndarray::Array of different type.
PixelArray(ndarray::Array< T, 1, 1 > const &array)
Construct from an ndarray::Array of the same type.
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: ImageBase.h:102
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:51
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
Reports invalid arguments.
Definition: Runtime.h:66
T copy(T... args)
T cend(T... args)
T make_pair(T... args)
std::shared_ptr< PixelArrayBase > makePixelArray(int bitpix, ndarray::Array< T, 1, 1 > const &array)
Create a PixelArray suitable for an image with the nominated BITPIX.
std::string compressionAlgorithmToString(ImageCompressionOptions::CompressionAlgorithm algorithm)
Provide string version of compression algorithm.
ImageScalingOptions::ScalingAlgorithm scalingAlgorithmFromString(std::string const &name)
Interpret scaling algorithm expressed in string.
int compressionAlgorithmToCfitsio(ImageCompressionOptions::CompressionAlgorithm algorithm)
Convert ImageCompressionOptions::CompressionAlgorithm to cfitsio.
std::string scalingAlgorithmToString(ImageScalingOptions::ScalingAlgorithm algorithm)
Provide string version of compression algorithm.
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromCfitsio(int cfitsio)
Convert compression algorithm from cfitsio to ImageCompressionOptions::CompressionAlgorithm.
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromString(std::string const &name)
Interpret compression algorithm expressed in string.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Extent< int, N > floor(Extent< double, N > const &input) noexcept
Return the component-wise floor (round towards more negative).
Definition: Extent.cc:109
A base class for image defects.
STL namespace.
T quiet_NaN(T... args)
Options for tile compression of image pixels.
ImageCompressionOptions(CompressionAlgorithm algorithm_, Tiles tiles_, float quantizeLevel_=0.0)
Custom compression.
float quantizeLevel
quantization level: 0.0 = none requires use of GZIP or GZIP_SHUFFLE
CompressionAlgorithm algorithm
Compresion algorithm to use.
ndarray::Array< long, 1, 1 > Tiles
ImageCompressionOptions(image::Mask< T > const &mask)
Tiles tiles
Tile size; a dimension with 0 means infinite (e.g., to specify one row: 0,1)
ImageCompressionOptions(image::Image< std::int64_t > const &image)
ImageCompressionOptions(image::Mask< std::uint64_t > const &mask)
ImageCompressionOptions(image::Image< std::uint64_t > const &image)
@ GZIP_SHUFFLE
GZIP compression with shuffle (most-significant byte first)
ImageCompressionOptions(image::Image< T > const &image)
Default compression for a particular style of image.
ImageCompressionOptions(image::Mask< std::int64_t > const &mask)
ImageCompressionOptions(CompressionAlgorithm algorithm_, std::vector< long > tiles_, float quantizeLevel_=0.0)
Scale to apply to image.
double bscale
Scale to apply when reading from FITS.
long blank
Value for integer images indicating non-finite values.
ImageScale(int bitpix_, double bscale_, double bzero_)
Constructor.
int bitpix
Bits per pixel; negative means floating-point: 8,16,32,64,-32,-64.
double bzero
Zero-point to apply when reading from FITS.
ndarray::Array< T, 2, 2 > fromFits(ndarray::Array< T, 2, 2 > const &image) const
Convert to an array.
std::shared_ptr< detail::PixelArrayBase > toFits(ndarray::Array< T const, 2, 2 > const &image, bool forceNonfiniteRemoval, bool fuzz=true, ndarray::Array< long, 1 > const &tiles=ndarray::Array< long, 1, 1 >(), int seed=1) const
Convert to an array of pixel values to write to FITS.
FITS BITPIX header value by C++ type.