-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DM-10155: Implement in-place SourceCatalog operators in PhotoCalib #457
Changes from all commits
b6fa80f
b17f127
0faae3a
4ce4f68
bea9032
5abe592
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ | |
#include "lsst/geom/Point.h" | ||
#include "lsst/afw/image/PhotoCalib.h" | ||
#include "lsst/afw/math/BoundedField.h" | ||
#include "lsst/afw/table/Source.h" | ||
#include "lsst/afw/table.h" | ||
#include "lsst/afw/table/io/CatalogVector.h" | ||
#include "lsst/afw/table/io/OutputArchive.h" | ||
#include "lsst/daf/base/PropertySet.h" | ||
|
@@ -293,6 +293,86 @@ MaskedImage<float> PhotoCalib::calibrateImage(MaskedImage<float> const &maskedIm | |
return result; | ||
} | ||
|
||
afw::table::SourceCatalog PhotoCalib::calibrateCatalog(afw::table::SourceCatalog const &catalog, | ||
std::vector<std::string> const &instFluxFields) const { | ||
auto const &inSchema = catalog.getSchema(); | ||
afw::table::SchemaMapper mapper(inSchema, true); // true: share the alias map | ||
mapper.addMinimalSchema(inSchema); | ||
|
||
using FieldD = afw::table::Field<double>; | ||
|
||
struct Keys { | ||
table::Key<double> instFlux; | ||
table::Key<double> instFluxErr; | ||
table::Key<double> flux; | ||
table::Key<double> fluxErr; | ||
table::Key<double> mag; | ||
table::Key<double> magErr; | ||
}; | ||
|
||
std::vector<Keys> keys; | ||
keys.reserve(instFluxFields.size()); | ||
for (auto const &field : instFluxFields) { | ||
Keys newKey; | ||
newKey.instFlux = inSchema[inSchema.join(field, "instFlux")]; | ||
newKey.flux = | ||
mapper.addOutputField(FieldD(inSchema.join(field, "flux"), "calibrated flux", "nJy"), true); | ||
newKey.mag = mapper.addOutputField( | ||
FieldD(inSchema.join(field, "mag"), "calibrated magnitude", "mag(AB)"), true); | ||
try { | ||
newKey.instFluxErr = inSchema.find<double>(inSchema.join(field, "instFluxErr")).key; | ||
newKey.fluxErr = mapper.addOutputField( | ||
FieldD(inSchema.join(field, "fluxErr"), "calibrated flux uncertainty", "nJy"), true); | ||
newKey.magErr = mapper.addOutputField( | ||
FieldD(inSchema.join(field, "magErr"), "calibrated magnitude uncertainty", "mag(AB)"), | ||
true); | ||
} catch (pex::exceptions::NotFoundError &) { | ||
; // Keys struct defaults to invalid keys; that marks the error as missing. | ||
} | ||
keys.emplace_back(newKey); | ||
} | ||
|
||
// Create the new catalog | ||
afw::table::SourceCatalog output(mapper.getOutputSchema()); | ||
output.insert(mapper, output.begin(), catalog.begin(), catalog.end()); | ||
|
||
auto calibration = evaluateCatalog(output); | ||
|
||
// fill in the catalog values | ||
int iRec = 0; | ||
for (auto &rec : output) { | ||
for (auto &key : keys) { | ||
double instFlux = rec.get(key.instFlux); | ||
double nanojansky = toNanojansky(instFlux, calibration[iRec]); | ||
rec.set(key.flux, nanojansky); | ||
rec.set(key.mag, toMagnitude(instFlux, calibration[iRec])); | ||
if (key.instFluxErr.isValid()) { | ||
double instFluxErr = rec.get(key.instFluxErr); | ||
rec.set(key.fluxErr, toNanojanskyErr(instFlux, instFluxErr, calibration[iRec], | ||
_calibrationErr, nanojansky)); | ||
rec.set(key.magErr, | ||
toMagnitudeErr(instFlux, instFluxErr, calibration[iRec], _calibrationErr)); | ||
} | ||
} | ||
++iRec; | ||
} | ||
|
||
return output; | ||
} | ||
|
||
afw::table::SourceCatalog PhotoCalib::calibrateCatalog(afw::table::SourceCatalog const &catalog) const { | ||
std::vector<std::string> instFluxFields; | ||
static std::string const SUFFIX = "_instFlux"; | ||
for (auto const &name : catalog.getSchema().getNames()) { | ||
// Pick every field ending in "_instFlux", grabbing everything before that prefix. | ||
if (name.size() > SUFFIX.size() + 1 && | ||
name.compare(name.size() - SUFFIX.size(), SUFFIX.size(), SUFFIX) == 0) { | ||
instFluxFields.emplace_back(name.substr(0, name.size() - 9)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could do something like
above the for loop, and then refer to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'd use |
||
} | ||
} | ||
return calibrateCatalog(catalog, instFluxFields); | ||
} | ||
|
||
// ------------------- persistence ------------------- | ||
|
||
namespace { | ||
|
@@ -465,38 +545,66 @@ double PhotoCalib::evaluate(lsst::geom::Point<double, 2> const &point) const { | |
return _calibration->evaluate(point); | ||
} | ||
|
||
ndarray::Array<double, 1> PhotoCalib::evaluateArray(ndarray::Array<double, 1> const &xx, | ||
ndarray::Array<double, 1> const &yy) const { | ||
if (_isConstant) { | ||
ndarray::Array<double, 1> result = ndarray::allocate(ndarray::makeVector(xx.size())); | ||
result.deep() = _calibrationMean; | ||
return result; | ||
} else { | ||
return _calibration->evaluate(xx, yy); | ||
} | ||
} | ||
|
||
ndarray::Array<double, 1> PhotoCalib::evaluateCatalog(afw::table::SourceCatalog const &sourceCatalog) const { | ||
ndarray::Array<double, 1> xx = ndarray::allocate(ndarray::makeVector(sourceCatalog.size())); | ||
ndarray::Array<double, 1> yy = ndarray::allocate(ndarray::makeVector(sourceCatalog.size())); | ||
size_t i = 0; | ||
for (auto const &rec : sourceCatalog) { | ||
auto point = rec.getCentroid(); | ||
xx[i] = point.getX(); | ||
yy[i] = point.getY(); | ||
++i; | ||
} | ||
return evaluateArray(xx, yy); | ||
} | ||
|
||
void PhotoCalib::instFluxToNanojanskyArray(afw::table::SourceCatalog const &sourceCatalog, | ||
std::string const &instFluxField, | ||
ndarray::Array<double, 2, 2> result) const { | ||
double instFlux, instFluxErr, nanojansky, calibration; | ||
auto instFluxKey = sourceCatalog.getSchema().find<double>(instFluxField + "_instFlux").key; | ||
auto instFluxErrKey = sourceCatalog.getSchema().find<double>(instFluxField + "_instFluxErr").key; | ||
|
||
auto calibration = evaluateCatalog(sourceCatalog); | ||
int i = 0; | ||
auto iter = result.begin(); | ||
for (auto const &rec : sourceCatalog) { | ||
instFlux = rec.get(instFluxKey); | ||
instFluxErr = rec.get(instFluxErrKey); | ||
calibration = evaluate(rec.getCentroid()); | ||
nanojansky = toNanojansky(instFlux, calibration); | ||
double instFlux = rec.get(instFluxKey); | ||
double instFluxErr = rec.get(instFluxErrKey); | ||
double nanojansky = toNanojansky(instFlux, calibration[i]); | ||
(*iter)[0] = nanojansky; | ||
(*iter)[1] = toNanojanskyErr(instFlux, instFluxErr, calibration, _calibrationErr, nanojansky); | ||
iter++; | ||
(*iter)[1] = toNanojanskyErr(instFlux, instFluxErr, calibration[i], _calibrationErr, nanojansky); | ||
++iter; | ||
++i; | ||
} | ||
} | ||
|
||
void PhotoCalib::instFluxToMagnitudeArray(afw::table::SourceCatalog const &sourceCatalog, | ||
std::string const &instFluxField, | ||
ndarray::Array<double, 2, 2> result) const { | ||
double instFlux, instFluxErr, calibration; | ||
auto instFluxKey = sourceCatalog.getSchema().find<double>(instFluxField + "_instFlux").key; | ||
auto instFluxErrKey = sourceCatalog.getSchema().find<double>(instFluxField + "_instFluxErr").key; | ||
|
||
auto calibration = evaluateCatalog(sourceCatalog); | ||
auto iter = result.begin(); | ||
int i = 0; | ||
for (auto const &rec : sourceCatalog) { | ||
instFlux = rec.get(instFluxKey); | ||
instFluxErr = rec.get(instFluxErrKey); | ||
calibration = evaluate(rec.getCentroid()); | ||
(*iter)[0] = toMagnitude(instFlux, calibration); | ||
(*iter)[1] = toMagnitudeErr(instFlux, instFluxErr, calibration, _calibrationErr); | ||
iter++; | ||
double instFlux = rec.get(instFluxKey); | ||
double instFluxErr = rec.get(instFluxErrKey); | ||
(*iter)[0] = toMagnitude(instFlux, calibration[i]); | ||
(*iter)[1] = toMagnitudeErr(instFlux, instFluxErr, calibration[i], _calibrationErr); | ||
++iter; | ||
++i; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add blank lines between methods.