Commits

Anonymous committed baecb37

Added Discrimination2_6.py

CS- is now valve 4
Now, the scent starts loading 1 second prior to the end of the ITI
and continues to load until the end of the trial (must keep an eye on odorant
levels)
Now a trial is simply the 1.2 s of response time. If we get too many false
alarms, we can always extend the response time.

Comments (0)

Files changed (4)

 from __init__ import *
 
 class Box_Test(InternalEvent):
-    def update(self):
-        if self.bReinforcement == True:
-            self.bReinforcement = self.reinforceUpdate()
     
+    def __init__(self): #add something to allow the starting block to be differnet
+        super(Box_Test, self).__init__() 
+        self.curState = 0
+        
+    def update(self):  
     
-    def toggleLight(self):
-        pass
+        curStateUpdate = getattr(self,'updateState%d' % self.curState)
+        curStateUpdate()
     
+    
+    
+    def updateState0:
+        
     

Discrimination2_6.py

+from __init__ import *
+import random
+
+class Discrimination2(InternalEvent):
+    '''
+    Basic replication of the D2 program in BBC basic
+    '''
+
+    def __init__(self, startBlock = 1, sessionType = 'D2', listExperimentInfo = ['default','mouse','experiment','tech','']): #add something to allow the starting block to be differnet
+        super(Discrimination2, self).__init__() 
+
+        self.curBlock = startBlock -2
+        self.sessionType = sessionType
+        self.initVars()
+        
+        
+        self.strExperimentInfo = listExperimentInfo
+        self.dataFile = OutputData(self.strExperimentInfo[0], self.strExperimentInfo[1],self.strExperimentInfo[2], self.strExperimentInfo[3], self.strExperimentInfo[4])
+        self.dataFileLong = OutputData(self.strExperimentInfo[0]+'Long', self.strExperimentInfo[1],self.strExperimentInfo[2], self.strExperimentInfo[3], self.strExperimentInfo[4])
+        #self.startIti(self.itiTime)    
+        self.newBlock()
+        
+        
+    def initVars(self):
+        self.statesStarted = 8*[0]
+        self.curState = 0
+
+
+        self.bTrialFinished = False
+        self.binRespList = -999
+        self.bReinforcement = False
+        self.bReinforcementAvailable = False
+        self.bItiReady = True
+
+        self.curTrialType = 'nan'
+        self.bContinuePhase = True
+        self.scentLoadTime = 0.5
+        self.maxValveOpenTime = 30
+        self.responseWindow = 2
+        self.sampleWindow = 0.5
+        self.repeatTrial = False
+        #self.reDoMissedTrials = False
+        #self.trialsPerBlock = 20
+        
+
+        
+        self.changingTrialLength = False
+        
+        #Valve Assignment
+
+        self.csPlusValve = 1
+        self.csMinusValve = 4
+        self.neutralValve = 2
+        self.genValve1 = 2
+        self.genValve2 = 3
+        self.genValve3 = 3
+        
+        if self.sessionType == 'D2':
+            #simple semi-random alternation between S+ and S-
+            self.totalBlocks = 10
+            self.blockTypes = ['Warmup'] + 9*['D2']
+            self.itiTime = self.totalBlocks*[5]
+            
+        elif self.sessionType == 'D2P2':
+            self.totalBlocks = 20
+            self.blockTypes = ['Warmup'] + 19*['D2P2']
+            self.itiTime = self.totalBlocks*[5]
+            
+        elif self.sessionType == 'GENTEST':
+            self.blockTypes = ['Warmup'] + 9*['GEN']
+            self.totalBlocks = self.blockTypes.__len__()
+            self.itiTime = self.totalBlocks*[5]            
+            
+        elif self.sessionType == 'Init1':
+            self.blockTypes = 4*['N1.0'] + 4*['N0.8'] + 4*['N0.6']
+            self.totalBlocks = self.blockTypes.__len__()
+            self.itiTime = self.totalBlocks*[5]
+            self.changingTrialLength = True
+            self.scentLoadTimeList = [0.2,0.2,0.3,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.0]
+            self.responseWindowList = [1.0, 1.2, 1.2, 1.4, 1.4, 1.6, 1.6, 1.8, 1.8, 2.0, 2.0, 2.0]
+            
+            
+        self.curBlockHits = self.totalBlocks*[0] #met the interval threshold
+        self.curBlockMisses = self.totalBlocks*[0] #missed the interval threshold
+        self.curBlockFalseAlarms = self.totalBlocks*[0] #made the interval but didn't lick
+        self.curBlockCorRejs = self.totalBlocks*[0]
+        self.curBlockAbstains = self.totalBlocks*[0]
+        
+        
+        self.GenPHits = 0
+        self.Gen1Hits = 0
+        self.Gen2Hits = 0
+        self.Gen3Hits = 0
+        self.GenPMiss = 0
+        self.Gen1Miss = 0
+        self.Gen2Miss = 0
+        self.Gen3Miss = 0
+        
+        self.bHeadTimeCount = False
+        
+    def headUpdate(self):
+        '''
+        Records Head Entry/Exits
+        '''
+        if self.bHeadTimeCount == True and self.bHeadIn == False:
+                self.bHeadTimeCount = False
+                headTimeIn = self.headUpdateTimer.timeSince()
+                self.dataFileLong.writeData(self.strCurBlockTrial + 'HEADOUT,' + str(headTimeIn))
+                print('Head Out')
+            
+        elif self.bHeadTimeCount == False and self.bHeadIn == True:
+                self.bHeadTimeCount = True
+                self.headUpdateTimer = RunInternalTimer()
+                self.dataFileLong.writeData(self.strCurBlockTrial + 'HEADIN,')
+                print('Head In')
+        
+    def update(self):
+        self.updateInputs()
+        
+        self.strCurBlockTrial = 'TIME,' + str(self.internalSessionTime.timeSince()) + ',BLOCK,' + str(self.curBlock) + ',TRIAL, ' + str(self.curTrialInBlock) + ','
+        
+        self.headUpdate()
+        curStateUpdate = getattr(self,'updateState%d' % self.curState)
+        curStateUpdate()
+        if self.curBlock > self.totalBlocks:
+            self.bContinuePhase = False
+        return self.bContinuePhase
+
+
+    
+    def updateState0(self):
+        '''        
+        ITI Component
+        
+        '''
+        self.repeatTrial = False
+        if self.statesStarted[self.curState] == False and self.bHeadIn == False:
+            
+            self.statesStarted[self.curState] = True
+            self.curTrialType = self.curTrialBlockList[self.curTrialInBlock]
+            self.dataFileLong.writeData(self.strCurBlockTrial + 'STARTTRIAL,' + self.curTrialType )
+                
+            if self.curTrialType == '+' or self.curTrialType == '+NR' or self.curTrialType == 'Gen+': #a reinforcer trial, or a CS+ trial with no reinforcer (+NR)
+                self.curValve =self.csPlusValve
+            elif self.curTrialType == '-':
+                self.curValve = self.csMinusValve
+            elif self.curTrialType == 'N+' or self.curTrialType == 'N-':
+                self.curValve = self.neutralValve
+            elif self.curTrialType == 'G1':
+                self.curValve = self.genValve1
+            elif self.curTrialType == 'G2':
+                self.curValve = self.genValve2                
+            elif self.curTrialType == 'G3':
+                self.curValve = self.genValve3
+                
+                
+            #ITI Time of the current block   
+            self.startIti(self.itiTime[self.curBlock]) #Start the ITI using the
+            valveTimer = max([self.itiTime[self.curBlock] - 2,0])
+            self.startValveTimer = RunInternalTimer(valveTimer)
+            
+        
+        
+        if self.startValveTimer.countDownComplete() and self.statesStarted[self.curState] == True:
+            self.finalValveOn()            
+            self.valveOn(self.curValve)
+            
+
+            
+            
+        if self.ItiTimerRun.countDownComplete() and self.bHeadIn == False and self.statesStarted[self.curState] == True:
+            self.endIti()
+            self.curState = 1
+            
+
+            
+    def updateState1(self):
+        '''        
+        start of trial, wait for a head entry
+        '''
+        if self.statesStarted[self.curState] == False and self.bHeadIn == False:
+            self.statesStarted[self.curState] = True
+            
+        if self.statesStarted[self.curState] == True and self.bHeadIn == True:
+            self.curState = 2
+            
+    def updateState2(self):
+        '''
+        Check to see if the head entry is more then 0.1 seconds. If so, continue
+        '''
+        if self.statesStarted[self.curState] == False and self.bHeadIn == True:
+            self.headInCheckTimer = RunInternalTimer(0.1)
+            self.statesStarted[self.curState] = True
+        if self.bHeadIn == False:
+            self.statesStarted[self.curState] = False
+        
+        if self.statesStarted[self.curState] == True and self.headInCheckTimer.countDownComplete():
+                self.dataFileLong.writeData(self.strCurBlockTrial + 'MOUSESTART,')
+                self.finalValveOff()
+                self.lightOn()
+                self.curState = 5
+        
+#no longer needed
+#    def updateState3(self):
+#        #turn on final valve and CS valve for 1 sec
+#        
+#        if self.statesStarted[self.curState] == False:
+#            self.statesStarted[self.curState] = True
+#            self.lightOn()
+#
+#
+#        if self.valveTimer.countDownComplete():
+#            self.dataFileLong.writeData(self.strCurBlockTrial + 'SCENT ON,')
+#            self.finalValveOff()
+#            del self.valveTimer
+#            self.curState = 4
+#            
+    
+#    def updateState4(self):
+#        '''
+#        Turn off the final valve, releasing scent
+#        
+#        '''
+#        if self.statesStarted[self.curState] == False:
+#            self.statesStarted[self.curState] = True
+#            self.nextState = RunInternalTimer(self.sampleWindow)
+#            if self.bHeadIn == False:
+#                self.dataFileLong.writeData(self.strCurBlockTrial +'HEADOUTATSCENT, ')
+#        if self.nextState.countDownComplete():
+#            self.dataFileLong.writeData(self.strCurBlockTrial +'SWINDOW, ')
+#            #self.valveOff(self.curValve)
+#            self.curState = 5
+        #self.noHeadEntryEndTrial
+            
+#    def updateState4(self):
+#        '''
+#        This state is now unneccesary
+#        '''
+#        #wait for 0.5 s, then start recording responses
+#        if self.statesStarted[self.curState] == False:
+#            self.statesStarted[self.curState] = True
+#            self.samplingTimer = RunInternalTimer(0.5)
+#        
+#        if self.samplingTimer.countDownComplete():
+#            del self.samplingTimer
+#            
+#            self.curState = 5
+            
+    def updateState5(self):
+        #discrimination trial record
+        if self.bHeadIn:
+            if self.statesStarted[self.curState] == False:
+                
+
+                self.dataFileLong.writeData(self.strCurBlockTrial +'RESPSTART, ')
+                self.statesStarted[self.curState] = True
+                self.curTrialRun = BinnedIntervalCount(self.responseWindow,0.2,0.6)
+            self.bTrialFinished, self.bReinforcementAvailable, self.binRespList \
+                = self.curTrialRun.update(self.bLickOn)
+                
+            if self.bTrialFinished == True:
+                
+                self.dataFileLong.writeData(self.strCurBlockTrial +'RESPFIN, ' + str(sum(self.binRespList)))
+                self.curState = 6
+                self.valveOff(self.curValve)
+        else:
+            self.dataFileLong.writeData(self.strCurBlockTrial +'RESPABORT, ')
+            self.bTrialFinished == True
+            self.bReinforcementAvailable = False
+            self.curState = 6
+            self.valveOff(self.curValve)
+#            self.curBlockAbstains[self.curBlock] += 1
+#            print(self.curBlockAbstains)
+            
+    def updateState6(self):
+        
+        '''
+        Assess what kind of outcome to record and whether to go to reinforcement or not
+        note that returning 'bReinforcementAvailable' doesn't neccesarily mean the trial should be
+        reinforced, only that a response was completed.
+        '''
+        
+        self.statesStarted[self.curState] = True
+        
+        if self.curTrialType == '+':
+            if self.bReinforcementAvailable == True: #reinforcement available is a minsnomer here, it should be something like 'if lick program reports completion'
+                self.curBlockHits[self.curBlock] += 1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'HIT, ')
+                self.curState = 7            
+            else:
+                self.curBlockMisses[self.curBlock] += 1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'MISS, ')
+                self.curState = 8
+        elif self.curTrialType == '-':
+            if self.bReinforcementAvailable == True:
+                self.curBlockFalseAlarms[self.curBlock] +=1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'FA, ')
+            else:
+                self.curBlockCorRejs[self.curBlock] +=1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'CR, ')
+            self.curState = 8
+        elif self.curTrialType == 'N+' or self.curTrialType == 'N-':
+            if self.bReinforcementAvailable == True:
+                self.curBlockHits[self.curBlock] += 1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'HIT, ')
+            else:
+                self.curBlockMisses[self.curBlock] += 1
+                if self.curTrialType == 'N+': #if it's an N+ (training) trial, and they missed by taking their head out, repeat the trial
+                    self.repeatTrial = True
+            if self.curTrialType == 'N+':
+                self.curState = 7
+            else:
+                self.curState = 8
+
+        elif self.curTrialType == '+NR':
+            if self.bReinforcementAvailable == True: #reinforcement available is a minsnomer here, it should be something like 'if lick program reports completion'
+                self.curBlockHits[self.curBlock] += 1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'HIT, ')
+                self.curState = 8            
+            else:
+                self.curBlockMisses[self.curBlock] += 1
+                self.dataFileLong.writeData(self.strCurBlockTrial +'MISS, ')
+                self.curState = 8
+        
+        elif self.curTrialType == 'Gen+' or self.curTrialType == 'G1' or self.curTrialType == 'G2' or self.curTrialType == 'G3':
+            if self.bReinforcementAvailable == True: #reinforcement available is a minsnomer here, it should be something like 'if lick program reports completion'
+                bGenHit = True
+                self.dataFileLong.writeData(self.strCurBlockTrial +'HIT, ')
+            else:
+                bGenHit = False
+                self.dataFileLong.writeData(self.strCurBlockTrial +'MISS, ')
+            if self.curTrialType == 'Gen+':
+                if bGenHit:
+                    self.GenPHits += 1
+                else:
+                    self.GenPMiss += 1    
+            elif self.curTrialType == 'G1':
+                if bGenHit:
+                    self.Gen1Hits += 1
+                else:
+                    self.Gen1Miss += 1   
+            elif self.curTrialType == 'G2':
+                if bGenHit:
+                    self.Gen2Hits += 1
+                else:
+                    self.Gen2Miss += 1                   
+            elif self.curTrialType == 'G3':
+                if bGenHit:
+                    self.Gen3Hits += 1
+                else:
+                    self.Gen3Miss += 1
+            
+                
+            bGenHit = False
+            self.curState = 8
+        
+            
+        else:
+            print 'Unknown Trial Type'
+                
+            
+    def updateState7(self):
+        #reinforcement state
+        if self.statesStarted[self.curState] == False:
+            self.statesStarted[self.curState] = True
+            self.bReinforcement = True
+            self.reinforceOn()
+            self.dataFileLong.writeData(self.strCurBlockTrial + 'REINF, ')
+            print 'reinforcer'
+        self.bReinforcement = self.reinforceUpdate()
+        if self.bReinforcement == False:
+            self.curState = 8            
+        
+    def updateState8(self):
+        #end of trial state
+        print 'end trial'
+        self.dataFileLong.writeData(self.strCurBlockTrial + 'TRIALEND, ')
+        self.valveOff(self.curValve)
+        self.finalValveOff()
+        self.lightOff()
+        self.checkBlockCount()
+        if 'self.curTrialRun' in locals():
+            print 'cur trial run removed'
+            del self.curTrialRun    
+        if self.bContinuePhase == True:
+            self.statesStarted = 8*[0]
+            self.curState = 0
+        
+        
+    def checkBlockCount(self):
+        if self.repeatTrial == True: #if repeat trial, don't advance the current trial in the block
+            pass
+        else:
+            
+            self.curTrialInBlock += 1
+        if self.curTrialInBlock > self.trialsPerBlock - 1: #-
+            self.newBlock()            
+            
+            print 'end of block'
+        if self.curBlock > self.totalBlocks:
+            self.reinforcerShutDown()
+            self.bContinuePhase = False
+            print'end of Phase'
+            
+        
+    def newBlock(self):
+        self.curBlock += 1
+        self.curTrialInBlock = 0
+        self.curTrialBlockList = self.determineTrialOrderWithinBlock(self.blockTypes[self.curBlock])
+        self.trialsPerBlock = self.curTrialBlockList.__len__()        
+        self.determineTrialTimes()
+        self.writeData()
+        
+    def writeData(self):
+        strWriteBlock = 'SUMMARY, BLOCK, ' + str(self.curBlock)
+        strWriteHits = 'SUMMARY, HITS, ' + str(self.curBlockHits)
+        strWriteMisses = 'SUMMARY, MISS, ' + str(self.curBlockMisses)
+        strWriteFA = 'SUMMARY, FALS, ' + str(self.curBlockFalseAlarms)
+        strWriteCR = 'SUMMARY, CORJ, ' + str(self.curBlockCorRejs)
+        strWriteAB = 'SUMMARY, ABST, ' + str(self.curBlockAbstains)
+        self.dataFile.writeData(strWriteBlock)
+        self.dataFile.writeData(strWriteHits)
+        self.dataFile.writeData(strWriteMisses)
+        self.dataFile.writeData(strWriteFA)
+        self.dataFile.writeData(strWriteCR)
+        
+        if self.sessionType == 'GENTEST':
+            strGPHits = 'SUMMARY, Gen+Hits, ' + str(self.GenPHits)
+            strGPMiss = 'SUMMARY, Gen+Miss, ' + str(self.GenPMiss)
+            strG1Hits = 'SUMMARY, G1Hits, ' + str(self.Gen1Hits)
+            strG1Miss = 'SUMMARY, G1Miss, ' + str(self.Gen1Miss)            
+            strG2Hits = 'SUMMARY, G2Hits, ' + str(self.Gen2Hits)
+            strG2Miss = 'SUMMARY, G2Miss, ' + str(self.Gen2Miss)
+            strG3Hits = 'SUMMARY, G3Hits, ' + str(self.Gen3Hits)
+            strG3Miss = 'SUMMARY, G3Miss, ' + str(self.Gen3Miss)      
+            
+            self.dataFile.writeData(strGPHits)
+            self.dataFile.writeData(strGPMiss)
+            self.dataFile.writeData(strG1Hits)
+            self.dataFile.writeData(strG1Miss)
+            self.dataFile.writeData(strG2Hits)
+            self.dataFile.writeData(strG2Miss)
+            self.dataFile.writeData(strG3Hits)
+            self.dataFile.writeData(strG3Miss)
+            
+        #self.writeSummarySigDetect()
+        #self.dataFile.writeData(strWriteAB)
+    
+    def writeSummarySigDetect(self):
+        if sessionType == 'D2':        
+            hits = sum(self.curBlockHits) - self.curBlockHits[0]
+            FA = sum(self.curBlockFalseAlarms) - self.curBlockFalseAlarms[0]
+            misses = sum(self.curBlockMisses) - self.curBlockMisses[0]
+            CR = sum(self.curBlockCorRejs) - self.curBlockCorRejs[0]
+            
+            hitP = hits / (hits + misses)
+            FAP = FA / (FA + CR)
+            
+            strHitP = 'SUMMARY, HITP, ' + str(hitP)
+            strFAP = 'SUMMARY, FAP, ' + str(FAP)
+            self.dataFile.writeData(strHitP)
+            self.dataFile.writeData(strFAP)
+    
+    def noHeadEntryEndTrial(self):
+        if self.bHead == False:
+            self.curState = 8
+
+    def determineTrialTimes(self):
+        if self.changingTrialLength:
+            self.scentLoadTime = self.scentLoadTimeList[self.curBlock]
+            self.responseWindow = self.responseWindowList[self.curBlock]
+            #self.sampleWindow = 0.5
+            
+        
+    def determineTrialOrderWithinBlock(self, blockType):
+        '''
+        Trials here are divided into '1' and '0', where 
+        '+' trials are S+
+        '-' trials are S-
+        'N+' trials are reinforced Neutral Trials
+        'N-' trials are unreinforced Neutral Trials
+        
+        trialBlockLength should be a multiple of 4 for D2
+        '''
+        
+        if blockType == 'D2P2':
+            #10 trials
+            basicList1 = ['+','-']
+            basicList2 = ['+','-','-','+NR']
+            trialListInBlock = []
+           # repeatingOfBasicList = round(trialBlockLength / basicList.__len__())
+            
+            
+            
+            for i in range(3):
+                randomList = random.sample(basicList1,2)
+                trialListInBlock = trialListInBlock + randomList
+            
+            randomList2 = random.sample(basicList2,4)
+            trialListInBlock = trialListInBlock + randomList2
+                
+                
+        elif blockType == 'D2':
+            basicList = ['+','+','-','-']
+            trialListInBlock = []
+           # repeatingOfBasicList = round(trialBlockLength / basicList.__len__())
+            
+            for i in range(5):
+                randomList = random.sample(basicList,4)
+                trialListInBlock = trialListInBlock + randomList
+        elif blockType == 'Warmup':
+            #Ten Trials of Normal
+            baseNum = 10
+            if self.sessionType == 'GENTEST':
+                baseNum = 20
+            trialListInBlock = baseNum*['+']
+            
+        elif blockType == 'N1.0':
+            trialListInBlock = 10*['N+']
+            trialListInBlock = random.sample(trialListInBlock,10)
+        elif blockType == 'N0.8':
+            trialListInBlock = 8*['N+'] + 2*['N-']
+            trialListInBlock = random.sample(trialListInBlock,10)
+        elif blockType == 'N0.6':
+            trialListInBlock = 6*['N+'] + 4*['N-']
+            trialListInBlock = random.sample(trialListInBlock,10)
+            
+        elif blockType == 'GEN':
+            basicList = ['Gen+', 'G1','G2','G3']
+            trialListInBlock = []
+            for i in range(5):
+                randomList = random.sample(basicList,4)
+                trialListInBlock = trialListInBlock + randomList
+            
+        else:
+            trialListInBlock = -9999
+            print('WRONG blockType INPUT')    
+        return trialListInBlock
+        
 from PyQt4 import QtCore, QtGui
 from __init__ import *
 import Phase1, Box_Test
-import Discrimination2_5 as D2
+import Discrimination2_6 as D2
 import Phase3_2 as P3
 
 class Communicate(QtCore.QObject):
     def deliverReinf(self):
         self.curPhase.reinforceOn()     
     
-    def changeValveNum(self, valveDesignation):
-        '''
-        valveDesignations:
-        '+'
-        '-'
-        'N'
-        'G1'
-        'G2'
-        'G3'
-        'G4'        
-        '''
     
     def startPhase1(self):
         self.startSession()
 
 # Form implementation generated from reading ui file 'gui.ui'
 #
-# Created: Thu Aug 01 17:37:17 2013
+# Created: Mon Aug 05 16:38:03 2013
 #      by: PyQt4 UI code generator 4.9.6
 #
 # WARNING! All changes made in this file will be lost!