nuff said
[TrainBwister.git] / trainbwister.py
blob8921d6650c2cbad892dfa5259050725cc4ea8a5d
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 # sometimes the random distribution of stimuli results in a very low interaction on your part.
23 # in order to address this, do some ITERATIONS and take the maximum of all random distributions.
24 ITERATIONS = 15
26 # UPPER ThresHold, above which N is increased
27 UPPERTH = 90
29 # LOWER ThresHold, below which N is decreased
30 LOWERTH = 75
32 # SIZE of FONT
33 FONTSIZE = 20
35 KEYLEFT = "a"
36 KEYRIGHT = "o"
37 SPACE = " "
38 IFS = ['1.png','2.png','3.png','4.png','5.png','6.png','7.png','8.png']
39 SFS = ['1.ogg','2.ogg','3.ogg','4.ogg','5.ogg','6.ogg','7.ogg','8.ogg']
41 ### END CONFIGURATION SECTION ###
43 TRIALS = MINTRIALS + N
44 TOPLEFT =((RESOLUTION[0]-SIZE[0])/2,(RESOLUTION[1]-SIZE[1])/2)
46 import time, sys
47 from random import randint
48 from pygame import display, image, key, Surface, mixer, event, mouse, font
49 from pygame import FULLSCREEN, KEYDOWN
50 from pygame.transform import scale
52 def selftests():
53 die = None
54 for f in IFS+SFS:
55 try:
56 open(f,"rb")
57 except IOError, e:
58 die = e
59 print >> sys.stderr, "FATAL:",die
60 if die:
61 raise die
63 if not len(IFS) == len(SFS):
64 print >> sys.stderr, "FATAL: amount of stimuli for different modalities do not match!"
65 sys.exit(1)
67 class Trial:
68 def __init__(self,imagefile,soundfile,trgtimg,trgtsnd):
69 self.image = scale(image.load(imagefile), SIZE).convert()
70 self.sound = mixer.Sound(soundfile)
71 self.trgtimg = trgtimg
72 self.trgtsnd = trgtsnd
73 self.result = [not(self.trgtimg),not(self.trgtsnd)]
75 def runtrial(self):
76 surface = display.get_surface()
77 surface.fill((255,255,255))
78 surface.blit(self.image,TOPLEFT)
79 display.flip()
80 self.sound.play()
81 time.sleep(ST_LENGTH)
82 surface.fill((255,255,255))
83 display.flip()
84 time.sleep(TB_LENGTH)
85 keypresses = []
86 for e in event.get(KEYDOWN):
87 keypresses += [e.dict['unicode']]
88 if unicode(KEYLEFT) in keypresses:
89 if self.trgtimg:
90 #print "user hit key \""+ KEYLEFT +"\" correctly"
91 self.result[0] = True
92 else:
93 #print "user hit key \""+ KEYLEFT +"\" incorrectly"
94 self.result[0] = False
95 if unicode(KEYRIGHT) in keypresses:
96 if self.trgtsnd:
97 #print "user hit key \""+ KEYRIGHT +"\" correctly"
98 self.result[1] = True
99 else:
100 #print "user hit key \""+ KEYRIGHT +"\" incorrectly"
101 self.result[1] = False
103 def nfroml(n,l):
104 if n > 0:
105 return [l[randint(0,len(l)-1)]]+nfroml(n-1,l)
106 else:
107 return []
109 def nback(n,l):
110 if n >= len(l):
111 return 0
112 elif l[0] == l[n]:
113 return 1+nback(n,l[1:])
114 else:
115 return nback(n,l[1:])
117 def cheatshuffle(l):
118 tmp1 = nfroml(TRIALS,l)
119 positives1 = nback(N,tmp1)
120 for i in range(0,ITERATIONS):
121 tmp2 = nfroml(TRIALS,l)
122 positives2 = nback(N,tmp2)
123 if positives1 < positives2:
124 #print positives1, "<", positives2
125 tmp1 = tmp2
126 positives1 = positives2
127 return tmp1
129 def gentrials():
130 trials = []
131 iis = cheatshuffle(range(0,len(IFS)-1))
132 sis = cheatshuffle(range(0,len(SFS)-1))
133 for i,j,k in zip(iis,sis,range(0,len(iis)-1)):
134 if k < N:
135 trials.append(Trial(IFS[i],SFS[j],False,False))
136 else:
137 nb = k - N
138 trials.append(Trial(IFS[i],SFS[j],iis[k]==iis[nb],sis[k]==sis[nb]))
139 return trials
141 def qcont(string):
142 event.clear()
143 mf = font.Font(font.get_default_font(),FONTSIZE)
144 foo = display.get_surface()
145 foo.fill((0,0,0))
146 foo.blit(mf.render(string,True,(0,255,0),(0,0,0)),TOPLEFT)
147 display.flip()
148 es = []
149 while not es:
150 for e in event.get(KEYDOWN):
151 es += [e.dict['unicode']]
152 if SPACE in es:
153 return True
154 else:
155 return False
159 def main():
160 selftests()
161 global N
162 while 1:
163 display.init()
164 display.set_mode(RESOLUTION, FULLSCREEN)
165 font.init()
166 mixer.init(44100)
167 event.set_grab(True)
168 mouse.set_visible(False)
169 trials = gentrials()
170 for trial in trials:
171 trial.runtrial()
172 print trial.result
173 display.quit()
174 vis = 0.0
175 acu = 0.0
176 for trial in trials:
177 if trial.result[0]:
178 vis+=1
179 if trial.result[1]:
180 acu+=1
181 vp = (vis/TRIALS)*100
182 ap = (acu/TRIALS)*100
183 message = """percentage in visual modality:%i\n
184 percentage in acoustic modality:%i\n""" %(int(vp),int(ap))
185 print message
186 if vp >= UPPERTH and ap >= UPPERTH:
187 N+=1
188 elif vp < LOWERTH or ap < LOWERTH and N > 1:
189 N-=1
191 if __name__ == "__main__":
192 main()