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

Bug channel annot merge #275

Merged
merged 13 commits into from
Aug 18, 2024
54 changes: 48 additions & 6 deletions mne_qt_browser/_pg_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -2267,7 +2267,7 @@ def __init__(self, mne, weakmain, annot, ch_name):

self.mne.plt.addItem(self, ignoreBounds=True)

self.annot.removeRequested.connect(self.remove)
self.annot.removeSingleChannelAnnots.connect(self.remove)
self.annot.sigRegionChangeFinished.connect(self.update_plot_curves)
self.annot.sigRegionChanged.connect(self.update_plot_curves)
self.annot.sigToggleVisibility.connect(self.update_visible)
Expand Down Expand Up @@ -2307,6 +2307,7 @@ class AnnotRegion(LinearRegionItem):
regionChangeFinished = Signal(object)
gotSelected = Signal(object)
removeRequested = Signal(object)
removeSingleChannelAnnots = Signal(object)
sigToggleVisibility = Signal(bool)
sigUpdateColor = Signal(str)

Expand Down Expand Up @@ -2343,29 +2344,66 @@ def __init__(self, mne, description, values, weakmain, ch_names=None):
self.mne.plt.addItem(self.label_item, ignoreBounds=True)

def _region_changed(self):
self.regionChangeFinished.emit(self)
self.old_onset = self.getRegion()[0]
# remove merged regions
# Check for overlapping regions
overlap_has_sca = []
overlapping_regions = list()
for region in self.mne.regions:
if region.description != self.description or id(self) == id(region):
continue
values = region.getRegion()
if any(self.getRegion()[0] <= val <= self.getRegion()[1] for val in values):
overlapping_regions.append(region)
overlap_has_sca.append(len(region.single_channel_annots) > 0)

# If this region or an overlapping region have
# channel specific annotations then terminate
if (len(self.single_channel_annots) > 0 or any(overlap_has_sca)) and len(
overlapping_regions
) > 0:
dur = self.getRegion()[1] - self.getRegion()[0]
self.setRegion((self.old_onset, self.old_onset + dur))
warn(
"Can not combine channel-based annotations with "
"any other annotation."
)
return

# figure out new boundaries
regions_ = np.array(
[region.getRegion() for region in overlapping_regions] + [self.getRegion()]
)

self.regionChangeFinished.emit(self)
self.old_onset = self.getRegion()[0]

# This annotation(s) has no sca but other has scas
# Other annotation(s) has sca but this annotation doesn't
# Both annotations have scas
# if len(self.single_channel_annots.keys()) == 0 or len(overlapping_scas) == 0:
# combine_scas = False
# else:
# combine_scas = True

onset = np.min(regions_[:, 0])
offset = np.max(regions_[:, 1])
logger.debug(f"New {self.description} region: {onset:.2f} - {offset:.2f}")
# remove overlapping regions
for region in overlapping_regions:
# region.removeSingleChannelAnnots.emit(region)
Copy link
Member

Choose a reason for hiding this comment

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

Cruft?

self.weakmain()._remove_region(region, from_annot=False)
# re-set while blocking the signal to avoid re-running this function
with SignalBlocker(self):
self.setRegion((onset, offset))

# if combine_scas:
# # combine single channel annotations
# for ch_name in overlapping_scas:
# if ch_name not in self.single_channel_annots.keys():
# self._toggle_single_channel_annot(ch_name, update_color=False)
# else:
# self.removeSingleChannelAnnots.emit(self)
#
# self.update_color(all_channels=(not list(self.single_channel_annots.keys())))
self.update_label_pos()

def _add_single_channel_annot(self, ch_name):
Expand All @@ -2377,7 +2415,7 @@ def _remove_single_channel_annot(self, ch_name):
self.single_channel_annots[ch_name].remove()
self.single_channel_annots.pop(ch_name)

def _toggle_single_channel_annot(self, ch_name):
def _toggle_single_channel_annot(self, ch_name, update_color=True):
"""Add or remove single channel annotations."""
# Exit if mne-python not updated to support shift-click
if not hasattr(self.weakmain(), "_toggle_single_channel_annotation"):
Expand All @@ -2394,7 +2432,10 @@ def _toggle_single_channel_annot(self, ch_name):
else:
self._remove_single_channel_annot(ch_name)

self.update_color(all_channels=(not list(self.single_channel_annots.keys())))
if update_color:
self.update_color(
all_channels=(not list(self.single_channel_annots.keys()))
)

def update_color(self, all_channels=True):
"""Update color of annotation-region.
Expand Down Expand Up @@ -2447,6 +2488,7 @@ def update_visible(self, visible):

def remove(self):
"""Remove annotation-region."""
self.removeSingleChannelAnnots.emit(self)
self.removeRequested.emit(self)
vb = self.mne.viewbox
if vb and self.label_item in vb.addedItems:
Expand Down