opiPresent: Use OPI to present stimulus

View source: R/opi.r

opiPresentR Documentation

Use OPI to present stimulus

Description

Generic function for presentation of stimulus stim. Depending on your choice of OPI implementation set using chooseOpi(), different parameters are available for opiPresent

Usage

opiPresent(stim, nextStim = NULL, ...)

compass.opiPresent(stim, nextStim = NULL)

display.opiPresent(stim, nextStim = NULL)

daydream.opiPresent(stim, nextStim = NULL)

imo.opiPresent(stim, nextStim = NULL)

kowaAP7000.opiPresent(stim, nextStim = NULL)

octo600.opiPresent(stim, nextStim = NULL)

octo900.opiPresentF310(stim, nextStim = NULL)

PhoneHMD.opiPresent(stim, nextStim = NULL)

simG.opiPresent(stim, nextStim = NULL, fpr = 0.03, fnr = 0.01, tt = 30)

simH.opiPresent(
  stim,
  nextStim = NULL,
  fpr = 0.03,
  fnr = 0.01,
  tt = 30,
  criteria = 0.97,
  rt_shape = 5.3,
  rt_rate = 1.4,
  rt_scale = 0.1
)

simH_RT.opiPresent(
  stim,
  nextStim = NULL,
  fpr = 0.03,
  fnr = 0.01,
  tt = 30,
  notSeenToSeen = TRUE
)

simNo.opiPresent(stim, nextStim = NULL)

simYes.opiPresent(stim, nextStim = NULL)

Arguments

stim

a list of class opiStaticStimulus, opiKineticStimulus, or opiTemporalStimulus to be presented.

nextStim

unused - included for compliance with OPI standard.

...

Parameters specific to your chosen opi implementation

fpr

false positive rate for OPI implementation "SimHenson"

fnr

false negative rate for OPI implementation "SimHenson"

tt

SOMETHING for OPI implementation "SimHenson"

criteria

CRITERIA for OPI implementation "SimHenson"

rt_shape

response time shape parameter for OPI implementation "SimHenson"

rt_rate

response time rate parameter for OPI implementation "SimHenson"

rt_scale

response time scale parameter for OPI implementation "SimHenson"

notSeenToSeen

SOMETHING for OPI implementation "SimHensonRT"

Details

opiPresent is blocking in that it will not return until either a response is obtained, or at least the responseWindow milliseconds has expired. (Note that more time might have expired.) Specifying nextStim allows the implementing machine to use the time waiting for a response to stim to make preparations for the next stimuli. (For example retargeting the projector or moving aperture and/or filter wheels.) There is no guarantee that the next call to opiPresent will have nextStim as the first argument; this could be checked by the machine specific implementations (but currently is not, I think).

Also note that to allow for different parameters depending on the implementation chosen with chooseOpi, every parameter MUST be named in a call to opiPresent.

Display

Present a circle of radius stim$size and color stim$color at (stim$x, stim$y) for stim$duration ms and wait for a keyboard or mouse response for stim$responseWindow ms.

stim$size, sitm$x and stim$y are in the same units as xlim and ylim as specified in opiInitialise.

If the chosen OPI implementation is Display, then nextStim is ignored.

Duration and response window are rounded to the nearest 5 ms.

Currently only implemented for opiStaticStimulus.

Daydream

If the chosen OPI implementation is Daydream, then nextStim is ignored.

Note that the dB level is rounded to the nearest cd/\mbox{m}^2 that is in the lut specified in opiInitialise.

Currently uses the most simple algorithm for drawing a 'circle' (ie not Bresenham's).

Currently only implemented for opiStaticStimulus.

imo

DETAILS HERE

KowaAP7000

opiPresent(stim, nextStim=NULL)

If the chosen OPI implementation is KowaAP7000, then nextStim is ignored.

Value

A list containing

  • err NULL if no error occurred, otherwise a machine-specific error message. This should include errors when the specified size cannot be achieved by the device (for example, in a projection system with an aperture wheel of predefined sizes.) If stim is NULL, then err contains the status of the machine.

  • seen TRUE if a response was detected in the allowed responseWindow, FALSE otherwise. (Note, see Octopus900F310 above).

  • time The time in milliseconds from the onset (or offset, machine-specific) of the presentation until the response from the subject if seen is TRUE. If seen is FALSE, this value is undefined. For kinetic perimetry on the O900, this value is unknown... (what does this mean!?)

O600

answer only returned for Octopus600. Can be the following values:

  • 0 = stimulus not seen;

  • 1 = stimulus seen;

  • 132 = Response button was pressed before stimulus presentation (Patient needs a break - hold on examination);

  • 36 = Eye is closed before stimulus presentation;

  • 68 = Fixation lost before stimulus presentation (pupil center is out of green window in video image);

  • 260 = Forehead rest lost before stimulus presentation;

  • 516 = Fast Eye movements before stimulus presentation;

  • 258 = Forehead rest lost during stimulus presentation;

  • 66 = Fixation lost during stimulus presentation (pupil center is out of green window in video image);

  • 34 = Eye was closed during stimulus presentation;

  • 18 = Patient answer was too early (<=100ms after stimulus presentation) - lucky punch;

  • 514 = Fast Eye movements during stimulus presentation

Kowa AP7000

  • pupilX Only returned for KowaAP7000 (in pixels) and an opiStaticStimulus or O900 (in degrees) and static/kinetic if gazeFeed==1. x-coordinate of centre of pupil during presentation.

  • pupilY Only returned for KowaAP7000 (in pixels) and an opiStaticStimulus or O900 (in degrees) and static/kinetic if gazeFeed==1. y-coordinate of centre of pupil during presentation.

  • purkinjeX Only returned for KowaAP7000 and an opiStaticStimulus. x-coordinate of centre of Purkinje Image in pixels during presentation.

  • purkinjeY Only returned for KowaAP7000 and an opiStaticStimulus. y-coordinate of centre of Purkinje Image in pixels during presentation.

Kowa AP7000 and Octopus O900

  • x Only returned for KowaAP7000 or Octopus900 and an opiKineticStimulus. x coordinate of stimuli when button is pressed.

  • y Only returned for KowaAP7000 or Octopus900 and an opiKineticStimulus. y coordinate of stimuli when button is pressed.

Compass

  • time_rec Time since epoch that the opiPresent command was received by the Compass in ms.

  • time_hw Hardware time of button press or response window expired (integer ms). To get the hardware time that a presentation began, subtract responseWindow from th (for aligning with fixation data returned by opiClose().

  • time_resp Time since epoch that the response was received or response window expired (in ms).

  • num_track_events The number of tracking events associated with this presentation.

  • num_motor_fails The number of time the motor could not keep pace with eye movements.

  • pupil_diam The diameter of the pupil on millimeters on presentation.

  • loc_x The x location in pixels of the presentation on the retinal image returned by opiInitialize.

  • loc_y The y location in pixels of the presentation on the retinal image returned by opiInitialize.

Compass

A list containing

  • err 0 all clear, >= 1 some error codes (eg cannot track, etc) (integer)

  • seen FALSE for not seen, TRUE for seen (button pressed in response window)

  • time response time in ms (integer) since stimulus onset, -1 for not seen

  • time_rec time since epoch when command was received at Compass (integer ms)

  • time_pres time since epoch that stimulus was presented (integer ms)

  • num_track_events number of tracking events that occurred during presentation (integer)

  • num_motor_fails number of times motor could not follow fixation movement during presentation (integer)

  • pupil_diam pupil diameter in mm (float)

  • loc_x pixels integer, location in image of presentation (integer)

  • loc_y pixels integer, location in image of presentation (integer)

Compass

opiPresent(stim, nextStim=NULL)

If the chosen OPI implementation is Compass, then nextStim is ignored. Note that the dB level is rounded to the nearest integer.

If tracking is on, then this will block until the tracking is obtained, and the stimulus presented.

Octopus600

opiPresent(stim, nextStim=NULL)

If the chosen OPI implementation is Octopus600, then nextStim is ignored. If eyeControl is non-zero, as set in opiInitialize, answer codes describing patient state may arise (see answer field in the Value section).

Octopus900F310

opiPresent(stim, nextStim=NULL)

This functions as for the Octopus900, but responses are taken from the F310 Controller.

If the L button is pressed, seen is set to 1.

If the R button is pressed, seen is set to 2.

If no button is pressed within responseWindow, then seen is set to 0.

PhoneHMD

If the chosen OPI implementation is PhoneHMD, then nextStim is ignored. PhonVR

SimGaussian

opiPresent(stim, nextStim=NULL, fpr=0.03, fnr=0.01, tt=30)

If the chosen OPI implementation is SimGaussian, then the response to a stimuli is determined by sampling from a Frequency-of-Seeing (FoS) curve (also known as the psychometric function) with formula fpr+(1-fpr-fnr)*(1-pnorm(x, tt, simG.global.sd)), where x is the stimulus value in Humphrey dB, and simG.global.sd is set with opiInitialize.

SimHenson

opiPresent(stim, nextStim=NULL, fpr=0.03, fnr=0.01, tt=30)

If the chosen OPI implementation is SimHenson, then the response to a stimuli is determined by sampling from a Frequency-of-Seeing (FoS) curve (also known as the psychometric function) with formula

\mbox{fpr}+(1-\mbox{fpr}-\mbox{fnr})(1-\mbox{pnorm}(x, \mbox{tt}

, where x is the stimulus value in Humphrey dB, and pxVar is

\min\left(\mbox{simH.global.cap}, e^{A\times\mbox{tt}+B}\right).

The ceiling simH.global.cap is set with the call to opiInitialize, and A and B are from Table 1 in Henson et al (2000). Which values are used is determined by simH.type which is also set in the call to opiInitialize.

Note that if the stimulus value is less than zero, then the Henson formula is not used. The probability of seeing is fpr.

opiPresent(stim, nextStim=NULL, fpr=0.03, fnr=0.01, tt=NULL, criteria=0.95, rt_shape=5.3, rt_rate=1.4, rt_scale=0.1)

For determinng seen/not-seen for kinetic, the first location (to a fidelity of 0.01 degrees) on the path (it only works for single paths now) where the probability of seeing is equal to criteria is found. If no such location exists, then the stimuli is not seen. The probability of seeing at each location is determined using a frequency-of-seeing curve defined as a cumulative Gaussian with parameters controlled by tt and opiInitialize. At each location along the path, the mean of the FoS is taken from the tt function, which takes a distance-along-path (in degrees) as an argument, and returns a dB value which is the static threshold at that distance along the path.

Function tt can return NA for not thresholds that are always not seen. At each location along the path, the standard deviation of the FoS is sampled from a Gaussion with mean taken from the formula of Henson et al (2000), as parametrised by opiInitialize, and standard deviation 0.25.

The location of a false positive response (for the total kinetic path) is sampled uniformly from the start of the path to the 'seeing' location, or the entire path if the stimuli is not seen.

Note that the false positive rate fpr and the false negative rate fnr are specified for the whole path, and not for the individual static responses along the way.

The actual location returned for a seen response is the location where the probability of seeing equals criteria, plus a response time sampled from a Gamma distribution parameterised by rt_shape and rt_rate and multiplied by rt_scale.That is: rgamma(1, shape=rt_shape, rate=rt_rate) / rt_scale.

SimHensonRT

opiPresent(stim, nextStim=NULL, fpr=0.03, fnr=0.01, tt=30, dist=stim$level - tt)

For static stimuli, this function is the same as for SimHenson, but reaction times are determined by sampling from rtData as passed to opiInitialize. The dist parameter is the distance of the stimulus level from the true threshold, and should be in the same units as the Dist column of rtData. The default is just the straight difference between the stimulus level and the true threshold, but you might want it scaled somehow to match rtData.

SimNo

opiPresent(stim, nextStim=NULL)

If the chosen OPI implementation is SimNo, then the response to a stimuli is always no, hence opiPresent always returns err=NULL, seen=FALSE, and time=0.

SimYes

opiPresent(stim, nextStim=NULL)

If the chosen OPI implementation is SimYes, then the response to a stimuli is always yes, hence opiPresent always returns err=NULL, seen=TRUE, and time=0.

References

David B. Henson, Shaila Chaudry, Paul H. Artes, E. Brian Faragher, and Alec Ansons. Response Variability in the Visual Field: Comparison of Optic Neuritis, Glaucoma, Ocular Hypertension, and Normal Eyes. Investigative Ophthalmology & Visual Science, February 2000, Vol. 41(2).

See Also

opiStaticStimulus, opiKineticStimulus, opiTemporalStimulus, chooseOpi, opiInitialize

Examples

## Not run: 
# Display a spot
 chooseOpi("Display")
 if(!is.null(opiInitialize(width = 1680, height = 1050, ppi = 128, viewdist = 25)))
   stop("opiInitialize failed")
 opiSetBackground(lum = 50, color = "white", fixation = "Cross")

 makeStim <- function(db) {
   s <- list(x = 9, y = 9, level = dbTocd(db, 400), size = 1.72, color = "white",
             duration = 1000, responseWindow = 1000)
   class(s) <- "opiStaticStimulus"
   return(s)
 }
 result <- opiPresent(makeStim(0))

 opiClose()

## End(Not run)
# Stimulus is Size III white-on-white as in the HFA
makeStim <- function(db, n) {
  s <- list(x=9, y=9, level=dbTocd(db, 10000/pi), size=0.43, color="white",
            duration=200, responseWindow=1500)
  class(s) <- "opiStaticStimulus"
  return(s)
}

chooseOpi("SimHenson")
if (!is.null(opiInitialize(type="C", cap=6)))
  stop("opiInitialize failed")

result <- opiPresent(stim=makeStim(10,0), tt=30, fpr=0.15, fnr=0.01)

# Will not work as 'stim' is not named
#result <- opiPresent(makeStim(10,0), tt=30, fpr=0.15, fnr=0.01)

if (!is.null(opiClose()))
  warning("opiClose() failed")
# Same but with simulated reaction times
chooseOpi("SimHensonRT")
data(RtSigmaUnits)
if (!is.null(opiInitialize(type="C", cap=6, rtData=RtSigmaUnits)))
  stop("opiInitialize failed")

dist <- (10 - 30)/min(exp(-0.098 * 30 + 3.62), 6)
result <- opiPresent(stim=makeStim(10,0), tt=30, fpr=0.15, fnr=0.01, dist=dist)

if (!is.null(opiClose()))
  warning("opiClose() failed")

OPI documentation built on Nov. 7, 2023, 9:06 a.m.