REM >super5choice progname$ = "super5Choice" version_date$ = "1-Aug-2003" debug% = 0 :REM in debugging mode? printing% = 0 :REM controls whether log is sent to printout (0=no, 1=yes) REM Based on the 5-choice task, by Rudolf Cardinal, for Anastasia Christakou. REM REM TASK DESCRIPTION REM Boxes are equipped with five front illuminable holes with IR detectors, plus a rear panel with pellet dispenser. REM REM At start: houselight on, free pellet. Enter please_push state. REM REM State Description, recording, consequences ("panel" = panel push; "hole" = nosepoke in front hole) REM ----------------------------------------------------------------------------------------------------------------------- REM dont_care% For debugging only. Not interested in any response. REM REM please_push% Houselight on. Awaiting push at the panel either at start of trial 1 or after darkness (timeout) REM Panel -> initiate trial REM Holes -> perseverative NP: record #, which hole, and in which sequence, not particularly interested in NP duration REM REM intertrial_interval% Hanging around before stimulus REM Panel -> perseverative PPs: how many, latency not particularly interesting REM Holes -> premature responses: where, (how many), what sequence, time relative to start of ITI [when it panelpoked] REM REM stim_on% Stimulus is being presented REM Panel -> perseverative PPs: how many, latency relative to stimulus onset REM Holes (correct) -> latency from stimulus onset, can only be one REM Holes (incorrect) -> latency from stim onset, which hole, can only be one REM REM stim_off% Stimulus off, still awaiting response REM Panel -> perseverative PPs: how many, latency relative to *stimulus onset* REM Holes (correct) -> latency from stimulus onset, can only be one REM Holes (incorrect) -> latency from stim onset, which hole, can only be one REM REM N.B. {stim_on + stim_off} constitute the limited hold period. REM REM awaiting_collect% Rat succeeded, waiting for collecting; goes to intertrial_interval REM Panel -> latency to collect reward, relative to (correct) response REM Holes (any) -> perseverative response, record which hole, need order, latency relative to stimulus onset REM REM timeout% Rat failed in some way, awaiting new trial (goes to please_push) REM Panel -> [which have no effect] -> not interested REM Holes (any) -> [which restarts this timeout] -> ??? AC to decide REM REM N.B. Need to record the actual timeout period (including any prolonging the rat has done by nosepoking) REM REM finished_state% Box has finished. REM REM aborted_state% Box has been aborted by the operator. REM REM ________________________________________________________________________________________________________ REM REM Set e.g. 100 trials or 30 min, whichever comes first. (Don't interrupt an ongoing trial.) REM (Trial can finish during please_push, intertrial_interval and timeout.) REM (Correct 100th trial: finishes as soon as intertrial_interval goes in; incorrect finishes at timeout.) REM REM ________________________________________________________________________________________________________ REM REM OUTPUT REM ------ REM For the {box/rat/session} as a whole: REM REM possible ITI values (up to ?6 of them) REM programmed stimulus duration REM maximum number of trials REM maximum session length REM number of trials completed REM total # correct REM total # incorrect REM total # omissions REM total # pellets given REM REM For each trial: REM REM ITI delay REM programmed stimulus duration REM which hole presented REM which hole responded to (0 = omission) REM latency to respond (relative to stimulus onset; invalid for omissions) REM latency to collect reward (invalid if chosen hole != presented hole) REM REM For each nosepoke/panelpress: REM REM (the rat/box/blahblahblah code) REM the trial it occurred in REM the phase (e.g. ITI, stim_on, blahblahblah) REM the location (hole number or some code like "99" for the panel) REM the time, relative to something important (like stimulus onset) REM REM -------------------------------------------------------------------------------------------------------- REM -------------------------------------------------------------------------------------------------------- REM -------------------------------------------------------------------------------------------------------- REM REM REVISION HISTORY REM ---------------- REM 29 May 99 - started (based on code I wrote for Yogi) REM - libraries integrated in my full form; 5-choice box constants go into boxconst. REM - question for AC: are perseverative PPs during ITI meant to be recorded separately from those during stim_off etc. (Aren't.) REM -- No, but never mind the totals, each response is in the response file. REM REM 30 May 99 - fixed some of the issues REM - traylight is now an option (always switches it off, doesn't always switch it on) REM - AC thinking about recording offered hole in per-response file (the RDBMS side of me says no) REM - things we mentioned and didn't do: letter code for Phase (AC prefers numbers); record use of traylight in the data file REM REM 07 Jun 99 - distinction between data/response output removed - NO it isn't. Good :-) REM - Noise. From ITI-stim onset (i.e. during phase 2), a noise comes on with a defined duration (e.g. 50 cs), REM "You would never mix variable ITIs and noise." So to be entered as "time after ITI". (e.g. 450 cs into 500 cs ITI) REM Program should check that start_time_into_ITI + noise_duration <= iti_time. REM Actually, to be entered relative to stimulus onset - could be after, or before. Needs some careful programming. REM So negative times are set up at the start of the ITI (), positive at the start of the stimulus (FNoffer_stimulus) REM User input done. Recording done. Noise itself done. REM - Four ITI times, not six (ndelay_options%) - done REM - Brightness. (AC's boxes can't automate it, so we just record what was done.) Currently, offers options 1-6 *** CHECK. REM (Controlled by manually changing resistors.) REM - When a rat is poking (NP/PP) and the box state changes, it is NOT counted as a REM - new poke. REM REM 09 Jun 99 - (Anastasia) I am now punishing premature nosepokes (this timeout period initiates a new trial). REM - Session now ends when the total of correct, incorrect and omitted trials REM reaches the PRESET maximum number of (such) trials, REM but the final TOTAL number of trials is now including the premature, REM which can be considered in the analysis as a possible trial initiation outcome. REM - Have reset defaults, minima and maxima for all parameters to accomodate my training schedule. REM REM 17 Jun 99 - (Anastasia) When asks to confirm (previously "are parameters correct") it waits for . REM - check with RC. REM REM 21 Jun 99 - (Anastasia) Sorted out output conflict by making sure all files are closed (!). REM - Rudolf corrected waiting for after confirmation (see 17 Jun 99). REM REM 02 Jul 99 - (Anastasia) Rudolf will not let me have one file per day REM - so now the program generates file names for every session REM REM 29 Sep 99 - (Rudolf) records all response times relative to trial start, for Mel Lyon's purposes REM - also records latencies of panel-pokes (99) in "please push" phase (1). REM - also records trial start time (relative to session start time), and trial duration. REM 30 Sep 99 - was recording trial_began_at = TIME, not TIME - session_began_at REM REM 11 Jul 00 - now asks if premature responses are to be punished (do the same for perseveration?). REM 26 Nov 00 - changes for Jeff: REM 5 Sep 01 - further changes for Jeff: REM with only one hole each session REM The important facility is that a different hole is selected for each training session. REM That is, one day it might be hole 1, the other hole 4 etc (the operator specifies this at the start). REM Once the animal is trained... a few sessions will be given with the normal 5-choice task... REM 19 Sep 01 - further changes for Jeff REM - bugfix (yes/yes%) REM - houselight/traylight off during timeout REM 1 Aug 03 - changes by RNC for Marie Pezze REM Request: REM "I would like to challenge some animals with some bursts of white noise in the 5CSRT. REM I have figured out how to change the parameters in order to do this, but still, REM I need to include some trials without any noise. REM I would like to have some bursts of noise, or nothing, in a random sequence REM with 3 possibilities for the time onset of the noise and one fraction noise free. REM Each possibility (4, 3 with noise and one with no noise) should constitute ''more or less'' REM 25% of the total number of trials, and every thing should be random." REM Action: REM noise_used_option%() REM noise_option%() REM noise_used%() REM Extant ISSUES: REM -------------- REM - search for asterisks in the code REM - artefact "repoking" at state changes (e.g. persev. poking as delay -> delay_done REM - the whole issue of noise and other manipulations REM REM ======================================================================== REM Libraries REM ======================================================================== PROCinit :REM Arachnid init PROCkill_all :REM Arachnid init LIBRARY ".ProgLibs.Ascii" LIBRARY ".ProgLibs.UI": PROCdefine_colours LIBRARY ".ProgLibs.DateTime": date_time$ = FNdate_time_code LIBRARY ".ProgLibs.Filename" LIBRARY ".ProgLibs.Arachnid" LIBRARY ".ProgLibs.BoxConst": PROCfive_hole_boxes LIBRARY ".ProgLibs.Random" MODE 12 dummy% = RND(-TIME) PROCbox_set_up PROCget_parameters PROCdisplay_startup FOR box% = 1 TO nboxes% IF using_the_box%(box%)=yes% THEN PROCstart_the_box(box%) PROCpipe_fkey(box%,1,0,"FNabort_box(",box%,E%) ENDIF NEXT PROCwait(E%):*AE PROCkill_all END DEF PROCbox_set_up maxtrials% = 200 :REM this is the _maximum_ possible number of trials (arrays dimensioned according to this) ndelay_options% = 4 :REM how many possible delays? nnoise_options% = 4 :REM how many possible noise onsets? iti_timer% = 0 * nboxes% timeout_timer% = 1 * nboxes% stim_on_timer% = 2 * nboxes% :REM I know that I don't need to define so many, but it doesn't hurt and reads more clearly. stim_off_timer% = 3 * nboxes% pellet_dispenser_timer% = 4 * nboxes% timeout_timer% = 5 * nboxes% noise1_timer% = 6 * nboxes% :REM used for time-to-noise noise2_timer% = 7 * nboxes% :REM used for noise-duration REM _____________________________________ global parameters: some are defaults only, superseded by per-box parameters (below) pulse% = 10 :REM pellet dispenser pulse on-time pellet_gap% = 10 :REM gap between subsequent pellets numpellets% = 1 :REM the reward size REM _____________________________________ per session (in) DIM rat_id$(nboxes%) DIM using_the_box%(nboxes%) DIM confirm%(nboxes%) :REM used after parameters fro each box are entered (or if box is not used) DIM session_number%(nboxes%) DIM treatment$(nboxes%) DIM numtrials%(nboxes%) DIM session_length%(nboxes%) DIM brightness_level%(nboxes%) DIM noise_duration%(nboxes%) DIM noise_onset_option%(nboxes%,nnoise_options%) DIM noise_used_option%(nboxes%,nnoise_options%) DIM delay_option%(nboxes%,ndelay_options%) DIM stimulus_duration%(nboxes%) DIM limited_hold%(nboxes%) DIM timeout_duration%(nboxes%) DIM traylight_used%(nboxes%) DIM prem_TO%(nboxes%) DIM force_a_hole%(nboxes%) :REM force the hole to be used as the stimulus? (yes/no) DIM forced_hole%(nboxes%) :REM if yes, which hole to use? REM _____________________________________ per session (out) DIM total_pellets%(nboxes%) DIM total_correct%(nboxes%) DIM total_incorrect%(nboxes%) DIM total_omissions%(nboxes%) REM _____________________________________ per trial DIM premature_nosepokes%(nboxes%,maxtrials%) :REM nosepokes in intertrial_interval DIM perseverative_panelpushes%(nboxes%,maxtrials%) :REM panelpushes in intertrial_interval DIM iti_duration%(nboxes%,maxtrials%) :REM how long the initial ITI was DIM noise_onset%(nboxes%,maxtrials%) :REM when was the noise? DIM offered_hole%(nboxes%,maxtrials%) :REM which hole was illuminated DIM chosen_hole%(nboxes%,maxtrials%) :REM which hole was first chosen (0=omission) DIM latency_to_respond%(nboxes%,maxtrials%) :REM time from stim. onset to first nosepoke DIM timeout_experienced%(nboxes%,maxtrials%) :REM the length of timeout it actually got (can exceed programmed timeout) DIM latency_to_collect_reward%(nboxes%,maxtrials%) :REM time from pellet delivery to collection DIM perseverative_nosepokes%(nboxes%,maxtrials%) :REM nosepokes in awaiting_collect / please_push. DIM trial_duration%(nboxes%,maxtrials%) :REM how long did that trial last? DIM trial_start_time%(nboxes%,maxtrials%) :REM trial start time, relative to session start time DIM noise_option%(nboxes%,maxtrials%) :REM which noise option was used? DIM noise_used%(nboxes%,maxtrials%) :REM was noise given? REM _____________________________________ per response REM *** Note REM This is the only place that I code boxes from 0-3, rather than 1-4. REM It's harder to read, but saves 25% on memory; this is the only place where such REM a saving is significant. Only referred to in PROCrecord_response and the final output code. REM Responses are still coded 1-max, though. max_responses% = 5000 :REM How many (interesting) responses to record. Have to try it and see - memory-dependent. DIM recorded_responses%(nboxes%) :REM how many individual responses have we recorded for this box? DIM response_trial%(nboxes%-1, max_responses%) :REM which trial was it on? DIM response_phase%(nboxes%-1, max_responses%) :REM e.g. ITI, timeout, ... DIM response_location%(nboxes%-1, max_responses%) panel_code% = 99 :REM the location code for panel-pushes DIM response_time%(nboxes%-1, max_responses%) :REM the time (relative to something interesting) that the response occurred DIM response_time_in_trial%(nboxes%-1, max_responses%) :REM absolute time (meaning relative to session start) REM _________________________________________ flags and internal variables DIM finished%(nboxes%) :REM finished or not DIM trial%(nboxes%) :REM current trial number DIM nosepoke_state%(nboxes%) :REM which State is the box in? DIM iti_began_at%(nboxes%) :REM time the "ITI" began DIM please_push_began_at%(nboxes%) :REM *** don't know if I need this; is to record latency of perseverative NPs in this phase DIM stim_on_at%(nboxes%) :REM stimulus onset (absolute time) DIM timeout_began_at%(nboxes%) :REM start of timeout (absolute time) DIM rewarded_at%(nboxes%) :REM time reward was given DIM session_began_at%(nboxes%) :REM session start time, to limit session length with DIM trial_began_at%(nboxes%) :REM this trial's start time REM _____________________________________ The all-important STATES OF THE BOX, see top. dont_care% = 0 please_push% = 1 intertrial_interval% = 2 stim_on% = 3 stim_off% = 4 awaiting_collect% = 5 timeout% = 6 finished_state% = 7 aborted_state% = 8 REM _____________________________________ other internal constants yes% = 1 no% = 0 DIM yesno$(1): yesno$(yes%)="Y": yesno$(no%)="N" ENDPROC DEF PROCget_parameters LOCAL box%, d%, noisetemp%, i% CLS COLOUR yellow% PRINT progname$;" by Rudolf Cardinal, ";version_date$ PRINT PRINT "Five-choice task." PRINT "________________________________________________________________________" COLOUR white% PRINT "Date/Time: ";date_time$ FOR box% =1 TO nboxes% REPEAT COLOUR yellow%:PRINT ''"Box number ";box%:COLOUR white% using_the_box%(box%) = FNget_num_param("Use the box? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",yes%,0,1) IF using_the_box%(box%) = yes% THEN rat_id$(box%) = FNget_str_param("Enter rat ID (NO COMMAS):", "???") session_number%(box%) = FNget_num_param("Enter session number", 1, 1, 1000) treatment$(box%) = FNget_str_param("Treatment (NO COMMAS):", "training") numtrials%(box%) = FNget_num_param("Number of trials",100,1,maxtrials%) session_length%(box%) = 60*100 * FNget_num_param("Session length limit (in MINUTES)",30,1,120) traylight_used%(box%) = FNget_num_param("Use traylight? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",yes%,0,1) prem_TO%(box%) = FNget_num_param("Punish premature? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",yes%,0,1) brightness_level%(box%) = FNget_num_param("Enter level of brightness (1 to 6)", 6, 1, 6) FOR d% = 1 TO ndelay_options% delay_option%(box%,d%) = FNget_num_param("Enter ITI delay option "+STR$(d%)+" of "+STR$(ndelay_options%)+" (csec)", 500, 0, 1000) NEXT stimulus_duration%(box%) = FNget_num_param("Enter stimulus duration (csec)", 50, 0, 10000) REPEAT limited_hold%(box%) = FNget_num_param("Enter limited hold (csec); must exceed stimulus duration", 500, 500, 10000) UNTIL limited_hold%(box%) > stimulus_duration%(box%) noise_duration%(box%) = FNget_num_param("Enter noise duration, 0 for no noise (cs)", 0, 0, 500) IF noise_duration%(box%) > 0 THEN FOR i%=1 TO nnoise_options% PRINT "--- NOISE OPTION ";i%;" OF ";nnoise_options% noise_used_option%(box%,i%) = FNget_num_param("Use noise for this option? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",yes%,0,1) IF noise_used_option%(box%,i%)=yes% THEN REPEAT noisetemp%=0 PRINT "Enter noise start time OPTION "; i% noise_onset_option%(box%,i%) = FNget_num_param(", relative to stim. onset, negative=before (cs)", -50, -1000, +6000) FOR d%=1 TO ndelay_options% IF delay_option%(box%,d%) + noise_onset_option%(box%,i%) < 0 THEN noisetemp%=1 PRINT "*** Illegal - noise begins before one of the ITIs!" ENDIF NEXT UNTIL noisetemp%=0 PRINT "--- This option: a ITI of "; FOR d%=1 TO ndelay_options% PRINT ;delay_option%(box%,d%);"/"; NEXT PRINT " cs, with a noise of ";noise_duration%(box%);" cs, beginning "; PRINT ABS(noise_onset_option%(box%,i%));" cs "; IF noise_onset_option%(box%,i%)<0 THEN PRINT "before";: ELSE PRINT "after"; PRINT " the stimulus onset." PRINT "The limited hold period is ";limited_hold%(box%);" cs, of which up to the first ";stimulus_duration%(box%);" cs" PRINT "is the stimulus itself." PRINT ENDIF NEXT ENDIF timeout_duration%(box%) = FNget_num_param("Enter minimum timeout (darkness) interval (csec)", 500, 500, 6000) force_a_hole%(box%) = FNget_num_param("Force only one hole to be used? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",yes%,0,1) IF force_a_hole%(box%)=yes% THEN forced_hole%(box%) = FNget_num_param("Hole to use",1,1,nholes%) ENDIF ENDIF UNTIL FNget_letter_param("Please confirm...(Y or N)", "YN", "") = "Y" NEXT PRINT' COLOUR red% OSCLI("CAT") REPEAT REM ...just press enter to get file names automatically... PRINT datafile$ = FNget_filename_default("DATA FILE - Filename for output","D"+rat_id$(1)+"_"+STR$(session_number%(1))) responsefile$ = FNget_filename_default("RESPONSE FILE - Filename for output","R"+rat_id$(1)+"_"+STR$(session_number%(1))) logfile$ = FNget_filename_default("TEXT FILE - Filename for output","T"+rat_id$(1)+"_"+STR$(session_number%(1))) IF (datafile$=logfile$ OR datafile$=responsefile$ OR logfile$=responsefile$) THEN PRINT"--- Unacceptable, can't have the same name for two." UNTIL NOT (datafile$=logfile$ OR datafile$=responsefile$ OR logfile$=responsefile$) COLOUR yellow% PRINT''"KICKOFF." PRINT "------------" PRINT'"Ensure rats in boxes. Press a key to start.";:COLOUR white%:IFGET ENDPROC REM ======================================================================== REM Main control code, excluding nosepoke/panelpush handlers REM ======================================================================== DEF PROCstart_the_box(box%) LOCAL hole% trial%(box%) = 0 :REM FNstart_trial increments it to 1 for the first trial finished%(box%) = no% nosepoke_state%(box%) = dont_care% FOR hole% = 1 TO nholes% PROCpipe_switch(nosepoke%(box%,hole%), On, 1, "FNnosepoke("+STR$(hole%)+",",box%,E%) NEXT PROCpipe_switch(panelpush%(box%), On, 1, "FNpanelpush(", box%, E%) PROCstart_session(box%) ENDPROC DEF PROCstart_session(box%) LOCAL dummy% PROCsingle_pellet(pellet_dispenser%(box%)) total_pellets%(box%) += 1 session_began_at%(box%) = TIME PROCrequire_a_poke(box%) ENDPROC DEF PROCrequire_a_poke(box%) PROCswitch_on(houselight%(box%),E%) IF traylight_used%(box%)=yes% THEN PROCswitch_on(traylight%(box%),E%) PROCset_np_state(box%, please_push%) please_push_began_at%(box%) = TIME PROCdisplay_box(box%) ENDPROC DEF PROCstart_trial_with_iti(box%) IF total_correct%(box%) + total_incorrect%(box%) + total_omissions%(box%) >= numtrials%(box%) OR trial%(box%) >= maxtrials% OR (TIME-session_began_at%(box%))>session_length%(box%) THEN REM ... until we (1) reach the trial criterion; (2) hit the memory limit; (3) run out of time. PROCset_np_state(box%,finished_state%) PROCfinished(box%) ELSE trial_duration%(box%, trial%(box%)) = TIME - trial_began_at%(box%) :REM one trial finishes, the next begins trial%(box%) += 1 trial_began_at%(box%) = TIME - session_began_at%(box%) trial_start_time%(box%, trial%(box%)) = trial_began_at%(box%) PROCswitch_on(houselight%(box%),E%) PROCswitch_off(traylight%(box%),E%) PROCset_np_state(box%, intertrial_interval%) iti_began_at%(box%) = TIME iti_duration%(box%,trial%(box%)) = FNget_programmed_delay(box%) IF iti_duration%(box%,trial%(box%))>0 THEN PROCpipe_timer(iti_timer%+box%, iti_duration%(box%,trial%(box%)), 0, "FNoffer_stimulus(", box%, E%) ELSE dummy% = FNoffer_stimulus(box%,1) ENDIF IF noise_duration%(box%) > 0 THEN REM SET UP NOISE noise_option%(box%,trial%(box%)) = FNrandom_integer(1,nnoise_options%) noise_used%(box%,trial%(box%)) = noise_used_option%(box%, noise_option%(box%,trial%(box%))) IF noise_used%(box%,trial%(box%))=yes% THEN noise_onset%(box%,trial%(box%)) = noise_onset_option%(box%,noise_option%(box%,trial%(box%))) REM if noise_onset >= 0, then FNoffer_stimulus deals with it IF noise_onset%(box%,trial%(box%)) < 0 THEN PROCpipe_timer(box%+noise1_timer%, iti_duration%(box%,trial%(box%)) + noise_onset%(box%,trial%(box%)), 0, "FNnoise(", box%, E%) REM note sign of calculation, e.g. 500cs ITI with onset at -50cs means 450cs from start of ITI (now). ENDIF ELSE noise_option%(box%,trial%(box%)) = -1; noise_used%(box%,trial%(box%)) = no%; ENDIF ENDIF PROCdisplay_box(box%) ENDPROC DEF FNget_programmed_delay(box%) = delay_option%(box%,FNrandom_integer(1,ndelay_options%)) DEF FNnoise(box%, bogus%) IF bogus%=0 THEN =0 PROCswitch_on(tone%(box%),E%) PROCpipe_timer(box% + noise2_timer%, noise_duration%(box%), 0, "FNswitch_off_line(",tone%(box%),E%) =0 DEF FNoffer_stimulus(box%, bogus%) IF bogus% = 0 THEN = 0 LOCAL loop%, dummy% PROCset_np_state(box%, dont_care%) :REM Rudolf's paranoia REM Changes 5-Sep-01 to be able to 'force' a hole IF force_a_hole%(box%)=yes% THEN offered_hole%(box%,trial%(box%)) = forced_hole%(box%) ELSE offered_hole%(box%,trial%(box%)) = FNrandom_integer(1,5) ENDIF PROCswitch_on(aperturelight%(box%, offered_hole%(box%,trial%(box%))), E%) stim_on_at%(box%) = TIME :REM time when light comes on PROCset_np_state(box%, stim_on%) :REM deals with all nosepoking! PROCpipe_timer(box% + stim_on_timer%, stimulus_duration%(box%), 0, "FNstimulus_off_still_waiting(", box%, E%) IF noise_duration%(box%)>0 AND noise_used%(box%,trial%(box%))=yes% THEN IF noise_onset%(box%,trial%(box%))=0 THEN dummy% = FNnoise(box%, 1) :REM noise starts now IF noise_onset%(box%,trial%(box%))>0 THEN PROCpipe_timer(box%+noise1_timer%, noise_onset%(box%,trial%(box%)), 0, "FNnoise(", box%, E%) REM ... and if noise_onset < 0 then it was handled earlier. ENDIF = 0 DEF FNstimulus_off_still_waiting(box%, bogus%) IF bogus%=0 =0 PROCset_np_state(box%, dont_care%) :REM Rudolf's paranoia PROCswitch_off(aperturelight%(box%, offered_hole%(box%,trial%(box%))), E%) PROCset_np_state(box%, stim_off%) PROCpipe_timer(box% + stim_off_timer%, limited_hold%(box%) - stimulus_duration%(box%), 0, "FNlimited_hold_up(", box%, E%) =0 DEF FNlimited_hold_up(box%, bogus%) IF bogus% = 0 THEN = 0 PROCset_timeout(box%) total_omissions%(box%) += 1 REM chosen_hole% will remain at zero, which flags this trial as an omission = 0 DEF PROCswitch_off_all_holes(box%) LOCAL h% FOR h%=1 TO nholes% PROCswitch_off(aperturelight%(box%, h%), E%) NEXT ENDPROC DEF PROCgive_reward(box%) PROCset_np_state(box%, dont_care%) PROCswitch_off_all_holes(box%) IF traylight_used%(box%)=yes% THEN PROCswitch_on(traylight%(box%), E%) PROCspaced_pellet(pellet_dispenser%(box%), numpellets%, pellet_dispenser_timer%+box%, pellet_gap%) total_pellets%(box%) += numpellets% rewarded_at%(box%) = TIME PROCset_np_state(box%, awaiting_collect%) ENDPROC DEF PROCset_timeout(box%) PROCswitch_off_all_holes(box%) PROCswitch_off(houselight%(box%), E%) PROCswitch_off(traylight%(box%), E%) timeout_began_at%(box%) = TIME PROCset_np_state(box%, timeout%) PROCpipe_timer(timeout_timer% + box%, timeout_duration%(box%), 0, "FNtimeout_finished(", box%, E%) ENDPROC DEF PROCrestart_timeout(box%) REM dappy rat did something to restart its timeout REM but we don't want to fiddle with timeout_began_at REM so we just restart the timer. PROCpipe_timer(timeout_timer% + box%, timeout_duration%(box%), 0, "FNtimeout_finished(", box%, E%) ENDPROC DEF FNtimeout_finished(box%, bogus%) IF bogus%=0 =0 timeout_experienced%(box%, trial%(box%)) = TIME - timeout_began_at%(box%) PROCrequire_a_poke(box%) =0 REM ======================================================================== REM Nosepoke and panel-push code REM Nosepoke *duration* is ignored. REM ======================================================================== DEF PROCset_np_state(box%, state%) nosepoke_state%(box%) = state% REM PROCcheck_np(box%) PROCdisplay_state(box%) ENDPROC REM Changes of state now ignore whatever the rat's doing at the time. REM It must repoke in all circumstances. REM REM DEF PROCcheck_np(box%) REM LOCAL dummy%, hole% REM FOR hole% = 1 TO nholes% REM IF FNswitch(nosepoke%(box%,hole%),E%)=On THEN dummy%=FNnosepoke(hole%,box%,1) REM NEXT REM IF FNswitch(panelpush%(box%),E%)=On THEN dummy%=FNpanelpush(box%,1) REM ENDPROC DEF FNnosepoke(hole%,box%,bogus%) IF bogus%=0 =0 REM In this program, we're not interested in NP duration, so never look at leaving the magazine. CASE nosepoke_state%(box%) OF WHEN dont_care%: REM not interested in NP REM NOTHING. WHEN please_push%: REM Perseverative nosepoke. PROCrecord_response(box%, hole%, TIME - please_push_began_at%(box%)) perseverative_nosepokes%(box%, trial%(box%)) += 1 WHEN intertrial_interval%: REM Premature response. PROCrecord_response(box%, hole%, TIME - iti_began_at%(box%)) premature_nosepokes%(box%, trial%(box%)) += 1 IF prem_TO%(box%) = yes% THEN PROCkill_timer(box% + iti_timer%, E%) REM The ITI timer is stopped so there is no stimulus ON after this ITI. PROCkill_timer(box% + noise1_timer%, E%) REM If there is noise scheduled, it is now cancelled. PROCset_timeout(box%) ENDIF WHEN stim_on%, stim_off%: REM Correct/incorrect response REM By the way, these two phases constitute the limited hold. latency_to_respond%(box%, trial%(box%)) = TIME - stim_on_at%(box%) PROCrecord_response(box%, hole%, TIME - stim_on_at%(box%)) chosen_hole%(box%, trial%(box%)) = hole% PROCkill_timer(box% + stim_on_timer%, E%) PROCkill_timer(box% + stim_off_timer%, E%) PROCkill_timer(box% + noise1_timer%, E%) :REM if rat nosepokes and noise scheduled, cancel it. Bang. PROCswitch_off_all_holes(box%) IF hole% = offered_hole%(box%, trial%(box%)) THEN REM correct total_correct%(box%) += 1 PROCgive_reward(box%) ELSE REM incorrect total_incorrect%(box%) += 1 PROCset_timeout(box%) ENDIF WHEN awaiting_collect%: REM Perseverative nosepoke. PROCrecord_response(box%, hole%, TIME - stim_on_at%(box%)) perseverative_nosepokes%(box%, trial%(box%)) += 1 WHEN timeout%: REM Restart timeout. *** AC to decide re recording PROCrestart_timeout(box%) WHEN finished_state%: REM NOTHING. WHEN aborted_state%: REM NOTHING. OTHERWISE: VDU7:COLOUR magenta%:PRINTTAB(0,0);"--- Invalid case to FNnosepoke ---"; ENDCASE =0 DEF FNpanelpush(box%, bogus%) IF bogus%=0 =0 CASE nosepoke_state%(box%) OF WHEN dont_care%: REM not interested in NP REM NOTHING. WHEN please_push%: REM Begin a new trial, which begins with the "ITI". PROCrecord_response(box%, panel_code%, TIME - please_push_began_at%(box%)) PROCstart_trial_with_iti(box%) WHEN intertrial_interval%: REM Perseverative panel-push. PROCrecord_response(box%, panel_code%, TIME - iti_began_at%(box%)) perseverative_panelpushes%(box%, trial%(box%)) += 1 WHEN stim_on%, stim_off%: REM Perseverative panel-push. PROCrecord_response(box%, panel_code%, TIME - stim_on_at%(box%)) perseverative_panelpushes%(box%, trial%(box%)) += 1 WHEN awaiting_collect%: REM Successful collection, record latency and begin a new trial with an ITI. latency_to_collect_reward%(box%, trial%(box%)) = TIME - rewarded_at%(box%) PROCstart_trial_with_iti(box%) WHEN timeout%: REM NOTHING. WHEN finished_state%: REM NOTHING. WHEN aborted_state%: REM NOTHING. OTHERWISE: VDU7:COLOUR magenta%:PRINTTAB(0,0);"--- Invalid case to FNpanelpush ---"; ENDCASE =0 DEF PROCrecord_response(box%, location%, time%) LOCAL r% IF recorded_responses%(box%) = max_responses% THEN COLOUR white% PRINTTAB(0,0);"--- Exceeded maximum number of recorded responses for box ";box%;" ---"; ENDPROC ELSE recorded_responses%(box%) += 1 r% = recorded_responses%(box%) response_time_in_trial%(box%-1, r%) = TIME - trial_began_at%(box%) response_trial%(box%-1, r%) = trial%(box%) response_phase%(box%-1, r%) = nosepoke_state%(box%) response_location%(box%-1, r%) = location% response_time%(box%-1, r%) = time% ENDIF ENDPROC REM ======================================================================== REM Displays during execution REM ======================================================================== DEF PROCdisplay_startup MODE 12 COLOUR yellow% PRINT "Five-choice task." PRINT progname$;" by Rudolf. Version of ";version_date$ PRINT "Date/Time: ";date_time$ PRINT "___________________________________________________________________________" COLOUR white% PRINT' PRINT"Box Trial State #Correct #Incorrect #Omission #Pellets" PRINT"-----------------------------------------------------------------------------" REM 0123456789012345678901234567890123456789012345678901234567890123456789 display_firstline%=VPOS ENDPROC DEF FNdisplay_line(box%) = display_firstline% + (box%-1)*3 DEF PROCdisplay_box(box%) line% = FNdisplay_line(box%) COLOUR white% PRINTTAB(0,line%);box%; PRINTTAB(5,line%);trial%(box%); PROCdisplay_state(box%) COLOUR white% PRINTTAB(40,line%);total_correct%(box%); PRINTTAB(46,line%);total_incorrect%(box%); PRINTTAB(57,line%);total_omissions%(box%); PRINTTAB(69,line%);total_pellets%(box%); ENDPROC DEF PROCdisplay_state(box%) line% = FNdisplay_line(box%) COLOUR yellow% PRINTTAB(12,line%); CASE nosepoke_state%(box%) OF WHEN dont_care%: PRINT "Nothing much "; WHEN please_push%: PRINT "Awaiting panel push. "; WHEN intertrial_interval%: PRINT "Trial started, in 'ITI'."; WHEN stim_on%: PRINT "Stimulus on... "; WHEN stim_off%: PRINT "Stimulus off... "; WHEN awaiting_collect%: PRINT "You won. Eat up. "; WHEN timeout%: PRINT "DARKNESSS ENGULFS YOU..."; WHEN finished_state%: PRINT "--- FINISHED --- "; WHEN aborted_state%: PRINT "--- ABORTED --- "; OTHERWISE: VDU7:COLOUR magenta%:PRINTTAB(0,0);"--- Invalid case to PROCdisplay_state ---"; ENDCASE COLOUR white% ENDPROC REM ======================================================================== REM Finishing up REM ======================================================================== DEF FNabort_box(box%,bogus%) :REM checked for AC IF bogus%=0 =0 PROCset_np_state(box%,aborted_state%) PROCfinished(box%) =0 DEF PROCfinished(box%) LOCAL hole%, i% trial_duration%(box%, trial%(box%)) = TIME - trial_began_at%(box%) PROCswitch_off_all_holes(box%) PROCswitch_off(houselight%(box%), E%) PROCswitch_off(traylight%(box%), E%) FOR hole% = 1 TO nholes% PROCkill_switch(nosepoke%(box%,hole%), E%) NEXT PROCkill_switch(panelpush%(box%), E%) REM ... any timers outstanding? Shouldn't be. finished%(box%) = yes% FOR i%=1 TO nboxes% IF using_the_box%(i%)=yes% AND finished%(i%)<>yes% THEN ENDPROC NEXT REM Now all boxes have finished. PROCkill_all REM ----------------------------------------------------------------- REM Output. REM ----------------------------------------------------------------- LOCAL ch%,t%,r%,d$,score, pers_np%, prem_np%, pers_pp% ch% = OPENOUT(datafile$) PTR#ch%=EXT#ch% REM Don't have lines longer than about 160 chars; BASIC can't load it ("Bad program"). PROCprint_string(ch%,"PROGNAME,DATE_TIME,RAT,BOX,SESSION,STIM_DUR,LIM_HOLD,BRIGHTNESS,") PROCprint_string(ch%,"NOISE_OPTION,NOISE_USED,NOISE_DUR,NOISE_ONSET,TIMEOUT_DUR,TREATMENT,") PROCprint_string(ch%,"FORCE_A_HOLE,") PROCprint_string(ch%,"TRIAL,ITI_TIME,PERSEV_PP,PREM_NP,OFFERED,CHOSEN,RESPONSE_LATENCY,PERSEV_RESPONSES,COLLECT_LATENCY,") PROCprint_line(ch%,"EXPERIENCED_TIMEOUT,TRIAL_START_TIME,TRIAL_DURATION") FOR box% = 1 TO nboxes% IF using_the_box%(box%)=yes% THEN FOR t% = 1 TO trial%(box%) PROCprint_string(ch%, progname$+"("+version_date$+"),"+date_time$+","+rat_id$(box%)+","+STR$(box%)) PROCprint_string(ch%, ","+STR$(session_number%(box%))+","+STR$(stimulus_duration%(box%))+","+STR$(limited_hold%(box%))) PROCprint_string(ch%, ","+STR$(brightness_level%(box%))+","+STR$(noise_option%(box%,t%))+","+STR$(noise_used%(box%,t%))) PROCprint_string(ch%, ","+STR$(noise_duration%(box%))+","+STR$(noise_onset%(box%,t%))) PROCprint_string(ch%, ","+STR$(timeout_duration%(box%))+","+treatment$(box%)) PROCprint_string(ch%, ","+yesno$(force_a_hole%(box%))) PROCprint_string(ch%, ","+STR$(t%)) PROCprint_string(ch%, ","+STR$(iti_duration%(box%,t%))) PROCprint_string(ch%, ","+STR$(perseverative_panelpushes%(box%,t%))) PROCprint_string(ch%, ","+STR$(premature_nosepokes%(box%,t%))) PROCprint_string(ch%, ","+STR$(offered_hole%(box%,t%))) PROCprint_string(ch%, ","+STR$(chosen_hole%(box%,t%))) PROCprint_string(ch%, ","+STR$(latency_to_respond%(box%,t%))) PROCprint_string(ch%, ","+STR$(perseverative_nosepokes%(box%,t%))) PROCprint_string(ch%, ","+STR$(latency_to_collect_reward%(box%,t%))) PROCprint_string(ch%, ","+STR$(timeout_experienced%(box%,t%))) PROCprint_string(ch%, ","+STR$(trial_start_time%(box%,t%))) PROCprint_line(ch%, ","+STR$(trial_duration%(box%,t%))) NEXT ENDIF NEXT CLOSE#ch% ch% = OPENOUT(responsefile$) PTR#ch%=EXT#ch% PROCprint_string(ch%,"PROGNAME,DATE_TIME,RAT,BOX,") PROCprint_line(ch%,"TRIAL,PHASE,LOCATION,TIME,TIME_IN_TRIAL") FOR box% = 1 TO nboxes% IF using_the_box%(box%)=yes% THEN d$ = progname$ + "," + date_time$ + "," + rat_id$(box%) + "," + STR$(box%) + "," FOR r% = 1 TO recorded_responses%(box%) PROCprint_string(ch%, d$ + STR$(response_trial%(box%-1,r%)) + "," + STR$(response_phase%(box%-1,r%))) PROCprint_string(ch%, "," + STR$(response_location%(box%-1,r%)) + "," + STR$(response_time%(box%-1,r%))) PROCprint_line(ch%, "," + STR$(response_time_in_trial%(box%-1,r%))) NEXT ENDIF NEXT CLOSE#ch% ch% = OPENOUT(logfile$) PTR#ch%=EXT#ch% IF printing%=1 THEN VDU 2 PRINT"=====================================================================" PRINT"!";progname$;", by Rudolf Cardinal, ";version_date$ PRINT"Finished at ";TIME$ PRINT"Date/time code: ";date_time$ PRINT"=====================================================================" PROCprint_line_visibly(ch%,"PROGNAME,DATE,RAT,SESSION,TREATMENT,TRAYLIGHT,TOTAL_CORRECT,TOTAL_INCORRECT,TOTAL_OMISSIONS,TOTAL_TRIALS,PC_CORRECT,PC_OMISSIONS,CORRECT_LATENCY,INCORRECT_LATENCY,PREM_NP,PERSEV_NP,PERS_PP,COLLECT_LATENCY") REM *** Stick all per-session information here FOR box%=1 TO nboxes% IF using_the_box%(box%)=yes% THEN PROCprint_string_visibly(ch%,progname$+"("+version_date$+")") PROCprint_string_visibly(ch%,","+date_time$) PROCprint_string_visibly(ch%,","+rat_id$(box%)) PROCprint_string_visibly(ch%,","+STR$(session_number%(box%))) PROCprint_string_visibly(ch%,","+treatment$(box%)) PROCprint_string_visibly(ch%,","+yesno$(traylight_used%(box%))) PROCprint_string_visibly(ch%,","+yesno$(prem_TO%(box%))) PROCprint_string_visibly(ch%,","+STR$(total_correct%(box%))) PROCprint_string_visibly(ch%,","+STR$(total_incorrect%(box%))) PROCprint_string_visibly(ch%,","+STR$(total_omissions%(box%))) PROCprint_string_visibly(ch%,","+STR$(trial%(box%))) :REM starts at zero, incremented at the start of each trial only IF (total_correct%(box%)+total_incorrect%(box%))=0 THEN PROCprint_string_visibly(ch%,",***") ELSE PROCprint_string_visibly(ch%,","+STR$( 100*total_correct%(box%)/(total_correct%(box%)+total_incorrect%(box%)) )) ENDIF IF trial%(box%)=0 THEN PROCprint_string_visibly(ch%,",***") ELSE PROCprint_string_visibly(ch%,","+STR$( 100*total_omissions%(box%)/trial%(box%) )) ENDIF IF total_correct%(box%)=0 THEN PROCprint_string_visibly(ch%,",***") ELSE REM correct latency score = 0 FOR t% = 1 TO trial%(box%) IF offered_hole%(box%,t%) = chosen_hole%(box%,t%) THEN score += latency_to_respond%(box%,t%) REM definition of an correct trial NEXT PROCprint_string_visibly(ch%,","+STR$( score/total_correct%(box%) )) ENDIF IF total_incorrect%(box%)=0 THEN PROCprint_string_visibly(ch%,",***") ELSE REM incorrect latency score = 0 FOR t% = 1 TO trial%(box%) IF chosen_hole%(box%,t%)<>0 AND offered_hole%(box%,t%)<>chosen_hole%(box%,t%) THEN score += latency_to_respond%(box%,t%) REM definition of an incorrect trial NEXT PROCprint_string_visibly(ch%,","+STR$( score/total_incorrect%(box%) )) ENDIF prem_np%=0 pers_np%=0 pers_pp%=0 FOR t% = 1 TO trial%(box%) pers_np% += perseverative_nosepokes%(box%,t%) prem_np% += premature_nosepokes%(box%, t%) pers_pp% += perseverative_panelpushes%(box%, t%) NEXT PROCprint_string_visibly(ch%,","+STR$(prem_np%)+","+STR$(pers_np%)+","+STR$(pers_pp%)) IF total_correct%(box%)=0 THEN PROCprint_line_visibly(ch%,",***") ELSE score = 0 FOR t% = 1 TO trial%(box%) IF offered_hole%(box%,t%) = chosen_hole%(box%,t%) THEN score += latency_to_collect_reward%(box%, t%) REM definition of an correct trial NEXT PROCprint_line_visibly(ch%,","+STR$( score/total_correct%(box%) )) ENDIF ENDIF NEXT CLOSE #ch% VDU 3 OSCLI("SETTYPE "+logfile$+" TEXT") IF FNget_letter_param("Run another?", "YN", "") = "Y" THEN CLS: RUN ENDIF ENDPROC