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
Feature: Bit behaviour for process_evt_read.m #544
Conversation
This doesn't work. Removing these three lines alters dramatically the behavior of the reader and makes the cortico-muscular coherence impossible to follow, as a lot more events are now detected. |
This behaviour is linked to cases where the edge has two (or even three!) steps. Verified on the CMC data and a file @Moo-Marc shared. Two examples, x-axis are samples, y-axis the value of the Stim (or UDIO001) channels. This transition "triggers " are avoided by setting the option "Reject events shorter than X samples" to |
I tested with our bit-wise data. It works well with "reject" set to 0 samples, but otherwise it rejected a lot of events it shouldn't (5% to 50% depending on the bit). Maybe it's because of the way the data is processed in blocks? Or it doesn't apply that filter on each bit channel independently? |
We discussed this issue during yesterday's meeting. Fixed trigshift:
Detection of events only from zero:
|
Hi François, Trig shift: This was basically an undocumented(?) small time shift applied to digital CTF triggers recreated in Brainstorm, right? Is the same shift applied when loading events from the MarkerFile? If not, then it's another reason to remove it. I can discuss it with Fieldtrip, but it's possible the specific delay changed with the different CTF electronics versions. It was your suggestion that "we completely get rid of this shift", and deal with it in the delay tutorial. In fact, it's something that probably applies to other systems, any that downsamples somewhere in the hardware or software processing. Event detection: bit-wise or not doesn't matter here, it depends on the values chosen by the task designer. In particular, assuming an 8-bit channel, if they have more than 8 distinct event types, they'd have to use decimal values from 0-255 instead of 8 independent bits. Simple example: a task with various events. The value on the digital channel is changed at each event: trial start = 0, first step = 1, second event = 10 or 20 depending on condition, response prompt = 30, response = 100 or 101. Or if it's designed bit-wise: start = 0, first step = 1, second = 2 or 4, prompt = 8, response = 16 or 32. So the stim channel looks like a staircase for each trial, but in the first case the numbers shouldn't be treated bit-wise. Now, when we use bit-wise and after the channel is converted to a set of bit "tracks", of course each event goes from 0 to 1, so the "from 0" criteria is logical, but it's also redundant at this stage. Transitions in general happen in the middle of a single sample, and for CTF, the channel will "and" the bits (initially collected at something like 192kHz) and we end up with larger values at these transition samples. This is normal and the existing functionality "reject events shorter than 2 samples" is a very good solution to dealt with this. If we wanted to be even more careful, I guess we could compare these one-sample values to the bit-and of the previous and following values, and "clean" the transitions. As to the impact of fixing this: I'd guess many people don't typically use these functions to generate events because they're created at collection time with a properly customized CTF configuration. Which is probably why nobody complained that bit-wise didn't work. But if the functionality is there, I think it's worth being able to recreate all the markers in Brainstorm, not just a subset of cases. |
Fieldtrip issue opened: fieldtrip/fieldtrip#2030 |
From Robert's reply, my previous understanding was wrong. I had another look at the code and it's not so exactly doing a time shift, but avoiding transition values: it finds when the channel value departs from 0, and then takes the channel value a few samples later as the "correct" event value. It was not to avoid the bit-and that we were talking about, but rather if the different bit changing are not all synchronized. The effect is similar to our "reject events shorter than X samples" with X equivalent to 7.5 ms, but it also "shifts" the stable event that occurs after a short "transition event" to the time of the transition start. I would suggest replacing that fixed duration "forward looking" feature, with a slightly modified "reject events shorter than": Filter out unwanted transition values, replacing them with the subsequent "stable value", hence similarly shifting the time of the stable events earlier. It's almost the same behavior as before for 0 to X transitions (but it can be longer than before if there are many different short duration values in a row - probably never happens), but it would also work for X to Y transitions. |
It's not uncommon. Though I agree using short pulses (and independent bits when possible) has advantages and may be more common in experienced people.
Actually, to maintain the current behavior, the default should be 7.5 ms (but I'd still vote for 2 or 0). In this example, the events are not detected with the current code. By looking forward 7.5 ms the value is 0 again. And even with "accept 0 values", they are rejected. Robert did mention that they always used pulses at least 10 ms, hence it was not an issue for them. By the way, I also noticed that a bunch of pulses are missing in the stim digital channel in this downsampled data. I would suggest that the downsampling procedure be modified for digital channels the same way CTF does it: bit-and of all values in the new sample period. This ensures no short events are lost.
I'll discuss with @rcassani first since he's now more familiar with the code. One of us will do that. Final comment: my suggestion above is meant to keep the same behavior, while replacing the fixed 7.5 ms by the "shorter than" parameter. Otherwise, I would have suggested to just remove this "shift correction" entirely. We know that digital triggers are not the best for timing anyway as we discuss in the delay tutorial. For any task where the timing must be precise within one or two samples, one should use a different method to get the timing anyway (e.g. photodiode, sound recording, etc). |
Ouch... indeed, it works in the tutorial dataset only because the files are notch-filtered first, and their format is "BST-BIN" instead of "CTF-CONTINUOUS". Detecting before filtering does not create any event. I guess it would be important to obtain coherent behaviors for the original or filtered files, right? But then, we need to maintain the behavior for the older files from the cortico-muscular coherence tutorial (which is the reason why I initially added this code, after checking why it was correctly read in the FieldTrip tutorial).
Indeed, a large amount of triggers are lost (e.g. 170 standard triggers instead of 200...) Thanks! |
…n trigger pulse 15 ms)
@Moo-Marc, at this point, |
Looks good to me. Tested the bit-wise mode. |
We should add a short description for the "reject events shorter than X samples" option to the Stim Delay Tutorial.
anything else? |
I tested the new version vs. the old one on all the tutorial datasets that use this function (all the FIF files, Yokogawa, NIRS, Frontiers2018), and obtained the same results. |
Edited tutorials:
Please have a look at the first two tutorials, and let me know if anything needs to be changed. Thank you both for this thorough debugging! |
This PR addresses the issue pointed by @Moo-Marc in the Forum post: https://neuroimage.usc.edu/forums/t/reading-ctf-digital-stim-events-in-bit-mode/34897