REM >DelayLib REM ======================================================================== REM Functions common to !AdjDelay, !Richards, !Evenden, !DTrain REM Interaction between those programs and this library is on the complex REM side, relative to most of the code round here. Read them together. REM ======================================================================== REM Decision: nosepoke time/count is irrelevant. We have latencies anyway. REM REM ======================================================================== REM Method (see methods document for a full description) REM ======================================================================== REM 1. Session begins in ITI state - all lights off, levers in. REM 2. Trials begin at regular intervals (the ITI). REM 3. Trial starts - houselight on REM - traylight on REM - wait for nosepoke (=initiation latency) (*) REM 4. Levers - traylight off REM - one/both levers out REM - wait for press (=choice latency) (*) REM 5. Delay - if delay, turn stim light on (or not) REM 6. R'forcement - traylight on REM - deliver pellets separated by pellet_gap REM - wait for poke (*) REM 7. Collection - traylight off REM - wait 6 sec REM - houselight off REM - wait for next trial, or end. REM REM (*) failure leads to ITI state REM REM ======================================================================== REM Thoughts/comments REM ======================================================================== REM * 13-Nov-98. If the rat is nosepoking when the trial begins, it may REM proceed immediately (and will score an initiation latency if ~0). This REM is different from the previous method, which used the centrelight to REM begin a trial. (a) centrelight not visible if you're "in", so made REM some sense to force a withdrawal; (b) but now, if the rat's in it'd be REM daft to make it repoke. REM * If a rat is 'in' when reward is delivered, it is scored as collecting REM with ~0 latency. (Light may flash briefly, never mind.) REM REM ======================================================================== REM Data input REM ======================================================================== REM This library needs to know... REM REM * libraries must have been initialised (e.g. to set box constants) REM * arrays are dimensioned based on maxnchoicetrials% (assumption: maxtrials <= 2 * maxnchoicetrials) REM REM * PROCschedule_next_trial() must set next_trial_type%(box%) REM * PROCtrial_setup() must set adj_delay%(box%,trial%(box%)), REM unadj_delay%(), adj_pellets%(), unadj_pellets%(). REM * PROCtrial_adjustingpoint() is called on trial completion. REM REM pellet_gap% - time between multiple pellets (0.5s) REM lights_bridge_delay% - stimulus light on over lever during delay? (yes%/no%) REM houselights_bridge_delay% - houselight on during delay and "nosh" period... or not? (yes%/no%) [4 Dec 98] REM nchoicetrials% - # of choice trials in the session (not always used - set to a large value) REM REM initiation_limhold% - traylight on, allow initiation for... (10s) REM choice_limhold% - levers out for... (10s) REM (13-Nov-98) collection_limhold% - time traylight is on to allow collection (10s) REM (13-Nov-98) reinf_collect_period% - tune houselight on following successful collection (6s) REM iti_time% - trials start every... REM REM NOTE - ITI *must* exceed the sum of the four variables above, plus the maximum possible delay. REM **** REM REM Other variables are provided (below). REM REM ======================================================================== REM Data output REM ======================================================================== REM PROGNAME - "AdjDelay", "Evenden", "Richards", "DTrain" as appropriate REM DATE_TIME REM RAT REM BOX REM ADJUSTEDLEVER REM SESSION REM TRIAL - trial number, includes forced-choice REM CHOICETRIAL - choice trial number (repeated in forced trials - ignore them) REM INITIATED - was the trial initiated in the limited hold period? REM INITIATIONLATENCY REM STIMULUS - Choice/Adj/Unadj/*** [stars imply initiation omission] REM RESPONSE - Adj/Unadj/Omit [Omit implies choice omission] REM CHOICELATENCY REM UNADJDELAY - unadjusted delay for this session REM ADJDELAY - delay operating on the Adj lever (usually 0) REM UNADJPELLETS REM ADJPELLETS REM PELLETS - number of pellets obtained REM REWARDCOLLECTED - did it nosepoke *before the next trial*? REM (NB can poke after lights out and still score Yes here.) REM COLLECTLATENCY - time to collect first pellet REM CHOICE_POKENUM - number of pokes while levers out REM CHOICE_POKETIME - total duration 'in' REM DELAY_POKENUM - ... during delay period REM DELAY_POKETIME REM FEEDING_POKENUM - ... during 6s feeding period REM FEEDING_POKETIME REM ITI_POKENUM - during ITI to next trial. REM ITI_POKETIME REM REM ======================================================================== REM Revision history REM ======================================================================== REM 26 Oct 98 - running REM 13 Nov 98 - updated with traylights etc. following TWR/YPL meeting REM - PROCreward_collected renamed _obtained to avoid name ambiguity REM 1 Dec 98 - the actual_pellets% system; was a bug where omission was recorded >0. REM - display update code is executed earlier in a function REM to ensure accuracy REM - suspect lever is bouncing; debouncing code added, i.e. kill_switch REM executed by the response code immediately. REM This is sufficient (empirically) and doesn't require software debouncing. REM (Arachnid is not equipped with a "use once" switch pipe.) REM 4 Dec 98 - houselights_bridge_delay% option, defaulted to 1 in PROCdelay_lib_init REM 3 Feb 99 - Implemented nosepoke counting. Output variables are CHOICE_POKENUM, REM CHOICE_POKETIME, DELAY_POKENUM, DELAY_POKETIME, FEEDING_POKENUM, REM FEEDING_POKETIME, ITI_POKENUM, ITI_POKETIME. REM Note that ITIs belong to the preceding trial. (trial% incremented in start_trial) REM 13 Aug 99 - new timer supported, for EVINFUSE. Also fixed a latent timer conflict bug. Surprised to find it. REM - Note that start_time% is used for the clock, but start_time%() for nosepoke timing. Not the best choice of names! DEF PROCdelay_lib_init maxtrials% = maxnchoicetrials% * 2 + 1 pellet_timer% = nboxes% * 0 :REM Arachnid timers iti_timer% = nboxes% * 1 delay_timer% = nboxes% * 2 clock_timer% = nboxes% * 3 + 1 :REM only one is used omission_timer% = nboxes% * 4 session_timer% = nboxes% * 5 + 1 :REM overall session time (DTRAIN only) infusion_timer% = nboxes% * 6 + 1 :REM infusion timer (EVINFUSE only) choice%=0:adj%=1:unadj%=2:omission%=3:notapp%=4 DIM desc$(4):desc$(choice%)="Choice":desc$(adj%)="Adj":desc$(unadj%)="Unadj" desc$(omission%)="Omit":desc$(notapp%)="***" left%=1:right%=2:DIM sidename$(2):sidename$(left%)="L":sidename$(right%)="R" yes%=1:no%=0:DIM yesno$(1):yesno$(yes%)="Y":yesno$(no%)="N" REM no%=0 is an important fixed assignment as vars are initiated to 0! mazur%=0:richards%=1:evenden%=2 DIM unadj_lever%(nboxes%) :REM unadjusted lever line (L/R) DIM adj_lever%(nboxes%) :REM adjusted lever line (L/R) DIM unadj_levercontrol%(nboxes%) :REM unadjusted lever control line (L/R) DIM adj_levercontrol%(nboxes%) :REM adjusted lever control line (L/R) DIM unadj_light%(nboxes%) :REM unadjusted CS light DIM adj_light%(nboxes%) :REM adjusted CS light DIM trial_starttime%(nboxes%) :REM trial start (used for initiation lat.) DIM choice_starttime%(nboxes%) :REM choice start (for choice latency) DIM pellet_starttime%(nboxes%) :REM pellets dispensed (for collect latency) DIM trial%(nboxes%) :REM trial number (includes forced-choice) DIM choicetrial%(nboxes%) :REM choice trial number DIM next_trial_type%(nboxes%) :REM may be choice%, adj%, unadj% DIM finished%(nboxes%) :REM Is the box finished? DIM np_state%(nboxes%) :REM Nosepoke state (was dontcare,waiting,collecting) REM possible states of the box (in temporal order) dontcare%=0 waiting%=1 :REM nosepoke will initiate levers choosing%=2 :REM levers are out, counting pokes delaying%=3 :REM in delay period, silly name, counting pokes collecting%=4 :REM nosepoke will initiate feeding period feeding%=5 :REM in feeding period, counting pokes iti_ing%=6 :REM in ITI, even more silly name, counting pokes DIM subject$(nboxes%) :REM Rat ID DIM adj_side%(nboxes%) :REM may be left%, right% DIM session_number%(nboxes%) :REM user-supplied session# DIM choicetrial_num%(nboxes%,maxtrials%):REM to save recalculation DIM initiated%(nboxes%,maxtrials%) :REM did rat initiate? DIM initiation_lat%(nboxes%,maxtrials%) :REM initiation latency DIM stimulus%(nboxes%,maxtrials%) :REM which lever(s) were presented DIM choice_lat%(nboxes%,maxtrials%) :REM choice latency DIM response%(nboxes%,maxtrials%) :REM which lever was chosen DIM adj_delay%(nboxes%,maxtrials%) :REM function depends on program DIM unadj_delay%(nboxes%,maxtrials%) :REM function depends on program DIM adj_pellets%(nboxes%,maxtrials%) :REM function depends on program DIM unadj_pellets%(nboxes%,maxtrials%) :REM function depends on program DIM actual_pellets%(nboxes%,maxtrials%) :REM actual number of pellets delivered DIM reward_collected%(nboxes%,maxtrials%):REM rat nosepoked before next trial started DIM collect_latency%(nboxes%,maxtrials%):REM latency to collect first pellet DIM pelletcount%(nboxes%) :REM Keeps track of the lardy bastards. DIM adjtotal%(nboxes%) :REM Total choice responses on Adj lever. DIM unadjtotal%(nboxes%) :REM Total choice responses on Unadj lever. DIM omissiontotal%(nboxes%) :REM sum of both kinds of omission houselights_bridge_delay% = no% :REM new default, 3 Feb 99 DIM choice_pokenum%(nboxes%,maxtrials%) :REM see descriptions above DIM choice_poketime%(nboxes%,maxtrials%) DIM delay_pokenum%(nboxes%,maxtrials%) DIM delay_poketime%(nboxes%,maxtrials%) DIM feeding_pokenum%(nboxes%,maxtrials%) DIM feeding_poketime%(nboxes%,maxtrials%) DIM iti_pokenum%(nboxes%,maxtrials%) DIM iti_poketime%(nboxes%,maxtrials%) DIM counting%(nboxes%) :REM for nosepoke counting - are we monitoring? DIM watching%(nboxes%) :REM for nosepoke counting - rat is poking, which state will it be recorded as? DIM start_time%(nboxes%) :REM for nosepoke counting - when this poke began ENDPROC DEF PROCselect_filenames REM made it quicker, 29-Jan-99 REM stopped filenames being the same, 29-Apr-99 PRINT' OSCLI("CAT") REPEAT PRINT datafile$ = FNget_filename("DATA FILE - Filename for output") logfile$ = FNget_filename("TEXT LOGFILE - Filename for output") IF datafile$=logfile$ THEN PRINT"*** Unacceptable, can't have the same name for both." UNTIL datafile$<>logfile$ ENDPROC DEF PROCwarn_kickoff COLOUR3 PRINT''"5. KICKOFF." PRINT "------------" PRINT'"Ensure rats in boxes. Press a key to start.";:COLOUR7:IFGET ENDPROC DEF PROCstart_box(box%) LOCAL dummy% REM 13-Nov-98: houselight off at start PROCswitch_off(houselight%(box%),E%) PROCswitch_off(leftlevercontrol%(box%),E%) PROCswitch_off(rightlevercontrol%(box%),E%) PROCswitch_off(leftlight%(box%),E%) PROCswitch_off(rightlight%(box%),E%) PROCswitch_off(centrelight%(box%),E%) PROCswitch_off(traylight%(box%),E%) PROCswitch_off(pellet%(box%),E%) CASE adj_side%(box%) OF WHEN left%: adj_lever%(box%) = leftlever%(box%) adj_levercontrol%(box%) = leftlevercontrol%(box%) adj_light%(box%) = leftlight%(box%) unadj_lever%(box%) = rightlever%(box%) unadj_levercontrol%(box%) = rightlevercontrol%(box%) unadj_light%(box%) = rightlight%(box%) WHEN right%: unadj_lever%(box%) = leftlever%(box%) unadj_levercontrol%(box%) = leftlevercontrol%(box%) unadj_light%(box%) = leftlight%(box%) adj_lever%(box%) = rightlever%(box%) adj_levercontrol%(box%) = rightlevercontrol%(box%) adj_light%(box%) = rightlight%(box%) OTHERWISE: VDU7:CLS:PRINT"Internal bug in PROCstart_box.":END ENDCASE finished%(box%) = no% trial%(box%) = 0 choicetrial%(box%) = 0 :REM they get incremented in a sec... PROCset_nosepoke_state(box%, dontcare%) :REM deals with np_state%, counting%, watching%. PROCpipe_switch(nosepoke%(box%),Over,1,"FNnosepoke_changed(",box%,E%) dummy% = FNstart_trial(box%,1) REM Oddly, when I used E% there, it never worked (E%=0). REM So beware using that for calling your own functions... ENDPROC REM ======================================================================== REM Major box control functions - INITIATING A TRIAL REM ======================================================================== DEF FNstart_trial(box%,R%) IF R%=0 =0 trial%(box%) += 1 PROCschedule_next_trial(box%) :REM call back to main program IF next_trial_type%(box%)=choice% THEN choicetrial%(box%)+=1 choicetrial_num%(box%,trial%(box%)) = choicetrial%(box%) stimulus%(box%,trial%(box%)) = next_trial_type%(box%) PROCtrial_setup(box%) :REM calls back to the main program REM 13-Nov-98: force call to FNnosepoke_changed if rat is already in, so the trial is started. REM 13-Nov-98: houselight/traylight (rather than centrelight) REM 1-Dec-98: moved the nosepoke initiation code to the end of this function (else display functions get called in wrong order?) PROCupdate_box(box%) PROCupdate_box_state(box%,"Poke?") PROCswitch_on(houselight%(box%),E%) PROCswitch_on(traylight%(box%),E%) IF initiation_limhold%>0 THEN PROCpipe_timer(omission_timer%+box%,initiation_limhold%,0,"FNinitiation_omission(",box%,E%) PROCpipe_timer(iti_timer%+box%,iti_time%,0,"FNtrial_finished(",box%,E%) trial_starttime%(box%) = TIME PROCset_nosepoke_state(box%, waiting%):REM The nosepoke machinery is already alert. =0 DEF PROCsuccessful_initiation(box%) REM Called by the nosepoke code. PROCkill_timer(omission_timer%+box%,E%) PROCset_nosepoke_state(box%, dontcare%): REM stop counting, stop any more calls coming here PROCswitch_off(traylight%(box%),E%): REM 13-Nov-98 initiated%(box%,trial%(box%))=yes% initiation_lat%(box%,trial%(box%)) = TIME - trial_starttime%(box%) CASE next_trial_type%(box%) OF WHEN choice%: PROCinitiate_choice(box%) WHEN adj%: PROCinitiate_adj(box%) WHEN unadj%: PROCinitiate_unadj(box%) ENDCASE PROCset_nosepoke_state(box%, choosing%) ENDPROC DEF FNinitiation_omission(box%,R%) IF R%=0 =0 PROCreset_to_iti_state(box%) initiated%(box%,trial%(box%))=no% stimulus%(box%,trial%(box%))=notapp% response%(box%,trial%(box%))=notapp% reward_collected%(box%,trial%(box%))=no% actual_pellets%(box%,trial%(box%))=0 omissiontotal%(box%) += 1 PROCupdate_box_stimulus(box%,"-----") PROCupdate_box_response(box%,"iOMIT") PROCupdate_box_state(box%,"ITI ") REM now wait for ITI to complete =0 DEF PROCreset_to_iti_state(box%) PROCset_nosepoke_state(box%, iti_ing%) PROCkill_switch(adj_lever%(box%),E%) PROCkill_switch(unadj_lever%(box%),E%) PROCkill_timer(delay_timer%+box%,E%) PROCkill_timer(omission_timer%+box%,E%) PROCswitch_off(centrelight%(box%),E%) REM 13-Nov-98: centrelight never gets switched on; traylight added; houselight off PROCswitch_off(traylight%(box%),E%) PROCswitch_off(houselight%(box%),E%) REM 4-Dec-98: even if houselight went off earlier, doesn't do any harm. PROCswitch_off(adj_levercontrol%(box%),E%) PROCswitch_off(unadj_levercontrol%(box%),E%) ENDPROC REM ======================================================================== REM Major box control functions - LEVERS COME OUT REM ======================================================================== DEF PROCinitiate_choice(box%) PROCupdate_box_state(box%,"Trial") PROCupdate_box_stimulus(box%,"Choice") PROCswitch_off(centrelight%(box%),E%) PROCswitch_on(adj_levercontrol%(box%),E%) PROCswitch_on(unadj_levercontrol%(box%),E%) PROCpipe_switch(adj_lever%(box%),On,1,"FNadj_response(",box%,E%) PROCpipe_switch(unadj_lever%(box%),On,1,"FNunadj_response(",box%,E%) choice_starttime%(box%) = TIME IF choice_limhold%>0 THEN PROCpipe_timer(omission_timer%+box%,choice_limhold%,0,"FNchoice_omission(",box%,E%) ENDPROC DEF PROCinitiate_adj(box%) PROCupdate_box_state(box%,"Trial") PROCupdate_box_stimulus(box%,"Adj ") PROCswitch_off(centrelight%(box%),E%) PROCswitch_on(adj_levercontrol%(box%),E%) PROCpipe_switch(adj_lever%(box%),On,1,"FNadj_response(",box%,E%) choice_starttime%(box%) = TIME IF choice_limhold%>0 THEN PROCpipe_timer(omission_timer%+box%,choice_limhold%,0,"FNchoice_omission(",box%,E%) ENDPROC DEF PROCinitiate_unadj(box%) PROCupdate_box_state(box%,"Trial") PROCupdate_box_stimulus(box%,"Unadj ") PROCswitch_off(centrelight%(box%),E%) PROCswitch_on(unadj_levercontrol%(box%),E%) PROCpipe_switch(unadj_lever%(box%),On,1,"FNunadj_response(",box%,E%) choice_starttime%(box%) = TIME IF choice_limhold%>0 THEN PROCpipe_timer(omission_timer%+box%,choice_limhold%,0,"FNchoice_omission(",box%,E%) ENDPROC DEF FNchoice_omission(box%,R%) IF R%=0 =0 PROCreset_to_iti_state(box%) response%(box%,trial%(box%))=omission% reward_collected%(box%,trial%(box%))=no% actual_pellets%(box%,trial%(box%))=0 omissiontotal%(box%) += 1 PROCupdate_box_response(box%,"cOMIT") PROCupdate_box_state(box%,"ITI ") REM now wait for ITI to complete =0 REM ======================================================================== REM Major box control functions - LEVER HAS BEEN PRESSED REM ======================================================================== DEF FNadj_response(box%,R%) IF R%=0 =0 LOCAL dummy% PROCeither_response(box%) response%(box%,trial%(box%)) = adj% PROCupdate_box_response(box%,"Adj ") IF adj_delay%(box%,trial%(box%)) = 0 THEN dummy% = FNadj_reinforcer(box%,1) ELSE IF lights_bridge_delay%=yes% THEN PROCswitch_on(adj_light%(box%),E%) PROCupdate_box_state(box%,"Delay") PROCpipe_timer(delay_timer%+box%,adj_delay%(box%,trial%(box%)),0,"FNadj_reinforcer(",box%,E%) PROCset_nosepoke_state(box%, delaying%) ENDIF IF stimulus%(box%,trial%(box%))=choice% THEN adjtotal%(box%)+=1 =0 DEF FNunadj_response(box%,R%) IF R%=0 =0 LOCAL dummy% PROCeither_response(box%) response%(box%,trial%(box%)) = unadj% PROCupdate_box_response(box%,"Unadj") IF unadj_delay%(box%,trial%(box%)) = 0 THEN dummy% = FNunadj_reinforcer(box%,1) ELSE IF lights_bridge_delay%=yes% THEN PROCswitch_on(unadj_light%(box%),E%) PROCupdate_box_state(box%,"Delay") PROCpipe_timer(delay_timer%+box%,unadj_delay%(box%,trial%(box%)),0,"FNunadj_reinforcer(",box%,E%) PROCset_nosepoke_state(box%, delaying%) ENDIF IF stimulus%(box%,trial%(box%))=choice% THEN unadjtotal%(box%)+=1 =0 DEF PROCeither_response(box%) choice_lat%(box%,trial%(box%)) = TIME - choice_starttime%(box%) PROCkill_timer(omission_timer%+box%,E%) PROCkill_switch(adj_lever%(box%),E%) PROCkill_switch(unadj_lever%(box%),E%) PROCswitch_off(adj_levercontrol%(box%),E%) PROCswitch_off(unadj_levercontrol%(box%),E%) IF houselights_bridge_delay%=no% THEN PROCswitch_off(houselight%(box%),E%) :REM 4 Dec 98 ENDPROC REM ======================================================================== REM Major box control functions - REINFORCER IS DELIVERED REM ======================================================================== DEF FNadj_reinforcer(box%,R%) IF R%=0 =0 PROCgeneral_reinforcer(box%, adj_pellets%(box%,trial%(box%))) =0 DEF FNunadj_reinforcer(box%,R%) IF R%=0 =0 PROCgeneral_reinforcer(box%, unadj_pellets%(box%,trial%(box%))) =0 DEF PROCgeneral_reinforcer(box%, numpellets%) PROCset_nosepoke_state(box%, dontcare%) PROCswitch_off(adj_light%(box%),E%) PROCswitch_off(unadj_light%(box%),E%) :REM shouldn't both have been on! REM 13-Nov-98: traylight PROCswitch_on(traylight%(box%),E%) PROCspaced_pellet(pellet%(box%),numpellets%,pellet_timer%+box%,pellet_gap%) pelletcount%(box%) += numpellets% actual_pellets%(box%,trial%(box%)) = numpellets% PROCupdate_box_pellets(box%,STR$(numpellets%)) PROCenter_collection_state(box%) ENDPROC DEF PROCenter_collection_state(box%) REM 3 Feb 99 PROCupdate_box_state(box%,"Reinf") pellet_starttime%(box%) = TIME IF collection_limhold%>0 THEN PROCpipe_timer(omission_timer%+box%,collection_limhold%,0,"FNcollection_omission(",box%,E%) PROCset_nosepoke_state(box%, collecting%) ENDPROC DEF FNcollection_omission(box%,R%) IF R%=0 =0 REM 3-Feb-99: Even if the "traylight" period is missed, collection latency is still recorded. REM On 13-Nov-98 this was done by leaving np_state% as collecting% until FNtrial_finished. REM Now we're recording ITI nosepokes, the ITI nosepoke code performs an explicit check REM for outstanding pellets and runs PROCreward_collect_latency. PROCreset_to_iti_state(box%) PROCupdate_box_state(box%,"ITI ") =0 DEF PROCreward_obtained(box%) REM We may never come here, if the ITI completes before the REM rat picks up the food. LOCAL dummy% PROCset_nosepoke_state(box%, dontcare%) PROCreward_collect_latency(box%) REM 13-Nov-98 omission, traylights, reinforcement collection period (usu. 6s) PROCkill_timer(omission_timer%+box%,E%) PROCswitch_off(traylight%(box%),E%) PROCupdate_box_state(box%,"Nosh.") IF reinf_collect_period%>0 THEN PROCpipe_timer(omission_timer%+box%,reinf_collect_period%,0,"FNreinforcement_collection_up(",box%,E%) PROCset_nosepoke_state(box%, feeding%) ELSE dummy%=FNreinforcement_collection_up(box%,1) :REM 3-Feb-99; code for reinf_collect_period%=0 was missing! ENDIF ENDPROC DEF PROCreward_collect_latency(box%) reward_collected%(box%,trial%(box%)) = yes% collect_latency%(box%,trial%(box%)) = TIME - pellet_starttime%(box%) ENDPROC DEF FNreinforcement_collection_up(box%,R%) REM 13-Nov-98: new IF R%=0 =0 PROCreset_to_iti_state(box%) PROCupdate_box_state(box%,"ITI ") =0 REM ======================================================================== REM Major box control functions - TRIAL OVER REM ======================================================================== DEF FNtrial_finished(box%,R%) REM We get here from the expiry of the overall ITI timer (and from nowhere else). REM This function alters delays appropriately and chooses the next trial. IF R%=0 =0 LOCAL dummy%, i%, doit% PROCreset_to_iti_state(box%) np_state%(box%) = dontcare% :REM if it's not collected its pellet, it's late. PROCtrial_adjustingpoint(box%) :REM call back to main program IF finished%(box%)=yes% THEN PROCbox_finished(box%):=0 REM if the main program decided to abort early. IF choicetrial%(box%) = nchoicetrials% THEN PROCbox_finished(box%):=0 IF trial%(box%) = maxtrials% THEN VDU7:CLS:COLOUR3:PRINTTAB(0,0);"*** Exceeded maxtrials on box ";box%;" ***";:COLOUR7 PROCbox_finished(box%) =0 ENDIF REM Assuming we're still here: dummy% = FNstart_trial(box%,1) =0 DEF PROCschedule_richards(box%) REM If we've just had max_consec_choice choice trials on the same lever, REM initiate a forced trial on the other lever. REM Trial number is the one about to be executed. IF trial%(box%)=1 THEN next_trial_type%(box%)=choice%:ENDPROC doit%=0 IF max_consec_choice%>0 AND trial%(box%)>max_consec_choice% THEN doit%=1 FOR i%=(trial%(box%)-1) TO (trial%(box%)-max_consec_choice%) STEP -1 IF stimulus%(box%,i%)<>choice% THEN doit%=0 IF response%(box%,i%)<>response%(box%,trial%(box%)-1) THEN doit%=0 NEXT ENDIF IF doit%=1 THEN CASE response%(box%,trial%(box%)-1) OF WHEN adj%: next_trial_type%(box%)=unadj% WHEN unadj%: next_trial_type%(box%)=adj% ENDCASE ELSE next_trial_type%(box%)=choice% ENDIF ENDPROC DEF PROCschedule_mazur(box%) LOCAL phase% phase% = ((trial%(box%) -1) MOD 4) + 1 CASE phase% OF WHEN 1: next_trial_type%(box%)=FNrandom_stim WHEN 2: next_trial_type%(box%)=FNother_than(stimulus%(box%,trial%(box%)-1)) WHEN 3: next_trial_type%(box%)=choice% WHEN 4: next_trial_type%(box%)=choice% ENDCASE ENDPROC DEF FNrandom_stim IF RND(2)=1 THEN =adj% ELSE =unadj% DEF FNother_than(stim%) IF stim%=adj% THEN =unadj% ELSE =adj% DEF PROCbox_finished(box%) LOCAL i% finished%(box%) = yes% PROCset_nosepoke_state(box%, dontcare%) :REM sort out any extant poking PROCkill_switch(nosepoke%(box%),E%) PROCkill_switch(leftlever%(box%),E%) PROCkill_switch(rightlever%(box%),E%) PROCkill_timer(iti_timer%+box%,E%) PROCkill_timer(delay_timer%+box%,E%) PROCkill_timer(pellet_timer%+box%,E%) PROCkill_timer(omission_timer%+box%,E%) PROCswitch_off(houselight%(box%),E%) PROCswitch_off(leftlevercontrol%(box%),E%) PROCswitch_off(rightlevercontrol%(box%),E%) PROCswitch_off(leftlight%(box%),E%) PROCswitch_off(rightlight%(box%),E%) PROCswitch_off(centrelight%(box%),E%) PROCswitch_off(pellet%(box%),E%) PROCupdate_box_state(box%,"Done.") FOR i%=1 TO nboxes% IF finished%(i%)=no% THEN ENDPROC NEXT PROCall_finished ENDPROC DEF PROCall_finished PROCkill_all PROCreport_results ENDPROC DEF FNabort_box(box%,R%) IF R%=0 =0 PROCupdate_box_stimulus(box%,"ABORT ") PROCupdate_box_response(box%,"ABORT") PROCbox_finished(box%) =0 REM ======================================================================== REM Nosepoke functions. Heavily modified 3-Feb-99. REM ======================================================================== DEF FNnosepoke_changed(box%,R%) IF R%=0 =0 REM This is where all changes to the nosepoke line come to. REM 1-Dec-98: screen update first PROCupdate_box_nosepoke(box%) IF FNswitch(nosepoke%(box%),E%)=On THEN PROCenter_magazine(box%) ELSE PROCleave_magazine(box%) ENDIF =0 DEF PROCenter_magazine(box%) CASE np_state%(box%) OF WHEN waiting%: PROCsuccessful_initiation(box%) WHEN choosing%: IF counting%(box%)=yes% THEN start_time%(box%)=TIME watching%(box%)=np_state%(box%) choice_pokenum%(box%,trial%(box%)) += 1 ENDIF WHEN delaying%: IF counting%(box%)=yes% THEN start_time%(box%)=TIME watching%(box%)=np_state%(box%) delay_pokenum%(box%, trial%(box%)) += 1 ENDIF WHEN collecting%: PROCreward_obtained(box%) WHEN feeding%: IF counting%(box%)=yes% THEN start_time%(box%)=TIME watching%(box%)=np_state%(box%) feeding_pokenum%(box%,trial%(box%)) += 1 ENDIF WHEN iti_ing%: IF counting%(box%)=yes% THEN start_time%(box%)=TIME watching%(box%)=np_state%(box%) iti_pokenum%(box%,trial%(box%)) += 1 ENDIF IF actual_pellets%(box%,trial%(box%)) > 0 AND reward_collected%(box%,trial%(box%)) <> yes% THEN PROCreward_collect_latency(box%) REM This situation is if the collection limited hold has expired; REM nosepoke does not prolong the traylight any more, but latency is still recorded. ENDIF WHEN dontcare%: ENDCASE ENDPROC DEF PROCleave_magazine(box%) CASE watching%(box%) OF WHEN choosing%: choice_poketime%(box%,trial%(box%)) += TIME-start_time%(box%) WHEN delaying%: delay_poketime%(box%,trial%(box%)) += TIME-start_time%(box%) WHEN feeding%: feeding_poketime%(box%,trial%(box%)) += TIME-start_time%(box%) WHEN iti_ing%: iti_poketime%(box%,trial%(box%)) += TIME-start_time%(box%) WHEN waiting%: WHEN collecting%: WHEN dontcare%: ENDCASE watching%(box%) = dontcare% ENDPROC DEF PROCstop_counting(box%) IF watching%(box%) <> dontcare% THEN PROCleave_magazine(box%) counting%(box%) = no% ENDPROC DEF PROCset_nosepoke_state(box%, s%) np_state%(box%) = s% PROCstop_counting(box%): REM safety device, calling function can do this itself earlier CASE s% OF WHEN choosing%: counting%(box%)=yes% WHEN delaying%: counting%(box%)=yes% WHEN feeding%: counting%(box%)=yes% WHEN iti_ing%: counting%(box%)=yes% WHEN waiting%: REM PROCenter_magazine deals with it all WHEN collecting%: REM PROCenter_magazine deals with it all WHEN dontcare%: REM PROCenter_magazine deals with it all ENDCASE IF FNswitch(nosepoke%(box%),E%)=On THEN PROCenter_magazine(box%) ENDPROC REM ======================================================================== REM Display/clock functions REM ======================================================================== DEF FNdisplay_line(box%) = display_firstline% + (box%-1)*2 DEF FNclock_tick(dummy%,R%) IF R%=0 =0 LOCAL t% t% = TIME - start_time% COLOUR4:PRINTTAB(clockx%,clocky%);t%DIV6000;" min ";(t%MOD6000)DIV100;" sec ";:COLOUR7 =0 REM ======================================================================== REM Results/output functions REM ======================================================================== DEF PROCreport_results PROCstore_data IF debug%=0 THEN VDU 2 OSCLI("SPOOL "+logfile$) PROCprint_config PROCprint_data PROCprint_summaries OSCLI("SPOOL") VDU 3 OSCLI("SETTYPE "+logfile$+" TEXT") ENDPROC DEF PROCstore_data LOCAL ch%,box%,t%,d$ ch% = OPENOUT(datafile$) REM Following line is too long to send in one go. Caused "bad program" error if you tried to load the code! PROCprint_string(ch%,"PROGNAME,DATE_TIME,RAT,BOX,ADJUSTEDLEVER,SESSION,TRIAL,CHOICETRIAL,INITIATED,INITIATIONLATENCY,STIMULUS,RESPONSE,CHOICELATENCY,UNADJDELAY,ADJDELAY,UNADJPELLETS,ADJPELLETS,PELLETS,REWARDCOLLECTED,COLLECTLATENCY,") PROCprint_line(ch%,"CHOICE_POKENUM,CHOICE_POKETIME,DELAY_POKENUM,DELAY_POKETIME,FEEDING_POKENUM,FEEDING_POKETIME,ITI_POKENUM,ITI_POKETIME") FOR box% = 1 TO nboxes% d$=progname$+","+date_time$+","+subject$(box%)+","+STR$(box%)+","+sidename$(adj_side%(box%))+","+STR$(session_number%(box%)) FOR t% = 1 TO trial%(box%) REM progname,date/time,rat,adjustedlever,box,session,trial,choicetrial PROCprint_string(ch%,d$+","+STR$(t%)+","+STR$(choicetrial_num%(box%,t%))) REM initiated, initiationlatency, stimulus, response, choicelatency PROCprint_string(ch%,","+yesno$(initiated%(box%,t%))) PROCprint_string(ch%,","+STR$(initiation_lat%(box%,t%))) PROCprint_string(ch%,","+desc$(stimulus%(box%,t%))) PROCprint_string(ch%,","+desc$(response%(box%,t%))) PROCprint_string(ch%,","+STR$(choice_lat%(box%,t%))) REM unadjusteddelay, adjusteddelay, unadjpel, adjpel, actualpel, rewardcollected, collectlatency PROCprint_string(ch%,","+STR$(unadj_delay%(box%,t%))) PROCprint_string(ch%,","+STR$(adj_delay%(box%,t%))) PROCprint_string(ch%,","+STR$(unadj_pellets%(box%,t%))) PROCprint_string(ch%,","+STR$(adj_pellets%(box%,t%))) PROCprint_string(ch%,","+STR$(actual_pellets%(box%,t%))) PROCprint_string(ch%,","+yesno$(reward_collected%(box%,t%))) PROCprint_string(ch%,","+STR$(collect_latency%(box%,t%))) REM choice_pokenum, choice_poketime, delay_pokenum, delay_poketime, REM feeding_pokenum, feeding_poketime, iti_pokenum, iti_poketime PROCprint_string(ch%,","+STR$(choice_pokenum%(box%,t%))) PROCprint_string(ch%,","+STR$(choice_poketime%(box%,t%))) PROCprint_string(ch%,","+STR$(delay_pokenum%(box%,t%))) PROCprint_string(ch%,","+STR$(delay_poketime%(box%,t%))) PROCprint_string(ch%,","+STR$(feeding_pokenum%(box%,t%))) PROCprint_string(ch%,","+STR$(feeding_poketime%(box%,t%))) PROCprint_string(ch%,","+STR$(iti_pokenum%(box%,t%))) PROCprint_line(ch%,","+STR$(iti_poketime%(box%,t%))) NEXT t% NEXT box% CLOSE#ch% ENDPROC