LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
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 
15 #include "lsst/afw/image/Image.h"
16 #include "lsst/afw/image/Mask.h"
17 
18 namespace lsst {
19 namespace afw {
20 namespace fits {
21 
22 // Forward declarations
23 class Fits;
24 
25 namespace detail {
26 
28 template <typename T>
29 struct Bitpix;
30 
31 template <>
32 struct Bitpix<std::uint8_t> {
33  static int const value = 8;
34 };
35 template <>
36 struct Bitpix<std::int16_t> {
37  static int const value = 16;
38 };
39 template <>
40 struct Bitpix<std::int32_t> {
41  static int const value = 32;
42 };
43 template <>
44 struct Bitpix<std::int64_t> {
45  static int const value = 64;
46 };
47 template <>
48 struct Bitpix<std::uint16_t> {
49  static int const value = 16;
50 };
51 template <>
52 struct Bitpix<std::uint32_t> {
53  static int const value = 32;
54 };
55 template <>
56 struct Bitpix<std::uint64_t> {
57  static int const value = 64;
58 };
59 template <>
60 struct Bitpix<float> {
61  static int const value = -32;
62 };
63 template <>
64 struct Bitpix<double> {
65  static int const value = -64;
66 };
67 
76 public:
77  virtual ~PixelArrayBase() {}
78 
80  virtual void const* getData() const = 0;
81 
83  std::size_t getNumElements() const { return _num; }
84 
85 protected:
86  PixelArrayBase(std::size_t num) : _num(num) {}
87 
88 private:
89  std::size_t _num; // Number of pixel values
90 };
91 
93 template <typename T>
94 class PixelArray : public PixelArrayBase {
95 public:
96  PixelArray() = delete;
97  PixelArray(PixelArray const&) = delete;
98 
102  PixelArray(ndarray::Array<T, 1, 1> const& array)
103  : PixelArrayBase(array.getNumElements()),
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 
123 private:
124  void const* _pixels; // The data
125  ndarray::Manager::Ptr _manager; // Memory manager; holds onto the data while we use it
126 };
127 
133 template <typename T>
134 std::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 
262 struct ImageScale {
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 
356 public:
364  };
366  int bitpix;
367  bool fuzz;
368  int seed;
371  float quantizePad;
372  double bscale;
373  double bzero;
374 
379  : ImageScalingOptions(NONE, 0, {}, 1, 4.0, 5.0, false, std::numeric_limits<double>::quiet_NaN(),
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  template <typename T>
413  std::shared_ptr<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, int N>
419  ImageScale determine(ndarray::Array<T const, N, N> const& image,
420  ndarray::Array<bool, N, N> const& mask) const;
422 
423 private:
425  template <typename T>
426  std::pair<ndarray::Array<T const, 2, 2>, ndarray::Array<bool, 2, 2>> _toArray(
427  image::ImageBase<T> const& image,
428  std::shared_ptr<image::Mask<image::MaskPixel> const> mask = nullptr) const {
429  if (mask && image.getDimensions() != mask->getDimensions()) {
431  os << "Size mismatch between image and mask: ";
432  os << image.getWidth() << "x" << image.getHeight();
433  os << " vs ";
434  os << mask->getWidth() << "x" << mask->getHeight();
436  }
437  ndarray::Array<T const, 2, 2> imageArray = ndarray::dynamic_dimension_cast<2>(image.getArray());
438  if (imageArray.empty()) imageArray = ndarray::copy(image.getArray());
439  ndarray::Array<bool, 2, 2> maskArray = ndarray::allocate(imageArray.getShape());
440  if (mask) {
441  maskArray.deep() = (mask->getArray() & mask->getPlaneBitMask(maskPlanes));
442  } else {
443  maskArray.deep() = false;
444  }
445  return std::make_pair(imageArray, maskArray);
446  }
447 
454  template <typename T, int N>
455  ImageScale determineFromRange(ndarray::Array<T const, N, N> const& image,
456  ndarray::Array<bool, N, N> const& mask, bool isUnsigned = false,
457  bool cfitsioPadding = true) const;
458 
465  template <typename T, int N>
466  ImageScale determineFromStdev(ndarray::Array<T const, N, N> const& image,
467  ndarray::Array<bool, N, N> const& mask, bool isUnsigned = false,
468  bool cfitsioPadding = true) const;
469 };
470 
473 
476 
477 } // namespace fits
478 } // namespace afw
479 } // namespace lsst
480 
481 #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.
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?
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
ImageScale determine(image::ImageBase< T > const &image, std::shared_ptr< image::Mask< image::MaskPixel > const > mask=nullptr) const
Determine the scaling for a particular image.
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.
virtual void const * getData() const =0
Return a void* array of the pixels.
std::size_t getNumElements() const
Return the number of 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.