Skip to content
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

Replace ModelContainer with ModelLibrary #1241

Merged
merged 61 commits into from
Jul 22, 2024

Conversation

braingram
Copy link
Collaborator

@braingram braingram commented May 17, 2024

This PR replaces ModelContainer with a ModelLibrary subclass.

Please see stpipe for the core documentation on ModelLibrary.

The main benefit is that ModelLibrary (in contrast to ModelContainer) will allow passing data between steps without holding it in memory (and instead keeping datamodels "on disk").

This will allow for future improvements to steps (especially those part of a pipeline) to allow them to run in a generically memory efficient way (the interface to an "in memory" and an "on disk" ModelLibrary are identical). Importantly this PR does not aim to make improvements to the steps (to limit the already wide scope of the changes). Follow-up PRs will be needed to address issues with some steps where they are coded in a way that keeps all models in memory (defeating the memory saving possible with ModelLibrary). To provide one example, the tweakreg step contains a call to create_astrometric_catalog which currently expects a list of models. In this PR the models are read from the library, which loads all models in memory. It is possible to change the code avoid reading in all of the models. However this would require changes to several utility functions (some in stcal) which are technically not required to add the ModelLibrary but are required to see performance benefits from using the library.

Regression tests:
https://github.com/spacetelescope/RegressionTests/actions/runs/9962595365
shows 5 minor metadata differences.

Fixes #1303

Todo:

  • address unit test differences
  • address regtest difference
  • update documentation
  • port over jwst model library tests
  • add support for __init__ from in memory association
  • add "index" API for cross-model attribute access (perhaps a map_function method)
  • finalize naming for __setitem__ __getitem__ discard
  • update minimum requirements
  • finalize stpipe changes (more may be required based on __setitem__ changes)
  • add ModelLibrary docs

Resolves RCAL-nnnn

Closes #

This PR addresses ...

Checklist

  • added entry in CHANGES.rst under the corresponding subsection
  • updated relevant tests
  • updated relevant documentation
  • updated relevant milestone(s)
  • added relevant label(s)
  • ran regression tests, post a link to the Jenkins job below. How to run regression tests on a PR

@github-actions github-actions bot added testing pipeline dependencies Pull requests that update a dependency file labels May 17, 2024
Copy link

codecov bot commented May 17, 2024

Codecov Report

Attention: Patch coverage is 87.41419% with 55 lines in your changes missing coverage. Please review.

Project coverage is 76.89%. Comparing base (7476678) to head (b5349d9).
Report is 249 commits behind head on main.

Files with missing lines Patch % Lines
romancal/tweakreg/tweakreg_step.py 79.64% 23 Missing ⚠️
romancal/resample/resample.py 92.45% 8 Missing ⚠️
romancal/pipeline/exposure_pipeline.py 14.28% 6 Missing ⚠️
romancal/resample/resample_step.py 72.72% 6 Missing ⚠️
romancal/pipeline/mosaic_pipeline.py 16.66% 5 Missing ⚠️
romancal/datamodels/library.py 93.87% 3 Missing ⚠️
romancal/flux/flux_step.py 85.71% 2 Missing ⚠️
romancal/skymatch/skymatch_step.py 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1241      +/-   ##
==========================================
- Coverage   79.28%   76.89%   -2.39%     
==========================================
  Files         117      114       -3     
  Lines        8065     7773     -292     
==========================================
- Hits         6394     5977     -417     
- Misses       1671     1796     +125     
Flag Coverage Δ
nightly ?

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@braingram braingram force-pushed the model_library branch 3 times, most recently from 391eb84 to 357a1c3 Compare May 20, 2024 18:35
@perrygreenfield

This comment was marked as resolved.

@braingram

This comment was marked as resolved.

@perrygreenfield

This comment was marked as resolved.

@braingram

This comment was marked as resolved.

@braingram

This comment was marked as outdated.

@braingram braingram force-pushed the model_library branch 2 times, most recently from 3dfd262 to c9f6274 Compare May 23, 2024 19:14
@github-actions github-actions bot added the documentation Improvements or additions to documentation label May 23, 2024
Copy link
Contributor

@emolter emolter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this "review" is just me asking clarification questions about how this works; thanks for humoring that. Not sure I have the expertise yet to add much more than that.

ddavis-stsci

This comment was marked as resolved.

@braingram

This comment was marked as resolved.

@ddavis-stsci

This comment was marked as resolved.

@ddavis-stsci
Copy link
Collaborator

ddavis-stsci commented May 31, 2024 via email

@braingram

This comment was marked as resolved.

@schlafly

This comment was marked as resolved.

@ddavis-stsci

This comment was marked as resolved.

@braingram

This comment was marked as resolved.

Copy link
Collaborator

@schlafly schlafly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lot of work here! I had a few comments. I still need to look at the main library code.

# members
# if self.input_models.filepaths is None
# else self.input_models.filepaths
# )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my fault. There was a request to store the actual file names of the L2 input files (as opposed to their meta.filenames, which may become disconnected). filepaths got populated with the file names from the association file in the model container here:

self.filepaths = [op.basename(m) for m in self._models]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for commenting on this. I don't yet fully understand how these are used or carried through the pipelines. Some discussion on expectations for this would be helpful. For example, when running the mosaic pipeline is the expectation that these will be the original input filenames? If so, I think this code in skymatch will lose the filepaths:

return ModelContainer([x.meta["image_model"] for x in images])

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlafly I believe this is now handled in resample (instead of the container):
https://github.com/spacetelescope/romancal/pull/1241/files#diff-f87241f9a890ac31d6813379a09b6eb7e1052e3ab53039449a8f0df91aa030e1R351
but it would be great if this could be confirmed (I don't see any test failures but I'm not sure if there is a test for this feature).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, sorry for losing this thread! The issue was that meta.filename can easily become disconnected from the actual file name on disk, and there was a request for storing the actual file names on disk used to create a L3 file, rather than the meta.filenames that contributed. My initial impression here
https://github.com/spacetelescope/romancal/pull/1241/files#diff-f87241f9a890ac31d6813379a09b6eb7e1052e3ab53039449a8f0df91aa030e1R351
is that this returns to the previous behavior of using meta.filename. If there's a convenient way to ask the container for the original on-disk filenames, that would be best.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Is there a test for this (so I can poke it to see what's going on with and without this PR)?

To make sure I'm understanding the goal, let's say an association is provided to the mosaic pipeline that lists members "foo.asdf" and "bar.asdf" which have meta.filename attributes that are something else "chutes.asdf" and "ladders.asdf". The goal is to have the output resampled product contain "foo.asdf" and "bar.asdf". I think that should be easy to do by using the members info from Library.asn but I'll have to run some tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlafly I switched to populating this using the asn members (which are the input filenames) in:
449a58d
I didn't see any test differences so I'm assuming there is no test for this behavior (and the mosaic pipeline input files all have meta.filenames that match the real filenames).

I modified the test data for the mos pipeline test (locally) renaming one file in the association and on disk (but leaving it's meta.filename the same) and then run the pipeline. The result from resample recorded the modified name (the real filename) and not meta.filename.

I'd be happy to open an issue to track adding a test for this or adding one to this PR (I think it should be possible to add as a resample only unit test but that would require some investigation). Which would you prefer, an issue to track adding the test or adding it to this PR?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks, that looks great. Just making sure I hadn't missed it before, that's a new feature in ModelLibrary that wasn't available to me when I wrote that bit of code before? Great. It looks like when the ModelLibrary is constructed from a list of models, these expnames default to meta.filename, but that seems like it isn't a regression since for some set of in-memory models I don't know what to do otherwise?

I tried to trace the code briefly and was a bit confused about what the resample step is now allowed to support as input. The docstring is presumably out of date:

input_models : list of objects
list of data models, one for each input image

This bit:
if (input_models is None) or (len(input_models) == 0):
raise ValueError(
"No input has been provided. Input should be a list of datamodel(s) or "
"a ModelLibrary."
)

says either a list of models or a ModelLibrary.
This bit
for i, m in enumerate(models):
self.input_models.shelve(m, i, modify=False)

suggests to me that it has to be a ModelLibrary (which presumably then always has the asn member).

I don't have strong preferences for an issue vs. an addition to this PR for a new test. It looks like this PR is pretty close to being ready to merge, so I'm happy to delay a new test to an issue. Thanks!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Just making sure I hadn't missed it before, that's a new feature in ModelLibrary that wasn't available to me when I wrote that bit of code before?

Exactly. I think the members entries previously got lost in skymatch due to:

return ModelContainer([x.meta["image_model"] for x in images])

It looks like when the ModelLibrary is constructed from a list of models, these expnames default to meta.filename, but that seems like it isn't a regression since for some set of in-memory models I don't know what to do otherwise?

Yup! Although we certainly could change that if something else seems more useful. The general idea is to make the ModelLibrary always have a "valid" association (even if it's made up based off the models) so the step code has a consistent interface (with ModelContainer I think you only get something in asn_table if the input is an association).

Re: resample step

Thanks for the catch. Yes the ResampleData class now only accepts a ModelLibrary. The ResampleStep should accept the same input as before (except for a ModelLibrary instead of a ModelContainer).
I pushed a change to the docstring in: 6184692
and the error message in: 899c9aa

I still have to rebase this to deal with the horde of conflicts following #1314 so the CI is unhappy temporarily.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the linked commits addressed the documentation issues (thanks for finding those!) and I was able to "rebase". Rerunning the regtests shows the same results as linked in the above description (the run link is up-to-date).

# self.log.info("* Images in GROUP 1:")
# for im in grp_img[0]:
# self.log.info(f" {im.meta.filename}")
# self.log.info("")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume that this and related logging issues are a temporary expedient rather than a proposed change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a partially proposed change at the moment. It does highlight one pattern that has some negative consequences when the ModelLibrary is on_disk. The logging commented out here (if the library is on_disk) will result in every model being read from disk to print out the meta.filename of each model. This is shortly followed by every model then being re-opened to set the cal_step status. I think a more complete change would be to combine these loops or remove the logging if printing out the filenames isn't that important (I don't think most steps do this).

Copy link
Collaborator

@mairanteodoro mairanteodoro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I left a few comments/suggestions.

@braingram

This comment was marked as outdated.

@schlafly
Copy link
Collaborator

Great. As far as you're concerned, this is good to merge? @ddavis-stsci , anything else that you would like to see?

Copy link
Collaborator

@schlafly schlafly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks for all of this!

@braingram braingram merged commit c49de36 into spacetelescope:main Jul 22, 2024
29 of 30 checks passed
@braingram braingram deleted the model_library branch July 22, 2024 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation pipeline regression_testing stpipe testing update webbpsf data
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test checks for intermediate files when save_intermediate_files is False
6 participants