Generate a classification image for any reverse correlation task.
Usage
generateCI(
stimuli,
responses,
baseimage,
rdata,
participants = NA,
save_individual_cis = FALSE,
save_as_png = TRUE,
filename = "",
targetpath,
antiCI = FALSE,
scaling = "independent",
scaling_constant = 0.1,
individual_scaling = "independent",
individual_scaling_constant = 0.1,
zmap = FALSE,
zmapmethod = "quick",
zmapdecoration = TRUE,
sigma = 3,
threshold = 3,
zmaptargetpath,
n_cores = default_ncores(),
mask = NA,
zmappointsize = 12
)Arguments
- stimuli
Numeric vector of stimulus numbers, one per response and in the same order. Each must be a positive whole number no larger than the number of trials saved for the selected base image. Numbers may repeat and need not be consecutive. Factors, characters and logicals are rejected: if your data hold stimulus labels, check them against the generated stimulus filenames before converting them to numbers.
- responses
Vector of responses in the same order as
stimuli: 1 where the original stimulus was chosen, -1 where the inverted one was. Must be numeric and finite; other finite numbers, such as ratings, weight the trials accordingly. Factors, characters and logicals are rejected, as areNA,NaNand infinite values: remove trials without a response from every argument alike.- baseimage
String naming the base image: not its file name, but its key in the
base_face_fileslist passed togenerateStimuli2IFC.- rdata
Path to the
.Rdatafile written when the stimuli were generated. It holds the contrast parameters of every stimulus.- participants
Optional vector with one participant ID per trial, the same length as
stimuliandresponses. When given, the CI is computed in two steps: one CI per participant, then their average. When missing or allNA, one CI is computed from all trials together. Some, but not all,NAis an error: give every trial an ID, or remove the trials without one.- save_individual_cis
Boolean: when
participantsis given, also save each participant's CI as a PNG image.- save_as_png
Boolean: also save the CI as a PNG image.
- filename
Optional file name for the PNG image.
- targetpath
Directory to save PNGs to. Required when
save_as_png = TRUEorsave_individual_cis = TRUE; there is no default. The directory is created if it does not exist; to just try the function out, usetempdir().- antiCI
Boolean: compute the anti-CI, the classification image with its sign flipped, instead of the CI.
- scaling
Scaling method:
none,constant,matchedorindependent(default). When both individual and group CIs are computed, this applies to the group CI.- scaling_constant
Scaling constant for the noise, used only when
scaling = 'constant'. When both individual and group CIs are computed, this applies to the group CI.- individual_scaling
Scaling method for the individual CIs:
none,constantorindependent(default).- individual_scaling_constant
Scaling constant for the individual CIs, used only when
individual_scaling = 'constant'.- zmap
Boolean: also create a z-map (default:
FALSE).- zmapmethod
Method for the z-map:
quick(default) ort.test.- zmapdecoration
Boolean: draw the z-map with margins, a caption (sigma, threshold) and a scale (default:
TRUE).- sigma
Amount of smoothing applied when creating the z-map (default: 3).
- threshold
Threshold z-score (default: 3). Z-scores below it are not drawn on the z-map.
- zmaptargetpath
Directory to save z-map PNGs to. Required when
zmap = TRUE; there is no default. The directory is created if it does not exist; to just try the function out, usetempdir().- n_cores
Number of CPU cores for the per-participant CIs (with
participants) and the't.test'z-map (default:detectCores() - 1; 2 underR CMD check, per CRAN policy). Each core runs a worker holding its own copy of the noise basis and a render's working memory: 0.8 to 1 GB per worker at 512 pixels in https://github.com/rdotsch/rcicr/blob/main/analyses/worker-memory.md. No more workers start than there are participants or trials.- mask
Optional mask for the CI: a 2D matrix (0 = masked, 1 = kept) or the path to a greyscale PNG image (black = masked, white = kept). Default:
NA, no mask. Documentation up to and including 1.1.0 described the matrix the wrong way round (1 = masked); the code has always masked where the matrix is 0.- zmappointsize
Text size of the z-map decoration, in points (default: 12). Passed to
plotZmap, which makes the z-map imageimg_sizepixels wide. The decoration needs roughly12.3 * zmappointsizepixels on a 72 ppi device and16.4 * zmappointsizeon a 96 ppi one. At the default, a stimulus set smaller than about 160 to 200 pixels is too small for it, andgenerateCI()stops with an error naming the minimum for your device. Lower this value to fit the decoration on a small z-map, or setzmapdecoration = FALSE.
Value
List of pixel matrices: the raw classification noise (ci), the scaled noise (scaled), the base image (base) and the two combined (combined), plus the z-map (zmap) when zmap = TRUE. Its trial_design attribute records which saved stimuli the CI was built from, so that computeInfoVal2IFC can check that its reference matches the CI; its scaling attribute records how scaled was made, for the group CI and, with participants, for the individual CIs. vignette("stored-data", package = "rcicr") lists the fields of both. To keep them in a file, save the whole result with saveRDS().
Details
This function returns the classification image (CI) and, by default, saves it as a PNG. How
the CI is scaled for display decides what the image looks like and whether two images can be
compared. The default, 'independent', picks the lowest scaling constant that avoids
clipping this particular CI (see 'constant' below for the formula). Each CI therefore
gets its own constant, and CIs with different noise ranges cannot be compared by eye.
'matched' scaling matches the range of the CI's pixel intensities to the range of the
base image's. This is nonlinear and depends on the ranges of both. It also shifts the zero point
of the noise: a pixel that would not have changed the base image before scaling may change it
afterwards, and the other way round. Use it as a quick look at how the noise affects the base
image, not for reporting.
'constant' scaling does not depend on the base image or the noise range, but the
constant is yours to choose, with the scaling_constant argument. The noise is scaled as
scaled <- (ci + constant) / (2 * constant). Pixel intensities must lie between 0 and 1;
if the scaled noise falls outside that range you get a warning and should pick a higher
constant. The higher the constant, the fainter the noise in the resulting image. Use the same
constant for every classification image you want to compare.
For several classification images, the lowest constant that works for all of them is a good
choice. autoscale finds it for you.
Repeated presentations of the same stimulus
When participants is NA (the default), repeated presentations of the same
stimulus are averaged before the CI is built, so each unique stimulus gets equal weight however
often it was shown. If every stimulus was shown equally often, this is the same as weighting
each trial equally. If not, it changes what the CI estimates: a stimulus shown three times counts
the same as one shown once, not three times as much.
So in an unbalanced design, where a participant saw some stimuli more often than others (an adaptive procedure, a crashed session, or by design), the CI is the average response per unique stimulus, not per trial. The two can differ a lot: on an 8-trial set with counts 4/2/1/1 they correlate at 0.77.
computeCumulativeCICorrelation does not average repeats; it weights each
trial equally. With unequal counts, the final CI it computes itself therefore differs from the
one this function returns. To compare against the CI you will report, pass this function's
output as its targetci.
See also
vignette("reverse-correlation-walkthrough", package = "rcicr"), sections "Computing one classification image" and "Scaling"; vignette("recipes", package = "rcicr") for rating scales as responses and for masked classification images.
Examples
# a synthetic square grayscale image stands in for a real base face photo
base_face <- tempfile(fileext = ".png")
png::writePNG(matrix(runif(32 * 32), 32, 32), base_face)
stimulus_path <- tempfile("stimuli")
generateStimuli2IFC(
base_face_files = list(face = base_face),
n_trials = 6,
img_size = 32,
stimulus_path = stimulus_path,
seed = 1,
ncores = 1,
nscales = 1,
save_as_png = FALSE
)
#>
|
| | 0%
|
|============ | 17%
|
|======================= | 33%
|
|=================================== | 50%
|
|=============================================== | 67%
|
|========================================================== | 83%
|
|======================================================================| 100%
rdata_file <- list.files(stimulus_path, pattern = "\\.Rdata$", full.names = TRUE)[1]
responses <- sample(c(1, -1), 6, replace = TRUE)
ci <- generateCI(
stimuli = 1:6, responses = responses, baseimage = "face",
rdata = rdata_file, save_as_png = FALSE
)
