35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wunused-variable"
37 #pragma clang diagnostic pop
38 #include "boost/format.hpp"
40 #include "boost/functional/hash.hpp"
60 template <
typename MaskPixelT>
61 void Mask<MaskPixelT>::_initializePlanes(
MaskPlaneDict const& planeDefs) {
62 LOGL_DEBUG(
"afw.image.Mask",
"Number of mask planes: %d", getNumPlanesMax());
67 template <
typename MaskPixelT>
70 _initializePlanes(planeDefs);
74 template <
typename MaskPixelT>
78 _initializePlanes(planeDefs);
82 template <
typename MaskPixelT>
85 _initializePlanes(planeDefs);
89 template <
typename MaskPixelT>
93 _initializePlanes(planeDefs);
97 template <
typename MaskPixelT>
100 _initializePlanes(planeDefs);
104 template <
typename MaskPixelT>
107 _initializePlanes(planeDefs);
108 *
this = initialValue;
111 template <
typename MaskPixelT>
114 :
ImageBase<MaskPixelT>(rhs,
bbox, origin, deep), _maskDict(rhs._maskDict) {}
116 template <
typename MaskPixelT>
118 :
ImageBase<MaskPixelT>(rhs, deep), _maskDict(rhs._maskDict) {}
120 template <
typename MaskPixelT>
123 template <
typename MaskPixelT>
126 template <
typename MaskPixelT>
129 :
image::
ImageBase<MaskPixelT>(array, deep, xy0), _maskDict(detail::MaskDict::getDefault()) {}
131 template <
typename PixelT>
136 swap(_maskDict, rhs._maskDict);
139 template <
typename PixelT>
144 template <
typename MaskPixelT>
152 template <
typename MaskPixelT>
157 template <
typename MaskPixelT>
159 fill_pixels(_getRawView(), rhs);
166 template <
typename MaskPixelT>
169 :
ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
171 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
173 metadata->combine(reader.readMetadata());
177 template <
typename MaskPixelT>
180 ImageOrigin origin,
bool conformMasks,
bool allowUnsafe)
181 : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
183 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
185 metadata->combine(reader.readMetadata());
189 template <
typename MaskPixelT>
193 : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
195 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
197 metadata->combine(reader.readMetadata());
201 template <
typename MaskPixelT>
206 writeFits(fitsfile, metadata_i);
209 template <
typename MaskPixelT>
214 writeFits(fitsfile, metadata_i);
217 template <
typename MaskPixelT>
220 writeFits(fitsfile, fits::ImageWriteOptions(*
this), metadata);
223 template <
typename MaskPixelT>
228 writeFits(fitsfile, options, header);
231 template <
typename MaskPixelT>
236 writeFits(fitsfile, options, header);
239 template <
typename MaskPixelT>
243 header ? header->deepCopy() : std::make_shared<dafBase::PropertySet>();
244 addMaskPlanesToMetadata(useHeader);
245 fitsfile.writeImage(*
this, options, useHeader);
250 template <
typename MaskPixelT>
253 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
254 for (
auto const &
iter : mpd) {
255 if (value & getBitMask(
iter.second)) {
256 if (result.
size() > 0) {
259 result +=
iter.first;
265 template <
typename MaskPixelT>
267 int id = getMaskPlaneNoThrow(
name);
270 id = _maskPlaneDict()->getUnusedPlane();
275 if (
id >= getNumPlanesMax()) {
277 str(boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
285 template <
typename MaskPixelT>
287 if (planeId < 0 || planeId >= getNumPlanesMax()) {
290 str(boost::format(
"mask plane ID must be between 0 and %1%") % (getNumPlanesMax() - 1)));
293 _maskPlaneDict()->add(
name, planeId);
298 template <
typename MaskPixelT>
300 return _maskDict->getMaskPlaneDict();
303 template <
typename MaskPixelT>
307 str(boost::format(
"Plane %s doesn't exist in the default Mask") %
name));
311 _maskPlaneDict()->erase(
name);
314 template <
typename MaskPixelT>
318 clearMaskPlane(getMaskPlane(
name));
323 _maskDict = _maskDict->clone();
326 _maskDict->erase(
name);
329 removeMaskPlane(
name);
333 template <
typename MaskPixelT>
335 return (planeId >= 0 && planeId < getNumPlanesMax()) ? (1 << planeId) : 0;
338 template <
typename MaskPixelT>
339 MaskPixelT Mask<MaskPixelT>::getBitMask(
int planeId) {
340 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
342 for (
auto const &i : mpd) {
343 if (planeId == i.second) {
344 MaskPixelT
const bitmask = getBitMaskNoThrow(planeId);
352 str(boost::format(
"Invalid mask plane ID: %d") % planeId));
355 template <
typename MaskPixelT>
357 int const plane = getMaskPlaneNoThrow(
name);
361 str(boost::format(
"Invalid mask plane name: %s") %
name));
367 template <
typename MaskPixelT>
372 template <
typename MaskPixelT>
374 return getBitMask(getMaskPlane(
name));
377 template <
typename MaskPixelT>
379 MaskPixelT mpix = 0x0;
380 for (
auto const &it :
name) {
381 mpix |= getBitMask(getMaskPlane(it));
386 template <
typename MaskPixelT>
388 return _maskPlaneDict()->size();
391 template <
typename MaskPixelT>
393 _maskPlaneDict()->clear();
396 template <
typename MaskPixelT>
401 template <
typename MaskPixelT>
403 *
this &= ~getBitMask(planeId);
406 template <
typename MaskPixelT>
410 if (*_maskDict == *currentMD) {
418 MaskPixelT keepBitmask = 0;
419 MaskPixelT canonicalMask[
sizeof(MaskPixelT) * 8];
420 MaskPixelT currentMask[
sizeof(MaskPixelT) * 8];
423 for (
auto const &i : currentPlaneDict) {
425 int const currentPlaneNumber = i.second;
426 int canonicalPlaneNumber = getMaskPlaneNoThrow(
name);
428 if (canonicalPlaneNumber < 0) {
429 canonicalPlaneNumber = addMaskPlane(
name);
432 if (canonicalPlaneNumber == currentPlaneNumber) {
433 keepBitmask |= getBitMask(canonicalPlaneNumber);
435 canonicalMask[numReMap] = getBitMask(canonicalPlaneNumber);
436 currentMask[numReMap] = getBitMaskNoThrow(currentPlaneNumber);
443 for (
int r = 0; r != this->getHeight(); ++r) {
446 MaskPixelT
const pixel = *ptr;
448 MaskPixelT newPixel =
pixel & keepBitmask;
449 for (
int i = 0; i < numReMap; i++) {
450 if (
pixel & currentMask[i]) newPixel |= canonicalMask[i];
462 template <
typename MaskPixelT>
467 template <
typename MaskPixelT>
473 template <
typename MaskPixelT>
478 template <
typename MaskPixelT>
484 template <
typename MaskPixelT>
490 template <
typename MaskPixelT>
496 template <
typename MaskPixelT>
498 if (*_maskDict != *other._maskDict) {
503 template <
typename MaskPixelT>
505 transform_pixels(_getRawView(), _getRawView(),
506 [&val](MaskPixelT
const& l) -> MaskPixelT {
return l | val; });
510 template <
typename MaskPixelT>
512 checkMaskDictionaries(rhs);
516 str(boost::format(
"Images are of different size, %dx%d v %dx%d") %
519 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
520 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l | r; });
524 template <
typename MaskPixelT>
526 transform_pixels(_getRawView(), _getRawView(), [&val](MaskPixelT
const& l) {
return l & val; });
530 template <
typename MaskPixelT>
532 checkMaskDictionaries(rhs);
536 str(boost::format(
"Images are of different size, %dx%d v %dx%d") %
539 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
540 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l & r; });
544 template <
typename MaskPixelT>
546 transform_pixels(_getRawView(), _getRawView(),
547 [&val](MaskPixelT
const& l) -> MaskPixelT {
return l ^ val; });
551 template <
typename MaskPixelT>
553 checkMaskDictionaries(rhs);
557 str(boost::format(
"Images are of different size, %dx%d v %dx%d") %
560 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
561 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l ^ r; });
565 template <
typename MaskPixelT>
567 MaskPixelT
const bitMask = getBitMask(planeId);
569 for (
int x = x0;
x <= x1;
x++) {
570 operator()(
x,
y) = operator()(
x,
y) | bitMask;
574 template <
typename MaskPixelT>
582 NameList paramNames = metadata->paramNames(
false);
583 for (
auto const ¶mName : paramNames) {
584 if (paramName.compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
585 metadata->remove(paramName);
589 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
592 for (
auto const &i : mpd) {
594 int const planeNumber = i.second;
596 if (planeName !=
"") {
597 metadata->add(maskPlanePrefix + planeName, planeNumber);
602 template <
typename MaskPixelT>
609 NameList paramNames = metadata->paramNames(
false);
610 int numPlanesUsed = 0;
613 for (
auto const ¶mName : paramNames) {
614 if (paramName.compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
617 int const planeId = metadata->getAsInt(paramName);
619 MaskPlaneDict::const_iterator plane = newDict.
find(planeName);
620 if (plane != newDict.
end() && planeId != plane->second) {
623 for (MaskPlaneDict::const_iterator j = newDict.
begin(); j != newDict.
end(); ++j) {
624 if (planeId == j->second) {
626 str(boost::format(
"File specifies plane %s has same value (%d) as %s") %
627 planeName % planeId % j->first));
631 if (numPlanesUsed >= getNumPlanesMax()) {
635 str(boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
637 newDict[planeName] = planeId;
643 template <
typename MaskPixelT>
651 template <
typename MaskPixelT>
654 template <
typename MaskPixelT>
662 template class Mask<MaskPixel>;
table::Key< std::string > name
table::PointKey< int > pixel
#define LSST_EXCEPT(type,...)
afw::table::PointKey< int > dimensions
#define LOGL_DEBUG(logger, message...)
A class used to request that array accesses be checked.
The base class for all image classed (Image, Mask, MaskedImage, ...)
typename Reference< PixelT >::type PixelReference
A Reference to a PixelT.
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y) in LOCAL coordinates.
int getWidth() const
Return the number of columns in the image.
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
int getHeight() const
Return the number of rows in the image.
typename _view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
_view_t _getRawView() const
void swap(ImageBase &rhs)
typename ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
A FITS reader class for Masks.
Represent a 2-dimensional array of bitmask pixels.
void writeFits(std::string const &fileName, std::shared_ptr< lsst::daf::base::PropertySet const > metadata=std::shared_ptr< lsst::daf::base::PropertySet >(), std::string const &mode="w") const
Write a mask to a regular FITS file.
Mask & operator=(MaskPixelT const rhs)
friend class MaskFitsReader
void printMaskPlanes() const
print the mask plane dictionary to std::cout
static int getMaskPlane(const std::string &name)
Return the mask plane number corresponding to a plane name.
static std::string interpret(MaskPixelT value)
Interpret a mask value as a comma-separated list of mask plane names.
static void removeMaskPlane(const std::string &name)
void removeAndClearMaskPlane(const std::string &name, bool const removeFromDefault=false)
Clear all pixels of the specified mask and remove the plane from the mask plane dictionary; optionall...
static void clearMaskPlaneDict()
Reset the maskPlane dictionary.
void setMaskPlaneValues(const int plane, const int x0, const int x1, const int y)
Set the bit specified by "planeId" for pixels (x0, y) ...
static void addMaskPlanesToMetadata(std::shared_ptr< lsst::daf::base::PropertySet >)
Given a PropertySet, replace any existing MaskPlane assignments with the current ones.
ImageBase< MaskPixelT >::PixelReference operator()(int x, int y)
get a reference to the specified pixel
Mask & operator^=(Mask const &rhs)
XOR a Mask into a Mask.
static int addMaskPlane(const std::string &name)
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
Mask(unsigned int width, unsigned int height, MaskPlaneDict const &planeDefs=MaskPlaneDict())
Construct a Mask initialized to 0x0.
MaskPlaneDict const & getMaskPlaneDict() const
Return the Mask's maskPlaneDict.
void conformMaskPlanes(const MaskPlaneDict &masterPlaneDict)
Adjust this mask to conform to the standard Mask class's mask plane dictionary, adding any new mask p...
Mask & operator|=(Mask const &rhs)
OR a Mask into a Mask.
static MaskPlaneDict parseMaskPlaneMetadata(std::shared_ptr< lsst::daf::base::PropertySet const > metadata)
Given a PropertySet that contains the MaskPlane assignments, setup the MaskPlanes.
void clearAllMaskPlanes()
Clear all the pixels.
static int getNumPlanesUsed()
void clearMaskPlane(int plane)
Clear the specified bit in all pixels.
Mask & operator&=(Mask const &rhs)
AND a Mask into a Mask.
static void addAllMasksPlane(std::string const &name, int bitId)
static std::shared_ptr< MaskDict > detachDefault()
static std::shared_ptr< MaskDict > getDefault()
static std::shared_ptr< MaskDict > copyOrGetDefault(MaskPlaneDict const &dict)
std::map< std::string, int > MaskPlaneDict
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
void swap(Image< PixelT > &a, Image< PixelT > &b)
A base class for image defects.