The Scheduler

How does the scheduler work?

class scheduler, method start():

Consider listScheduler.py line 134, function start(): the scheduler tells the other modules that the experiment begins using self.broadCastStatus('start'), gets ready to process jobs by specifying that the first "next job" that will need to be done is to choose the next (i.e. first) trial to present (self.nextJob=self.chooseNextTrial), make a note of when things get going by noting time.time() in internal variables, and then calling self.processJobs().

class scheduler, method processJobs():

At the heart of the scheduler is variable self.nextJob, which points to the function that is to be executed next. Whatever that function is, it needs to return the function that is to be executed after. Hence in listScheduler.py line 149:  self.nextJob=self.nextJob(). If we want to tell the scheduler that we are done and there is nothing else to do we simply set self.nextJob=None. Example: assume that self.nextJob=self.chooseNextTrial. What will happen if we get to self.nextJob=self.nextJob()? Well, as nextJob=chooseNextTrial, the function chooseNextTrial() (Line 183) will be called, but before exiting it says (Line 203: return self.waitForStart). Consequently, when we chooseNextTrial() returns, nextJob will be set to waitForStart(), which will be executed next. Now, waitForStart() may either return itself (line 230) if the schedule needs to do more waiting, or it may return presentTrial()  if we are done waiting and it is time to trigger the next stimulus. In this way the scheduler will simply step through functions chooseNextTrial(), waitForStart(), presentTrial(), getResponse(), reward() or punish() in the order that is determined by whatever those functions happen to return. Normally the idea is that in chooseNextTrial(), we work through the schedule  and tell the stimulus module which stimulus parameters to prepare. In waitForStart() we make sure that we are ready to play the stimulus, perhaps by waiting for a signal from the detectors that an animal has triggered a "start" spout. In presentTrial() we trigger the stimulus. In getResponse() we read the detector output, and, if this is a task with feedback, we may set reward() or punish().

Other parts of the software (outside the  scheduler) can also abort the scheduler by setting config.status="abort"

class scheduler, method statusChange():

For the stimulus module, the data handler and the detectors to be able to play nice with the schedule, we have to create a common interface. This interface is provided by the function statusChange() which all stimulus modules, data handlers and detectors must provide. The scheduler simply calls the statusChange(newStatus) repeatedly for all the modules it has been given, and it is up to the modules to make sure that they do what is required at the right time in response to the "newStatus" message. Example: function "broadCastStatus()" line 157 of listScheduler.py