def Listen(self, mythread):

		mythread.read('stop', remove=True)
		mythread.read('start', wait=True, remove=True)

		nchan = self.audiochannels
		nsamp = int(round(self.audiochunk))
		
		w = WavTools.wav(fs=self.audiofs, bits=self.audiobits, nchan=nchan)
		interface = WavTools.PyAudioInterface.grab_interface()
		format = interface.get_format_from_width(w.nbytes)	
		recorder = interface.open(format=format, channels=nchan, rate=self.audiofs, input=True)
		
		mythread.read('stop', remove=True)
		mythread.post('ready', wait=True)
		
		while not mythread.read('stop'):
			#while self.ring.to_write() < nsamp: pass
			strdat = recorder.read(nsamp)
			w.y = w.str2dat(strdat, nsamp, nchan)
			self.ring.write(w.y.T * w.fac) # multiply by w.fac to undo str2dat's normalization to +/-1
			                               # (let the AudioBitDepth and SourceChGain parameters sort it out)
		
		recorder.close()
		WavTools.PyAudioInterface.release_interface(interface)
Exemple #2
0
    def Listen(self, mythread):

        mythread.read('stop', remove=True)
        mythread.read('start', wait=True, remove=True)

        nchan = self.audiochannels
        nsamp = int(round(self.audiochunk))

        w = WavTools.wav(fs=self.audiofs, bits=self.audiobits, nchan=nchan)
        interface = WavTools.PyAudioInterface.grab_interface()
        format = interface.get_format_from_width(w.nbytes)
        recorder = interface.open(format=format,
                                  channels=nchan,
                                  rate=self.audiofs,
                                  input=True)

        mythread.read('stop', remove=True)
        mythread.post('ready', wait=True)

        while not mythread.read('stop'):
            #while self.ring.to_write() < nsamp: pass
            strdat = recorder.read(nsamp)
            w.y = w.str2dat(strdat, nsamp, nchan)
            self.ring.write(
                w.y.T * w.fac
            )  # multiply by w.fac to undo str2dat's normalization to +/-1
            # (let the AudioBitDepth and SourceChGain parameters sort it out)

        recorder.close()
        WavTools.PyAudioInterface.release_interface(interface)
	def Initialize(self, indim, outdim):
		self.warp = 1000.0 # let the audio samples flowing into the ring buffer set the pace
		self.eegfs = self.samplingrate()
		self.audiofs = int(self.params['AudioSamplingRate'])
		self.audiobits = int(self.params['AudioBitDepth'])
		self.audiochunk = WavTools.msec2samples(float(self.params['AudioChunkMsec']), self.audiofs)
		self.audiochannels = int(self.params['NumberOfAudioChannels'])
		self.use_env = int(self.params['UseAudioEnvelope'])
		ringsize = WavTools.msec2samples(float(self.params['AudioBufferSizeMsec']), self.audiofs)
		self.ring = SigTools.ring(ringsize, self.audiochannels)
		self.ring.allow_overflow = True
		self.nominal['AudioSamplesPerPacket'] = WavTools.msec2samples(self.nominal['SecondsPerPacket']*1000.0, self.audiofs)
		self.dsind = numpy.linspace(0.0, self.nominal['AudioSamplesPerPacket'], self.nominal['SamplesPerPacket']+1, endpoint=True)
		self.dsind = numpy.round(self.dsind).astype(numpy.int).tolist()
		self._threads['listen'].post('start')
		self._threads['listen'].read('ready', wait=True, remove=True)
		self._check_threads()
Exemple #4
0
 def Initialize(self, indim, outdim):
     self.warp = 1000.0  # let the audio samples flowing into the ring buffer set the pace
     self.eegfs = self.samplingrate()
     self.audiofs = int(self.params['AudioSamplingRate'])
     self.audiobits = int(self.params['AudioBitDepth'])
     self.audiochunk = WavTools.msec2samples(
         float(self.params['AudioChunkMsec']), self.audiofs)
     self.audiochannels = int(self.params['NumberOfAudioChannels'])
     self.use_env = int(self.params['UseAudioEnvelope'])
     ringsize = WavTools.msec2samples(
         float(self.params['AudioBufferSizeMsec']), self.audiofs)
     self.ring = SigTools.ring(ringsize, self.audiochannels)
     self.ring.allow_overflow = True
     self.nominal['AudioSamplesPerPacket'] = WavTools.msec2samples(
         self.nominal['SecondsPerPacket'] * 1000.0, self.audiofs)
     self.dsind = numpy.linspace(0.0,
                                 self.nominal['AudioSamplesPerPacket'],
                                 self.nominal['SamplesPerPacket'] + 1,
                                 endpoint=True)
     self.dsind = numpy.round(self.dsind).astype(numpy.int).tolist()
     self._threads['listen'].post('start')
     self._threads['listen'].read('ready', wait=True, remove=True)
     self._check_threads()
	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(cls, app, indim, outdim):
        if int(app.params['ContFeedbackEnable'])==1:
            if int(app.params['ShowSignalTime']):
                app.addstatemonitor('FBValue')
                app.addstatemonitor('FBBlock')
                app.addstatemonitor('Feedback')
                app.addstatemonitor('InRange')

            #===================================================================
            # Load fake data if we will be using fake feedback.
            #===================================================================
            if int(app.params['FakeFeedback']):
                import csv
                fp=app.params['FakeFile']
                app.fake_data = np.genfromtxt(fp, delimiter=',')
                np.random.shuffle(app.fake_data)

            #===================================================================
            # We need to know how many blocks per feedback period
            # so (non-bar) feedback can be scaled appropriately.
            #===================================================================
            fbdur = app.params['TaskDur'].val #feedback duration
            fbblks = fbdur * app.eegfs / app.spb #feedback blocks

            #===================================================================
            # Visual Feedback
            #===================================================================
            if app.params['VisualFeedback'].val:
                #===================================================================
                # Set a coordinate frame for the screen.
                #===================================================================
                scrsiz = min(app.scrw,app.scrh)
                siz = (scrsiz, scrsiz)
                b = box(size=siz, position=(app.scrw/2.0,app.scrh/2.0), sticky=True)
                #b is now our perfect box taking up as much of our screen as we are going to use.
                #its center is the center pixel, its width and height are equal to the smallest of screen width and height
                center = b.map((0.5,0.5), 'position') #what is the center pixel value? e.g.([400.0, 225.0])

                #===================================================================
                # TODO: Get the arrows working for more than 2 targets
                #===================================================================
                #===============================================================
                # b.scale(x=0.25,y=0.4)#How big should the arrow be, relative to the screen size
                # 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)
                # app.stimulus('arrow', z=4.5, stim=arrow)#Register the arrow stimulus.
                #
                # b.scale(x=4.0, y=2.5)#Reset the box
                # b.anchor='center'#Reset the box
                #===============================================================

                #===============================================================
                # Target rectangles.
                #===============================================================
                targtw = 0.5
                for x in range(app.nclasses):
                    my_target = app.target_range[x]
                    targ_h = int((my_target[1] - my_target[0]) * scrsiz / 200.0)
                    targ_y = int(center[1] + (my_target[0] + my_target[1]) * scrsiz / 400.0)
                    targ_stim = Block(position = [center[0], targ_y], size = [targtw * scrsiz, targ_h], color=(1, 0.1, 0.1, 0.5), on=False)
                    app.stimulus('target_'+str(x), z=2, stim=targ_stim)

                #Our feedback will range from -10 to +10
                app.m=app.scrh/20.0#Conversion factor from signal amplitude to pixels.
                app.b_offset=app.scrh/2.0 #Input 0.0 should be at this pixel value.

                #===============================================================
                # Add feedback elements
                #===============================================================
                app.vfb_keys = []
                for j in range(app.nclasses):
                    if app.vfb_type[j]==0: #Bar
                        app.addbar(color=(0,0.9,0), pos=(app.scrw/2.0,app.b_offset), thickness=app.scrw/10, fac=app.m)
                        app.vfb_keys.append('barrect_' + str(len(app.bars)))
                        app.stimuli['bartext_'+ str(len(app.bars))].position=(50,50)#off in the lower corner
                        #app.stimuli['bartext_'+ str(len(app.bars))].color=[0,0,0]#hide it
                        app.stimuli['bartext_'+ str(len(app.bars))].on = False#hide it

                    elif app.vfb_type[j]==1: #Cursor
                        app.stimulus('cursor_'+str(j), z=3, stim=Disc(position=(app.scrw/2.0,app.b_offset), radius=10, color=(0.9,0.9,0.9), on=False))
                        app.vfb_keys.append('cursor_'+str(j))
                        #Set cursor speed so that it takes entire feedback duration to go from bottom to top at amplitude 1 (= 1xvar; =10% ERD; =10%MVC)
                        app.curs_speed = scrsiz / fbblks #pixels per block

                    elif app.vfb_type[j]==2: #Color-change circle.
                        app.col_zero = (0, 1, 0)#Green in the middle.
                        app.stimulus('col_circle_'+str(j), z=3, stim=Disc(position=center, radius=100, color=app.col_zero, on=False))
                        app.col_speed = 1.0*(2.0 / fbblks) #Colors will be mapped from -1 to +1. #Trying to double the speed to see if that helps.
                        app.vfb_keys.append('col_circle_'+str(j))

                    elif app.vfb_type[j]==3: #None
                        app.stimulus('cursor_'+str(j), z=-10, stim=Disc(radius=0, color=(0,0,0,0), on=False))
                        app.vfb_keys.append('cursor_'+str(j))

            #===================================================================
            # Audio Feedback
            #===================================================================
            if app.params['AudioFeedback'].val:
            # load, and silently start, the sounds
            # They will be used for cues and for feedback.
                app.sounds = []
                wavmat = app.params['AudioWavs']
                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]
                    app.sounds.append(snd)
                    snd.vol = 0
                    snd.play(-1)
                #Set the speed at which the fader can travel from -1 (sounds[0]) to +1 (sounds[1])
                app.fader_speed = 2 / fbblks

            #===================================================================
            # Handbox Feedback
            #===================================================================
            if app.params['HandboxFeedback'].val:
                from Handbox.HandboxInterface import Handbox
                serPort=app.params['HandboxPort'].val
                app.handbox=Handbox(port=serPort)
                #When x is +1, we have ERD relative to baseline
                #It should take fbblks at x=+1 to travel from 90 to 0
                app.hand_speed = -90 / fbblks #hand speed in degrees per block when x=+1

            #===================================================================
            # Neuromuscular Electrical Stimulation Feedback
            #===================================================================
            if app.params['NMESFeedback'].val:
                stimrange=np.asarray(app.params['NMESRange'].val,dtype='float64')#midpoint and max
                stim_min = 2*stimrange[0] - stimrange[1]
                from Handbox.NMESInterface import NMES
                serPort=app.params['NMESPort'].val
                app.nmes=NMES(port=serPort)
                app.nmes.width = 1.0

                #from Caio.NMES import NMESFIFO
                ##from Caio.NMES import NMESRING
                #app.nmes = NMESFIFO()
                ##app.nmes = NMESRING()
                #app.nmes.running = True

                #It should take fbblks at x=+1 to get intensity from min to max
                app.nmes_baseline = stimrange[0]
                app.nmes_max = stimrange[1]
                app.nmes_i = app.nmes.intensity
                app.nmes_speed = (stimrange[1]-stim_min) / float(fbblks) #nmes intensity rate of change per block when x=+1
    def initialize(cls, app, indim, outdim):
        if int(app.params['ContFeedbackEnable']) == 1:
            if int(app.params['ShowSignalTime']):
                app.addstatemonitor('FBValue')
                app.addstatemonitor('FBBlock')
                app.addstatemonitor('Feedback')
                app.addstatemonitor('InRange')

            #===================================================================
            # Load fake data if we will be using fake feedback.
            #===================================================================
            if int(app.params['FakeFeedback']):
                import csv
                fp = app.params['FakeFile']
                app.fake_data = np.genfromtxt(fp, delimiter=',')
                np.random.shuffle(app.fake_data)

            #===================================================================
            # We need to know how many blocks per feedback period
            # so (non-bar) feedback can be scaled appropriately.
            #===================================================================
            fbdur = app.params['TaskDur'].val  #feedback duration
            fbblks = fbdur * app.eegfs / app.spb  #feedback blocks

            #===================================================================
            # Visual Feedback
            #===================================================================
            if app.params['VisualFeedback'].val:
                #===================================================================
                # Set a coordinate frame for the screen.
                #===================================================================
                scrsiz = min(app.scrw, app.scrh)
                siz = (scrsiz, scrsiz)
                b = box(size=siz,
                        position=(app.scrw / 2.0, app.scrh / 2.0),
                        sticky=True)
                #b is now our perfect box taking up as much of our screen as we are going to use.
                #its center is the center pixel, its width and height are equal to the smallest of screen width and height
                center = b.map(
                    (0.5, 0.5), 'position'
                )  #what is the center pixel value? e.g.([400.0, 225.0])

                #===================================================================
                # TODO: Get the arrows working for more than 2 targets
                #===================================================================
                #===============================================================
                # b.scale(x=0.25,y=0.4)#How big should the arrow be, relative to the screen size
                # 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)
                # app.stimulus('arrow', z=4.5, stim=arrow)#Register the arrow stimulus.
                #
                # b.scale(x=4.0, y=2.5)#Reset the box
                # b.anchor='center'#Reset the box
                #===============================================================

                #===============================================================
                # Target rectangles.
                #===============================================================
                targtw = 0.5
                for x in range(app.nclasses):
                    my_target = app.target_range[x]
                    targ_h = int(
                        (my_target[1] - my_target[0]) * scrsiz / 200.0)
                    targ_y = int(center[1] + (my_target[0] + my_target[1]) *
                                 scrsiz / 400.0)
                    targ_stim = Block(position=[center[0], targ_y],
                                      size=[targtw * scrsiz, targ_h],
                                      color=(1, 0.1, 0.1, 0.5),
                                      on=False)
                    app.stimulus('target_' + str(x), z=2, stim=targ_stim)

                #Our feedback will range from -10 to +10
                app.m = app.scrh / 20.0  #Conversion factor from signal amplitude to pixels.
                app.b_offset = app.scrh / 2.0  #Input 0.0 should be at this pixel value.

                #===============================================================
                # Add feedback elements
                #===============================================================
                app.vfb_keys = []
                for j in range(app.nclasses):
                    if app.vfb_type[j] == 0:  #Bar
                        app.addbar(color=(0, 0.9, 0),
                                   pos=(app.scrw / 2.0, app.b_offset),
                                   thickness=app.scrw / 10,
                                   fac=app.m)
                        app.vfb_keys.append('barrect_' + str(len(app.bars)))
                        app.stimuli['bartext_' +
                                    str(len(app.bars))].position = (
                                        50, 50)  #off in the lower corner
                        #app.stimuli['bartext_'+ str(len(app.bars))].color=[0,0,0]#hide it
                        app.stimuli['bartext_' +
                                    str(len(app.bars))].on = False  #hide it

                    elif app.vfb_type[j] == 1:  #Cursor
                        app.stimulus('cursor_' + str(j),
                                     z=3,
                                     stim=Disc(position=(app.scrw / 2.0,
                                                         app.b_offset),
                                               radius=10,
                                               color=(0.9, 0.9, 0.9),
                                               on=False))
                        app.vfb_keys.append('cursor_' + str(j))
                        #Set cursor speed so that it takes entire feedback duration to go from bottom to top at amplitude 1 (= 1xvar; =10% ERD; =10%MVC)
                        app.curs_speed = scrsiz / fbblks  #pixels per block

                    elif app.vfb_type[j] == 2:  #Color-change circle.
                        app.col_zero = (0, 1, 0)  #Green in the middle.
                        app.stimulus('col_circle_' + str(j),
                                     z=3,
                                     stim=Disc(position=center,
                                               radius=100,
                                               color=app.col_zero,
                                               on=False))
                        app.col_speed = 1.0 * (
                            2.0 / fbblks
                        )  #Colors will be mapped from -1 to +1. #Trying to double the speed to see if that helps.
                        app.vfb_keys.append('col_circle_' + str(j))

                    elif app.vfb_type[j] == 3:  #None
                        app.stimulus('cursor_' + str(j),
                                     z=-10,
                                     stim=Disc(radius=0,
                                               color=(0, 0, 0, 0),
                                               on=False))
                        app.vfb_keys.append('cursor_' + str(j))

            #===================================================================
            # Audio Feedback
            #===================================================================
            if app.params['AudioFeedback'].val:
                # load, and silently start, the sounds
                # They will be used for cues and for feedback.
                app.sounds = []
                wavmat = app.params['AudioWavs']
                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]
                    app.sounds.append(snd)
                    snd.vol = 0
                    snd.play(-1)
                #Set the speed at which the fader can travel from -1 (sounds[0]) to +1 (sounds[1])
                app.fader_speed = 2 / fbblks

            #===================================================================
            # Handbox Feedback
            #===================================================================
            if app.params['HandboxFeedback'].val:
                from Handbox.HandboxInterface import Handbox
                serPort = app.params['HandboxPort'].val
                app.handbox = Handbox(port=serPort)
                #When x is +1, we have ERD relative to baseline
                #It should take fbblks at x=+1 to travel from 90 to 0
                app.hand_speed = -90 / fbblks  #hand speed in degrees per block when x=+1

            #===================================================================
            # Neuromuscular Electrical Stimulation Feedback
            #===================================================================
            if app.params['NMESFeedback'].val:
                stimrange = np.asarray(app.params['NMESRange'].val,
                                       dtype='float64')  #midpoint and max
                stim_min = 2 * stimrange[0] - stimrange[1]
                from Handbox.NMESInterface import NMES
                serPort = app.params['NMESPort'].val
                app.nmes = NMES(port=serPort)
                app.nmes.width = 1.0

                #from Caio.NMES import NMESFIFO
                ##from Caio.NMES import NMESRING
                #app.nmes = NMESFIFO()
                ##app.nmes = NMESRING()
                #app.nmes.running = True

                #It should take fbblks at x=+1 to get intensity from min to max
                app.nmes_baseline = stimrange[0]
                app.nmes_max = stimrange[1]
                app.nmes_i = app.nmes.intensity
                app.nmes_speed = (stimrange[1] - stim_min) / float(
                    fbblks)  #nmes intensity rate of change per block when x=+1