LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
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  typedef ndarray::Array<long, 1, 1> Tiles;
195 
197  Tiles tiles;
199 
201  explicit ImageCompressionOptions(CompressionAlgorithm algorithm_, Tiles tiles_,
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
232  : ImageCompressionOptions(NONE) {}
233  explicit ImageCompressionOptions(image::Mask<std::int64_t> const& mask) : ImageCompressionOptions(NONE) {}
235  : ImageCompressionOptions(NONE) {}
237  : ImageCompressionOptions(NONE) {}
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
ImageCompressionOptions(image::Mask< std::uint64_t > const &mask)
T copy(T... args)
int bitpix
Bits per pixel (0, 8,16,32,64,-32,-64)
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.
afw::table::Key< afw::table::Array< MaskPixelT > > mask
Scale to preserve dynamic range.
int compressionAlgorithmToCfitsio(ImageCompressionOptions::CompressionAlgorithm algorithm)
Convert ImageCompressionOptions::CompressionAlgorithm to cfitsio.
long blank
Value for integer images indicating non-finite values.
int getHeight() const
Return the number of rows in the image.
Definition: ImageBase.h:335
int bitpix
Bits per pixel; negative means floating-point: 8,16,32,64,-32,-64.
PixelArray(ndarray::Array< T, 1, 1 > const &array)
Construct from an ndarray::Array of the same type.
ImageCompressionOptions(image::Mask< std::int64_t > const &mask)
STL namespace.
PixelArray(ndarray::Array< U, 1, 1 > const &array)
Construct from an ndarray::Array of different type.
T cend(T... args)
CompressionAlgorithm
Compression algorithms.
std::size_t getNumElements() const
Return the number of pixels.
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: ImageBase.h:102
Typed array of pixel values.
FITS BITPIX header value by C++ type.
int seed
Seed for random number generator when fuzzing.
Fits * fits
Definition: FitsWriter.cc:90
ImageCompressionOptions(image::Mask< T > const &mask)
STL class.
ImageCompressionOptions(image::Image< std::uint64_t > const &image)
Tiles tiles
Tile size; a dimension with 0 means infinite (e.g., to specify one row: 0,1)
ImageCompressionOptions(CompressionAlgorithm algorithm_, Tiles tiles_, float quantizeLevel_=0.0)
Custom compression.
Options for tile compression of image pixels.
A base class for image defects.
float quantizeLevel
Divisor of the standard deviation for STDEV_* scaling.
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
double bzero
Zero-point to apply when reading from FITS.
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromString(std::string const &name)
Interpret compression algorithm expressed in string.
double bscale
Manually specified BSCALE (for MANUAL scaling)
T str(T... args)
T make_pair(T... args)
ImageCompressionOptions(image::Image< T > const &image)
Default compression for a particular style of image.
ndarray::Array< long, 1, 1 > Tiles
Options for scaling image pixels.
double bscale
Scale to apply when reading from FITS.
std::string scalingAlgorithmToString(ImageScalingOptions::ScalingAlgorithm algorithm)
Provide string version of compression algorithm.
std::string compressionAlgorithmToString(ImageCompressionOptions::CompressionAlgorithm algorithm)
Provide string version of compression algorithm.
ImageCompressionOptions(image::Image< std::int64_t > const &image)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
STL class.
T cbegin(T... args)
void const * getData() const override
Return a void* array of the pixels.
Abstract base class for an array of pixel values.
int getWidth() const
Return the number of columns in the image.
Definition: ImageBase.h:333
float quantizeLevel
quantization level: 0.0 = none requires use of GZIP or GZIP_SHUFFLE
Scale based on the standard deviation, dynamic range negative.
double bzero
Manually specified BZERO (for MANUAL scaling)
ImageScale(int bitpix_, double bscale_, double bzero_)
Constructor.
Reports invalid arguments.
Definition: Runtime.h:66
CompressionAlgorithm algorithm
Compresion algorithm to use.
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromCfitsio(int cfitsio)
Convert compression algorithm from cfitsio to ImageCompressionOptions::CompressionAlgorithm.
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.
Extent< int, N > floor(Extent< double, N > const &input) noexcept
Return the component-wise floor (round towards more negative).
Definition: Extent.cc:109
ScalingAlgorithm algorithm
Scaling algorithm to use.
Scale based on the standard deviation, dynamic range positive+negative.
T quiet_NaN(T... args)
float quantizePad
Number of stdev to allow on the low/high side (for STDEV_POSITIVE/NEGATIVE)
ImageCompressionOptions(CompressionAlgorithm algorithm_, std::vector< long > tiles_, float quantizeLevel_=0.0)
bool fuzz
Fuzz the values when quantising floating-point values?
lsst::geom::Extent2I getDimensions() const
Return the image&#39;s size; useful for passing to constructors.
Definition: ImageBase.h:393
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
std::vector< std::string > maskPlanes
Mask planes to ignore when doing statistics.
std::ostream * os
Definition: Schema.cc:746
ArrayKeyVector arrays
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:58
Scale based on the standard deviation. dynamic range positive.
ImageScalingOptions(int bitpix_, double bscale_=1.0, double bzero_=0.0)
Manual scaling Ctor.
ImageScalingOptions::ScalingAlgorithm scalingAlgorithmFromString(std::string const &name)
Interpret scaling algorithm expressed in string.
GZIP compression with shuffle (most-significant byte first)
Scale to apply to image.