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);
392 template<
typename MaskPixelT>
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 boost::bind(std::equal_to<int>(),
667 boost::bind(&detail::MaskPlaneDict::value_type::second, _1),
_id));
668 if (it != dict->end()) {
672 if (dict->find(
_name) == dict->end()) {
682 template<
typename MaskPixelT>
685 std::string result =
"";
686 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
687 for (MaskPlaneDict::const_iterator
iter = mpd.begin();
iter != mpd.end(); ++
iter) {
688 if (value & getBitMask(
iter->second)) {
689 if (result.size() > 0) {
692 result +=
iter->first;
698 template<
typename MaskPixelT>
701 int id = getMaskPlaneNoThrow(name);
704 id = _maskPlaneDict()->getUnusedPlane();
709 if (
id >= getNumPlanesMax()) {
711 str(
boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
714 _state.forEachMaskDict(addPlaneFunctor(name,
id));
724 template<
typename MaskPixelT>
729 if (planeId < 0 || planeId >= getNumPlanesMax()) {
731 str(
boost::format(
"mask plane ID must be between 0 and %1%") % (getNumPlanesMax() - 1)));
734 _maskPlaneDict()->add(name, planeId);
742 template<
typename MaskPixelT>
746 return _maskDict->getMaskPlaneDict();
749 template<
typename MaskPixelT>
753 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
754 str(
boost::format(
"Plane %s doesn't exist in the default Mask") % name));
758 _maskPlaneDict()->erase(name);
767 template<
typename MaskPixelT>
769 bool const removeFromDefault
773 clearMaskPlane(getMaskPlane(name));
778 _maskDict = _maskDict->clone();
781 _maskDict->erase(name);
784 removeMaskPlane(name);
791 template<
typename MaskPixelT>
793 return (planeId >= 0 && planeId < getNumPlanesMax()) ? (1 << planeId) : 0;
801 template<
typename MaskPixelT>
803 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
805 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end(); ++i) {
806 if (planeId == i->second) {
807 MaskPixelT
const bitmask = getBitMaskNoThrow(planeId);
814 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
823 template<
typename MaskPixelT>
825 int const plane = getMaskPlaneNoThrow(name);
828 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
838 template<
typename MaskPixelT>
840 return _maskPlaneDict()->getMaskPlane(name);
848 template<
typename MaskPixelT>
850 return getBitMask(getMaskPlane(name));
858 template<
typename MaskPixelT>
860 MaskPixelT mpix = 0x0;
861 for (std::vector<std::string>::const_iterator it = name.begin(); it != name.end(); ++it) {
862 mpix |= getBitMask(getMaskPlane(*it));
870 template<
typename MaskPixelT>
873 return _maskPlaneDict()->size();
879 template<
typename MaskPixelT>
881 _maskPlaneDict()->clear();
887 template<
typename MaskPixelT>
895 template<
typename MaskPixelT>
897 *
this &= ~getBitMask(planeId);
911 template<
typename MaskPixelT>
918 if (*_maskDict == *currentMD) {
926 MaskPixelT keepBitmask = 0;
927 MaskPixelT canonicalMask[
sizeof(MaskPixelT)*8];
928 MaskPixelT currentMask[
sizeof(MaskPixelT)*8];
931 for (MaskPlaneDict::const_iterator i = currentPlaneDict.begin(); i != currentPlaneDict.end() ; i++) {
932 std::string
const name = i->first;
933 int const currentPlaneNumber = i->second;
934 int canonicalPlaneNumber = getMaskPlaneNoThrow(name);
936 if (canonicalPlaneNumber < 0) {
937 canonicalPlaneNumber = addMaskPlane(name);
940 if (canonicalPlaneNumber == currentPlaneNumber) {
941 keepBitmask |= getBitMask(canonicalPlaneNumber);
943 canonicalMask[numReMap] = getBitMask(canonicalPlaneNumber);
944 currentMask[numReMap] = getBitMaskNoThrow(currentPlaneNumber);
951 for (
int r = 0; r != this->getHeight(); ++r) {
952 for (
typename Mask::x_iterator ptr = this->row_begin(r), end = this->row_end(r);
954 MaskPixelT
const pixel = *ptr;
956 MaskPixelT newPixel = pixel & keepBitmask;
957 for (
int i = 0; i < numReMap; i++) {
958 if (pixel & currentMask[i]) newPixel |= canonicalMask[i];
975 template<
typename MaskPixelT>
986 template<
typename MaskPixelT>
998 template<
typename MaskPixelT>
1009 template<
typename MaskPixelT>
1021 template<
typename MaskPixelT>
1034 template<
typename MaskPixelT>
1051 template<
typename MaskPixelT>
1054 throw LSST_EXCEPT(pexExcept::RuntimeError,
"Mask dictionaries do not match");
1066 namespace bl = boost::lambda;
1071 template<
typename MaskPixelT>
1073 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 | val));
1079 template<
typename MaskPixelT>
1081 checkMaskDictionaries(rhs);
1085 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1088 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 | bl::_2));
1094 template<
typename MaskPixelT>
1096 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 & val));
1102 template<
typename MaskPixelT>
1104 checkMaskDictionaries(rhs);
1108 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1111 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 & bl::_2));
1117 template<
typename MaskPixelT>
1119 transform_pixels(_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 ^ val));
1125 template<
typename MaskPixelT>
1127 checkMaskDictionaries(rhs);
1131 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
1134 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(), bl::ret<MaskPixelT>(bl::_1 ^ bl::_2));
1140 template<
typename MaskPixelT>
1142 int const x0,
int const x1,
int const y) {
1143 MaskPixelT
const bitMask = getBitMask(planeId);
1145 for (
int x = x0;
x <= x1;
x++) {
1146 operator()(
x, y) = operator()(
x, y) | bitMask;
1153 template<
typename MaskPixelT>
1156 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"Null PTR(PropertySet)");
1160 typedef std::vector<std::string> NameList;
1161 NameList paramNames = metadata->
paramNames(
false);
1162 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1163 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1168 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
1171 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end() ; ++i) {
1172 std::string
const& planeName = i->first;
1173 int const planeNumber = i->second;
1175 if (planeName !=
"") {
1176 metadata->
add(maskPlanePrefix + planeName, planeNumber);
1186 template<
typename MaskPixelT>
1193 typedef std::vector<std::string> NameList;
1194 NameList paramNames = metadata->
paramNames(
false);
1195 int numPlanesUsed = 0;
1198 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1199 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
1201 std::string planeName = i->substr(maskPlanePrefix.size());
1202 int const planeId = metadata->
getAsInt(*i);
1204 MaskPlaneDict::const_iterator plane = newDict.find(planeName);
1205 if (plane != newDict.end() && planeId != plane->second) {
1207 "File specifies plane " + planeName +
" twice");
1209 for (MaskPlaneDict::const_iterator j = newDict.begin(); j != newDict.end(); ++j) {
1210 if (planeId == j->second) {
1212 str(
boost::format(
"File specifies plane %s has same value (%d) as %s") %
1213 planeName % planeId % j->first));
1217 if (numPlanesUsed >= getNumPlanesMax()) {
1220 str(
boost::format(
"Max number of planes (%1%) already used") %
1221 getNumPlanesMax()));
1223 newDict[planeName] = planeId;
1232 template<
typename MaskPixelT>
1241 template<
typename MaskPixelT>
1244 template<
typename MaskPixelT>
std::vector< std::string > paramNames(bool topLevelOnly=true) const
static MaskPlaneDict parseMaskPlaneMetadata(boost::shared_ptr< lsst::daf::base::PropertySet const >)
Given a PropertySet that contains the MaskPlane assignments, setup the MaskPlanes.
static void clearMaskPlaneDict()
Reset the maskPlane dictionary.
ImageBase< MaskPixelT >::PixelReference operator()(int x, int y)
get a reference to the specified pixel
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
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...
std::string const & _name
afw::table::Key< afw::table::Point< int > > dimensions
MaskPlaneDict const & getMaskPlaneDict() const
bool operator!=(lsst::afw::coord::Coord const &lhs, lsst::afw::coord::Coord const &rhs)
Inequality; the complement of equality.
std::map< std::string, int > MaskPlaneDict
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y)
definition of the Trace messaging facilities
void operator^=(Mask const &rhs)
XOR a Mask into a Mask.
detail::MaskPlaneDict _dict
static void addMaskPlanesToMetadata(boost::shared_ptr< lsst::daf::base::PropertySet >)
Given a PropertySet, replace any existing MaskPlane assignments with the current ones.
static int getMaskPlane(const std::string &name)
Return the mask plane number corresponding to a plane name.
bool operator==(CoordKey const &lhs, CoordKey const &rhs)
Compare CoordKeys for equality using the constituent Keys.
limited backward compatibility to the DC2 run-time trace facilities
static void removeMaskPlane(const std::string &name)
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, ...)
static int addMaskPlane(const std::string &name)
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)
boost::shared_ptr< detail::MaskDict > _maskDict
table::Key< table::Point< int > > pixel
An integer coordinate rectangle.
table::Key< table::Array< Kernel::Pixel > > image
static MaskPixelT getBitMask(int plane)
Return the bitmask corresponding to plane ID.
void clearAllMaskPlanes()
Clear all the pixels.
int getWidth() const
Return the number of columns in the image.
void swap(ImageBase &rhs)
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
virtual Ptr deepCopy(void) const
Represent a 2-dimensional array of bitmask pixels.
Lifetime-management for memory that goes into FITS memory files.
static std::string interpret(MaskPixelT value)
Interpret a mask value as a comma-separated list of mask plane names.
int getMaskPlane(const std::string &name) const
detail::MaskPlaneDict MaskPlaneDict
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
void add(std::string const &name, T const &value)
void _initializePlanes(MaskPlaneDict const &planeDefs)
Initialise mask planes; called by constructors.
A class used to request that array accesses be checked.
boost::shared_ptr< lsst::daf::base::PropertyList > createTrivialWcsAsPropertySet(std::string const &wcsName, int const x0=0, int const y0=0)
static void listMaskDicts()
int getUnusedPlane() const
void operator|=(Mask const &rhs)
OR a Mask into a Mask.
static int getMaskPlaneNoThrow(const std::string &name)
Return the mask plane number corresponding to a plane name, or -1 if not found.
Mask & operator=(MaskPixelT const rhs)
static boost::shared_ptr< MaskDict > setDefaultDict(boost::shared_ptr< MaskDict > dict)
static const std::string maskPlanePrefix
#define LSST_EXCEPT(type,...)
A multidimensional strided array.
void operator&=(Mask const &rhs)
AND a Mask into a Mask.
Mask(unsigned int width, unsigned int height, MaskPlaneDict const &planeDefs=MaskPlaneDict())
Construct a Mask initialized to 0x0.
void checkMaskDictionaries(Mask const &other)
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.
void clearMaskPlane(int plane)
Clear the specified bit in all pixels.
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
Class for storing generic metadata.
static MaskPixelT getBitMaskNoThrow(int plane)
Return the bitmask corresponding to a plane ID, or 0 if invalid.
int getAsInt(std::string const &name) const
boost::shared_ptr< detail::MaskDict > _defaultMaskDict
void conformMaskPlanes(const MaskPlaneDict &masterPlaneDict)
Adjust this mask to conform to the standard Mask class's mask plane dictionary, adding any new mask p...
virtual void remove(std::string const &name)
afw::table::Key< double > b
int getHeight() const
Return the number of rows in the image.
boost::shared_ptr< MaskDict > clone() const
void printMaskPlanes() const
print the mask plane dictionary to std::cout
static boost::shared_ptr< MaskDict > incrDefaultVersion()
static boost::shared_ptr< MaskDict > makeMaskDict()
Definition of default types for Masks and Variance Images.
MaskDict(MapWithHash const *dict)
geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
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 >())
Include files required for standard LSST Exception handling.
std::string const wcsNameForXY0
_view_t _getRawView() const
static int getNumPlanesUsed()
Reset the maskPlane dictionary.