REM >5chyok progname$ = "5ChYok" version_date$ = "19-Jan-2000" debug% = 0 :REM in debugging mode? printing% = 1 :REM controls whether log is sent to printout (0=no, 1=yes) REM 5-choice task, by Rudolf Cardinal, for Anastasia Christakou. Started 29 May 99. REM Aim: to replicate Paul Fray code entitled "5Choice task for Archimedes - V1.10 for A5000" REM but with per-response recording, proper data output and legible code. REM REM January 2000: converted to enable master/yoked boxes, for Jeff. REM Control/state variables are only stored for the master boxes, as are "start time"-type variables REM Inputs are piped for all boxes. REM ---------------------------------------------- REM Yoking this task is easy, but getting sensible classification of the slave responses is hard. REM ---------------------------------------------- REM Jeff's basic task does NOT extinguish houselight during timeouts. REM And some other things. Search for jefftask% throughout. REM REM Summary measures are recorded for each trial, and a DIALYSIS_TIMEBIN field gives the time bin REM into which that trial's start time falls, for easy calculation of binned measures using SQL (Access). REM This means bins are accurate to the nearest trial. (Bins usually 10 min, trials a very small fraction of that.) REM REM DEFINITION OF CORRECT/INCORRECT/PERSEV/PREMATURE NOSEPOKES FOR SLAVES REM REM Problem: when the master box changes state, but we're still interested in what the slave does next (because REM it doesn't know the box has changed state) REM REM - "Trial start" is defined by the master box at all times. REM REM - Between trial start and stimulus onset, all slave nosepoke (NP) responses are considered premature. REM REM - The first NP after stimulus presentation is marked as a correct or incorrect response, unless the limited REM hold time has elapsed from stimulus onset. This is true even if the master rat has responded correctly REM (causing the box to be in a 'reward collection' state, which means that the slave rat can even collect its REM reward before making a correct response). This is also true if the master has responded incorrectly (in which REM case the box is in a timeout). (See all refs to PROCrecord_first_response.) REM REM - If the limited hold elapses (from stimulus onset) before the slave makes a response, it is considered to have REM made an omission. (FNslave_limhold_up) REM REM - If a new trial begins before the slave's limited hold elapses and it has not made a response, REM it is considered to have made an omission. (FNstart_trial_with_iti; checking slave_in_limhold). REM REM - If the limited hold expires and a new trial has not yet begun, the master box will either be in a timeout REM or awaiting a panel-push to start a new trial. Like the master, NPs during the timeout are not classified REM (though they are, of course, recorded in the full log) and NPs during in the "awaiting panelpush" state REM are considered perseverative. (It would be an option to consider such timeout NPs as perseverative; in the master REM box, such NPs extend the timeout.) REM REM -- NOTE that this requires timeouts following limhold expiry to be distinguished from those not (e.g. after REM master incorr. response). REM REM - All slave NP responses after the first are considered perseverative. REM REM This definition requires (1) that a limited hold timer be maintained for slave boxes independently of their masters REM and (2) that first/subsequent NP responses be distinguished for slaves. REM The 'timer' can be done in software, as its expiry never has immediate consequences. Omissions can be checked REM at the next convenient stage. REM REM Most functions are master-only. The main ones that deal with slave input are the nosepoke/panelpush handlers. REM REM Trial numbers are stored for master box only. REM So all functions that handle slaves must use trial%(FNmaster_of(box%)) REM rather than trial%(box%). REM Similarly for offered_hole%(). And trial_start_time%(). REM ________________________________________________________________________________________________________ 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 *** Special case for slaves: can poke multiply here with no consequence 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 *** Special case for slaves: can poke multiply here with no consequence (stim. stays on) REM *** And we want the first response to be labelled correct/incorrect, and subsequent to be perseverative 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 --- ALSO, EXPERIENCED STIMULUS DURATION (useful to know for slave) 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 --- RELATIVE TO REWARD DELIVERY TIME (ALWAYS) 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 19 Jan 00 - trial_began_at=TIME was right anyway, what was I thinking? REM 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 ... up to 14 Jan 2000... Anastasia may have modified a few things... REM REM 17 Jan 2000 - The Day of Mutation: 5ChYok Arises REM A yoked version according to Jeff's specifications. 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": PROCjeff_five_hole_boxes_for_yoking LIBRARY ".ProgLibs.Random" MODE 12 dummy% = RND(-TIME) PROCbox_set_up jefftask% = 1 :REM Jeff's version of the task, rather than (say) Anastasia's. 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% noise1_timer% = 6 * nboxes% :REM used for time-to-noise noise2_timer% = 7 * nboxes% :REM used for noise-duration slave_limhold_timer% = 8 * nboxes% 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 delay_option%(nboxes%,ndelay_options%) DIM stimulus_duration%(nboxes%) DIM limited_hold%(nboxes%) DIM timeout_duration%(nboxes%) DIM traylight_used%(nboxes%) 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 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 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 noise_onset%(nboxes%,maxtrials%) :REM when was the noise? MASTER ONLY DIM iti_duration%(nboxes%,maxtrials%) :REM how long the initial ITI was MASTER ONLY DIM timeout_experienced%(nboxes%,maxtrials%) :REM the length of timeout it actually got (can exceed programmed timeout) MASTER ONLY DIM trial_duration%(nboxes%,maxtrials%) :REM how long did that trial last? MASTER ONLY DIM trial_start_time%(nboxes%,maxtrials%) :REM trial start time, relative to session start time MASTER ONLY DIM experienced_stimulus_duration%(nboxes%,maxtrials%) :REM MASTER ONLY DIM undiscriminated_nosepokes%(nboxes%,maxtrials%) DIM undiscriminated_panelpushes%(nboxes%,maxtrials%) 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% = 4000 :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) DIM response_time_in_session%(nboxes%-1, max_responses%) :REM new for Jeff's version 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 (and for recording) DIM trial_began_at%(nboxes%) :REM this trial's start time DIM slave_has_responded%(nboxes%) :REM ... in this trial DIM slave_in_limhold%(nboxes%) :REM for the special independent monitoring of slave state 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" REM _____________________________________ for yoking unused% = 0: master% = 1: slave% = 2 DIM box_type$(2) box_type$(unused%)="Unused": box_type$(master%)="Master": box_type$(slave%)="Slave" DIM box_type%(nboxes%) :REM unused/master/slave DIM master_of_box%(nboxes%) :REM for slaves, holds box number of their master ENDPROC DEF PROCget_parameters LOCAL box%, d%, noisetemp%, i%, config_valid%, num_masters%, num_slaves% CLS COLOUR yellow% PRINT progname$;" by Rudolf Cardinal, ";version_date$ PRINT PRINT "Five-choice task - YOKED VERSION." PRINT "________________________________________________________________________" COLOUR white% PRINT "Date/Time: ";date_time$ dialysis_timebin_size% = 60*100 * FNget_num_param("Enter dialysis time bin size (min)", 10, 1, 60) PRINT REPEAT num_masters% = 0 REM Get configuration. FOR box% = 1 TO nboxes% box_type%(box%) = FNget_letter_param_as_num("Box "+STR$(box%)+": Enter box type (Unused, Master, Slave)", "UMS", "U") - 1 REM FNget_letter_param_as_num() returns 1-..., and we want 0... (0=unused, 1=master, 2=slave) CASE box_type%(box%) OF WHEN unused%: using_the_box%(box%) = no% WHEN master%: using_the_box%(box%) = yes% num_masters% += 1 WHEN slave%: using_the_box%(box%) = yes% num_slaves% += 1 master_of_box%(box%) = FNget_num_param(" Enter box to act as master for box "+STR$(box%), 0, 1, nboxes%) OTHERWISE: VDU7:PRINT"Bug in PROCget_parameters":END ENDCASE NEXT PRINT REM Check configuration is internally consistent. config_valid% = yes% IF num_masters% = 0 THEN config_valid% = no% IF num_slaves% = 0 THEN VDU 7:PRINT "Warning: no slaves - why use this program?" FOR box% = 1 TO nboxes% IF box_type%(box%)=slave% AND box_type%(master_of_box%(box%))<>master% THEN config_valid%=no% NEXT IF config_valid%<>yes% THEN VDU 7:PRINT "Configuration invalid. Try again."' UNTIL config_valid% = yes% FOR box% =1 TO nboxes% IF using_the_box%(box%) = yes% THEN REPEAT COLOUR yellow%:PRINT ''"Box number ";box%:COLOUR white% 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") IF FNis_master(box%) THEN 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) _temp_traylight_default% = yes% IF jefftask% THEN _temp_traylight_default% = no% traylight_used%(box%) = FNget_num_param("Use traylight? "+STR$(yes%)+"=yes, "+STR$(no%)+"=no",_temp_traylight_default%,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% 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." NEXT ENDIF timeout_duration%(box%) = FNget_num_param("Enter minimum timeout (darkness) interval (csec)", 500, 500, 6000) ENDIF UNTIL FNget_letter_param("Please confirm...(Y or N)", "YN", "") = "Y" ENDIF 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%) REM Master/slave; slaves -> set up pipes, masters -> set up pipes and set state. LOCAL hole% 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%) trial%(box%) = 0 :REM FNstart_trial increments it to 1 for the first trial finished%(box%) = no% nosepoke_state%(box%) = dont_care% :REM these variables are ignored for slaves, anyway IF FNis_master(box%) THEN PROCstart_session(box%) ENDPROC DEF PROCstart_session(box%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC LOCAL b% FOR b%=1 TO nboxes% IF FNmaster_of(b%)=box% THEN PROCsingle_pellet(pellet_dispenser%(b%)) ENDIF NEXT total_pellets%(box%) += 1 session_began_at%(box%) = TIME trial_began_at%(box%) = TIME :REM just for PROCrecord_response, when it does the initiating panel-push... PROCrequire_a_poke(box%) ENDPROC DEF PROCrequire_a_poke(box%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC PROCmaster_switch_on(houselight_group%, box%, 0) IF traylight_used%(box%)=yes% THEN PROCmaster_switch_on(traylight_group%, box%, 0) PROCset_np_state(box%, please_push%) please_push_began_at%(box%) = TIME PROCdisplay_box(box%) ENDPROC DEF PROCstart_trial_with_iti(box%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC LOCAL b% 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%) FOR b%=1 TO nboxes% IF FNmaster_of(b%)=box% AND b%<>box% AND slave_in_limhold%(b%)=yes% THEN PROCkill_timer(box% + slave_limhold_timer%, E%) total_omissions%(b%) += 1 ENDIF NEXT :REM one trial finishes, the next begins trial%(box%) += 1 trial_began_at%(box%) = TIME trial_start_time%(box%, trial%(box%)) = trial_began_at%(box%) iti_began_at%(box%) = TIME iti_duration%(box%,trial%(box%)) = FNget_programmed_delay(box%) PROCmaster_switch_on(houselight_group%, box%, 0) PROCmaster_switch_off(traylight_group%, box%, 0) PROCset_np_state(box%, intertrial_interval%) FOR b%=1 TO nboxes% IF FNmaster_of(b%)=box% THEN slave_has_responded%(b%) = no% slave_in_limhold%(b%) = no% ENDIF NEXT 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 noise_onset%(box%,trial%(box%)) = noise_onset_option%(box%,FNrandom_integer(1,nnoise_options%)) 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 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 REM Master only. IF NOT FNis_master(box%) THEN =0 PROCmaster_switch_on(tone_group%, box%, 0) 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 REM Master only, BUT it does things for its slaves IF NOT FNis_master(box%) THEN =0 LOCAL loop%, dummy% PROCset_np_state(box%, dont_care%) :REM Rudolf's paranoia offered_hole%(box%,trial%(box%)) = FNrandom_integer(1,5) stim_on_at%(box%) = TIME: REM time when light comes on (see below) LOCAL b% FOR b%=1 TO nboxes% IF FNmaster_of(b%) = box% AND b%<>box% THEN slave_in_limhold%(b%) = yes% PROCpipe_timer(b% + slave_limhold_timer%, limited_hold%(FNmaster_of(box%)), 0, "FNslave_limhold_up(", b%, E%) ENDIF NEXT PROCmaster_switch_on(aperturelight_group%, box%, offered_hole%(box%,trial%(box%))) 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 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 REM Master only. IF NOT FNis_master(box%) THEN =0 experienced_stimulus_duration%(box%, trial%(box%)) = stimulus_duration%(box%) PROCset_np_state(box%, dont_care%) :REM Rudolf's paranoia PROCmaster_switch_off(aperturelight_group%, box%, offered_hole%(box%,trial%(box%))) 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 REM Master only. IF NOT FNis_master(box%) 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 FNslave_limhold_up(box%, bogus%) IF bogus%=0 =0 slave_in_limhold%(box%) = no% total_omissions%(box%) += 1 =0 DEF PROCswitch_off_all_holes(box%) LOCAL h% FOR h%=1 TO nholes% PROCmaster_switch_off(aperturelight_group%, box%, h%) :REM will fail if a non-master box gets through NEXT ENDPROC DEF PROCgive_reward(box%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC PROCset_np_state(box%, dont_care%) PROCswitch_off_all_holes(box%) IF traylight_used%(box%)=yes% THEN PROCmaster_switch_on(traylight_group%, box%, 0) LOCAL b% FOR b%=1 TO nboxes% IF FNmaster_of(b%) = box% THEN PROCspaced_pellet(pellet_dispenser%(b%), numpellets%, pellet_dispenser_timer%+b%, pellet_gap%) ENDIF NEXT total_pellets%(box%) += numpellets% rewarded_at%(box%) = TIME PROCset_np_state(box%, awaiting_collect%) ENDPROC DEF PROCset_timeout(box%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC PROCswitch_off_all_holes(box%) IF jefftask% = yes% THEN PROCmaster_switch_on(houselight_group%, box%, 0) ELSE PROCmaster_switch_off(houselight_group%, box%, 0) ENDIF PROCmaster_switch_off(traylight_group%, box%, 0) 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 Master only. IF NOT FNis_master(box%) THEN ENDPROC 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 REM Master only. IF NOT FNis_master(box%) THEN =0 timeout_experienced%(box%, trial%(box%)) = TIME - timeout_began_at%(box%) REM *********************************************************************** REM *** This may be where Jeff's task differs from others, REM in that a panel-push is not required to start a trial after a timeout. REM Normal here is to use PROCrequire_a_poke(). REM Jeff may want PROCstart_trial_with_iti(). REM *********************************************************************** IF jefftask% = yes% THEN PROCstart_trial_with_iti(box%) ELSE PROCrequire_a_poke(box%) ENDIF =0 REM ======================================================================== REM Nosepoke and panel-push code REM Nosepoke *duration* is ignored. REM ======================================================================== DEF PROCset_np_state(box%, state%) REM Master only. IF NOT FNis_master(box%) THEN ENDPROC 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 *** Yoking principle: never call a state-setting function here for slave boxes undiscriminated_nosepokes%(box%, trial%(FNmaster_of(box%)) ) += 1 REM In this program, we're not interested in NP duration, so never look at leaving the magazine. CASE nosepoke_state%(FNmaster_of(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%(FNmaster_of(box%))) perseverative_nosepokes%(box%, trial%(FNmaster_of(box%))) += 1 WHEN intertrial_interval%: REM Premature response. PROCrecord_response(box%, hole%, TIME - iti_began_at%(FNmaster_of(box%))) premature_nosepokes%(box%, trial%(FNmaster_of(box%))) += 1 IF FNis_master(box%) 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. REM as the stimulus ends now, ... PROCrecord_response(box%, hole%, TIME - stim_on_at%(FNmaster_of(box%))) IF FNis_master(box%) THEN experienced_stimulus_duration%(box%, trial%(box%)) = TIME - stim_on_at%(FNmaster_of(box%)) PROCrecord_first_response(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 PROCgive_reward(box%) ELSE PROCset_timeout(box%) ENDIF ELSE REM SLAVE REM Will always be safely within the limited hold time... IF slave_has_responded%(box%) = no% THEN PROCrecord_first_response(box%, hole%) ELSE perseverative_nosepokes%(box%, trial%(FNmaster_of(box%))) += 1 ENDIF ENDIF WHEN awaiting_collect%: REM Master - perseverative nosepoke (has just earned reward). PROCrecord_response(box%, hole%, TIME - stim_on_at%(FNmaster_of(box%))) IF FNis_master(box%) THEN perseverative_nosepokes%(box%, trial%(FNmaster_of(box%))) += 1 ELSE REM SLAVE IF slave_has_responded%(box%) = no% AND slave_in_limhold%(box%)=yes% THEN PROCrecord_first_response(box%, hole%) ELSE perseverative_nosepokes%(box%, trial%(FNmaster_of(box%))) += 1 ENDIF ENDIF WHEN timeout%: REM Restart timeout. PROCrecord_response(box%, hole%, TIME - timeout_began_at%(FNmaster_of(box%))) IF FNis_master(box%) THEN PROCrestart_timeout(box%) ELSE IF slave_has_responded%(box%) = no% AND slave_in_limhold%(box%)=yes% THEN PROCrecord_first_response(box%, hole%) ENDIF ENDIF WHEN finished_state%: REM NOTHING. WHEN aborted_state%: REM NOTHING. OTHERWISE: VDU7:COLOUR magenta%:PRINTTAB(0,0);"--- Invalid case to FNnosepoke ---"; ENDCASE =0 DEF PROCrecord_first_response(box%, hole%) latency_to_respond%(box%, trial%(FNmaster_of(box%))) = TIME - stim_on_at%(FNmaster_of(box%)) chosen_hole%(box%, trial%(FNmaster_of(box%))) = hole% IF hole% = offered_hole%(FNmaster_of(box%), trial%(FNmaster_of(box%))) THEN REM correct total_correct%(box%) += 1 ELSE REM incorrect total_incorrect%(box%) += 1 ENDIF IF NOT FNis_master(box%) THEN slave_has_responded%(box%) = yes% IF slave_in_limhold%(box%) = yes% THEN PROCkill_timer(box% + slave_limhold_timer%, E%) slave_in_limhold%(box%) = no% ENDIF ENDPROC DEF FNpanelpush(box%, bogus%) IF bogus%=0 =0 REM *** Yoking principle: never call a state-setting function here for slave boxes undiscriminated_panelpushes%(box%, trial%(FNmaster_of(box%)) ) += 1 CASE nosepoke_state%(FNmaster_of(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%(FNmaster_of(box%))) IF FNis_master(box%) THEN PROCstart_trial_with_iti(box%) WHEN intertrial_interval%: REM Perseverative panel-push. PROCrecord_response(box%, panel_code%, TIME - iti_began_at%(FNmaster_of(box%))) perseverative_panelpushes%(box%, trial%(FNmaster_of(box%))) += 1 WHEN stim_on%, stim_off%: REM Perseverative panel-push. PROCrecord_response(box%, panel_code%, TIME - stim_on_at%(FNmaster_of(box%))) perseverative_panelpushes%(box%, trial%(FNmaster_of(box%))) += 1 WHEN awaiting_collect%: REM Successful collection, record latency and begin a new trial with an ITI. latency_to_collect_reward%(box%, trial%(FNmaster_of(box%))) = TIME - rewarded_at%(FNmaster_of(box%)) IF FNis_master(box%) THEN PROCstart_trial_with_iti(box%) WHEN timeout%: PROCrecord_response(box%, hole%, TIME - timeout_began_at%(FNmaster_of(box%))) 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%(FNmaster_of(box%)) response_time_in_session%(box%-1, r%) = TIME - session_began_at%(FNmaster_of(box%)) response_trial%(box%-1, r%) = trial%(FNmaster_of(box%)) response_phase%(box%-1, r%) = nosepoke_state%(FNmaster_of(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: YOKED VERSION" PRINT progname$;" by Rudolf Cardinal. 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(masterbox%) IF NOT FNis_master(masterbox%) THEN ENDPROC FOR box%=1 TO nboxes% IF FNmaster_of(box%)=masterbox% THEN line% = FNdisplay_line(box%) COLOUR white% PRINTTAB(0,line%);box%; IF FNis_master(box%) THEN PRINTTAB(5,line%);trial%(box%); PROCdisplay_state(box%) PRINTTAB(69,line%);total_pellets%(box%); ELSE PRINTTAB(5,line%);"Slaved to box ";FNmaster_of(box%); ENDIF COLOUR white% PRINTTAB(40,line%);total_correct%(box%); PRINTTAB(46,line%);total_incorrect%(box%); PRINTTAB(57,line%);total_omissions%(box%); ENDIF NEXT ENDPROC DEF PROCdisplay_state(box%) IF NOT FNis_master(box%) THEN ENDPROC 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 REM Master only. IF NOT FNis_master(box%) THEN =0 PROCset_np_state(box%,aborted_state%) PROCfinished(box%) =0 DEF PROCfinished(box%) REM Master only. IF NOT FNis_master(box%) ENDPROC LOCAL hole%, i%, b% trial_duration%(box%, trial%(box%)) = TIME - trial_began_at%(box%) PROCswitch_off_all_holes(box%) PROCmaster_switch_off(houselight_group%, box%, 0) PROCmaster_switch_off(traylight_group%, box%, 0) FOR b%=1 TO nboxes% IF FNmaster_of(b%) = box% THEN FOR hole% = 1 TO nholes% PROCkill_switch(nosepoke%(b%,hole%), E%) NEXT PROCkill_switch(panelpush%(b%), E%) PROCkill_timer(iti_timer% + b%, E%) PROCkill_timer(timeout_timer% + b%, E%) PROCkill_timer(stim_on_timer% + b%, E%) PROCkill_timer(stim_off_timer% + b%, E%) PROCkill_timer(pellet_dispenser_timer% + b%, E%) PROCkill_timer(noise1_timer% + b%, E%) PROCkill_timer(noise2_timer% + b%, E%) PROCkill_timer(slave_limhold_timer% + b%, E%) ENDIF NEXT REM ... any timers outstanding? Shouldn't be. REM Ah, no, there might be. Also for the slave. Hence the blunderbuss REM approach above. finished%(box%) = yes% FOR i%=1 TO nboxes% IF using_the_box%(i%)=yes% AND box_type%(i%)=master% 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,BOX_TYPE,MASTER_BOX,SESSION,PROGRAMMED_STIM_DUR,") PROCprint_string(ch%,"LIM_HOLD,BRIGHTNESS,NOISE_DUR,NOISE_ONSET,TIMEOUT_DUR,TREATMENT,") PROCprint_string(ch%,"TRIAL,ITI_TIME,EXPERIENCED_STIM_DUR,PERSEV_PP,PREM_NP,OFFERED,CHOSEN,RESPONSE_LATENCY,PERSEV_RESPONSES,COLLECT_LATENCY,") PROCprint_line(ch%,"EXPERIENCED_TIMEOUT,TRIAL_START_TIME,TRIAL_DURATION,ALL_NOSEPOKES,ALL_PANELPUSHES,DIALYSIS_TIMEBIN") FOR box% = 1 TO nboxes% IF using_the_box%(box%)=yes% THEN FOR t% = 1 TO trial%(FNmaster_of(box%)) PROCprint_string(ch%, progname$+"("+version_date$+"),"+date_time$+","+rat_id$(box%)+","+STR$(box%)) PROCprint_string(ch%, ","+box_type$( box_type%(box%) )) PROCprint_string(ch%, ","+STR$(FNmaster_of(box%)) ) PROCprint_string(ch%, ","+STR$(session_number%(box%))+","+STR$(stimulus_duration%(FNmaster_of(box%)))+","+STR$(limited_hold%(FNmaster_of(box%)))) PROCprint_string(ch%, ","+STR$(brightness_level%(FNmaster_of(box%)))+","+STR$(noise_duration%(FNmaster_of(box%)))+","+STR$(noise_onset%(FNmaster_of(box%),t%))) PROCprint_string(ch%, ","+STR$(timeout_duration%(FNmaster_of(box%)))+","+treatment$(box%)) PROCprint_string(ch%, ","+STR$(t%)) PROCprint_string(ch%, ","+STR$(iti_duration%(FNmaster_of(box%),t%))) PROCprint_string(ch%, ","+STR$(experienced_stimulus_duration%(FNmaster_of(box%),t%))) PROCprint_string(ch%, ","+STR$(perseverative_panelpushes%(box%,t%))) PROCprint_string(ch%, ","+STR$(premature_nosepokes%(box%,t%))) PROCprint_string(ch%, ","+STR$(offered_hole%(FNmaster_of(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%(FNmaster_of(box%),t%))) PROCprint_string(ch%, ","+STR$(trial_start_time%(FNmaster_of(box%),t%) - session_began_at%(FNmaster_of(box%) ) )) REM Internally, trial start time is in TIME units, but REM it's much more informative to have it relative to sessionstart PROCprint_string(ch%, ","+STR$(trial_duration%(FNmaster_of(box%),t%))) PROCprint_string(ch%, ","+STR$(undiscriminated_nosepokes%(box%,t%))) PROCprint_string(ch%, ","+STR$(undiscriminated_panelpushes%(box%,t%))) PROCprint_line(ch%, ","+STR$( FNdialysis_timebin(trial_start_time%(FNmaster_of(box%),t%) - session_began_at%(FNmaster_of(box%)) ) )) 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_IN_WHATEVER,TIME_IN_TRIAL,TIME_IN_SESSION") FOR box% = 1 TO nboxes% IF using_the_box%(box%)=yes% AND recorded_responses%(box%)>0 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_string(ch%, "," + STR$(response_time_in_trial%(box%-1,r%)) ) PROCprint_line( ch%, "," + STR$(response_time_in_session%(box%-1,r%)) ) NEXT ENDIF NEXT CLOSE#ch% ch% = OPENOUT(logfile$) PTR#ch%=EXT#ch% IF printing%=1 THEN VDU 2 PRINT PRINT"=====================================================================" PRINT"!";progname$;", by Rudolf Cardinal, ";version_date$ PRINT"Finished at ";TIME$ PRINT"Date/time code: ";date_time$ PRINT"Per-trial data stored in: ";datafile$ PRINT"Per-response data stored in: ";responsefile$ PRINT"=====================================================================" PRINT PRINT"--- Time bin information can be extracted from the per-trial data file." PRINT"--- The sort of information that Anastasia wants:" PRINT PROCprint_string_visibly(ch%,"PROGNAME,DATE,RAT,SESSION,TREATMENT,BOX,BOX_TYPE,MASTER_BOX,TRAYLIGHT,TOTAL_CORRECT,TOTAL_INCORRECT,") PROCprint_string_visibly(ch%,"TOTAL_OMISSIONS,TOTAL_TRIALS,PC_CORRECT,PC_OMISSIONS,CORRECT_LATENCY,INCORRECT_LATENCY,") PROCprint_line_visibly(ch%,"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%,","+STR$(box%)) PROCprint_string_visibly(ch%,","+box_type$(box_type%(box%))) PROCprint_string_visibly(ch%,","+STR$(FNmaster_of(box%))) PROCprint_string_visibly(ch%,","+yesno$(traylight_used%(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%))) _temp_trials% = trial%(FNmaster_of(box%)) REM starts at zero, incremented at the start of each trial only REM and maintained for master box only PROCprint_string_visibly(ch%,","+STR$( _temp_trials% )) 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 _temp_trials%=0 THEN PROCprint_string_visibly(ch%,",***") ELSE PROCprint_string_visibly(ch%,","+STR$( 100*total_omissions%(box%)/_temp_trials% )) ENDIF IF total_correct%(box%)=0 THEN PROCprint_string_visibly(ch%,",***") ELSE REM correct latency score = 0 FOR t% = 1 TO _temp_trials% IF offered_hole%(FNmaster_of(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 _temp_trials% IF chosen_hole%(box%,t%)<>0 AND offered_hole%(FNmaster_of(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 _temp_trials% 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 _temp_trials% IF offered_hole%(FNmaster_of(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 REM ====================================================== REM Yoking code REM ====================================================== DEF FNis_master(box%) REM returns TRUE if box% is a master, FALSE if it's yoked IF box_type%(box%)=master% THEN =TRUE =FALSE DEF FNmaster_of(box%) REM returns the box-which-is-the-master-of-this-box IF FNis_master(box%) THEN =box% =master_of_box%(box%) DEF PROCmaster_switch_on(linegroup%, masterbox%, holenum%) REM holenum% is ignored unless linegroup% = aperturelight_group% PROCmaster_switch(linegroup%, masterbox%, holenum%, TRUE) ENDPROC DEF PROCmaster_switch_off(linegroup%, masterbox%, holenum%) REM holenum% is ignored unless linegroup% = aperturelight_group% PROCmaster_switch(linegroup%, masterbox%, holenum%, FALSE) ENDPROC DEF PROCmaster_switch(linegroup%, masterbox%, holenum%, on%) REM switches a given line on/off for box% and all boxes yoked to it REM holenum% is ignored unless linegroup% = aperturelight_group% IF NOT FNis_master(masterbox%) THEN VDU 7:PRINTTAB(0,0);"*** Error: PROCmaster_switch() attempted for a slave or unused box ***":END ENDIF LOCAL b%, line% FOR b% = 1 TO nboxes% IF FNmaster_of(b%) = masterbox% THEN line% = FNjeff_five_hole_get_line(linegroup%, b%, holenum%) IF on% THEN PROCswitch_on(line%, E%) ELSE PROCswitch_off(line%, E%) ENDIF NEXT ENDPROC DEF FNdialysis_timebin(time%) REM time% is from trial_start_time%(), which is relative to session start and in cs. = time% DIV dialysis_timebin_size%