User Manual: Inquisit Letter Cancellation Task


___________________________________________________________________________________________________________________

											MILLISECOND LETTER CANCELLATION TASK
___________________________________________________________________________________________________________________

Script Author:	David Nitz for Millisecond Software, LLC
Date:			06-16-2023
last updated:	06-16-2023

Script Copyright © 06-12-2023 Millisecond Software

For questions about this script, please contact support@millisecond.com.

___________________________________________________________________________________________________________________
BACKGROUND INFO
___________________________________________________________________________________________________________________
This script implements a letter cancellation task similar to and inspired by the procedure described in:

	Pahor, A., Mester R.E, Carrillo A.A., Ghil E., Reimer J.F., Jaeggi S.M., Seitz A.R. (2022). 
	UCancellation: A new mobile measure of selective attention and concentration. 
	Behavior Research Methods. 54(5), 2602-2617. 
	https://doi.org/10.3758/s13428-021-01765-5

	Collins, C.L., Pina, A., Carrillo, A., Ghil, E., Smith-Peirce, R.N., Gomez, M., Okolo, P., Chen, Y., Pahor, A., Jaeggi, S.M., Seitz, A.R. (2022). 
	Video-Based Remote Administration of Cognitive Assessments and Interventions: a Comparison with In-Lab Administration. 
	Journal of Cognitive Enhancement. 6(3), 316-326.
	https://doi.org/10.1007/s41465-022-00240-z

The task is intended as a simple, modern alternative to the classic, commercial d2 / d2-C / d2-R family of attention-concentration tests.

	Brickenkamp, R., & Zilmer, E. (1998). d2 Test of Attention (d2) [Database record]. APA PsycTests.
	https://doi.org/10.1037/t03299-000

The procedure is optimized and primarily intended for use on touch-screen devices (tablets), but can be completed using the mouse on
regular Windows / Mac desktop or laptop computers as well.

NOTE: While the task implemented here is similar to the UCancellation Letters variant, it is NOT and is NOT SUPPOSED to 
be a 1:1 clone of UCancellation Letters. Among other things, the task differs in visual presentation, configuration options, 
data file structure, and some aspects of the practice phase.

___________________________________________________________________________________________________________________
TASK DESCRIPTION
___________________________________________________________________________________________________________________
Rows of 8 letters are presented on-screen. Letters are either targets ("d"s with two marks) or distractors 
("d"s with fewer or more than two marks, "p"s with any number of marks). Participants are instructed to select the 
targets in each row from left to right and to ignore the distractors. An animated demonstration illustrates the task. 
This is followed by a guided practice phase consisting of 3 rows. Detailed feedback is provided during this practice phase. 
The practice phase is repeated if participants make errors in more than one of the 3 practice rows.

During the test phase, the number of target letters in each row varies between 3 and 5, with exactly 40 targets in each set 
of 10 rows. Each row is presented on-screen for a maximum of 6 seconds, after which the next row is presented after a 
1-second blank period. Participants may advance to the next row early via a Next button (green arrow) at the right side of 
the screen. The goal is to complete as many rows as possible within a set time limit of 3.5 minutes, as indicated by a 
countdown timer displayed at the upper left corner of the screen. 
At the conclusion of the test phase, feedback on the number of "perfect" rows completed is provided.

With the default settings, at least 30 rows, containing a total of 120 targets, are presented:
- Max. duration of row + blank period is 7 seconds.
- Global time limit is 210 seconds (3.5 minutes).
  -> 210 / 7 = 30 rows if a participant never advances early to the next row.

___________________________________________________________________________________________________________________
	ADDITIONAL NOTES
___________________________________________________________________________________________________________________

- The task as implemented potentially differs from UCancellation Letters in a number of -- mostly minor -- aspects.
- values.rowLayout is an 8 character string consisting one 1s and 0s, indicating ordinal target and distractor positions in the given row.
  I.e., "01001100" indicates targets present in positions 2, 5, and 6 from left to right. 
  Distractors are present in positions 1, 3, 4, 7, and 8 respectively.
- values.item1Type to values.item8Type indicate the type of item in each position. A value of 1 indicates that the item in that position is
  a target; conversely, a value of 0 indicates the item in that position is a distractor.
- values.item1ItemNumber to values.item8ItemNumber indicate the specific stimulus item in that position. The targets (letters d with two marks)
  have are item numbers 1, 2, and 3. Item numbers 4 to 16 are the distractor items (letters d with fewer or more than two marks, all letters p).
  See item.letterItems, list.targetItemNumbers, and list.distractorItemNumbers for details.
- Target types are sampled such that, across each chunk of 30 rows, each type of target will be sampled *approximately* equally often.
  See /poolSize in list.targetItemNumbers for details.
  In addition, target type sampling is such that no more than 3 targets of the same type should be sampled in succession.
  See /maxrunsize in list.target_itemnubers for details.
- Distractor types are sampled randomly without replacement on a *per row* basis, i.e. no type of distractor should appear more than once in any 
  given row.
- values.responseLayout indicates which items were marked by the participant in a given row. It, too, is an 8 character string consisting of 1s and
  0s, e.g. "10100011" indicates that the participant marked row items 1, 3, 7, and 8.
- Test phase timing parameters are chosen such that if you were to let each row time out (instead of advancing to the next row early by clicking the 
  arrow), you will be able to complete exactly 30 rows within the 3.5 time limit (max. duration per row ~6 seconds, 1 second inter-row blank period), 
  i.e. (6s + 1s) * 30 rows = 210s = 3.5m.
- Slight timing variances cannot be avoided, i.e. combined duration of all rowAction trials within a given row might exceed the nominal 6 seconds 
  slightly, on the order of 6000ms + 10ms. Note: According to Pashor et al. (2022), UCancellation gives row time in seconds, whereas Inquisit gives 
  it in milliseconds, so the timing in this script may actually be tighter than UCancellation's.
- The task will allow an already started row to be finished within the 6 second time limited allotted for each row *even if* the global test phase 
  timeout of 3.5 minutes runs out *before* the row's 6 second limit. Once the global 3.5 minute timeout nears its end, the script performs the following 
  check: If 3.5s or less are left on the clock [(6s time per row + 1s inter-row blank period)/2], the test phase terminates. If more than 3.5s are left,
  the script allows another row to be started and completed. This can result in the effective test phase being either slightly shorter or slightly longer than the
  nominal value of 3.5 minutes, on the order of 210s +/- 3.5s.
  In essence, this implementation opts in favor of having useful data for all started rows instead of terminating mid-row and having ambiguous or 
  uninterpretable data for the last row.
- The 1-second inter-row interval is split 50/50 between two trial elements to minimize timing variance due to writing data to disk.
  There is a 500ms blank period trial before each row, which sets up the parameters for the row about to start (number of targets & distractors
  in the row, etc.). -> See trial.preBlank for details.
  There is a 500ms blank period trial after each row, which logs the summary information for the just completed row (number of hits, misses, etc.) and 
  displays auditory cues for perfect rows or row timeout, if applicable. -> See trial.rowSummary for details.
  Together, these result in a 1-second inter-row blank period.
- The UCancellation Letters task produces three data files, whereas this implementation only produces two: There is no separate "Action" data file, 
  all within-row actions as well as per-row summary information is logged to a single raw data file. If you wish to focus on the per-row summaries 
  only, you can filter this file for the "rowSummary" trials. If you wish to drill down on the timestamped, within-row actions (i.e. which item was
  interacted with when), you can filter the raw data file for the "rowAction" trials.
  Like the UCancellation Letters task, this implementation also produces a separate summary data file, which includes the overall performance summary 
  metrics as well as relevant task metadata (start time, duration, the chosen parameters, etc.).

___________________________________________________________________________________________________________________
DURATION 
___________________________________________________________________________________________________________________
The task can be administered in 7 minutes or less.

___________________________________________________________________________________________________________________
DATA FILE INFORMATION 
___________________________________________________________________________________________________________________
The default data stored in the data files are:

(1) Raw data file: 'lettercancellationtask_raw*.iqdat' (a separate file for each participant)

computer.platform:							The platform the script was run on (win/mac/ios/and).
inquisit.version, inquisit.build:			The specific Inquisit version (e.g. "6.6.1") and build number (e.g. "6581") used to collect the data.
display.screenwidth, display.screenheight:	The device's screen width and height in pixels.
display.canvasWidth, display.canvasHeight:	The canvas width and height in pixels, i.e. the subsection of the screen used to display stimuli.
date, time,									Date and time script was run
subject, group, session:					with the current subject id/group number/session number.
values.taskPhase:							Current task phase (practice or test).
script.elapsedTime:							Time elapsed since beginning of script execution in milliseconds.
blocknum, blockcode:						The number and name of the current block (built-in Inquisit variable).
values.rowNumber:							The current row number.
values.inRowTrialCount:						Count of rowAction trials within the current row.
trialcode:									Name of the currently recorded trial (built-in Inquisit variable).
response:									The participant's response. Row item i1 to i8 selected, nextButton, or 0 for no response.
values.isTarget:							Whether the item selected is a target (1) or distractor (0). nextButton is coded as -1.
											No response is coded as empty string.
values.lastResponse:						The last item interacted with in the current row. i1 to i8 or nextButton.
values.ordinalResponsePos:					The ordinal position of the current response (item selected). Can be 1 to 8 for row items i1 to i8, 
											9 for nextButton, no response is coded as -1.
latency:									Response latency relative to the onset of the current trial.
correct:									Whether the response given was correct (here: item selected was a target).
values.rowActionTimeStamp:					Time stamp of the current row action relative to the start of the current row.
values.timeRowStart:						Time when the current row started.
values.timeRowEnd:							Time when the current row ended.
values.rowDuration:							The current row's effective duration.
values.rowHits:								Number of hits (targets selected) in the current row.
values.rowMisses:							Number of misses (targets not selected) in the current row.
values.rowFalseAlarms:						Number of false alarms (distractors selected) in the current row.
values.rowCorrectRejections:				Number of correct rejections (distractors not selected) in the current row.
values.rowPerfect:							1 if the row was "perfect", i.e. all targets identified, no distractors selected. 0 otherwise.
values.nTargets:							Number of targets present in the current row.
values.nDistractors:						Number of distractors present in the current row.
values.rowLayout:							The current row's layout as a string of 1s and 0s, where 1 indicates the item in that position is a target
											and 0 indicates the item is a distractor. 
											E.g. "01100100" means i2, i3, and i6 are targets, whereas i1, i4, i5, i7, and i8 are distractors.
values.responseLayout:						The response pattern for the current row as a string of 1s and 0s, where 1 indicates the participant 
											selected the item in that position and 0 indicates an item was not selected.
											E.g. "10111001" means the participant selected i1, i3, i4, i5, and i8. i2, i6 and i7 were not selected.
values.nItemInteractions:					Count of the item interactions in the current row.

values.item1Type to 
values.item8Type:							Conveys the same information as values.rowLayout as separate variables. 
											1 indicates the given item is a target, 0 indicates it is a distractor.

values.item1ItemNumber to 
values.item8ItemNumber:						The speciic stimulus item number selected for each row item. Item numbers 1 to 3 represent the different
											target items (letters d with two surrounding marks). Item numbers 4 to 16 represent the various distractor 
											items. See item.letterItems for details.

(2) Summary data file: 'lettercancellationtask_summary*.iqdat' (a separate file for each participant)

computer.platform:							The platform the script was run on (win/mac/ios/and).
inquisit.version, inquisit.build:			The specific Inquisit version (e.g. "6.6.1") and build number (e.g. "6581") used to collect the data.
display.screenwidth, display.screenheight:	The device's screen width and height in pixels.
display.canvasWidth, display.canvasHeight:	The canvas width and height in pixels, i.e. the subsection of the screen used to display stimuli.
script.startDate:							Date the script was started.
script.startTime:							Time the script was started.
script.subjectId:							The assigned subject ID.
script.groupId:								The assigned group ID.
script.sessionId:							The assigned session ID.
script.completed:							0 = script was not completed (prematurely aborted); 
											1 = script was completed (all conditions run)
script.elapsedTime:							Time it took to run script (in ms); measured from onset to offset of script.
values.nPracticeBlocks:						The number of practice blocks run.
values.rowNumber:							The number of rows administered.
expressions.testPhaseDuration:				The effective test phase duration in ms.

parameters.testPhaseTimeout:				Setting for the test phase time limit in ms.
parameters.timePerRow:						Setting for the time allowed to to complete each row ("row timeout") in ms.
parameters.interRowInterval:				Setting for the duration of the inter-row interval in ms.
parameters.minTargetsPerRow:				Setting for mim. number of targets per row.
parameters.maxTargetsPerRow:				Setting for max. number of targets per row.
parameters.nTargetsPer10Rows:				Setting for number of targets in each chunk of 10 rows.

values.totalHits:							Number of hits (selected targets) across all administered test phase rows.
values.totalMisses:							Number of misses (skipped targets) across all administered test phase rows.
values.totalFalseAlarms:					Number of false alarms (selected distractors) across all administered test phase rows.
values.totalCorrectRejections:				Number of correct rejections (skipped distractors) across all administered test phase rows.
values.totalPerfect:						Number of "perfect" rows across all administered test phase rows.
expressions.TotalItemsProcessed:			The total number of items the participant was exposed to (8 items * amount of rows).
											This metric is sometimes also referred to as "Speed" or "Processing Speed".
expressions.TotalPerformance:				Total Perfomance (TP) = ∑N − ∑(Misses + False Alarms), 
											where N is the number of rows processed multiplied by 8 (number of items per row).
expressions.ConcentrationPerformance:		Concentration Performance (CP) = ∑Hits − ∑False Alarms.

NOTE: Measures covering the first 30 rows only are included for the sake of completeness. Pahor et. al (2022) caution against
using these measures and recommend using the measure covering all rows completed (including any "bonus" rows) instead.

values.totalHits30:							Number of hits (selected targets) in the first 30 test phase rows only. 
values.totalMisses30:						Number of misses (skipped targets) in the first 30 test phase rows only.
values.totalFalseAlarms30:					Number of false alarms (selected distractors) in the first 30 test phase rows only.
values.totalCorrectRejections30:			Number of correct rejections (skipped distractors) in the first 30 test phase rows only.
values.totalPerfect30:						Number of "perfect" rows for the first 30 test phase rows only.
expressions.TotalPerformance30:				Total Performance (TP) for the first 30 test phase rows only.
expressions.ConcentrationPerformance30:		Concentration Performace (CP) for the first 30 test phase rows only.

___________________________________________________________________________________________________________________
EXPERIMENTAL SET-UP 
___________________________________________________________________________________________________________________
- Row generator utility block:
  Generates a pre-specified number of rows (-> parameters.nRowsToGenerate), such that
  (1) there are between 3 (-> parameters.minTargetsPerRow) and 5 (-> parameters.maxTargetsPerRow) targets
  in any given row, and
  (2) there are exactly 40 targets (-> parameters.nTargetsPer10Rows) across each chunk of 10 rows.

-  Guided practice block consisting of an animated demonstration (-> trial.practiceIntro), followed by
  3 practice rows (containing 3, 4, and five targets, in random order); detailed error feedback is provided
  during this guided practice phase. If the participants achieves fewer than 2 "perfect" rows (-> parameters.minPerfectPractice), 
  the guided practice phase is repeated one more time, i.e. there is a maximum of two practice blocks 
  (-> parameters.maxPracticeBlocks).

- Test block with a set time limit of 3.5 minutes (-> parameters.testPhaseTimeout).
- Default trial sequence: 
  (1) Pre-row blank period (trial.preBlank; 500ms; half of -> parameters.interRowInterval).
  (2) row action trials (trial.rowAction; max. 6000ms; -> parameters.timePerRow).
  (3) Post-row blank period & row summary logging (trial.rowSummary; 500ms; half of -> parameters.interRowInterval).

  When using up the max. amount of time allowed for each row (6 seconds), the participant will be exposed to 
  exactly 30 rows within the global time limit of 3.5 minutes.

  See ADDITIONAL NOTES section for detailed information about timing considerations and timing-related task behavior.

___________________________________________________________________________________________________________________
INSTRUCTIONS 
___________________________________________________________________________________________________________________
Instructions are not original, but partly adapted from those found in UCancellation Letters.
You can easily change them by editing item.instructionItems.

___________________________________________________________________________________________________________________
EDITABLE CODE 
___________________________________________________________________________________________________________________
Check below for (relatively) easily editable parameters, stimuli, instructions etc. 
Keep in mind that you can use this script as a template and therefore always "mess" with the entire code 
to further customize your experiment.

The parameters you can change are:

minTargetsPerRow			The minimum number of target stimuli presented in each row (default: 3).
maxTargetsPerRow			The maximum number of target stimuli presented in each row (default: 5).
nTargetsPer10Rows			The total number of target stimuli presented in each chunk of 10 rows (default: 40).

							NOTE: You can change the above parameters, but you should consider this carefully beforehand.
							(1) Defining too wide a spread between min. and max. targets per row may lead to row generation taking a long time, 
							because satisfying the N targets per 10 rows criterion becomes more difficult when there's a wider spread.
							(2) Take care to avoid impossible settings. For example, with min. targets per row set to 1 and max. set to 3, 
							it would not actually be possible to arrive at 40 targets in 10 rows. The theoretical maximum would be 30, and that would
							only be achieved with every row having exactly 3 targets.

timePerRow					The time limit for completing each row (default: 6000ms). This is the row's maximum duration, a participant may advance to 
							the next row earlier by pressing the Next button (green arrow).
timePerRowPractice			The time limit for completing each row in the practice phase. Set to high value to effectively disable.
							NOTE: This only applies when the "unguided" practice mode is enabled.
							In the default "guided" practice mode, there is no time limit.
							See parameters.practiceMode below.
nRowsToGenerate				The number of rows to pregenerate (default: 90).
							NOTE: In the default configuration, rows are generated in chunks of 10, such that there are exactly 
							40 targets in each chunk of 10 rows (see parameters.nTargetsPer10Rows above).
							A participant who uses up the full 6s for each row, will get to complete exactly 30 rows within the 
							global test phase time limit (3.5mins; see parameters.testPhaseTimeout below).
							Participants who don't use the full 6 seconds (i.e. advance to next row early via the next button), 
							will get to complete additonal "bonus" rows.
							parameters.nRowsToGenerate determines how many rows should be pregenerated to cover these "bonus" rows.
							The value should be a multiple of 10. As a guideline, in Pahor et al. (2022) no participant completed 
							more than 52 rows (p. 2607) within 3.5mins, so pregenerating 90 rows should be more than sufficient when
							the default settings are used.
testPhaseTimeout			Global time limit for the test phase. Default: 210000 ms (3.5 minutes).
interRowInterval			Blank period between two rows. Default: 1000 ms (1 second).
							NOTE: Do NOT drastically reduce the inter-row interval. When set too low, it will lead to timing issues.
forceLeftToRight			Force participants to work from left to right. Default: true. 
							When set to false, participants may mark letters in any order.
							NOTE: When parameters.forceLeftToRight is set to false, the unguided practice mode should be used for consistency.
enableTestPhaseFeedback		Whether to show in-row correct & error feedback during the test phase. Default: false.
enableAuditoryCues			Whether to present auditory cues indicating row timeout or achievement of a "perfect" row. Default: false.
maxPracticeBlocks			The maximum number of practice blocks. Default: 2.
minPerfectPractice			The passing criterion for the practice block, in terms of the min. number of "perfect" rows the participant ought to achieve.
							Default: 2 (out of 3 practice rows).
							Explanation: When a participant fails the first practice block, practice is repeated until parameters.maxPracticeBlocks 
							is reached. The task then moves on to the test phase, regardless of whether the criterion was met.
practiceMode				Determines how the practice phase works. There are two modes.
							1 = "guided" mode (default). Participant receives very detailed feedback regarding any errors made, no time limit.
							2 = "unguided" mode. Like the actual test, but with per-item correct & incorrect feedback. The row timeout for this mode can 
							be set separately via parameters.timePerRowPractice above.
xPos1 to xPos8				Horizontal on-screen positions (in percent) of the 8 letter stimuli making up a row.
							Default values are 10%, 20%, 30%, 40%, 50%, 60%, 70%, and 80% respectively.
nextButtonPos				Horizontal on-screen position of the Next button (green arrow). Default: 92%.
							Slightly shifted to the right to avoid mistaps (i.e. hitting the next button when they meant to hit the 8th letter item).