-
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
Enable editing of composite subsets in the subset plugin #2182
Changes from all commits
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 |
---|---|---|
|
@@ -909,8 +909,6 @@ def get_subsets(self, subset_name=None, spectral_only=False, | |
# Remove duplicate spectral regions | ||
if is_spectral and isinstance(subset_region, SpectralRegion): | ||
subset_region = self._remove_duplicate_bounds(subset_region) | ||
elif is_spectral: | ||
subset_region = self._remove_duplicate_bounds_in_dict(subset_region) | ||
|
||
if spectral_only and is_spectral: | ||
if object_only and not simplify_spectral: | ||
|
@@ -942,22 +940,6 @@ def get_subsets(self, subset_name=None, spectral_only=False, | |
else: | ||
return all_subsets | ||
|
||
def _remove_duplicate_bounds_in_dict(self, subset_region): | ||
new_subset_region = [] | ||
for elem in subset_region: | ||
if not new_subset_region: | ||
new_subset_region.append(elem) | ||
continue | ||
unique = True | ||
for elem2 in new_subset_region: | ||
if (elem['region'].lower == elem2['region'].lower and | ||
elem['region'].upper == elem2['region'].upper and | ||
elem['glue_state'] == elem2['glue_state']): | ||
unique = False | ||
if unique: | ||
new_subset_region.append(elem) | ||
return new_subset_region | ||
|
||
def _is_subset_spectral(self, subset_region): | ||
if isinstance(subset_region, SpectralRegion): | ||
return True | ||
|
@@ -1060,23 +1042,34 @@ def get_sub_regions(self, subset_state, simplify_spectral=True): | |
return new_spec | ||
else: | ||
if isinstance(two, list): | ||
# two[0]['glue_state'] = subset_state.state2.__class__.__name__ | ||
two[0]['glue_state'] = "AndNotState" | ||
# Return two first so that we preserve the chronology of how | ||
# subset regions are applied. | ||
return one + two | ||
elif subset_state.op is operator.and_: | ||
# This covers the AND subset mode | ||
|
||
# Example of how this works: | ||
# a = SpectralRegion(4 * u.um, 7 * u.um) | ||
# b = SpectralRegion(5 * u.um, 6 * u.um) | ||
# Example of how this works with "one" being the AND region | ||
# and "two" being two Range subsets connected by an OR state: | ||
# one = SpectralRegion(4.5 * u.um, 7.5 * u.um) | ||
# two = SpectralRegion(4 * u.um, 5 * u.um) + SpectralRegion(7 * u.um, 8 * u.um) | ||
# | ||
# b.invert(a.lower, a.upper) | ||
# oppo = two.invert(one.lower, one.upper) | ||
# Spectral Region, 1 sub-regions: | ||
# (5.0 um, 7.0 um) | ||
# | ||
# oppo.invert(one.lower, one.upper) | ||
# Spectral Region, 2 sub-regions: | ||
# (4.0 um, 5.0 um) (6.0 um, 7.0 um) | ||
# (4.5 um, 5.0 um) (7.0 um, 7.5 um) | ||
if isinstance(two, SpectralRegion): | ||
return two.invert(one.lower, one.upper) | ||
# Taking an AND state of an empty region is allowed | ||
# but there is no way for SpectralRegion to display that information. | ||
# Instead, we raise a ValueError | ||
if one.upper.value < two.lower.value or one.lower.value > two.upper.value: | ||
raise ValueError("AND mode should overlap with existing subset") | ||
Comment on lines
+1068
to
+1069
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. how would this get triggered? I tried creating this situation in specviz and it displays the state as I'd expect in the plugin and just doesn't highlight anything in the viewer (as expected), but I didn't see any traceback. Is this not needed? Or is the traceback caught somewhere? 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. Hmm, thought I wrote a test for this one. Let me look at this for a bit and get back to you. 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 checked, the problem is: what should be returned from the result of applying Range, then OR, then AND on an empty region (i.e. not where the two subregions are)? Ideally it should be empty but we cannot send an empty I agree this is an issue but I'm not sure at the moment how to resolve it. 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. Is there something equivalent to "identity" where it is not empty but it also won't change the result? But I agree it might be out of scope to fix here. 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. When you say "identity", what do you mean? I couldn't find anything that achieved that goal but I agree that should be out of scope for this PR. |
||
oppo = two.invert(one.lower, one.upper) | ||
|
||
return oppo.invert(one.lower, one.upper) | ||
else: | ||
return two + one | ||
elif subset_state.op is operator.or_: | ||
|
@@ -1089,10 +1082,38 @@ def get_sub_regions(self, subset_state, simplify_spectral=True): | |
elif two: | ||
return two | ||
elif subset_state.op is operator.xor: | ||
# This covers the XOR case which is currently not working | ||
return None | ||
else: | ||
return None | ||
# This covers the ADD subset mode | ||
|
||
# Example of how this works, with "one" acting | ||
# as the XOR region and "two" as two ranges joined | ||
# by an OR: | ||
# a = SpectralRegion(4 * u.um, 5 * u.um) | ||
# b = SpectralRegion(6 * u.um, 9 * u.um) | ||
# | ||
# one = SpectralRegion(4.5 * u.um, 12 * u.um) | ||
# two = a + b | ||
|
||
# two.invert(one.lower, one.upper) | ||
# Spectral Region, 2 sub-regions: | ||
# (5.0 um, 6.0 um) (9.0 um, 12.0 um) | ||
|
||
# one.invert(two.lower, two.upper) | ||
# Spectral Region, 1 sub-regions: | ||
# (4.0 um, 4.5 um) | ||
|
||
# two.invert(one.lower, one.upper) + one.invert(two.lower, two.upper) | ||
# Spectral Region, 3 sub-regions: | ||
# (4.0 um, 4.5 um) (5.0 um, 6.0 um) (9.0 um, 12.0 um) | ||
|
||
if isinstance(two, SpectralRegion): | ||
if one.lower > two.lower: | ||
# If one.lower is less than two.lower, it will be included | ||
# in the two.invert() call. Otherwise, we can add it like this. | ||
return (two.invert(one.lower, one.upper) + | ||
one.invert(two.lower, two.upper)) | ||
return two.invert(one.lower, one.upper) | ||
else: | ||
return two + one | ||
else: | ||
# This gets triggered in the InvertState case where state1 | ||
# is an object and state2 is None | ||
|
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.
does this still need the second term now that the
elif
is removed?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 does, because
subset_region
could be alist
object and we do not remove duplicate bounds in that case (since there shouldn't be any).