48 #pragma clang diagnostic push
49 #pragma clang diagnostic ignored "-Wunused-variable"
50 #pragma clang diagnostic pop
51 #include "boost/format.hpp"
52 #include "boost/filesystem/path.hpp"
54 #include "boost/functional/hash.hpp"
69 #include "boost/mpl/vector.hpp"
70 #include "boost/gil/gil_all.hpp"
74 namespace afwGeom = lsst::afw::geom;
75 namespace dafBase = lsst::daf::base;
76 namespace pexExcept = lsst::pex::exceptions;
80 namespace lsst {
namespace afw {
namespace image {
86 void setInitMaskBits(
PTR(detail::MaskDict) dict);
95 typedef detail::MaskPlaneDict::value_type value_type;
96 typedef detail::MaskPlaneDict::const_iterator const_iterator;
103 bool operator==(MapWithHash
const& rhs)
const {
104 return _hash == rhs._hash;
107 const_iterator begin()
const {
return _dict.begin(); }
108 const_iterator end()
const {
return _dict.end(); }
109 const_iterator find(detail::MaskPlaneDict::key_type
const&
name)
const {
return _dict.find(name); }
111 void add(std::string
const& str,
int val) {
117 return _dict.empty();
124 std::size_t size()
const {
128 void erase(std::string
const& str) {
139 std::size_t getHash()
const {
147 std::size_t _calcHash() {
149 for (const_iterator ptr = begin(); ptr != end(); ++ptr) {
151 boost::hash<std::string>()((*ptr).first + str(
boost::format(
"%d") % ptr->second));
158 bool operator!=(MapWithHash
const& lhs, MapWithHash
const& rhs) {
159 return !(lhs == rhs);
171 friend class ::lsst::afw::image::DictState;
174 MaskDict(MapWithHash
const* dict) : MapWithHash(*dict) {}
188 for (MapWithHash::const_iterator ptr = begin(); ptr != end(); ++ptr) {
189 std::cout <<
"Plane " << ptr->second <<
" -> " << ptr->first << std::endl;
208 typedef std::map<MapWithHash *, int> HandleList;
220 for (HandleList::iterator ptr =
_dicts.begin(); ptr !=
_dicts.end(); ++ptr) {
226 template<
typename FunctorT>
227 void forEachMaskDict(FunctorT func) {
228 for (HandleList::const_iterator ptr =
_dicts.begin(); ptr !=
_dicts.end(); ++ptr) {
234 PTR(detail::MaskDict) getDefaultDict() {
235 static bool first =
true;
252 void addDict(MapWithHash *dict) {
256 void eraseDict(MapWithHash *dict) {
260 PTR(detail::MaskDict) incrDefaultVersion() {
272 static DictState _state;
287 return _state.getDefaultDict();
296 MapWithHash mwh(mpd);
298 _state.addDict(dict.get());
307 return _state.setDefaultDict(dict);
313 _state.addDict(dict.get());
319 _state.eraseDict(
this);
333 MapWithHash::const_iterator
const it =
334 std::max_element(begin(), end(), std::bind(std::less<int>(),
335 std::bind(&MapWithHash::value_type::second,
336 std::placeholders::_1),
337 std::bind(&MapWithHash::value_type::second,
338 std::placeholders::_2)
342 int id = it->second + 1;
344 for (
int i = 0; i <
id; ++i) {
345 MapWithHash::const_iterator
const it =
346 std::find_if(begin(), end(), std::bind(std::equal_to<int>(),
347 std::bind(&MapWithHash::value_type::second,
348 std::placeholders::_1), i));
360 MapWithHash::const_iterator i = find(name);
362 return (i == end()) ? -1 : i->second;
377 dict->add(
"BAD", ++i);
378 dict->add(
"SAT", ++i);
379 dict->add(
"INTRP", ++i);
380 dict->add(
"CR", ++i);
381 dict->add(
"EDGE", ++i);
382 dict->add(
"DETECTED", ++i);
383 dict->add(
"DETECTED_NEGATIVE", ++i);
384 dict->add(
"SUSPECT", ++i);
385 dict->add(
"NO_DATA", ++i);
392 template<
typename MaskPixelT>
394 LOGL_DEBUG(
"afw.image.Mask",
"Number of mask planes: %d", getNumPlanesMax());
402 template<
typename MaskPixelT>
416 template<
typename MaskPixelT>
420 MaskPixelT initialValue,
425 *
this = initialValue;
431 template<
typename MaskPixelT>
444 template<
typename MaskPixelT>
447 MaskPixelT initialValue,
452 *
this = initialValue;
458 template<
typename MaskPixelT>
471 template<
typename MaskPixelT>
474 MaskPixelT initialValue,
479 *
this = initialValue;
485 template<
typename MaskPixelT>
492 ImageBase<MaskPixelT>(rhs, bbox, origin, deep), _maskDict(rhs._maskDict) {
498 template<
typename MaskPixelT>
503 ImageBase<MaskPixelT>(rhs, deep), _maskDict(rhs._maskDict) {
506 template<
typename MaskPixelT>
510 _maskDict(detail::MaskDict::makeMaskDict()) {
515 template<
typename PixelT>
523 template<
typename PixelT>
528 template<
typename MaskPixelT>
536 template<
typename MaskPixelT>
538 fill_pixels(_getRawView(), rhs);
543 #ifndef DOXYGEN // doc for this section is already in header
545 template<
typename MaskPixelT>
547 std::string
const & fileName,
553 ) :
ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict()) {
555 fitsfile.setHdu(hdu);
556 *
this =
Mask(fitsfile, metadata, bbox, origin, conformMasks);
559 template<
typename MaskPixelT>
567 ) : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict()) {
570 fitsfile.setHdu(hdu);
571 *
this =
Mask(fitsfile, metadata, bbox, origin, conformMasks);
574 template<
typename MaskPixelT>
576 fits::Fits & fitsfile,
580 bool const conformMasks
582 ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict())
585 typedef boost::mpl::vector<
595 fits_read_image<fits_mask_types>(fitsfile, *
this, *metadata, bbox, origin);
599 PTR(detail::MaskDict) fileMD = detail::MaskDict::makeMaskDict(fileMaskDict);
601 if (*fileMD == *detail::MaskDict::makeMaskDict()) {
613 template<
typename MaskPixelT>
615 std::string
const & fileName,
617 std::string
const & mode
620 writeFits(fitsfile, metadata_i);
623 template<
typename MaskPixelT>
625 fits::MemFileManager & manager,
627 std::string
const & mode
630 writeFits(fitsfile, metadata_i);
633 template<
typename MaskPixelT>
635 fits::Fits & fitsfile,
645 addMaskPlanesToMetadata(metadata);
652 metadata->combine(wcsAMetadata);
660 struct addPlaneFunctor {
661 addPlaneFunctor(std::string
const& name,
int id) :
_name(name),
_id(id) {}
663 void operator()(MapWithHash *dict) {
664 detail::MaskPlaneDict::const_iterator
const it =
665 std::find_if(dict->begin(), dict->end(),
666 std::bind(std::equal_to<int>(),
667 std::bind(&detail::MaskPlaneDict::value_type::second,
668 std::placeholders::_1),
_id));
669 if (it != dict->end()) {
673 if (dict->find(
_name) == dict->end()) {
683 template<
typename MaskPixelT>
686 std::string result =
"";
687 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
688 for (MaskPlaneDict::const_iterator
iter = mpd.begin();
iter != mpd.end(); ++
iter) {
689 if (value & getBitMask(
iter->second)) {
690 if (result.size() > 0) {
693 result +=
iter->first;
699 template<
typename MaskPixelT>
702 int id = getMaskPlaneNoThrow(name);
705 id = _maskPlaneDict()->getUnusedPlane();
710 if (
id >= getNumPlanesMax()) {
712 str(
boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
715 _state.forEachMaskDict(addPlaneFunctor(name,
id));
725 template<
typename MaskPixelT>
730 if (planeId < 0 || planeId >= getNumPlanesMax()) {
732 str(
boost::format(
"mask plane ID must be between 0 and %1%") % (getNumPlanesMax() - 1)));
735 _maskPlaneDict()->add(name, planeId);
743 template<
typename MaskPixelT>
747 return _maskDict->getMaskPlaneDict();
750 template<
typename MaskPixelT>
754 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
755 str(
boost::format(
"Plane %s doesn't exist in the default Mask") % name));
759 _maskPlaneDict()->erase(name);
768 template<
typename MaskPixelT>
770 bool const removeFromDefault
774 clearMaskPlane(getMaskPlane(name));
779 _maskDict = _maskDict->clone();
782 _maskDict->erase(name);
785 removeMaskPlane(name);
792 template<
typename MaskPixelT>
794 return (planeId >= 0 && planeId < getNumPlanesMax()) ? (1 << planeId) : 0;
802 template<
typename MaskPixelT>
804 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
806 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end(); ++i) {
807 if (planeId == i->second) {
808 MaskPixelT
const bitmask = getBitMaskNoThrow(planeId);
815 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
824 template<
typename MaskPixelT>
826 int const plane = getMaskPlaneNoThrow(name);
829 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
839 template<
typename MaskPixelT>
841 return _maskPlaneDict()->getMaskPlane(name);
849 template<
typename MaskPixelT>
851 return getBitMask(getMaskPlane(name));
859 template<
typename MaskPixelT>
861 MaskPixelT mpix = 0x0;
862 for (std::vector<std::string>::const_iterator it = name.begin(); it != name.end(); ++it) {
863 mpix |= getBitMask(getMaskPlane(*it));
871 template<
typename MaskPixelT>
874 return _maskPlaneDict()->size();
880 template<
typename MaskPixelT>
882 _maskPlaneDict()->clear();
888 template<
typename MaskPixelT>
896 template<
typename MaskPixelT>
898 *
this &= ~getBitMask(planeId);
912 template<
typename MaskPixelT>
919 if (*_maskDict == *currentMD) {
927 MaskPixelT keepBitmask = 0;
928 MaskPixelT canonicalMask[
sizeof(MaskPixelT)*8];
929 MaskPixelT currentMask[
sizeof(MaskPixelT)*8];
932 for (MaskPlaneDict::const_iterator i = currentPlaneDict.begin(); i != currentPlaneDict.end() ; i++) {
933 std::string
const name = i->first;
934 int const currentPlaneNumber = i->second;
935 int canonicalPlaneNumber = getMaskPlaneNoThrow(name);
937 if (canonicalPlaneNumber < 0) {
938 canonicalPlaneNumber = addMaskPlane(name);
941 if (canonicalPlaneNumber == currentPlaneNumber) {
942 keepBitmask |= getBitMask(canonicalPlaneNumber);
944 canonicalMask[numReMap] = getBitMask(canonicalPlaneNumber);
945 currentMask[numReMap] = getBitMaskNoThrow(currentPlaneNumber);
952 for (
int r = 0; r != this->getHeight(); ++r) {
953 for (
typename Mask::x_iterator ptr = this->row_begin(r), end = this->row_end(r);
955 MaskPixelT
const pixel = *ptr;
957 MaskPixelT newPixel = pixel & keepBitmask;
958 for (
int i = 0; i < numReMap; i++) {
959 if (pixel & currentMask[i]) newPixel |= canonicalMask[i];
976 template<
typename MaskPixelT>
987 template<
typename MaskPixelT>
999 template<
typename MaskPixelT>
1010 template<
typename MaskPixelT>
1022 template<
typename MaskPixelT>
1035 template<
typename MaskPixelT>
1052 template<
typename MaskPixelT>
1055 throw LSST_EXCEPT(pexExcept::RuntimeError,
"Mask dictionaries do not match");
1062 template<
typename MaskPixelT>
1064 transform_pixels(_getRawView(), _getRawView(),
1065 [&val](MaskPixelT
const& l) -> MaskPixelT {
return l |
val; });
1071 template<
typename MaskPixelT>
1073 checkMaskDictionaries(rhs);
1077 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1080 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
1081 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l | r; });
1087 template<
typename MaskPixelT>
1089 transform_pixels(_getRawView(), _getRawView(),
1090 [&val](MaskPixelT
const& l) {
return l &
val; });
1096 template<
typename MaskPixelT>
1098 checkMaskDictionaries(rhs);
1102 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1105 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
1106 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l & r; });
1112 template<
typename MaskPixelT>
1114 transform_pixels(_getRawView(), _getRawView(),
1115 [&val](MaskPixelT
const& l) -> MaskPixelT {
return l ^
val; });
1121 template<
typename MaskPixelT>
1123 checkMaskDictionaries(rhs);
1127 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1130 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
1131 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l ^ r; });
1137 template<
typename MaskPixelT>
1139 int const x0,
int const x1,
int const y) {
1140 MaskPixelT
const bitMask = getBitMask(planeId);
1142 for (
int x = x0;
x <= x1;
x++) {
1143 operator()(
x, y) = operator()(
x, y) | bitMask;
1150 template<
typename MaskPixelT>
1153 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"Null PTR(PropertySet)");
1157 typedef std::vector<std::string> NameList;
1158 NameList paramNames = metadata->
paramNames(
false);
1159 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1160 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1165 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
1168 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end() ; ++i) {
1169 std::string
const& planeName = i->first;
1170 int const planeNumber = i->second;
1172 if (planeName !=
"") {
1173 metadata->
add(maskPlanePrefix + planeName, planeNumber);
1183 template<
typename MaskPixelT>
1190 typedef std::vector<std::string> NameList;
1191 NameList paramNames = metadata->
paramNames(
false);
1192 int numPlanesUsed = 0;
1195 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1196 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1198 std::string planeName = i->substr(maskPlanePrefix.size());
1199 int const planeId = metadata->
getAsInt(*i);
1201 MaskPlaneDict::const_iterator plane = newDict.find(planeName);
1202 if (plane != newDict.end() && planeId != plane->second) {
1204 "File specifies plane " + planeName +
" twice");
1206 for (MaskPlaneDict::const_iterator j = newDict.begin(); j != newDict.end(); ++j) {
1207 if (planeId == j->second) {
1209 str(
boost::format(
"File specifies plane %s has same value (%d) as %s") %
1210 planeName % planeId % j->first));
1214 if (numPlanesUsed >= getNumPlanesMax()) {
1217 str(
boost::format(
"Max number of planes (%1%) already used") %
1218 getNumPlanesMax()));
1220 newDict[planeName] = planeId;
1229 template<
typename MaskPixelT>
1238 template<
typename MaskPixelT>
1241 template<
typename MaskPixelT>
static std::string interpret(MaskPixelT value)
Interpret a mask value as a comma-separated list of mask plane names.
void _initializePlanes(MaskPlaneDict const &planeDefs)
Initialise mask planes; called by constructors.
static void clearMaskPlaneDict()
Reset the maskPlane dictionary.
void add(std::string const &name, T const &value)
Appends a single value to the vector of values for a property name (possibly hierarchical).
table::Key< std::string > name
static MaskPixelT getBitMaskNoThrow(int plane)
Return the bitmask corresponding to a plane ID, or 0 if invalid.
void writeFits(std::string const &fileName, boost::shared_ptr< lsst::daf::base::PropertySet const > metadata=boost::shared_ptr< lsst::daf::base::PropertySet >(), std::string const &mode="w") const
Write a mask to a regular FITS file.
static int getMaskPlane(const std::string &name)
Return the mask plane number corresponding to a plane name.
std::string const & _name
virtual Ptr deepCopy(void) const
Copy the PropertySet and all of its contents.
Include files required for standard LSST Exception handling.
bool operator!=(lsst::afw::coord::Coord const &lhs, lsst::afw::coord::Coord const &rhs)
Inequality; the complement of equality.
void operator|=(Mask const &rhs)
OR a Mask into a Mask.
void operator&=(Mask const &rhs)
AND a Mask into a Mask.
std::map< std::string, int > MaskPlaneDict
Mask & operator=(MaskPixelT const rhs)
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
boost::shared_ptr< MaskDict > clone() const
detail::MaskPlaneDict _dict
boost::shared_ptr< lsst::daf::base::PropertyList > createTrivialWcsAsPropertySet(std::string const &wcsName, int const x0, int const y0)
Define a trivial WCS that maps the lower left corner (LLC) pixel of an image to a given value...
detail::MaskPlaneDict MaskPlaneDict
bool operator==(CoordKey const &lhs, CoordKey const &rhs)
Compare CoordKeys for equality using the constituent Keys.
static boost::shared_ptr< MaskDict > setDefaultDict(boost::shared_ptr< MaskDict > dict)
int getUnusedPlane() const
static int getNumPlanesUsed()
Reset the maskPlane dictionary.
void swap(Mask< PixelT > &a, Mask< PixelT > &b)
lsst::daf::base::PropertyList PropertyList
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
The base class for all image classed (Image, Mask, MaskedImage, ...)
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 int getMaskPlaneNoThrow(const std::string &name)
Return the mask plane number corresponding to a plane name, or -1 if not found.
static const std::string maskPlanePrefix
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
ImageBase< MaskPixelT >::PixelReference operator()(int x, int y)
get a reference to the specified pixel
An integer coordinate rectangle.
void operator^=(Mask const &rhs)
XOR a Mask into a Mask.
table::Key< table::Array< Kernel::Pixel > > image
LSST DM logging module built on log4cxx.
static boost::shared_ptr< MaskDict > incrDefaultVersion()
Mask(unsigned int width, unsigned int height, MaskPlaneDict const &planeDefs=MaskPlaneDict())
Construct a Mask initialized to 0x0.
afw::table::PointKey< int > dimensions
void ImageT ImageT int float saturatedPixelValue int const width
static MaskPixelT getBitMask(int plane)
Return the bitmask corresponding to plane ID.
geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
Represent a 2-dimensional array of bitmask pixels.
Lifetime-management for memory that goes into FITS memory files.
_view_t _getRawView() const
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 MaskPlaneDict parseMaskPlaneMetadata(boost::shared_ptr< lsst::daf::base::PropertySet const >)
Given a PropertySet that contains the MaskPlane assignments, setup the MaskPlanes.
std::vector< std::string > paramNames(bool topLevelOnly=true) const
Get the names of parameters (non-subproperties) in the PropertySet, optionally including those in sub...
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
A class used to request that array accesses be checked.
int getHeight() const
Return the number of rows in the image.
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
void swap(ImageBase &rhs)
MaskDict(MapWithHash const *dict)
void ImageT ImageT int float saturatedPixelValue int const height
static void listMaskDicts()
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
static void removeMaskPlane(const std::string &name)
static void addMaskPlanesToMetadata(boost::shared_ptr< lsst::daf::base::PropertySet >)
Given a PropertySet, replace any existing MaskPlane assignments with the current ones.
void checkMaskDictionaries(Mask const &other)
MaskPlaneDict const & getMaskPlaneDict() const
Return the Mask's maskPlaneDict.
Class for storing generic metadata.
static boost::shared_ptr< MaskDict > makeMaskDict()
boost::shared_ptr< detail::MaskDict > _defaultMaskDict
afw::table::Key< double > b
table::PointKey< int > pixel
virtual void remove(std::string const &name)
Removes all values for a property name (possibly hierarchical).
void conformMaskPlanes(const MaskPlaneDict &masterPlaneDict)
Adjust this mask to conform to the standard Mask class's mask plane dictionary, adding any new mask p...
#define CONST_PTR(...)
A shared pointer to a const object.
boost::shared_ptr< detail::MaskDict > _maskDict
void clearMaskPlane(int plane)
Clear the specified bit in all pixels.
void printMaskPlanes() const
print the mask plane dictionary to std::cout
int getWidth() const
Return the number of columns in the image.
Definition of default types for Masks and Variance Images.
void clearAllMaskPlanes()
Clear all the pixels.
static int addMaskPlane(const std::string &name)
void fits_write_image(fits::Fits &fitsfile, const ImageT &image, boost::shared_ptr< daf::base::PropertySet const > metadata=boost::shared_ptr< daf::base::PropertySet const >())
std::string const wcsNameForXY0
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y)
int getMaskPlane(const std::string &name) const