Article 77SMP CodeSOD: Back to the Lab

CodeSOD: Back to the Lab

by
Remy Porter
from The Daily WTF on (#77SMP)

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 trialnPress = 0;%counting button presses, noting the position in the logfor v = 1:height(resVmrk)%read each triggerswitch 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 patterncase 1%an almost reliable stimulusnPress = nPress+1;%trial startif strcmp(resVmrk.TriggerCode{v},'S1')%it must be a non-responseresVmrk.TriggerCode{v} = 'cross';%name it properlynMk = 2;%and expect the next oneelse%except when it is notresLog.miss(nPress) = 1;%then note it down as missednMk = 0;%and skip to responseendcase 2%usually reliableif strcmp(resVmrk.TriggerCode{v},'S1')%if the face loaded successfullyresVmrk.TriggerCode{v} = 'face';%note itnMk = 3;%and proceed accordinglyif nPress<=height(resLog)%trailing triggers at the end should be ignoredresLog.facePos(nPress) = v;%note the positionendelse%if it failed to load it is a responseresVmrk.Dur(v-1:v+1) = 0;%mark the whole trial for deletionresLog.miss(nPress) = 1;%and note it down as missing the facenMk = 0;%and skip to responseendcase 3%this one is not reliable, and sometimes is duplicated instead of missingif strcmp(resVmrk.TriggerCode{v},'S1')%if it is present at allresVmrk.TriggerCode{v} = 'empty';%first name itif v<height(resVmrk)%if it is not a trailing trigger, since it'll break the check otherwiseif ~strcmp(resVmrk.TriggerCode{v+1},'S1')%if the next trigger is a responsenMk = 0;%all is fine and it didn't freak out, proceed to responseelse%otherwisenMk = 3;%just treat as a double%and then count how many excess triggers are actually herenExcess = 1;%definitely one here alreadywhile strcmp(resVmrk.TriggerCode{v+nExcess+1},'S1')nExcess = nExcess+1;%and everything until the responseendresVmrk.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 trialif nPress<=height(resLog)resLog.bad(nPress) = 1;%also note it down as borkedendendendelsenMk = 0;%if it didn't happen at all simply proceed to responseendcase 0%this one reliably follows the response, so I address the response by elisionif strcmp(resVmrk.TriggerCode{v},'S1')%skip response itselfresVmrk.TriggerCode{v} = 'blink';%note the only reliable non-response (always following the response)nMk = 1;%start the trial anewif nPress<=height(resLog)%if it is not a trailing triggerresLog.respPos(nPress) = v-1;%note down the response positionif resLog.miss(nPress)==1%and if it's a response without a stimulusresVmrk.Dur(v-1:v) = 0;%mark it for deletion as wellendendendendend

Ah, 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.

proget-icon.png [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments