LSST Applications  21.0.0+c4f5df5339,21.0.0+e70536a077,21.0.0-1-ga51b5d4+7c60f8a6ea,21.0.0-10-g560fb7b+411cd868f8,21.0.0-10-gcf60f90+8c49d86aa0,21.0.0-13-gc485e61d+38156233bf,21.0.0-16-g7a993c7b9+1041c3824f,21.0.0-2-g103fe59+d9ceee3e5a,21.0.0-2-g1367e85+0b2f7db15a,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g5242d73+0b2f7db15a,21.0.0-2-g7f82c8f+feb9862f5e,21.0.0-2-g8f08a60+9c9a9cfcc8,21.0.0-2-ga326454+feb9862f5e,21.0.0-2-gde069b7+bedfc5e1fb,21.0.0-2-gecfae73+417509110f,21.0.0-2-gfc62afb+0b2f7db15a,21.0.0-3-g21c7a62+a91f7c0b59,21.0.0-3-g357aad2+062581ff1a,21.0.0-3-g4be5c26+0b2f7db15a,21.0.0-3-g65f322c+85aa0ead76,21.0.0-3-g7d9da8d+c4f5df5339,21.0.0-3-gaa929c8+411cd868f8,21.0.0-3-gc44e71e+fd4029fd48,21.0.0-3-ge02ed75+5d9b90b8aa,21.0.0-38-g070523fc+44fda2b515,21.0.0-4-g591bb35+5d9b90b8aa,21.0.0-4-g88306b8+3cdc83ea97,21.0.0-4-gc004bbf+d52368b591,21.0.0-4-gccdca77+a5c54364a0,21.0.0-5-g7ebb681+81e2098694,21.0.0-5-gdf36809+87b8d260e6,21.0.0-6-g2d4f3f3+e70536a077,21.0.0-6-g4e60332+5d9b90b8aa,21.0.0-6-g5ef7dad+3f4e29eeae,21.0.0-7-gc8ca178+0f5e56d48f,21.0.0-9-g9eb8d17+cc2c7a81aa,master-gac4afde19b+5d9b90b8aa,w.2021.07
LSST Data Management Base Package
fits.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2016 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #include <pybind11/pybind11.h>
24 #include <pybind11/stl.h>
25 
26 #include "ndarray/pybind11.h"
27 
31 #include "lsst/daf/base.h"
32 #include "lsst/afw/image/Image.h"
33 
34 #include "lsst/afw/fits.h"
35 
36 namespace py = pybind11;
37 
38 using namespace lsst::afw::fits;
39 using namespace lsst::afw::fits::detail;
40 using namespace pybind11::literals;
41 
42 
44  py::class_<ImageCompressionOptions> cls(mod, "ImageCompressionOptions");
45 
46  py::enum_<ImageCompressionOptions::CompressionAlgorithm>(cls, "CompressionAlgorithm").
47  value("NONE", ImageCompressionOptions::CompressionAlgorithm::NONE).
48  value("GZIP", ImageCompressionOptions::CompressionAlgorithm::GZIP).
49  value("GZIP_SHUFFLE", ImageCompressionOptions::CompressionAlgorithm::GZIP_SHUFFLE).
50  value("RICE", ImageCompressionOptions::CompressionAlgorithm::RICE).
51  value("PLIO", ImageCompressionOptions::CompressionAlgorithm::PLIO).
52  export_values();
53 
54  cls.def(py::init<ImageCompressionOptions::CompressionAlgorithm, ImageCompressionOptions::Tiles, float>(),
55  "algorithm"_a, "tiles"_a, "quantizeLevel"_a=0.0);
56  cls.def(py::init<ImageCompressionOptions::CompressionAlgorithm, int, float>(), "algorithm"_a, "rows"_a=1,
57  "quantizeLevel"_a=0.0);
58 
67 
72 
73  cls.def_readonly("algorithm", &ImageCompressionOptions::algorithm);
74  cls.def_readonly("tiles", &ImageCompressionOptions::tiles);
75  cls.def_readonly("quantizeLevel", &ImageCompressionOptions::quantizeLevel);
76 }
77 
78 
79 template <typename T>
80 void declareImageScalingOptionsTemplates(py::class_<ImageScalingOptions> & cls) {
81  cls.def("determine", &ImageScalingOptions::determine<T>);
82 }
83 
85  py::class_<ImageScalingOptions> cls(mod, "ImageScalingOptions");
86  py::enum_<ImageScalingOptions::ScalingAlgorithm>(cls, "ScalingAlgorithm").
87  value("NONE", ImageScalingOptions::ScalingAlgorithm::NONE).
88  value("RANGE", ImageScalingOptions::ScalingAlgorithm::RANGE).
89  value("STDEV_POSITIVE", ImageScalingOptions::ScalingAlgorithm::STDEV_POSITIVE).
90  value("STDEV_NEGATIVE", ImageScalingOptions::ScalingAlgorithm::STDEV_NEGATIVE).
91  value("STDEV_BOTH", ImageScalingOptions::ScalingAlgorithm::STDEV_BOTH).
92  value("MANUAL", ImageScalingOptions::ScalingAlgorithm::MANUAL).
93  export_values();
94 
95  cls.def(py::init<>());
97  unsigned long, float, float, bool, double, double>(),
98  "algorithm"_a, "bitpix"_a, "maskPlanes"_a=std::vector<std::string>(), "seed"_a=1,
99  "quantizeLevel"_a=4.0, "quantizePad"_a=5.0, "fuzz"_a=true, "bscale"_a=1.0, "bzero"_a=0.0);
100 
101  cls.def_readonly("algorithm", &ImageScalingOptions::algorithm);
102  cls.def_readonly("bitpix", &ImageScalingOptions::bitpix);
103  cls.def_readonly("maskPlanes", &ImageScalingOptions::maskPlanes);
104  cls.def_readonly("seed", &ImageScalingOptions::seed);
105  cls.def_readonly("quantizeLevel", &ImageScalingOptions::quantizeLevel);
106  cls.def_readonly("quantizePad", &ImageScalingOptions::quantizePad);
107  cls.def_readonly("fuzz", &ImageScalingOptions::fuzz);
108  cls.def_readonly("bscale", &ImageScalingOptions::bscale);
109  cls.def_readonly("bzero", &ImageScalingOptions::bzero);
110 
111  declareImageScalingOptionsTemplates<float>(cls);
112  declareImageScalingOptionsTemplates<double>(cls);
113 }
114 
115 template <typename T>
116 void declareImageScaleTemplates(py::class_<ImageScale> & cls, std::string const& suffix) {
117  cls.def("toFits", &ImageScale::toFits<T>, "image"_a, "forceNonfiniteRemoval"_a=false, "fuzz"_a=true,
118  "tiles"_a=ndarray::Array<long, 1, 1>(), "seed"_a=1);
119  cls.def("fromFits", &ImageScale::fromFits<T>);
120 }
121 
123  py::class_<ImageScale> cls(mod, "ImageScale");
124  cls.def(py::init<int, double, double>(), "bitpix"_a, "bscale"_a, "bzero"_a);
125  cls.def_readonly("bitpix", &ImageScale::bitpix);
126  cls.def_readonly("bscale", &ImageScale::bscale);
127  cls.def_readonly("bzero", &ImageScale::bzero);
128  cls.def_readonly("blank", &ImageScale::blank);
129 
130  declareImageScaleTemplates<float>(cls, "F");
131  declareImageScaleTemplates<double>(cls, "D");
132 }
133 
135  py::class_<ImageWriteOptions> cls(mod, "ImageWriteOptions");
136 
142 
144 
145  cls.def(py::init<ImageCompressionOptions const&, ImageScalingOptions const&>(),
146  "compression"_a, "scaling"_a=ImageScalingOptions());
147  cls.def(py::init<ImageScalingOptions const&>());
148 
149  cls.def(py::init<lsst::daf::base::PropertySet const&>());
150 
151  cls.def_readonly("compression", &ImageWriteOptions::compression);
152  cls.def_readonly("scaling", &ImageWriteOptions::scaling);
153 
154  cls.def_static("validate", &ImageWriteOptions::validate);
155 }
156 
157 // Wrapping for lsst::afw::fits::Fits
158 //
159 // Not every feature is wrapped, only those that we guess might be useful.
160 // In particular, the header keyword read/write and table read/write are not wrapped.
161 void declareFits(py::module & mod) {
162  py::class_<Fits> cls(mod, "Fits");
163 
164  cls.def(py::init<std::string const&, std::string const&, int>(), "filename"_a, "mode"_a,
165  "behavior"_a=Fits::AUTO_CLOSE | Fits::AUTO_CHECK);
166  cls.def(py::init<MemFileManager &, std::string const&, int>(), "manager"_a, "mode"_a,
167  "behavior"_a=Fits::AUTO_CLOSE | Fits::AUTO_CHECK);
168 
169  cls.def("closeFile", &Fits::closeFile);
170  cls.def("getFileName", &Fits::getFileName);
171  cls.def("getHdu", &Fits::getHdu);
172  cls.def("setHdu", &Fits::setHdu, "hdu"_a, "relative"_a=false);
173  cls.def("countHdus", &Fits::countHdus);
174 
175  cls.def("writeMetadata", &Fits::writeMetadata);
176  cls.def("readMetadata", [](Fits & self, bool strip=false) { return readMetadata(self, strip); },
177  "strip"_a=false);
178  cls.def("createEmpty", &Fits::createEmpty);
179 
180  cls.def("readImageI", [](Fits &self) {
181  ndarray::Vector<int, 2> const offset; // initialized to zero by default
182  ndarray::Vector<ndarray::Size, 2> shape = self.getImageShape<2>();
183  ndarray::Array<int, 2, 2> result = ndarray::allocate(shape[0], shape[1]);
184  self.readImage(result, offset);
185  return result;
186  });
187 
188  cls.def("gotoFirstHdu", [](Fits & self) { self.setHdu(DEFAULT_HDU); });
189 
190  cls.def("setImageCompression", &Fits::setImageCompression);
191  cls.def("getImageCompression", &Fits::getImageCompression);
192  cls.def("checkCompressedImagePhu", &Fits::checkCompressedImagePhu);
193 
194  cls.def_readonly("status", &Fits::status);
195 }
196 
197 
199  py::class_<MemFileManager> clsMemFileManager(mod, "MemFileManager");
200 
201  py::module::import("lsst.pex.exceptions");
202 
203  lsst::pex::exceptions::python::declareException<FitsError, lsst::pex::exceptions::IoError>(
204  mod, "FitsError", "IoError");
205  // lsst::pex::exceptions::python::declareException<FitsTypeError, FitsError>(mod, "FitsTypeError",
206  // "FitsError");
207 
208  clsMemFileManager.def(py::init<>());
209  clsMemFileManager.def(py::init<size_t>());
210 
211  /* TODO: We should really revisit persistence and pickling as this is quite ugly.
212  * But it is what Swig did (sort of, it used the cdata.i extension), so I reckon this
213  * is cleaner because it does not expose casting to the Python side. */
214  clsMemFileManager.def("getLength", &MemFileManager::getLength);
215  clsMemFileManager.def("getData", [](MemFileManager &m) {
216  return py::bytes(static_cast<char *>(m.getData()), m.getLength());
217  });
218  clsMemFileManager.def("setData", [](MemFileManager &m, py::bytes const &d, size_t size) {
219  memcpy(m.getData(), PyBytes_AsString(d.ptr()), size);
220  });
221  clsMemFileManager.def("readMetadata",
222  [](MemFileManager & self, int hdu=DEFAULT_HDU, bool strip=false) {
223  return readMetadata(self, hdu, strip);
224  }, "hdu"_a=DEFAULT_HDU, "strip"_a=false);
225 
228  declareImageScale(mod);
230  declareFits(mod);
231 
232  mod.attr("DEFAULT_HDU") = DEFAULT_HDU;
233  mod.def("combineMetadata", combineMetadata, "first"_a, "second"_a);
234  mod.def("makeLimitedFitsHeader", &makeLimitedFitsHeader, "metadata"_a,
235  "excludeNames"_a = std::set<std::string>());
236  mod.def("readMetadata",
237  [](std::string const& filename, int hdu=DEFAULT_HDU, bool strip=false) {
238  return readMetadata(filename, hdu, strip);
239  }, "fileName"_a, "hdu"_a=DEFAULT_HDU, "strip"_a=false);
240  mod.def("setAllowImageCompression", &setAllowImageCompression, "allow"_a);
241  mod.def("getAllowImageCompression", &getAllowImageCompression);
242 
243  mod.def("compressionAlgorithmFromString", &compressionAlgorithmFromString);
244  mod.def("compressionAlgorithmToString", &compressionAlgorithmToString);
245  mod.def("scalingAlgorithmFromString", &scalingAlgorithmFromString);
246  mod.def("scalingAlgorithmToString", &scalingAlgorithmToString);
247 }
py::object result
Definition: _schema.cc:429
Fits * fits
Definition: FitsWriter.cc:90
table::Key< table::Array< std::uint8_t > > bytes
Definition: python.h:135
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:297
void closeFile()
Close a FITS file.
Definition: fits.cc:1623
ImageCompressionOptions getImageCompression()
Return the current image compression settings.
Definition: fits.cc:1495
void createEmpty()
Create an empty image HDU with NAXIS=0 at the end of the file.
Definition: fits.cc:1240
void setHdu(int hdu, bool relative=false)
Set the current HDU.
Definition: fits.cc:513
bool checkCompressedImagePhu()
Go to the first image header in the FITS file.
Definition: fits.cc:1726
int countHdus()
Return the number of HDUs in the file.
Definition: fits.cc:534
std::string getFileName() const
Return the file name associated with the FITS object or "<unknown>" if there is none.
Definition: fits.cc:498
void setImageCompression(ImageCompressionOptions const &options)
Set compression options for writing FITS images.
Definition: fits.cc:1518
int getHdu()
Return the current HDU (0-indexed; 0 is the Primary HDU).
Definition: fits.cc:507
void writeMetadata(daf::base::PropertySet const &metadata)
Read a FITS header into a PropertySet or PropertyList.
Definition: fits.cc:1095
Options for scaling image pixels.
ScalingAlgorithm algorithm
Scaling algorithm to use.
float quantizeLevel
Divisor of the standard deviation for STDEV_* scaling.
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)
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)
Lifetime-management for memory that goes into FITS memory files.
Definition: fits.h:121
std::size_t getLength() const
Return the buffer length.
Definition: fits.h:194
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:58
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
const int DEFAULT_HDU
Specify that the default HDU should be read.
Definition: fitsDefaults.h:18
std::shared_ptr< daf::base::PropertyList > combineMetadata(std::shared_ptr< const daf::base::PropertyList > first, std::shared_ptr< const daf::base::PropertyList > second)
Combine two sets of metadata in a FITS-appropriate fashion.
Definition: fits.cc:1628
std::string compressionAlgorithmToString(ImageCompressionOptions::CompressionAlgorithm algorithm)
Provide string version of compression algorithm.
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
Definition: fits.cc:1657
ImageScalingOptions::ScalingAlgorithm scalingAlgorithmFromString(std::string const &name)
Interpret scaling algorithm expressed in string.
void setAllowImageCompression(bool allow)
Definition: fits.cc:1546
bool getAllowImageCompression()
Definition: fits.cc:1548
std::string scalingAlgorithmToString(ImageScalingOptions::ScalingAlgorithm algorithm)
Provide string version of compression algorithm.
std::string makeLimitedFitsHeader(lsst::daf::base::PropertySet const &metadata, std::set< std::string > const &excludeNames={})
Format a PropertySet into an FITS header string in a simplistic fashion.
Definition: fits.cc:457
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromString(std::string const &name)
Interpret compression algorithm expressed in string.
def init()
Definition: tests.py:59
void declareImageScaleTemplates(py::class_< ImageScale > &cls, std::string const &suffix)
Definition: fits.cc:116
void declareImageScalingOptions(py::module &mod)
Definition: fits.cc:84
void declareImageCompression(py::module &mod)
Definition: fits.cc:43
void declareImageWriteOptions(py::module &mod)
Definition: fits.cc:134
void declareFits(py::module &mod)
Definition: fits.cc:161
void declareImageScalingOptionsTemplates(py::class_< ImageScalingOptions > &cls)
Definition: fits.cc:80
PYBIND11_MODULE(fits, mod)
Definition: fits.cc:198
void declareImageScale(py::module &mod)
Definition: fits.cc:122
bool strip
Definition: fits.cc:911
int m
Definition: SpanSet.cc:49
float quantizeLevel
quantization level: 0.0 = none requires use of GZIP or GZIP_SHUFFLE
CompressionAlgorithm algorithm
Compresion algorithm to use.
Tiles tiles
Tile size; a dimension with 0 means infinite (e.g., to specify one row: 0,1)
double bscale
Scale to apply when reading from FITS.
long blank
Value for integer images indicating non-finite values.
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.
ImageCompressionOptions compression
Options controlling compression.
Definition: fits.h:220
ImageScalingOptions scaling
Options controlling scaling.
Definition: fits.h:221
static std::shared_ptr< daf::base::PropertySet > validate(daf::base::PropertySet const &config)
Validate a PropertySet.
Definition: fits.cc:1781