Open scott-huberty opened 1 year ago
... and then we have to figure out how to disallow changing channel removal/addition when the annotation is off-screen time-wise. I think the simple solution is that a channel can be added/removed from the selected annotation only if some part of the the selected annotation is in the visible time span.
And could we also add that the selected annotation can be changed into a channel-wise annotation and/or additional channels can be added to the currently selected channel-wise annotation by clicking on the channel trace? Thus disabling entirely the bad/not bad interaction when in annotation mode.
Updated!
Here's some code that could be useful. It works by interacting with the ChannelAxis (the y-axis listing channel names) and doing shift+left-click to toggle the channel being part of the active annotation. It adds to the already existing mouseClickEvent
for it. Basically, if in annotation mode, it gets the name of the channel pressed, gets the annotation index currently active, and then adds/removes that channel to the list of channels associated with that annotation. The added function for this is in the "####" section. I think pieces of it can be used for this next step.
def mouseClickEvent(self, event):
"""Customize mouse click events for ChannelAxis"""
# Clean up channel-texts
if not self.mne.butterfly:
self.ch_texts = {k: v for k, v in self.ch_texts.items()
if k in [tr.ch_name for tr in self.mne.traces]}
# Get channel-name from position of channel-description
ypos = event.scenePos().y()
y_values = np.asarray(list(self.ch_texts.values()))[:, 1, :]
y_diff = np.abs(y_values - ypos)
ch_idx = int(np.argmin(y_diff, axis=0)[0])
ch_name = list(self.ch_texts)[ch_idx]
trace = [tr for tr in self.mne.traces
if tr.ch_name == ch_name][0]
########################################################
# If shift+left-click in annotation mode then add to the annotation
if event.button() == Qt.LeftButton and bool(Qt.ShiftModifier) and self.mne.annotation_mode:
# Find what the currently active annotation is: self.mne.current_description
# Access the instance of the annotation
current_annotation_idx = [annot_ii for annot_ii in range(len(self.mne.inst.annotations))
if self.mne.inst.annotations[annot_ii]['description'] == self.mne.current_description][0]
ch_list_in_annot = list(self.mne.inst.annotations.ch_names[current_annotation_idx])
if ch_name not in ch_list_in_annot:
self.mne.inst.annotations.ch_names[current_annotation_idx] = tuple( ch_list_in_annot + [ch_name] )
else:
# Remove ch_name from annotation
ch_list_in_annot.pop(ch_list_in_annot.index(ch_name))
self.mne.inst.annotations.ch_names[current_annotation_idx] = tuple(ch_list_in_annot)
########################################################
elif event.button() == Qt.LeftButton:
trace.toggle_bad()
elif event.button() == Qt.RightButton:
self.weakmain()._create_ch_context_fig(trace.range_idx)
Thx @nmarkowitz !
I probably won't have time this month to get to this so feel free to start a PR if you beat me to it.
current_annotation_idx = [annot_ii for annot_ii in range(len(self.mne.inst.annotations)) if self.mne.inst.annotations[annot_ii]['description'] == self.mne.current_description][0]
FYI I don't think this will work. If there is more than 1 annotation with the same description, this will always return the index of the first annotation that matches the description. I think we'll need a more robust way to find the current annotation. (EDIT) I can probably make a suggestion but I'd need to dig into the code a bit 😄
Now that #202 is merged, I wanted to leave a summary here of our game-plan for interactively drawing channel-specific annotations. (this was discussed with @larsoner and @drammock during the September 2023 intermediate code sprint).
CC @nmarkowitz who I believe is also interested in working on this.
To draw a channel specific annotation interactively
Ground work that needs to be done.
alpha
and a dashed border, plus the shaded rectangles around associated channels).