Fix plot_conditions plotting a single epoch instead of the condition average - #329
Open
adityasingh2400 wants to merge 1 commit into
Open
Fix plot_conditions plotting a single epoch instead of the condition average#329adityasingh2400 wants to merge 1 commit into
adityasingh2400 wants to merge 1 commit into
Conversation
plot_conditions built a wide epochs-by-time DataFrame and passed the channel number as seaborn's `y`. Seaborn read that as a column key, so it selected column number `ch` of the frame. Those columns are epochs, not channels, so each subplot showed a single arbitrary epoch with no averaging and no confidence interval. The legend had a related problem. It was built from a bare list of labels, which matplotlib pairs with whatever artists it finds in draw order. The labels were written difference-first while the artists are drawn conditions-first, and seaborn's confidence bands are picked up as handles too, so labels ended up on the wrong lines. Reshape the data to long form so seaborn averages over epochs, and build the legend from explicit Line2D handles so every label carries its own colour.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
plot_conditionsineegnb/analysis/analysis_utils.pydoes not plot the ERP. It plots one arbitrary single epoch per channel. This is the function behind every example in the gallery, so the N170, P300, SSVEP and cueing figures in the published docs are all showing raw single trials rather than condition averages.The cause is a wide-versus-long data problem. The function builds
pd.DataFrame(X[y.isin(cond), ch].T, index=times), whose columns are epochs, and then callssns.lineplot(data=..., x=times, y=ch). Seaborn readsy=chas a column key, and column numberchof that frame is epoch numberch. So channel 0 draws epoch 0, channel 1 draws epoch 1, and so on, with no averaging over trials and no confidence interval. I think this is the same regression pellet described on the issue when he noted the plots looked wrong after the seaborn line plotting change, since a single trial looks exactly that noisy.The legend has a related problem, which is what the issue reports directly. It was built by passing a bare list of labels to
axes[-1].legend(...), and matplotlib pairs a bare label list with whatever artists it finds on the axis in draw order. The labels are written difference-waveform-first while the artists are drawn conditions-first, and on current seaborn the confidence band is picked up as a handle as well, so the labels land on the wrong lines and the black difference waveform gets no entry at all. On my machine the legend read2 - 1next to the red Non-Target line,NonTargetnext to a shaded band, andTargetnext to the green Target line.The fix reshapes each condition to long form so seaborn averages across epochs and bootstraps the interval, which is what the original
sns.tsplotcall did before the migration, and builds the legend from explicitLine2Dhandles so each label carries its own colour regardless of how many artists the plotting calls add.eegnb/analysis/utils.pyalready holds a corrected copy of this function, so this brings the module the examples actually import back in line with it.I added
tests/test_analysis_plots.py, which runs on synthetic MNE epochs and needs no hardware and no downloaded dataset. Reverting only the source change and rerunning gives 3 failed, withchannel 0: plotted 1.0 but the condition average is 4.0for the averaging test andlegend handles should be lines, not confidence-interval bandsfor the legend test. With the change applied all 3 pass. As a further check, on synthetic data with 30 epochs per condition and 2 uV of per-trial noise the averaged trace now has a standard deviation of 0.365 uV, matching the 2.0/sqrt(30) you expect from a real average, where before it was the full single-trial 2 uV.mypyis clean on both files.Fixes #226