A research student recently had an issue with their EEG data from a recently completed study. During the early stages, the parallel cable connection had been disturbed between the EEG PC and the Stimulus PC, which had resulted in triggers being sent at key points of the experiment, but with completely different values than originally specified.
Markers are indications within the Brainvision Recorder software of when key events occur that you want to “mark” for later analysis. In the case of this experiment, when particular responses or stimuli were presented onto the screen, particular marker numbers would be fired down the parallel port and embedded into the EEG data.
Luckily the issue was detected early on and fixed for the majority of participants, but this still left around 6 participant data files with incorrect markers.
For most cases, Brainvision Analyser offers the opportunity to replace all data markers with another value. This is all well and good if the marker sent is unique to the event. In this particular case, when the parallel connection had corrupted – the same event marker value was put in. Luckily the experiment also records its own participant data file, which has details of what stimuli were shown and when – so by hand, you could go through both sets of data simultaneously and work out what the code was. To do this though could take you probably an entire day per participant file, and probably leave you seeing marker numbers and mumbling expletives about parallel cables in your sleep.
Avoiding unnecessary pain
Thankfully, for analysis and replacement of this scale, you can automate the process using a programming language like Python – which in this case is exactly what was done.
When talking through with the researcher, we obtained what conditions from the stimuli data file would indicate which marker flag to be expected. Next we established how the marker data was stored – which is luckily in a separated data file with a “.vmrk” extension. The marker data is just a flat list in sequence, so the other key detail is to correlate how many marker events will occur within a single trial loop (3 in this case). So as we read in a single trial and check its conditions, we apply the conditions on only those amount of markers at one time per trial.
PsychoPy experiments output a CSV data file, and the .vmrk file is also conveniently a form of CSV. Python can easily read in CSV data and turn into an array with a few short commands, after which we could simply loop through the data, apply the conditional checks as we go to the marker array created. Once we have finished processing all our trials – we just save the contents of the marker array, to create our replacement .vmrk file.
Replacing this within the Brainvision data directory, we just need to remove any history files for the analyser to pick up the changed marker data.
The script was less than an afternoon’s work, and very simple in its implementation to “get the job done”. Most of the simplicity was thanks to the power of Python and how simple it can be to create your own scripts to do data processing or fixing for you. This particular script runs over command line, and takes two arguments – firstly a PsychoPy data CSV file, followed by the corresponding .VMRK file. Within a matter of seconds, the changes are made and the new file outputted into an output directory with the same file name (pre-existing files are overwritten).
E.g.
> python convert.py input/psychopydata.csv input/participant01.vmrk
The script used has been attached below in case you want to take a look at it and see how it was done. Comments have been left throughout to indicate what each part is doing – so hopefully if you come to do something similar, you can adapt or re-use parts for your own scripts.
More details on data processing from John can also be found here:
Hi,
It sounds promising for me too. But, the problem is i am not familiar with Python. I have 3 markers for each trial. First two as stimuli and third one response (all of them are seen as stimulus in .vmrk file but it is not a problem since i can change it in brain vision analyzer later). But, unfortunately, i forgot to define response markers corresponding to correct or wrong responses. I want to change each third marker in the list. I can use a little guidance how to do this. I am pasting the head of the both .vmrk and csv files to give an idea about my data. Csv file includes the name of the each third marker (response). Thank you in advance for any suggestions etc.
.vmrk file:
Brain Vision Data Exchange Marker File Version 1.0
; Created by Porter 2.4.2.0 16-MAR-2015 15:47:16
[Common Infos]
sbj10.bva
[Marker Infos]
Mk5=Stimulus,c61,72733,1,0
Mk6=Stimulus,c62,73357,1,0
Mk7=Stimulus,c63,73840,1,0
Mk8=Stimulus,c11,74544,1,0
Mk9=Stimulus,c12,74734,1,0
Mk10=Stimulus,c13,75016,1,0
…..
csv file:
L1long
shortshort
longlong
GMshort
L2long
S2short
S1short
L1long
GMlong
L2long
shortshort
longlong
S2short
S1short
S1short
longlong
GMlong
S2short
L2short
L1long
Hi there,
The example script shows a way of looping through the VMRK file and detecting the “Stimulus” lines already. For your issue, what you need to do is stop on every 3rd “Stimulus” line and change the trigger, and for this you can use a Modulus function (symbol is % in Python).
We need to have a “counter” which counts every “Stimulus” line found, and then do a check like so:
IF counter % 3 == 0 THEN
… Change my trigger to something else
In your case, as you want it to be changed to whatever is in the CSV (in sequence order), then we just have another counter for the CSV, starting at 0. If we made a modulus match above, then we set the trigger to the contents of the CSV at its counter position (which at the start is 0 – for the first line). We then increase the CSV counter for next time when we make a match.
Here is an example working with your data supplied. I hope this is a good starting point:
http://www.kent.ac.uk/psychology/technical/scripts/marker-script-mod.zip
Thank you very much, i got the point. You really saved quite a lot of time, best wishes.
No worries, happy to help.
Hi! This is a really helpful post but the link to the actual code is broken. I was just wondering whether you could re-upload it? Thank you!
No problem – i’ve just fixed the link for you.