48 #pragma clang diagnostic push
49 #pragma clang diagnostic ignored "-Wunused-variable"
50 #include "boost/lambda/lambda.hpp"
51 #pragma clang diagnostic pop
52 #include "boost/format.hpp"
53 #include "boost/filesystem/path.hpp"
55 #include "boost/functional/hash.hpp"
57 #include "boost/bind.hpp"
72 #include "boost/mpl/vector.hpp"
73 #include "boost/gil/gil_all.hpp"
77 namespace afwGeom = lsst::afw::geom;
78 namespace dafBase = lsst::daf::base;
79 namespace pexExcept = lsst::pex::exceptions;
80 namespace pexLog = lsst::pex::logging;
84 namespace lsst {
namespace afw {
namespace image {
90 void setInitMaskBits(
PTR(detail::MaskDict) dict);
99 typedef detail::MaskPlaneDict::value_type value_type;
100 typedef detail::MaskPlaneDict::const_iterator const_iterator;
107 bool operator==(MapWithHash
const& rhs)
const {
108 return _hash == rhs._hash;
111 const_iterator begin()
const {
return _dict.begin(); }
112 const_iterator end()
const {
return _dict.end(); }
113 const_iterator find(detail::MaskPlaneDict::key_type
const&
name)
const {
return _dict.find(name); }
115 void add(std::string
const& str,
int val) {
121 return _dict.empty();
128 std::size_t size()
const {
132 void erase(std::string
const& str) {
143 std::size_t getHash()
const {
151 std::size_t _calcHash() {
153 for (const_iterator ptr = begin(); ptr != end(); ++ptr) {
155 boost::hash<std::string>()((*ptr).first + str(
boost::format(
"%d") % ptr->second));
162 bool operator!=(MapWithHash
const& lhs, MapWithHash
const& rhs) {
163 return !(lhs == rhs);
175 friend class ::lsst::afw::image::DictState;
178 MaskDict(MapWithHash
const* dict) : MapWithHash(*dict) {}
192 for (MapWithHash::const_iterator ptr = begin(); ptr != end(); ++ptr) {
193 std::cout <<
"Plane " << ptr->second <<
" -> " << ptr->first << std::endl;
212 typedef std::map<MapWithHash *, int> HandleList;
224 for (HandleList::iterator ptr =
_dicts.begin(); ptr !=
_dicts.end(); ++ptr) {
230 template<
typename FunctorT>
231 void forEachMaskDict(FunctorT func) {
232 for (HandleList::const_iterator ptr =
_dicts.begin(); ptr !=
_dicts.end(); ++ptr) {
238 PTR(detail::MaskDict) getDefaultDict() {
239 static bool first =
true;
256 void addDict(MapWithHash *dict) {
260 void eraseDict(MapWithHash *dict) {
264 PTR(detail::MaskDict) incrDefaultVersion() {
276 static DictState _state;
291 return _state.getDefaultDict();
300 MapWithHash mwh(mpd);
302 _state.addDict(dict.get());
311 return _state.setDefaultDict(dict);
317 _state.addDict(dict.get());
323 _state.eraseDict(
this);
337 MapWithHash::const_iterator
const it =
338 std::max_element(begin(), end(), boost::bind(std::less<int>(),
339 boost::bind(&MapWithHash::value_type::second, _1),
340 boost::bind(&MapWithHash::value_type::second, _2)
344 int id = it->second + 1;
346 for (
int i = 0; i <
id; ++i) {
347 MapWithHash::const_iterator
const it =
348 std::find_if(begin(), end(), boost::bind(std::equal_to<int>(),
349 boost::bind(&MapWithHash::value_type::second, _1), i));
361 MapWithHash::const_iterator i = find(name);
363 return (i == end()) ? -1 : i->second;
378 dict->add(
"BAD", ++i);
379 dict->add(
"SAT", ++i);
380 dict->add(
"INTRP", ++i);
381 dict->add(
"CR", ++i);
382 dict->add(
"EDGE", ++i);
383 dict->add(
"DETECTED", ++i);
384 dict->add(
"DETECTED_NEGATIVE", ++i);
385 dict->add(
"SUSPECT", ++i);
386 dict->add(
"NO_DATA", ++i);
393 template<
typename MaskPixelT>
403 template<
typename MaskPixelT>
417 template<
typename MaskPixelT>
421 MaskPixelT initialValue,
426 *
this = initialValue;
432 template<
typename MaskPixelT>
445 template<
typename MaskPixelT>
448 MaskPixelT initialValue,
453 *
this = initialValue;
459 template<
typename MaskPixelT>
472 template<
typename MaskPixelT>
475 MaskPixelT initialValue,
480 *
this = initialValue;
486 template<
typename MaskPixelT>
493 ImageBase<MaskPixelT>(rhs, bbox, origin, deep), _maskDict(rhs._maskDict) {
499 template<
typename MaskPixelT>
504 ImageBase<MaskPixelT>(rhs, deep), _maskDict(rhs._maskDict) {
507 template<
typename MaskPixelT>
511 _maskDict(detail::MaskDict::makeMaskDict()) {
516 template<
typename PixelT>
524 template<
typename PixelT>
529 template<
typename MaskPixelT>
537 template<
typename MaskPixelT>
539 fill_pixels(_getRawView(), rhs);
544 #ifndef DOXYGEN // doc for this section is already in header
546 template<
typename MaskPixelT>
548 std::string
const & fileName,
554 ) :
ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict()) {
556 fitsfile.setHdu(hdu);
557 *
this =
Mask(fitsfile, metadata, bbox, origin, conformMasks);
560 template<
typename MaskPixelT>
568 ) : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict()) {
571 fitsfile.setHdu(hdu);
572 *
this =
Mask(fitsfile, metadata, bbox, origin, conformMasks);
575 template<
typename MaskPixelT>
577 fits::Fits & fitsfile,
581 bool const conformMasks
583 ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::makeMaskDict())
586 typedef boost::mpl::vector<
596 fits_read_image<fits_mask_types>(fitsfile, *
this, *metadata, bbox, origin);
600 PTR(detail::MaskDict) fileMD = detail::MaskDict::makeMaskDict(fileMaskDict);
602 if (*fileMD == *detail::MaskDict::makeMaskDict()) {
614 template<
typename MaskPixelT>
616 std::string
const & fileName,
618 std::string
const & mode
621 writeFits(fitsfile, metadata_i);
624 template<
typename MaskPixelT>
626 fits::MemFileManager & manager,
628 std::string
const & mode
631 writeFits(fitsfile, metadata_i);
634 template<
typename MaskPixelT>
636 fits::Fits & fitsfile,
646 addMaskPlanesToMetadata(metadata);
653 metadata->combine(wcsAMetadata);
661 struct addPlaneFunctor {
662 addPlaneFunctor(std::string
const& name,
int id) :
_name(name),
_id(id) {}
664 void operator()(MapWithHash *dict) {
665 detail::MaskPlaneDict::const_iterator
const it =
666 std::find_if(dict->begin(), dict->end(),
667 boost::bind(std::equal_to<int>(),
668 boost::bind(&detail::MaskPlaneDict::value_type::second, _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");
1067 namespace bl = boost::lambda;
1072 template<
typename MaskPixelT>
1074 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 | val));
1080 template<
typename MaskPixelT>
1082 checkMaskDictionaries(rhs);
1086 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1089 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 | bl::_2));
1095 template<
typename MaskPixelT>
1097 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 & val));
1103 template<
typename MaskPixelT>
1105 checkMaskDictionaries(rhs);
1109 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1112 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 & bl::_2));
1118 template<
typename MaskPixelT>
1120 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 ^ val));
1126 template<
typename MaskPixelT>
1128 checkMaskDictionaries(rhs);
1132 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1135 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 ^ bl::_2));
1141 template<
typename MaskPixelT>
1143 int const x0,
int const x1,
int const y) {
1144 MaskPixelT
const bitMask = getBitMask(planeId);
1146 for (
int x = x0;
x <= x1;
x++) {
1147 operator()(
x, y) = operator()(
x, y) | bitMask;
1154 template<
typename MaskPixelT>
1157 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"Null PTR(PropertySet)");
1161 typedef std::vector<std::string> NameList;
1162 NameList paramNames = metadata->
paramNames(
false);
1163 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1164 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1169 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
1172 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end() ; ++i) {
1173 std::string
const& planeName = i->first;
1174 int const planeNumber = i->second;
1176 if (planeName !=
"") {
1177 metadata->
add(maskPlanePrefix + planeName, planeNumber);
1187 template<
typename MaskPixelT>
1194 typedef std::vector<std::string> NameList;
1195 NameList paramNames = metadata->
paramNames(
false);
1196 int numPlanesUsed = 0;
1199 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1200 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1202 std::string planeName = i->substr(maskPlanePrefix.size());
1203 int const planeId = metadata->
getAsInt(*i);
1205 MaskPlaneDict::const_iterator plane = newDict.find(planeName);
1206 if (plane != newDict.end() && planeId != plane->second) {
1208 "File specifies plane " + planeName +
" twice");
1210 for (MaskPlaneDict::const_iterator j = newDict.begin(); j != newDict.end(); ++j) {
1211 if (planeId == j->second) {
1213 str(
boost::format(
"File specifies plane %s has same value (%d) as %s") %
1214 planeName % planeId % j->first));
1218 if (numPlanesUsed >= getNumPlanesMax()) {
1221 str(
boost::format(
"Max number of planes (%1%) already used") %
1222 getNumPlanesMax()));
1224 newDict[planeName] = planeId;
1233 template<
typename MaskPixelT>
1242 template<
typename MaskPixelT>
1245 template<
typename MaskPixelT>
std::vector< std::string > paramNames(bool topLevelOnly=true) const
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.
table::Key< std::string > name
static MaskPixelT getBitMaskNoThrow(int plane)
Return the bitmask corresponding to a plane ID, or 0 if invalid.
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
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.
virtual void remove(std::string const &name)
std::string const & _name
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)
definition of the Trace messaging facilities
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
boost::shared_ptr< MaskDict > clone() const
detail::MaskPlaneDict _dict
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
limited backward compatibility to the DC2 run-time trace facilities
static int getNumPlanesUsed()
Reset the maskPlane dictionary.
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
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
static boost::shared_ptr< MaskDict > incrDefaultVersion()
Mask(unsigned int width, unsigned int height, MaskPlaneDict const &planeDefs=MaskPlaneDict())
Construct a Mask initialized to 0x0.
int getAsInt(std::string const &name) const
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) ... (x1, y)
static MaskPlaneDict parseMaskPlaneMetadata(boost::shared_ptr< lsst::daf::base::PropertySet const >)
Given a PropertySet that contains the MaskPlane assignments, setup the MaskPlanes.
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.
boost::shared_ptr< lsst::daf::base::PropertyList > createTrivialWcsAsPropertySet(std::string const &wcsName, int const x0=0, int const y0=0)
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,...)
A multidimensional strided array.
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
Class for storing generic metadata.
virtual Ptr deepCopy(void) const
static boost::shared_ptr< MaskDict > makeMaskDict()
boost::shared_ptr< detail::MaskDict > _defaultMaskDict
afw::table::Key< double > b
table::PointKey< int > pixel
void conformMaskPlanes(const MaskPlaneDict &masterPlaneDict)
Adjust this mask to conform to the standard Mask class's mask plane dictionary, adding any new mask p...
void add(std::string const &name, T const &value)
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