Beispiel #1
0
    def Initialize(self, indim, outdim):
        #=======================================================================
        # Make a few variables easier to access, especially those accessed every packet.
        #=======================================================================
        self.max_thresh = self.params['MaxThresh'].val
        self.min_thresh = self.params['MinThresh'].val
        self.xpos = (-23.0, -8.0)
        self.ypos = (3.0, 18.0)
        self.fbpos = (8, -50, -56.5)
        self.trigger = False
        self.triggerSig = 0
        
        #=======================================================================
        # Screen
        #=======================================================================
        self.screen.color = (0,0,0) #let's have a black background
        self.scrw,self.scrh = self.screen.size #Get the screen dimensions.
        self.screen.app.camera.position = (0, 0, 0)
        self.screen.app.camera.lookAt ((0, -35, -40))
        self.screen.app.camera.nearClipDistance = 1
        import ogre.renderer.OGRE as ogre
        self.screen.app.camera.setFOVy(ogre.Degree(21.2))
        
        #=======================================================================
        # Register the cue text stimuli.
        #=======================================================================
        self.stimulus('cue', z=5, stim=VisualStimuli.Text(text='?', position=(400,400,0), anchor='center', color=(1,1,1), font_size=50, on=True))
        self.stimuli['cue'].on = False
              
        #=======================================================================
        # Create the feedback
        #=======================================================================
        self.feedback = OgreRenderer.TailStimulus()
        self.vx, self.vy = -8, 18
        self.feedback.inverseKinematics(True, True, self.vx, self.vy, 0)
        self.screen.app.camera.lookAt ((0, 0, -1))
        self.fbpos = (10, -13, -45)
        self.screen.app.camera.setFOVy(ogre.Degree(27.0))
        self.feedback.node.setPosition(self.fbpos)
        self.feedback.node.setVisible(True)
        
        #=======================================================================
        # State monitors for debugging.
        #=======================================================================
        if int(self.params['ShowSignalTime']):
            # turn on state monitors if the packet clock is also turned on
            addstatemonitor(self, 'Running', showtime=True)
            addstatemonitor(self, 'CurrentBlock')
            addstatemonitor(self, 'CurrentTrial')
            addstatemonitor(self, 'TargetClass')
            addphasemonitor(self, 'phase', showtime=True)
            addstatemonitor(self, 'ShouldAnim')
            addstatemonitor(self, 'IsAnim')
            addstatemonitor(self, 'AnimPcnt')

            m = addstatemonitor(self, 'fs_reg')
            m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_avg')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('global', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('running', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fr_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('FramesPerSecond',{}).get('running', 0)
            m.pargs = (self,)
	def Initialize(self, indim, outdim):
				
		# compute how big everything should be
		itf = float(self.params['InnerTriangleSize'])
		otf = float(self.params['OuterTriangleSize'])
		scrw,scrh = self.screen.size
		scrsiz = min(scrw,scrh)
		circle_radius = scrsiz * 0.5 * float(self.params['CircleRadius'])
		siz = (scrsiz * otf * 0.866,   scrsiz * otf * 0.75)
		
		# use a handy AppTools.Boxes.box object as the coordinate frame for the triangle
		b = box(size=siz, position=(scrw/2.0,scrh/2.0 - siz[1]/6.0), sticky=True)
		center = b.map((0.5,2.0/3.0), 'position')
		self.positions = {'origin': numpy.matrix(center)}
		
		# draw the main triangle
		triangle = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0,0,0,0.5))
		
		# the red target triangle
		b.anchor='bottom'
		b.scale(itf)
		self.positions['red'] = numpy.matrix(b.position)
		red = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(1,0.1,0.1))
		b.scale(1.0 / itf)

		# the green target triangle
		b.anchor='upperleft'
		b.scale(itf)
		self.positions['green'] = numpy.matrix(b.position)
		green = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0.1,1,0.1))
		b.scale(1.0 / itf);

		# the blue target triangle
		b.anchor='upperright'
		b.scale(itf)
		self.positions['blue'] = numpy.matrix(b.position)
		blue = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0.1,0.1,1))
		b.scale(1.0 / itf);

		# and the arrow
		b.anchor='center'
		fac = (0.25,0.4)
		b.scale(fac)
		arrow = PolygonTexture(frame=b, vertices=((0.22,0.35),(0,0.35),(0.5,0),(1,0.35),(0.78,0.35),(0.78,0.75),(0.22,0.75),), color=(1,1,1), on=False, position=center)
		b.scale((1.0/fac[0],1.0/fac[1]))
				
		# store the significant points on the screen for later use
		self.p = numpy.concatenate((self.positions['red'],self.positions['green'],self.positions['blue']), axis=0)

		# let's have a black background
		self.screen.color = (0,0,0)
		
		# OK, now register all those stimuli, plus a few more, with the framework
		self.stimulus('circle',   z=-1,  stim=Disc(position=center, radius=circle_radius, color=(0,0,0)))
		self.stimulus('triangle', z=1,   stim=triangle)
		self.stimulus('red',      z=2,   stim=red)
		self.stimulus('green',    z=2,   stim=green)
		self.stimulus('blue',     z=2,   stim=blue)
		self.stimulus('cursor1',  z=3,   stim=Disc(position=center, radius=10, color=(1,1,1), on=False))
		self.stimulus('cursor2',  z=4,   stim=Disc(position=center, radius=8,  color=(0,0,0), on=False))
		self.stimulus('arrow',    z=4.5, stim=arrow)
		self.stimulus('cue',      z=5,   stim=VisualStimuli.Text(text='?', position=center, anchor='center', color=(1,1,1), font_size=50, on=False))
		self.stimulus('fixation', z=4.2, stim=Disc(position=center, radius=5, color=(1,1,1), on=False))
		
		# set up the strings that are going to be presented in the 'cue' stimulus
		self.cuetext = ['relax', 'feet', 'left', 'right']
		
		# load, and silently start, the continuous feedback sounds
		self.sounds = []
		if int(self.params['AudioFeedback']):
			wavmat = self.params['FeedbackWavs']
			for i in range(len(wavmat)):
				wavlist = wavmat[i]
				if len(wavlist) != 1: raise EndUserError, 'FeedbackWavs matrix should have 1 column'
				try: snd = WavTools.player(wavlist[0])
				except IOError: raise EndUserError, 'failed to load "%s"'%wavlist[0]
				self.sounds.append(snd)
				snd.vol = 0
				snd.play(-1)

		# finally, some fancy stuff from AppTools.StateMonitors, for the developer to check
		# that everything's working OK
		if int(self.params['ShowSignalTime']):
			# turn on state monitors iff the packet clock is also turned on
			addstatemonitor(self, 'Running', showtime=True)
			addstatemonitor(self, 'CurrentBlock')
			addstatemonitor(self, 'CurrentTrial')
			addstatemonitor(self, 'TargetClass')
			addstatemonitor(self, 'Learn')
			
			addphasemonitor(self, 'phase', showtime=True)

			m = addstatemonitor(self, 'fs_reg')
			m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fs_avg')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('global', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fs_run')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('running', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fr_run')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('FramesPerSecond',{}).get('running', 0)
			m.pargs = (self,)
					
		self.distance = lambda a,b: numpy.sqrt((numpy.asarray(a-b)**2).sum(axis=-1))
		self.distance_scaling = (2.0 ** self.bits['DistanceFromCenter'] - 1.0) / self.distance(self.positions['green'], self.positions['red'])
	def Initialize(self, indim, outdim):
				
		# compute how big everything should be
		itf = float(self.params['InnerTriangleSize'])
		otf = float(self.params['OuterTriangleSize'])
		scrw,scrh = self.screen.size
		scrsiz = min(scrw,scrh)
		circle_radius = scrsiz * 0.5 * float(self.params['CircleRadius'])
		siz = (scrsiz * otf * 0.866,   scrsiz * otf * 0.75)
		
		# use a handy AppTools.Boxes.box object as the coordinate frame for the triangle
		b = box(size=siz, position=(scrw/2.0,scrh/2.0 - siz[1]/6.0), sticky=True)
		center = b.map((0.5,2.0/3.0), 'position')
		self.positions = {'origin': numpy.matrix(center)}
		
		# draw the main triangle
		triangle = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0,0,0,0.5))
		
		# the red target triangle
		b.anchor='bottom'
		b.scale(itf)
		self.positions['red'] = numpy.matrix(b.position)
		red = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(1,0.1,0.1))
		b.scale(1.0 / itf)

		# the green target triangle
		b.anchor='upperleft'
		b.scale(itf)
		self.positions['green'] = numpy.matrix(b.position)
		green = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0.1,1,0.1))
		b.scale(1.0 / itf);

		# the blue target triangle
		b.anchor='upperright'
		b.scale(itf)
		self.positions['blue'] = numpy.matrix(b.position)
		blue = PolygonTexture(frame=b, vertices=((0,1),(1,1),(0.5,0)), color=(0.1,0.1,1))
		b.scale(1.0 / itf);

		# and the arrow
		b.anchor='center'
		fac = (0.25,0.4)
		b.scale(fac)
		arrow = PolygonTexture(frame=b, vertices=((0.22,0.35),(0,0.35),(0.5,0),(1,0.35),(0.78,0.35),(0.78,0.75),(0.22,0.75),), color=(1,1,1), on=False, position=center)
		b.scale((1.0/fac[0],1.0/fac[1]))
				
		# store the significant points on the screen for later use
		self.p = numpy.concatenate((self.positions['red'],self.positions['green'],self.positions['blue']), axis=0)

		# let's have a black background
		self.screen.color = (0,0,0)
		
		# OK, now register all those stimuli, plus a few more, with the framework
		self.stimulus('circle',   z=-1,  stim=Disc(position=center, radius=circle_radius, color=(0,0,0)))
		self.stimulus('triangle', z=1,   stim=triangle)
		self.stimulus('red',      z=2,   stim=red)
		self.stimulus('green',    z=2,   stim=green)
		self.stimulus('blue',     z=2,   stim=blue)
		self.stimulus('cursor1',  z=3,   stim=Disc(position=center, radius=10, color=(1,1,1), on=False))
		self.stimulus('cursor2',  z=4,   stim=Disc(position=center, radius=8,  color=(0,0,0), on=False))
		self.stimulus('arrow',    z=4.5, stim=arrow)
		self.stimulus('cue',      z=5,   stim=VisualStimuli.Text(text='?', position=center, anchor='center', color=(1,1,1), font_size=50, on=False))
		self.stimulus('fixation', z=4.2, stim=Disc(position=center, radius=5, color=(1,1,1), on=False))
		
		# set up the strings that are going to be presented in the 'cue' stimulus
		self.cuetext = ['relax', 'feet', 'left', 'right']
		
		# load, and silently start, the continuous feedback sounds
		self.sounds = []
		if int(self.params['AudioFeedback']):
			wavmat = self.params['FeedbackWavs']
			for i in range(len(wavmat)):
				wavlist = wavmat[i]
				if len(wavlist) != 1: raise EndUserError, 'FeedbackWavs matrix should have 1 column'
				try: snd = WavTools.player(wavlist[0])
				except IOError: raise EndUserError, 'failed to load "%s"'%wavlist[0]
				self.sounds.append(snd)
				snd.vol = 0
				snd.play(-1)

		# finally, some fancy stuff from AppTools.StateMonitors, for the developer to check
		# that everything's working OK
		if int(self.params['ShowSignalTime']):
			# turn on state monitors iff the packet clock is also turned on
			addstatemonitor(self, 'Running', showtime=True)
			addstatemonitor(self, 'CurrentBlock')
			addstatemonitor(self, 'CurrentTrial')
			addstatemonitor(self, 'TargetClass')
			addstatemonitor(self, 'Learn')
			
			addphasemonitor(self, 'phase', showtime=True)

			m = addstatemonitor(self, 'fs_reg')
			m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fs_avg')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('global', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fs_run')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('running', 0)
			m.pargs = (self,)
			m = addstatemonitor(self, 'fr_run')
			m.func = lambda x: '% 6.1fHz' % x.estimated.get('FramesPerSecond',{}).get('running', 0)
			m.pargs = (self,)
					
		self.distance = lambda a,b: numpy.sqrt((numpy.asarray(a-b)**2).sum(axis=-1))
		self.distance_scaling = (2.0 ** self.bits['DistanceFromCenter'] - 1.0) / self.distance(self.positions['green'], self.positions['red'])
    def Initialize(self, indim, outdim):       
        #=======================================================================
        # Set the list of TargetClasss (pseudorandomized)
        #=======================================================================
        n_trials = self.params['TrialsPerBlock'].val * self.params['BlocksPerRun'].val
        classes_per_cluster = self.params['ClusterTargets'].val
        trials_per_class = int(n_trials / self.nclasses)
        if classes_per_cluster == 0: #We will cycle through targets.
            self.target_codes = [item for sublist in [range(self.nclasses) for j in range(trials_per_class)] for item in sublist]
            self.target_codes = [x+1 for x in self.target_codes]
        elif classes_per_cluster ==1:
            self.target_codes = [1 + x / trials_per_class for x in range(n_trials)] #Forcing int yields e.g., [0,0,0,1,1,1,2,2,2]
            shuffle(self.target_codes)
        else:
            n_clusters = trials_per_class / classes_per_cluster
            temp = []
            for cc in range(n_clusters):
                temp2 = [[j for jj in range(classes_per_cluster)] for j in range(self.nclasses)] #Generate a list of clusters, one per target
                shuffle(temp2) #Shuffle the list of clusters
                temp.append(temp2) #Append the list of clusters to what we have already.
            self.target_codes = 1 + [x2 for x3 in [item for sublist in temp for item in sublist] for x2 in x3] #Flatten

        #=======================================================================
        # Screen
        #=======================================================================
        self.screen.color = (0,0,0) #let's have a black background
        self.scrw,self.scrh = self.screen.size #Get the screen dimensions.

        #===================================================================
        # Create a box object as the coordinate frame for the screen.
        # Manipulate its properties to get positional information for stimuli.
        #===================================================================
        scrsiz = min(self.scrw,self.scrh)
        siz = (scrsiz, scrsiz)
        b = box(size=siz, position=(self.scrw/2.0,self.scrh/2.0), sticky=True)
        center = b.map((0.5,0.5), 'position')
        self.positions = {'origin': np.matrix(center)} #Save the origin for later.

        #=======================================================================
        # Register the basic stimuli.
        #=======================================================================
        self.stimulus('cue', z=5, stim=VisualStimuli.Text(text='?', position=center, anchor='center', color=(1,1,1), font_size=50, on=False))
        self.stimulus('fixation', z=4.2, stim=Disc(position=center, radius=5, color=(1,1,1), on=False))

        #=======================================================================
        # Make a few variables easier to access.
        #=======================================================================
        self.eegfs = self.nominal['SamplesPerSecond'] #Sampling rate
        self.spb = self.nominal['SamplesPerPacket'] #Samples per block/packet
        self.block_dur = 1000*self.spb/self.eegfs#duration (ms) of a sample block
        self.taskMaxNBlocks = self.params['TaskMax'].val * self.eegfs / self.spb#Task will always go to response after this many blocks, even if extensions not ready

        #=======================================================================
        # State monitors for debugging.
        #=======================================================================
        if int(self.params['ShowSignalTime']):
            # turn on state monitors iff the packet clock is also turned on
            addstatemonitor(self, 'Running', showtime=True)
            addstatemonitor(self, 'CurrentBlock')
            addstatemonitor(self, 'CurrentTrial')
            addstatemonitor(self, 'TargetClass')
            addstatemonitor(self, 'LastTargetClass')
            addstatemonitor(self, 'TaskMinNBlocks')
            addphasemonitor(self, 'phase', showtime=True)

            m = addstatemonitor(self, 'fs_reg')
            m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_avg')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('global', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('running', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fr_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('FramesPerSecond',{}).get('running', 0)
            m.pargs = (self,)

        if 'MSEnable' in self.params:	MagstimApp.initialize(self, indim, outdim)
        if 'DigitimerEnable' in self.params:	DigitimerApp.initialize(self, indim, outdim)
        if 'GatingEnable' in self.params:	GatingApp.initialize(self, indim, outdim)
        if 'ERPDatabaseEnable' in self.params:	ERPApp.initialize(self, indim, outdim)
        if 'ContFeedbackEnable' in self.params:	FeedbackApp.initialize(self, indim, outdim)
    def Initialize(self, indim, outdim):
        #=======================================================================
        # Make a few variables easier to access, especially those accessed every packet.
        #=======================================================================
        self.go_thresh = self.params['GoThresh'].val
        self.rev_thresh = self.params['ReverseThresh'].val
        self.fbpos = (8, -50, -56.5)
        
        #=======================================================================
        # Screen
        #=======================================================================
        self.screen.color = (0,0,0) #let's have a black background
        self.scrw,self.scrh = self.screen.size #Get the screen dimensions.
        self.screen.app.camera.position = (0, 0, 0)
        self.screen.app.camera.lookAt ((0, -35, -40))
        self.screen.app.camera.nearClipDistance = 1
        import ogre.renderer.OGRE as ogre
        self.screen.app.camera.setFOVy(ogre.Degree(21.2))
        
        #=======================================================================
        # Register the cue text stimuli.
        #=======================================================================
        self.stimulus('cue', z=5, stim=VisualStimuli.Text(text='?', position=(400,400,0), anchor='center', color=(1,1,1), font_size=50, on=True))
        self.stimuli['cue'].on = False
        
        #=======================================================================
        # Create the ruler
        #=======================================================================
        # #import ogre.renderer.OGRE as ogre
        # ovm = ogre.OverlayManager.getSingleton()
        # screen = ovm.getOverlayElement("screen")
        # ve = screen.getChild("visionegg")
        # #self.ruler = ovm.getByName("MyOverlays/Ruler")
        # #self.ruler.show()
        # self.ruler = ovm.createOverlayElement("Panel","Ruler")
        # self.ruler.setMaterialName("MyMaterials/Ruler")
        # self.ruler.setMetricsMode(ogre.GMM_PIXELS)
        # #the ruler png is 8032 x 318
        # rulerw = self.scrw*2
        # rulerh = rulerw * 318.0/8032.0
        # self.ruler.setWidth(rulerw)
        # self.ruler.setHeight(rulerh)
        # self.ruler.setTop(self.scrh/2.0 - rulerh)
        # ve.addChild(self.ruler)
        # self.ruler.hide()
        self.ruler = OgreRenderer.EntityStimulus(mesh_name = 'Cube.mesh')
        x = 5.0
        self.ruler.node.scale(x, x, x)
        self.ruler.node.setPosition(self.fbpos)
        self.ruler.node.setVisible(False)
        
        #=======================================================================
        # Create the guillotine
        #=======================================================================
        self.guillotine = OgreRenderer.EntityStimulus(mesh_name = 'Box01.mesh') #starts off Vector3(63.7515, 3.38875, 86.0819)
        self.guillotine.node.setPosition(self.fbpos)
        self.guillotine.node.translate((0, 10, 0))
        self.guillotine.node.scale(0.1, 0.1, 0.1)
        self.guillotine.node.pitch(ogre.Degree(90))
        self.guillotine.node.setVisible(False)
        
        #=======================================================================
        # Create the feedback
        #=======================================================================
        if self.params['FeedbackType'].val == 0 or self.params['FeedbackType'].val == 1:
            self.feedback = OgreRenderer.HandStimulus()
            self.feedback.node.yaw(ogre.Degree(-60))
            self.feedback.node.roll(ogre.Degree(-40))
            self.feedback.node.pitch(ogre.Degree(10))
            #self.feedback.on = True
            animState = self.feedback.entity.getAnimationState('my_animation')
            animState.Loop = False
            animState.timePosition = animState.length
            animState.Enabled = True
            #print self.feedback.entity.getWorldBoundingBox().getSize()
            #Vector3(21.9954, 5.94256, 6.04828)
        elif self.params['FeedbackType'].val == 2:
            self.feedback = Disc()
            self.feedback.node.scale(0.05, 0.05, 0.05)
            self.feedbackspd = 12 #ogreunits / second
        self.feedback.node.setPosition(self.fbpos)
        self.feedback.node.setVisible(False)
        if self.params['FeedbackType'].val == 1:
            self.feedback.node.yaw(ogre.Degree(-180))
        
        #=======================================================================
        # State monitors for debugging.
        #=======================================================================
        if int(self.params['ShowSignalTime']):
            # turn on state monitors iff the packet clock is also turned on
            addstatemonitor(self, 'Running', showtime=True)
            addstatemonitor(self, 'CurrentBlock')
            addstatemonitor(self, 'CurrentTrial')
            addstatemonitor(self, 'TargetClass')
            addphasemonitor(self, 'phase', showtime=True)
            addstatemonitor(self, 'RulerOffset')
            addstatemonitor(self, 'ShouldAnim')
            addstatemonitor(self, 'IsAnim')
            addstatemonitor(self, 'AnimPcnt')

            m = addstatemonitor(self, 'fs_reg')
            m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_avg')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('global', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fs_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('SamplesPerSecond',{}).get('running', 0)
            m.pargs = (self,)
            m = addstatemonitor(self, 'fr_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get('FramesPerSecond',{}).get('running', 0)
            m.pargs = (self,)
Beispiel #6
0
    def Initialize(self, indim, outdim):
        #=======================================================================
        # Set the list of TargetClasss (pseudorandomized)
        #=======================================================================
        n_trials = self.params['TrialsPerBlock'].val * self.params[
            'BlocksPerRun'].val
        classes_per_cluster = self.params['ClusterTargets'].val
        trials_per_class = int(n_trials / self.nclasses)
        if classes_per_cluster == 0:  #We will cycle through targets.
            self.target_codes = [
                item for sublist in
                [range(self.nclasses) for j in range(trials_per_class)]
                for item in sublist
            ]
            self.target_codes = [x + 1 for x in self.target_codes]
        elif classes_per_cluster == 1:
            self.target_codes = [
                1 + x / trials_per_class for x in range(n_trials)
            ]  #Forcing int yields e.g., [0,0,0,1,1,1,2,2,2]
            shuffle(self.target_codes)
        else:
            n_clusters = trials_per_class / classes_per_cluster
            temp = []
            for cc in range(n_clusters):
                temp2 = [[j for jj in range(classes_per_cluster)]
                         for j in range(self.nclasses)
                         ]  #Generate a list of clusters, one per target
                shuffle(temp2)  #Shuffle the list of clusters
                temp.append(
                    temp2
                )  #Append the list of clusters to what we have already.
            self.target_codes = 1 + [
                x2 for x3 in [item for sublist in temp for item in sublist]
                for x2 in x3
            ]  #Flatten

        #=======================================================================
        # Screen
        #=======================================================================
        self.screen.color = (0, 0, 0)  #let's have a black background
        self.scrw, self.scrh = self.screen.size  #Get the screen dimensions.

        #===================================================================
        # Create a box object as the coordinate frame for the screen.
        # Manipulate its properties to get positional information for stimuli.
        #===================================================================
        scrsiz = min(self.scrw, self.scrh)
        siz = (scrsiz, scrsiz)
        b = box(size=siz,
                position=(self.scrw / 2.0, self.scrh / 2.0),
                sticky=True)
        center = b.map((0.5, 0.5), 'position')
        self.positions = {
            'origin': np.matrix(center)
        }  #Save the origin for later.

        #=======================================================================
        # Register the basic stimuli.
        #=======================================================================
        self.stimulus('cue',
                      z=5,
                      stim=VisualStimuli.Text(text='?',
                                              position=center,
                                              anchor='center',
                                              color=(1, 1, 1),
                                              font_size=50,
                                              on=False))
        self.stimulus('fixation',
                      z=4.2,
                      stim=Disc(position=center,
                                radius=5,
                                color=(1, 1, 1),
                                on=False))

        #=======================================================================
        # Make a few variables easier to access.
        #=======================================================================
        self.eegfs = self.nominal['SamplesPerSecond']  #Sampling rate
        self.spb = self.nominal['SamplesPerPacket']  #Samples per block/packet
        self.block_dur = 1000 * self.spb / self.eegfs  #duration (ms) of a sample block
        self.taskMaxNBlocks = self.params[
            'TaskMax'].val * self.eegfs / self.spb  #Task will always go to response after this many blocks, even if extensions not ready

        #=======================================================================
        # State monitors for debugging.
        #=======================================================================
        if int(self.params['ShowSignalTime']):
            # turn on state monitors iff the packet clock is also turned on
            addstatemonitor(self, 'Running', showtime=True)
            addstatemonitor(self, 'CurrentBlock')
            addstatemonitor(self, 'CurrentTrial')
            addstatemonitor(self, 'TargetClass')
            addstatemonitor(self, 'LastTargetClass')
            addstatemonitor(self, 'TaskMinNBlocks')
            addphasemonitor(self, 'phase', showtime=True)

            m = addstatemonitor(self, 'fs_reg')
            m.func = lambda x: '% 6.1fHz' % x._regfs.get('SamplesPerSecond', 0)
            m.pargs = (self, )
            m = addstatemonitor(self, 'fs_avg')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get(
                'SamplesPerSecond', {}).get('global', 0)
            m.pargs = (self, )
            m = addstatemonitor(self, 'fs_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get(
                'SamplesPerSecond', {}).get('running', 0)
            m.pargs = (self, )
            m = addstatemonitor(self, 'fr_run')
            m.func = lambda x: '% 6.1fHz' % x.estimated.get(
                'FramesPerSecond', {}).get('running', 0)
            m.pargs = (self, )

        if 'MSEnable' in self.params:
            MagstimApp.initialize(self, indim, outdim)
        if 'DigitimerEnable' in self.params:
            DigitimerApp.initialize(self, indim, outdim)
        if 'GatingEnable' in self.params:
            GatingApp.initialize(self, indim, outdim)
        if 'ERPDatabaseEnable' in self.params:
            ERPApp.initialize(self, indim, outdim)
        if 'ContFeedbackEnable' in self.params:
            FeedbackApp.initialize(self, indim, outdim)