33 #include <boost/algorithm/string/case_conv.hpp>
38 #define SAVE_SLOT(NAME, Name) \
39 if (table->get ## Name ## Key().isValid()) { \
40 std::string s = table->getSchema().find(table->get ## Name ## Key()).field.getName(); \
41 std::replace(s.begin(), s.end(), '.', '_'); \
42 _fits->writeKey(#NAME "_SLOT", s.c_str(), "Defines the " #Name " slot"); \
45 #define SAVE_FILTER_SLOT(FILTER, filter, NAME, Name) \
46 if (table->get ## Name ## Key(filter).isValid()) { \
47 std::string s = table->getSchema().find(table->get ## Name ## Key(filter)).field.getName(); \
48 std::replace(s.begin(), s.end(), '.', '_'); \
49 _fits->writeKey(FILTER + "_" #NAME "_SLOT", s.c_str(), \
50 "Defines the " #Name " slot in the " + filter + " filter"); \
53 #define SAVE_COMPOUND_SLOT(FILTER, filter, NAME, Name) \
54 SAVE_FILTER_SLOT(FILTER, filter, NAME, Name) \
55 SAVE_FILTER_SLOT(FILTER, filter, NAME ## _ERR, Name ## Err) \
56 SAVE_FILTER_SLOT(FILTER, filter, NAME ## _COUNT, Name ## Count)
58 #define LOAD_SLOT(NAME, Name) \
60 _fits->behavior &= ~lsst::afw::fits::Fits::AUTO_CHECK; \
62 _fits->readKey(#NAME "_SLOT", s); \
63 if (_fits->status == 0) { \
64 metadata->remove(#NAME "_SLOT"); \
65 std::replace(s.begin(), s.end(), '_', '.'); \
66 table->define ## Name (schema[s]); \
70 _fits->behavior |= lsst::afw::fits::Fits::AUTO_CHECK; \
73 #define LOAD_FILTER_SLOT(FILTER, filter, NAME, Name) \
75 _fits->behavior &= ~lsst::afw::fits::Fits::AUTO_CHECK; \
77 _fits->readKey(FILTER + "_" #NAME "_SLOT", s); \
78 if (_fits->status == 0) { \
79 metadata->remove(FILTER + "_" #NAME "_SLOT"); \
80 std::replace(s.begin(), s.end(), '_', '.'); \
81 table->define ## Name (filter, schema[s]); \
85 _fits->behavior |= lsst::afw::fits::Fits::AUTO_CHECK; \
88 #define LOAD_COMPOUND_SLOT(FILTER, filter, NAME, Name) \
90 _fits->behavior &= ~lsst::afw::fits::Fits::AUTO_CHECK; \
91 std::string s, sErr, sCount; \
92 _fits->readKey(FILTER + "_" #NAME "_SLOT", s); \
93 _fits->readKey(FILTER + "_" #NAME "_ERR_SLOT", sErr); \
94 _fits->readKey(FILTER + "_" #NAME "_COUNT_SLOT", sCount); \
95 if (_fits->status == 0) { \
96 metadata->remove(FILTER + "_" #NAME "_SLOT"); \
97 metadata->remove(FILTER + "_" #NAME "_ERR_SLOT"); \
98 metadata->remove(FILTER + "_" #NAME "_COUNT_SLOT"); \
99 std::replace(s.begin(), s.end(), '_', '.'); \
100 std::replace(sErr.begin(), sErr.end(), '_', '.'); \
101 std::replace(sCount.begin(), sCount.end(), '_', '.'); \
102 table->define ## Name (filter, schema[s], schema[sErr], schema[sCount]); \
106 _fits->behavior |= lsst::afw::fits::Fits::AUTO_CHECK; \
110 namespace except = lsst::pex::exceptions;
118 namespace lsst {
namespace ap {
namespace cluster {
128 class SourceClusterTableImpl;
130 class SourceClusterRecordImpl :
public SourceClusterRecord {
132 explicit SourceClusterRecordImpl(
PTR(SourceClusterTable)
const & table) :
133 SourceClusterRecord(table) { }
136 class SourceClusterTableImpl :
public SourceClusterTable {
138 explicit SourceClusterTableImpl(
141 ) : SourceClusterTable(schema, idFactory) { }
143 SourceClusterTableImpl(SourceClusterTableImpl
const & other) :
144 SourceClusterTable(other) { }
148 return boost::make_shared<SourceClusterTableImpl>(*this);
152 PTR(SourceClusterRecord) record =
153 boost::make_shared<SourceClusterRecordImpl>(
154 getSelf<SourceClusterTableImpl>());
155 if (getIdFactory()) {
156 record->setId((*getIdFactory())());
172 class SourceClusterFitsWriter :
public FitsWriter {
180 void SourceClusterFitsWriter::_writeTable(
CONST_PTR(
BaseTable)
const & t,
size_t nRows) {
182 boost::dynamic_pointer_cast<SourceClusterTable
const>(t);
184 throw LSST_EXCEPT(except::LogicError,
"SourceClusterFitsWriter "
185 "can only write out SourceClusterTable instances!");
189 if (metadata && metadata->exists(
"FILTERS")) {
190 metadata->remove(
"FILTERS");
192 FitsWriter::_writeTable(table, nRows);
193 metadata = boost::make_shared<PropertyList>();
194 std::vector<std::string>
const filters = table->getFilters();
195 if (!filters.empty()) {
196 metadata->set<std::string>(
"FILTERS", filters);
197 _fits->writeMetadata(*metadata);
199 _fits->writeKey(
"AFW_TYPE",
"SOURCE_CLUSTER",
200 "Tells lsst::afw to load this as a SourceClusterTable.");
204 SAVE_SLOT(WMCOORD_ERR, WeightedMeanCoordErr)
205 SAVE_SLOT(WMCOORD_COUNT, WeightedMeanCoordCount)
211 typedef std::vector<std::string>::const_iterator Iter;
212 for (Iter i = filters.begin(), e = filters.end(); i != e; ++i) {
213 std::string
const f = *i;
214 std::string
const F = boost::to_upper_copy(f);
236 class SourceClusterFitsReader :
public FitsReader {
238 explicit SourceClusterFitsReader(
240 boost::shared_ptr<lsst::afw::table::io::InputArchive> archive,
249 _fits->readMetadata(*metadata,
true);
250 if (metadata->exists(
"AFW_TYPE")) {
251 metadata->remove(
"AFW_TYPE");
259 LOAD_SLOT(WMCOORD_ERR, WeightedMeanCoordErr)
260 LOAD_SLOT(WMCOORD_COUNT, WeightedMeanCoordCount)
266 std::vector<std::string> filters;
267 if (metadata->exists(
"FILTERS")) {
268 filters = metadata->getArray<std::string>(
"FILTERS");
269 metadata->remove(
"FILTERS");
271 typedef std::vector<std::string>::const_iterator Iter;
272 for (Iter i = filters.begin(), e = filters.end(); i != e; ++i) {
273 std::string
const f = *i;
274 std::string
const F = boost::to_upper_copy(f);
284 _startRecords(*table);
285 table->setMetadata(metadata);
290 static FitsReader::FactoryT<SourceClusterFitsReader> sourceClusterFitsReaderFactory(
"SOURCE_CLUSTER");
298 lsst::afw::table::SimpleRecord(table) { }
305 PTR(lsst::afw::
table::IdFactory) const & idFactory)
307 if (!checkSchema(schema)) {
309 "Schema for SourceClusterTable must contain at least the keys "
310 "defined by getMinimalSchema().");
312 return boost::make_shared<SourceClusterTableImpl>(
schema, idFactory);
318 ) : lsst::afw::
table::SimpleTable(schema, idFactory),
320 _keyWeightedMeanCoord(),
321 _keyWeightedMeanCoordErr(),
322 _keyWeightedMeanCoordCount(),
331 lsst::afw::
table::SimpleTable(other),
332 _keyCoordErr(other._keyCoordErr),
333 _keyWeightedMeanCoord(other._keyWeightedMeanCoord),
334 _keyWeightedMeanCoordErr(other._keyWeightedMeanCoordErr),
335 _keyWeightedMeanCoordCount(other._keyWeightedMeanCoordCount),
336 _keyNumSources(other._keyNumSources),
337 _keyTimeMin(other._keyTimeMin),
338 _keyTimeMean(other._keyTimeMean),
339 _keyTimeMax(other._keyTimeMax),
340 _filterSlots(other._filterSlots)
346 typedef FilterSlotsMap::const_iterator Iter;
347 std::vector<std::string> filters;
349 filters.push_back(i->first);
351 std::sort(filters.begin(), filters.end());
358 return boost::make_shared<SourceClusterFitsWriter>(fits, flags);
362 FilterSlotsMap::const_iterator i =
_filterSlots.find(filter);
364 throw LSST_EXCEPT(except::NotFoundError,
"SourceClusterTable "
365 "contains no slot mappings for the filter named " + filter);
388 _skyTileId(skyTileId)
395 if (static_cast<int>(
id >> 32) !=
_skyTileId) {
397 "Source cluster ID space exhausted! Note that SourceClusterIdFactory "
398 "can hand out a maximum of 2^32 - 1 IDs for a given sky-tile. If there "
399 "are more than that many clusters, the sky-tile size must be reduced.");
407 "SourceClusterIdFactory does not support the notify() method "
408 "of lsst::afw::table::IdFactory");
416 std::string
const & filter,
417 std::string
const & name,
418 std::string
const & doc)
423 filter +
"." + name, doc,
"rad^2");
425 filter +
"." + name +
".err",
426 "covariance matrix for " + filter +
"." + name,
429 filter +
"." + name +
".count",
430 "Number of samples used to compute the " + filter +
431 "." + name +
" mean");
437 std::string
const & filter,
438 std::string
const & name,
439 std::string
const & doc,
440 std::string
const & unit)
445 filter +
"." + name, doc, unit);
447 filter +
"." + name +
".err",
448 "uncertainty for " + filter +
"." + name,
451 filter +
"." + name +
".count",
452 "Number of samples used to compute the " + filter +
453 "." + name +
" mean");
Defines the fields and offsets for a table.
Writer subclass for FITS binary tables.
A Reader subclass for FITS binary tables.
virtual lsst::afw::table::RecordId operator()()
Return a new unique RecordId.
virtual ~SourceClusterIdFactory()
A custom container class for records, based on std::vector.
Class for storing ordered metadata with comments.
std::vector< SourceCatalog > const cluster(SourceCatalog const &sources, ClusteringControl const &control)
FilterSlotsMap _filterSlots
lsst::daf::base::PropertyList PropertyList
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
#define SAVE_FILTER_SLOT(FILTER, filter, NAME, Name)
MeasurementT::MeasKey mean
Key used for the mean measured value.
Table class that contains measurement means on clusters of single exposure sources.
afw::geom::ellipses::Quadrupole Shape
Table and record classes for source cluster attributes.
virtual void notify(lsst::afw::table::RecordId id)
Notify the IdFactory that the given ID has been used and must not be returned by operator().
FilterSlots const & getFilterSlots(std::string const &filter) const
lsst::afw::table::RecordId _id
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
#define SAVE_COMPOUND_SLOT(FILTER, filter, NAME, Name)
SourceClusterTable(lsst::afw::table::Schema const &schema, boost::shared_ptr< lsst::afw::table::IdFactory > const &idFactory)
#define SAVE_SLOT(NAME, Name)
static boost::shared_ptr< SourceClusterTable > make(lsst::afw::table::Schema const &schema, boost::shared_ptr< lsst::afw::table::IdFactory > const &idFactory)
Construct a new table.
#define LOAD_SLOT(NAME, Name)
A polymorphic functor base class for generating record IDs for a table.
#define LSST_EXCEPT(type,...)
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
Base class for all records.
std::vector< std::string > const getFilters() const
Get the lexicographically sorted list of filter names for which slots have been defined.
lsst::afw::table::Key< int > count
Key used for the sample count.
MeasurementT::ErrKey err
Key used for the uncertainty.
#define LOAD_FILTER_SLOT(FILTER, filter, NAME, Name)
SourceClusterRecord(boost::shared_ptr< SourceClusterTable > const &table)
boost::int64_t RecordId
Type used for unique IDs for records.
std::map< Citizen const *, CitizenInfo > table
SourceClusterIdFactory(int skyTileId)
#define LOAD_COMPOUND_SLOT(FILTER, filter, NAME, Name)
Base class for all tables.
KeyTuple< lsst::afw::table::Shape > addShapeFields(lsst::afw::table::Schema &schema, std::string const &filter, std::string const &name, std::string const &doc)
Convenience function to setup fields for shapes.
KeyTuple< lsst::afw::table::Flux > addFluxFields(lsst::afw::table::Schema &schema, std::string const &filter, std::string const &name, std::string const &doc, std::string const &unit)
Convenience function to setup fields for fluxes.