-
Notifications
You must be signed in to change notification settings - Fork 74
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
Data Quality plugin for Imviz #2767
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2767 +/- ##
==========================================
+ Coverage 88.72% 88.82% +0.10%
==========================================
Files 110 111 +1
Lines 16353 16879 +526
==========================================
+ Hits 14509 14993 +484
- Misses 1844 1886 +42 ☔ View full report in Codecov by Sentry. |
# TODO: uncomment this line before merging into main: | ||
# irrelevant_msg = Unicode("Data Quality plugin is in development.").tag(sync=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.
you can always uncomment this and just reset it to empty in your own testing notebook and any tests 🤷♂️
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.
Of course! I just wanted devs to be able to play with this by checking out the PR, without having to change source code to use it.
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 intention still to include this or is it mature enough that we can remove it entirely and have it enabled in main on merge (and whenever 3.10 is released)?
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.
(we could also have this be considered irrelevant if there are no data quality layers available... 🤔 )
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’m in favor of keeping it out until we decide it’s more stable. It’s likely some things will change when we add support for other configs. Hopefully they aren’t major things, but just in case, let’s defer.
I got some early ~"user feedback" by giving a demo today to @tddesjardins, who will be a Roman-focused DQ plugin user. Tyler likes where things are headed. The outstanding tasks in our epic that he specifically touched on in our conversation included:
Feature ideas from Tyler that we don't yet have ticketed:
Note from Brett on the above request: the DQ-to-boolean-mask part of this request is trivial to implement. The slightly less trivial effort is adding the infrastructure to the aperture photometry plugin to check science data for an associated DQ array loaded in the viewer, and passing that along to photutils. But if accomplish that effort, it would be almost no extra effort to pass along the ERR array to photutils too, which would also give us uncertainties from photutils-derived outputs. Further note on the above note: DQ arrays only exist for L2 products, but ERR arrays exist for L2+. So while it might seem like a narrow use-case (only L2) to implement this for DQ, the ERR use-case applies much more broadly (L2 and beyond). |
Thank you very much for the feedback @tddesjardins!! |
@javerbukh Thanks for mentioning that PR – I have a ticket for doing what you did there for all configs, so I'm glad to see you already got Cubeviz 🙌🏻. |
I got more feedback from giving a demo to @rgcosentino:
|
Thank you @rgcosentino!! |
@camipacifici It's easy to implement, but may not be very performant. I'll look into it 👌🏻 |
Today I added @rgcosentino's UI feature request, which solves a couple of the UI challenges in one go: dq-bit-filter.mov |
def layer_is_not_dq(data): | ||
return not data.label.endswith('[DQ]') |
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 surest way to identify a DQ layer is to rely on the data label if we're always producing it consistently. I think we can rely on this for now as written, but we could instead, e.g., add a private metadata flag.
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.
In #2718 there is a app._jdaviz_helper._loaded_mask_cube
variable that we can use instead of this. That way, if the DQ data is renamed, the _loaded_mask_cube
should be able to track that (it does not currently do that in that PR but it would be a useful addition). We've been moving away from using data labels since we are planning (at some point in the future) to enable label renaming. I'm also worried about the scenario where a user manually loads the DQ layer with a custom name, which would mean it is not caught by this line.
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.
@javerbukh - but we intentionally want to be able to support multiple DQ layers. I agree that the eventual solution is probably to move all of this "what type of data is this entry considered" into private metadata that can be populated by the parser.
if associated_dq_layer is not None: | ||
if np.isnan(dq_value): | ||
dq_text = '' | ||
else: | ||
dq_text = f' (DQ: {int(dq_value):d})' | ||
else: | ||
dq_text = '' | ||
self.row1b_text = f'{value:+10.5e} {unit}{dq_text}' |
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 the simplest and fastest possible DQ injection into coords-info that I could do. We could also decompose the bit flag, but that is (1) hard to fit in the horizontal space, and (2) a tiny bit more expensive.
The DQ plugin so far is a great addition to Imviz, nice work! I left a couple comments in the code but I also want to mention the DQ relative opacity slider. I was confused at first why only the DQ array was loaded, until I moved that slider and saw the data underneath. Is there a reason we cannot use the opacity sliders in plot options to handle this functionality? I was also nervous to see the amount of lines added and no test coverage for them. I understand that adding the bulk of test coverage will be a follow-up effort, but can you add some simple tests just to show the intended workflow with this plugin? Let me know your thoughts, I'm happy to re-review again soon because it would be great to get this merged! |
By default the DQ opacity is 0.9 * (science opacity). Do you think it would be less confusing if we brought it down to 0.5 or so?
I agree that DQ opacity is a "plot option" in the literal sense, but we need a different strategy for the DQ opacity slider than for the other layers. We wouldn't allow the user to change any but one of the options (opacity) on DQ layers – not the colormap, bias, contrast, stretch, etc. And DQ opacity is defined relative to the science layer opacity, which would mean its opacity slider behaves differently from the others. None of the above is to say that we couldn't put DQ plot options in Plot Options, but that we'd have to find a way to make these subtleties less confusing. |
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 really coming along nicely (and quickly)! Just a few comments from a first pass - would you mind exposing whatever you intend to expose and think is fairly stable through the user API so that its obvious what is expected to be tested directly vs internally?
Thank you @kecnry, all your points are now addressed. |
|
||
dq_layer.state.alpha = self.dq_layer_opacity | ||
|
||
def update_visibility(self, index): |
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 index (here and in update_color
) convenient for the user? This isn't a big deal since we're not exposing this in the user API yet, but definitely something to think about as we play with this in workflows, etc.
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.
Good point. Right now, the index corresponds to an entry in self.decoded_flags
, which is a list of dictionaries. We could instead choose to make decoded_flags
a dictionary, where the key is the flag. I made it a list because I had better luck iterating over a list in the vue file than a dict.
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.
Right, but even if it internally is a dictionary, maybe we should support passing the key and just internally iterating to look up the entry to change?
# TODO: uncomment this line before merging into main: | ||
# irrelevant_msg = Unicode("Data Quality plugin is in development.").tag(sync=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.
(we could also have this be considered irrelevant if there are no data quality layers available... 🤔 )
@property | ||
def user_api(self): | ||
return PluginUserApi( | ||
self, | ||
expose=( | ||
'science_layer', 'dq_layer', | ||
'decoded_flags', 'flags_filter' | ||
) | ||
) |
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.
for now, I think we also at least want viewer
(and possibly flag_map
- but that would require using a PluginSelectComponent for that instead of handling the items manually here). How about dq_layer_opacity
?
I do think it makes sense to hold back on the color/visibility methods if we're not sure of their API yet.... but eventually I'm guessing we'll want those exposed as well.
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.
Done in c2cd379.
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 noticed a strange bug where if I filter by bit (10 in the concept notebook in this PR), then change the color of 1311747 for example, the pixels are no longer colored in at all. The color comes back if I press "clear filter".
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.
Works great! Once CI is working I'll approve.
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.
LGTM!
Last remaining failure exists on main and is expected (for now). Thanks all! |
This PR implements a Data Quality plugin, with a focus on Imviz. This is part of a larger effort which will support other configs too.
The Data Quality plugin allows a user to load science data and an associated DQ array (using #2761). Imviz will recognize DQ extensions at load time, identify the correct flag mapping (either JWST or Roman, for now; see #2765).
The plugin will assign colors to the flags, and show the DQ array in the viewer. Pixels without flags have no additional color overlay (via glue-viz/glue#2468). The data quality for a pixel is shown in the coordinate info in the top toolbar by appending
(DQ: <int>)
on pixels with flags (screenshot below).There's a multi-select dropdown labeled "Filter by bits" where a user can select flags to visualize by checking any of the decomposed bits that each flag contains. The visibility and color of each flag can be set manually.
There's a relative opacity slider for the DQ layer, which sets the DQ layer opacity relative to the science layer. There's a callback on the science layer opacity, so they stay in sync.
Demo video
I took the unusual step to record a narrated, five-minute screen recording with a DQ demo, to help you see the features. The video is too big for GitHub, so you can view it on Box. One feature that is not demonstrated in this video is color selection – if you click the color of the DQ flag in the plugin, you can select any color you like from a full color palette.
Example notebook
Try out the concept notebook included in this PR.
Other notes
I used the
no-changelog-entry-needed
label because this should produce no user facing changes once we do the last item on the to-do list below.I could use advice from a wizard (@kecnry 🧙🏻?) to improve the vertical spacing of the vue elements.
Tickets addressed
Three tickets are completed with this PR, and one is partly addressed.
To do list
Change log entry
CHANGES.rst
? If you want to avoid merge conflicts,list the proposed change log here for review and add to
CHANGES.rst
before merge. If no, maintainershould add a
no-changelog-entry-needed
label.Checklist for package maintainer(s)
This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.
trivial
label.