some code cleanup
[TrainBwister.git] / trainbwister.py
blob187b374d974e1040953e6e0cc72d9dffb9341eb3
1 #!/usr/bin/env python
3 ### BEGIN CONFIGURATION SECTION ###
4 # which RESOLUTION?
5 RESOLUTION = (1024,768)
7 # which SIZE of the visible area?
8 SIZE = (600,600)
10 # how many TRIALS per round (MINimum)
11 MINTRIALS = 20
13 # LENGTH of STimulus presentation in seconds
14 ST_LENGTH = 0.5
16 # LENGTH of Break between Trials in seconds
17 TB_LENGTH = 2.5
19 # which N-back initially?
20 N = 1
22 # UPPER ThresHold, above which N is increased
23 UPPERTH = 90
25 # LOWER ThresHold, below which N is decreased
26 LOWERTH = 75
28 # SIZE of FONT
29 FONTSIZE = 20
31 KEYLEFT = "a"
32 KEYRIGHT = "o"
33 SPACE = " "
34 IFS = ['1.png','2.png','3.png','4.png','5.png','6.png','7.png','8.png']
35 SFS = ['1.ogg','2.ogg','3.ogg','4.ogg','5.ogg','6.ogg','7.ogg','8.ogg']
36 BASE = 'base.png'
38 ### END CONFIGURATION SECTION ###
40 TOPLEFT =((RESOLUTION[0]-SIZE[0])/2,(RESOLUTION[1]-SIZE[1])/2)
42 import time, sys, re
43 from random import randint
44 from pygame import display, image, key, Surface, mixer, event, mouse, font
45 from pygame import FULLSCREEN, KEYDOWN
46 from pygame.transform import scale
48 def selftests():
49 die = None
50 for f in IFS+SFS+[BASE]:
51 try:
52 open(f,"rb")
53 except IOError, e:
54 die = e
55 print >> sys.stderr, "FATAL:",die
56 if die:
57 raise die
59 if not len(IFS) == len(SFS):
60 print >> sys.stderr, "FATAL: amount of stimuli for different modalities do not match!"
61 sys.exit(1)
63 class Trial:
64 def __init__(self,imagefile,soundfile,trgtimg,trgtsnd):
65 self.image = scale(image.load(imagefile), SIZE).convert()
66 self.fill = scale(image.load(BASE),SIZE).convert()
67 self.sound = mixer.Sound(soundfile)
68 self.trgtimg = trgtimg
69 self.trgtsnd = trgtsnd
70 self.result = [not(self.trgtimg),not(self.trgtsnd)]
72 def runtrial(self):
73 surface = display.get_surface()
74 surface.fill((255,255,255))
75 surface.blit(self.image,TOPLEFT)
76 display.flip()
77 self.sound.play()
78 time.sleep(ST_LENGTH)
79 surface.blit(self.fill,TOPLEFT)
80 display.flip()
81 time.sleep(TB_LENGTH)
82 keypresses = []
83 for e in event.get(KEYDOWN):
84 keypresses += [e.dict['unicode']]
85 if SPACE in keypresses:
86 return None
87 if unicode(KEYLEFT) in keypresses:
88 if self.trgtimg:
89 #print "user hit key \""+ KEYLEFT +"\" correctly"
90 self.result[0] = True
91 else:
92 #print "user hit key \""+ KEYLEFT +"\" incorrectly"
93 self.result[0] = False
94 if unicode(KEYRIGHT) in keypresses:
95 if self.trgtsnd:
96 #print "user hit key \""+ KEYRIGHT +"\" correctly"
97 self.result[1] = True
98 else:
99 #print "user hit key \""+ KEYRIGHT +"\" incorrectly"
100 self.result[1] = False
101 return True
103 def myrandom(l):
104 result = []
105 for i in range(0,N):
106 result.append(l[randint(0,len(l)-1)])
107 for i in range(0,MINTRIALS):
108 if randint(0,1):
109 result.append(result[-N])
110 else:
111 # be strict about probabilities
112 myl = l[:]
113 myl.pop(result[-N])
114 result.append(myl[randint(0,len(myl)-1)])
115 return result
117 def gentrials():
118 trials = []
119 iis = myrandom(range(0,len(IFS)-1))
120 sis = myrandom(range(0,len(SFS)-1))
121 for i,j,k in zip(iis,sis,range(0,len(iis))):
122 if k < N:
123 trials.append(Trial(IFS[i],SFS[j],False,False))
124 else:
125 nb = k - N
126 trials.append(Trial(IFS[i],SFS[j],iis[k]==iis[nb],sis[k]==sis[nb]))
127 return trials
129 def main():
130 selftests()
131 global N
132 while 1:
133 print "(Hint: while training, you can hit SPACE to abort)"
134 print "Hit '"+KEYLEFT+"' if the",str(N)+". previous image is identical to the one shown"
135 print "Hit '"+KEYRIGHT+"' if the",str(N)+". previous sound is identical to the one heard"
136 while 1:
137 print "Ready to train with N=%i?" %(N),
138 spam = raw_input(" [Yes/No]? ")
139 if re.match("y(es)?", spam, re.I):
140 break
141 elif re.match("n(o)?", spam, re.I):
142 print "bye ._."
143 sys.exit(1)
144 display.init()
145 display.set_mode(RESOLUTION, FULLSCREEN)
146 font.init()
147 mixer.init(44100)
148 event.set_grab(True)
149 mouse.set_visible(False)
150 trials = gentrials()
151 for trial in trials:
152 if not trial.runtrial():
153 break
154 display.quit()
155 vis = 0.0
156 acu = 0.0
157 for trial in trials:
158 if trial.result[0]:
159 vis+=1
160 if trial.result[1]:
161 acu+=1
162 vp = (vis/(MINTRIALS+N))*100
163 ap = (acu/(MINTRIALS+N))*100
164 message = "percentage in visual modality:%i\npercentage in acoustic modality:%i\n" %(int(vp),int(ap))
165 print message
166 if vp >= UPPERTH and ap >= UPPERTH:
167 N+=1
168 elif (vp < LOWERTH or ap < LOWERTH) and N > 1:
169 N-=1
171 if __name__ == "__main__":
172 main()