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
implement PhotoCalib tickets/DM-9192 #195
Conversation
67018d3
to
ddd6a95
Compare
59d1b70
to
4f8fbb8
Compare
include/lsst/afw/image/PhotoCalib.h
Outdated
* | ||
* @return The flux in maggies and error (sigma). | ||
*/ | ||
std::pair<double, double> countsToMaggies(double counts, double countsSigma, |
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.
Is there a "value with error" class? Pair is really not the best API for this.
I won't ask if you really need eight overloads...
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.
Pair is basically a python tuple containing two things, right? Other suggestions are welcome.
I'd be happy to flatten the overloads, if someone has a suggestion of how. About half of these are already used somewhere in the stack, the others (e.g. SourceRecord
or SourceCatalog
) are ones we know we want to use.
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.
Pair is a bit generic, and it can be hard to remember what the first and second elements are after it's been passed around some. But the appropriateness/inappropriateness of tuples as return types is a controversial subject, so I won't belabor the point.
I'll have to think about the overloads; part of the problem is that apart from Point
vs. average I don't see much of a pattern to them.
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.
Maybe when I've got some more of the unittest written the use cases will be clearer?
70b9062
to
862e6bb
Compare
src/image/PhotoCalib.cc
Outdated
return instance; | ||
} | ||
|
||
PersistenceHelper(int tableVersion=PHOTOCALIB_TABLE_CURRENT_VERSION) : |
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.
I realise the tableVersion
is just here to provide for future evolution, but I'm unclear how it's supposed to work, in particular in relation to the get()
above with its static instance
.
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.
(Per my comment on JIRA) could this be private?
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.
Table version has been removed after discussion with @TallJimbo who said that we typically only do that when it becomes necessary. That may not be optimal, but then I can also wait and see if we implement a more persistence versioning generic system in the future.
src/image/PhotoCalib.cc
Outdated
field = schema.addField<int>("field", "archive ID of the BoundedField object"); | ||
} | ||
|
||
PersistenceHelper(table::Schema const & s) : |
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.
Is this necessary? Could you just use PersistenceHelper::get()
? Is the idea to support future evolution? If so, could you use get()
in conjunction with a tableVersion
derived from the table you're reading?
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.
I mostly stole all of this code from @r-owen 's VisitInfo implementation. I don't know what best practices for persistence are, at all. Do we have any guide on the topic?
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.
The most useful document I found was https://github.com/lsst/afw/blob/master/doc/tablePersistence.dox, which (for reasons I've not had chance to investigate) doesn't actually seem to be being published by Doxygen. It's by no means a complete reference though.
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.
@jdswinbank it's published at https://lsst-web.ncsa.illinois.edu/doxygen/x_masterDoxyDoc/afw_table_persistence.html. Maybe a cross-reference needs to be added from the persistence classes?
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.
DM-10265.
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.
I switched to using the get()
, removed the schema-based constructor, and made the empty constructor private.
src/math/ChebyshevBoundedField.cc
Outdated
@@ -381,7 +381,7 @@ class ChebyshevBoundedFieldFactory : public table::io::PersistableFactory { | |||
LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); | |||
table::BaseRecord const & record = catalogs.front().front(); | |||
PersistenceHelper const keys(record.getSchema()); | |||
geom::Box2I bbox(record.get(keys.bboxMin), record.get(keys.bboxMax)); | |||
geom::Box2I bbox(record.get(keys.bboxMin), record.get(keys.bboxMax), false); |
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.
This is (I assume) what the commit message refers to as
Fix to ChebyshevBF when persisting empty BBox, with test
I think it'd be nice to add a note explaining what the issue was (to the code and/or the commit message), and citing RFC-324.
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.
(Nice catch, by the way)
src/math/ChebyshevBoundedField.cc
Outdated
auto& rhsCasted = dynamic_cast<ChebyshevBoundedField const&>(rhs); | ||
bool coefficientsEqual = _coefficients.getShape() == rhsCasted._coefficients.getShape() && | ||
all(equal(_coefficients, rhsCasted._coefficients)); | ||
return getBBox() == rhsCasted.getBBox() && coefficientsEqual; |
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.
Personally, I'd find that easier to read with some parentheses. I realise that the coding standards might advocate for omitting them, but here I think it's worth the extra visual noise. Your call.
@@ -62,6 +62,7 @@ | |||
class ChebyshevBoundedFieldTestCase(lsst.utils.tests.TestCase): | |||
|
|||
def setUp(self): | |||
self.longMessage = True |
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.
I hadn't come across this before. Nice.
src/image/PhotoCalib.cc
Outdated
countsMag0 = schema.addField<double>("countsMag0", "counts of a zero-magnitude object", "count"); | ||
countsMag0Sigma = schema.addField<double>("countsMag0Sigma", "1-sigma error on countsmag0", "count"); | ||
isConstant = schema.addField<table::Flag>("isConstant", "Is this spatially-constant?"); | ||
field = schema.addField<int>("field", "archive ID of the BoundedField object"); |
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.
Put these in the member initializer list?
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.
Again per JIRA, you need to mark the schema as persistent.
src/image/PhotoCalib.cc
Outdated
(*iter)[1] = toMaggiesSigma(counts, countsSigma, countsMag0, _countsMag0Sigma, maggies); | ||
iter++; | ||
} | ||
if (negatives > 0 && throwOnNegativeFlux) { |
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.
Hmm.
If you are returning a new array (ie, result
was created by the immediate caller rather than being passed into it), and throwOnNegativeFlux
is true, then after you've thrown nothing is going to get returned. You might as well save time by bailing after the first negative.
If you are not returning a new array, you're going to fill the complete array (with NaNs where you had negative counts), and then throw. The owner of the array will get back the data, but also have to deal with the exception. That's... not unreasonable, but probably deserves documenting.
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.
Per our discussion, I've completely removed the throwOnNegative
functionality, thus mooting this question.
src/image/PhotoCalib.cc
Outdated
(*iter)[1] = toMagnitudeSigma(counts, countsSigma, countsMag0, _countsMag0Sigma, maggies); | ||
iter++; | ||
} | ||
if (negatives > 0 && throwOnNegativeFlux) { |
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.
Same comment as above, obviously.
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.
throw functionality removed, so moot.
python/lsst/afw/image/photoCalib.cc
Outdated
"sourceCatalog"_a, "countsField"_a, "result"_a, "throwOnNegativeCounts"_a=false); | ||
|
||
cls.def("countsToMaggies", | ||
(void (PhotoCalib::*)(afw::table::SourceCatalog &, std::string const &, std::string const &, bool) const) |
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.
Line length.
include/lsst/afw/image/PhotoCalib.h
Outdated
* | ||
* A PhotoCalib is a BoundedField (a function with a specified domain) that converts between calibrated | ||
* counts-on-chip (ADU) to flux and magnitude. It is defined in terms of "maggies", which are a linear | ||
* unit defined in SDSS: http://www.sdss.org/dr12/algorithms/magnitudes/#nmgy |
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.
maggies or nanomaggies?
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.
I've defined PhotoCalib in terms of Maggies. I've clarified the docstring here to note that the SDSS link gives the definition in terms of nanomaggies.
I've renamed things to use "err" and also renamed |
d8e25cf
to
f13db1e
Compare
src/math/ChebyshevBoundedField.cc
Outdated
return false; | ||
} | ||
auto rhsCasted = dynamic_cast<ChebyshevBoundedField const *>(&rhs); | ||
if (!rhsCasted) return false; |
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.
Is the "efficiency" just sidestepping the exception handler, or is there something more subtle going on?
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.
It's just avoiding (possible) overhead from catch/throw. I'm not sure if the compiler should be able to optimize any of that away in this case, but I'm pretty sure some major ones wouldn't, at least as of a couple of years ago.
5bf5ebf
to
daed811
Compare
Add BoundedField str/repr to pybind11
Fix to ChebyshevBF when persisting empty BBox, with test Add note about invert bbox on ingest
RFC-322-related code not implemented Add ticket links and make isConstant a Flag
daed811
to
4a9eb9b
Compare
No description provided.