New allegations emerge about Scots College students accused of sexually assaulting teenage girl
Physicists Entangle Quantum Memories Across a Record-Breaking 420 Kilometers
Read more of this story at Slashdot.
Revealed: The films and series you HAVE to see to be cultured
Labour's net zero dogma is costing cash-strapped families £540 a year, bombshell analysis that was scrapped by Ed Miliband shows
Moment pedestrians narrowly avoid being run down by cyclists who fail to stop for bike lane zebra crossing at one of Sadiq Khan's 'floating bus stops'
Family wiped out in Shoreham beach tragedy died after going for a swim in choppy seas while camping nearby, locals say: Young girl fights for life after man, woman and teen girl lost their lives in summer holiday horror
Andy Burnham has accepted £345,000 in donations... plus Aintree and Glastonbury tickets
CodeSOD: Back to the Lab
Matlab is special. Scientists and researchers love it. Programmers hate it, and not just because it uses 1-based arrays. I've worked on a number of projects where the task was "take this Matlab code and convert it to C so we can run it on an embedded CPU". Somehow, in that process, I've avoided learning much about Matlab.
Andre works on a team that uses Matlab to manage experimental scenarios. They wanted to do a simple task: generate a set of participant-specific images, store them in a database, and reference them later. Somewhere in the intersection of the database product they were using, the Matlab license they had, and other constraints, they discovered that there simply was no good way to do this.
Enter "Jude". Jude said, "Don't worry about it, I can hack something together."
I present the code in its entirety, but don't ask me to explain it. Instead, read the comments.
nMk = 1;%counting non-response triggers, this cycles with each trial nPress = 0;%counting button presses, noting the position in the log for v = 1:height(resVmrk)%read each trigger switch nMk %it's kinda roundabout, but the only recognisable part is the response %yet I refer to it only by elision %and instead count the stimuli to reconstruct the pattern case 1%an almost reliable stimulus nPress = nPress+1;%trial start if strcmp(resVmrk.TriggerCode{v},'S1')%it must be a non-response resVmrk.TriggerCode{v} = 'cross';%name it properly nMk = 2;%and expect the next one else%except when it is not resLog.miss(nPress) = 1;%then note it down as missed nMk = 0;%and skip to response end case 2%usually reliable if strcmp(resVmrk.TriggerCode{v},'S1')%if the face loaded successfully resVmrk.TriggerCode{v} = 'face';%note it nMk = 3;%and proceed accordingly if nPress<=height(resLog)%trailing triggers at the end should be ignored resLog.facePos(nPress) = v;%note the position end else%if it failed to load it is a response resVmrk.Dur(v-1:v+1) = 0;%mark the whole trial for deletion resLog.miss(nPress) = 1;%and note it down as missing the face nMk = 0;%and skip to response end case 3%this one is not reliable, and sometimes is duplicated instead of missing if strcmp(resVmrk.TriggerCode{v},'S1')%if it is present at all resVmrk.TriggerCode{v} = 'empty';%first name it if v<height(resVmrk)%if it is not a trailing trigger, since it'll break the check otherwise if ~strcmp(resVmrk.TriggerCode{v+1},'S1')%if the next trigger is a response nMk = 0;%all is fine and it didn't freak out, proceed to response else%otherwise nMk = 3;%just treat as a double %and then count how many excess triggers are actually here nExcess = 1;%definitely one here already while strcmp(resVmrk.TriggerCode{v+nExcess+1},'S1') nExcess = nExcess+1;%and everything until the response end resVmrk.Dur(v-2:v+nExcess+2) = 0;%then mark the whole trial for deletion %this overwrites the same positions several time, but the important part is to get the preceding two, because I don't know which one of them is correct one, so I delete the whole trial if nPress<=height(resLog) resLog.bad(nPress) = 1;%also note it down as borked end end end else nMk = 0;%if it didn't happen at all simply proceed to response end case 0%this one reliably follows the response, so I address the response by elision if strcmp(resVmrk.TriggerCode{v},'S1')%skip response itself resVmrk.TriggerCode{v} = 'blink';%note the only reliable non-response (always following the response) nMk = 1;%start the trial anew if nPress<=height(resLog)%if it is not a trailing trigger resLog.respPos(nPress) = v-1;%note down the response position if resLog.miss(nPress)==1%and if it's a response without a stimulus resVmrk.Dur(v-1:v) = 0;%mark it for deletion as well end end end end endAh, the classic "for-case" antipattern. That's gross enough, but what the heck is happening inside each of those cases?
My personal favorite comment is this one: "%this overwrites the same positions several time, but the important part is to get the preceding two, because I don't know which one of them is correct one, so I delete the whole trial"
Now, you may suspect comments like "usually reliable" are about what we see in the dataset, but I'm not so certain. Andre writes:
After reverting the last discovered way for his creation to corrupt the data I was able to figure out that 20% of the logs provided corresponded to different (unknown) experiments altogether.
.comment { border: none; }