Generic function for presentation of stimulus stim. Depending on
your choice of OPI implementation set using chooseOpi()
, different
parameters are available for opiPresent
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)
phoneVR.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)
a list of class opiStaticStimulus
,
opiKineticStimulus
, or opiTemporalStimulus
to be presented.
unused - included for compliance with OPI standard.
Parameters specific to your chosen opi implementation
false positive rate for OPI implementation "SimHenson"
false negative rate for OPI implementation "SimHenson"
SOMETHING for OPI implementation "SimHenson"
CRITERIA for OPI implementation "SimHenson"
response time shape parameter for OPI implementation "SimHenson"
response time rate parameter for OPI implementation "SimHenson"
response time scale parameter for OPI implementation "SimHenson"
SOMETHING for OPI implementation "SimHensonRT"
A list containing
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.
TRUE
if a response was detected in the allowed
responseWindow
, FALSE
otherwise. (Note, see
Octopus900F310 above).
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...
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
Only returned for KowaAP7000 (in pixels) and an opiStaticStimulus or O900 (in degrees) and staic/kinetic if gazeFeed==1. x-coordinate of centre of pupil during presentation.
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.
Only returned for KowaAP7000 and an opiStaticStimulus. x-coordinate of centre of Purkinje Image in pixels during presentation.
Only returned for KowaAP7000 and an opiStaticStimulus. y-coordinate of centre of Purkinje Image in pixels during presentation.
Only returned for KowaAP7000 or Octopus900 and an opiKineticStimulus. x coordinate of stimuli when button is pressed.
Only returned for KowaAP7000 or Octopus900 and an opiKineticStimulus. y coordinate of stimuli when button is pressed.
Only returned for Compass. Time since epoch that the opiPresent command was received by the Compass in ms.
Only returned for Compass. 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()
.
Only returned for Compass. Time since epoch that the response was received or response window expired (in ms).
Only returned for Compass. The number of tracking events associated with this presentation.
Only returned for Compass. The number of time the motor could not keep pace with eye movements.
Only returned for Compass. The diameter of the pupil on milimetres on presentation.
Only returned for Compass. The x location in pixels of the
presentation on the retinal image returned by opiInitialize
.
Only returned for Compass. The y location in pixels of the
presentation on the retinal image returned by opiInitialize
.
Compass A list containing
err0 all clear, >= 1 some error codes (eg cannot track, etc) (integer)
seenFALSE
for not seen, TRUE
for seen (button pressed in response window)
timeresponse time in ms (integer) since stimulus onset, -1 for not seen
time_rectime since epoch when command was received at Compass (integer ms)
time_prestime since epoch that stimulus was presented (integer ms)
num_track_eventsnumber of tracking events that occurred during presentation (integer)
num_motor_failsnumber of times motor could not follow fixation movement during presentation (integer)
pupil_diampupil diameter in mm (float)
loc_xpixels integer, location in image of presentation (integer)
loc_ypixels integer, location in image of presentation (integer)
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
.
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.
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
.
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
.
DETAILS HERE
opiPresent(stim, nextStim=NULL)
If the chosen OPI implementation is KowaAP7000
, then nextStim
is ignored.
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).
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.
If the chosen OPI implementation is PhoneVR
, then nextStim
is ignored. PhonVR
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
.
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
.
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
.
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
.
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
.
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).
opiStaticStimulus
, opiKineticStimulus
,
opiTemporalStimulus
, chooseOpi
,
opiInitialize
# 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()
# }
# 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")
# }
Run the code above in your browser using DataLab