Skip to content

Match-to-Sample Task

Try the Demo

In this task, participants are presented with a sample (target) stimulus alongside two alternative stimuli. The participant selects which of the two alternatives matches the sample by clicking on it. This task is a fundamental paradigm for studying learning, memory, discrimination, and concept formation.

The matching-to-sample paradigm has been extensively used in behavioral research since the 1960s1. Originally developed for operant conditioning studies, it has become a versatile tool for investigating perceptual matching, working memory, and conceptual similarity across diverse stimulus domains including visual, auditory, and abstract stimuli. The paradigm is particularly valuable because it provides a clear measure of whether participants can discriminate and match stimuli based on specific features or learned associations.

Example Match-to-Sample task

Example Match-to-Sample task showing a sample stimulus (top) with two alternatives below. The participant clicks on the matching alternative.

Quick Start

  1. Create or open an experiment from your Dashboard
  2. Click Add task and select "Match-to-Sample"
  3. Select a stimulus set with at least 2 stimuli
  4. Configure spatial layout and stimulus sizes
  5. Preview your experiment

New to Meadows? See the Getting Started guide for a complete walkthrough.

Alternative tasks

  • Use a Triplet Choice task for odd-one-out judgments with three stimuli where all are clickable.
  • Use a Discriminability task for same/different judgments between pairs of stimuli.
  • Use a Circular Matching task for matching to a central reference from multiple arranged alternatives.

Parameters

Customize the task by changing these on the Parameters tab of the task.

General Interface settings

Customize the instruction at the top of the page, as well as toolbar buttons. These apply to most task types on Meadows.

Instruction hint

Text that you can display during the task at the top of the page.

Extended instruction

A longer instruction that only appears if the participant hovers their mouse cursor over the hint.

Tip

Make clear to participants what criterion they should use for matching. For example: "Click on the image that matches the one at the top" or "Select the stimulus that is most similar to the sample."

Hint size

Whether to display the instruction, or hide it, and what font size to use.

Fullscreen button

Whether to display a button in the bottom toolbar that participants can use to switch fullscreen mode on and off.

Trials and stimuli

Control the number of trials and how stimuli are combined into triplets.

Maximum Number Of Trials

The number of trials will equal the total number of unique triplet combinations of stimuli, or this parameter, whichever is smaller. The task generates triplets by combining stimuli where one serves as the sample and two as alternatives. Default: 50. Must be between 1 and 1000.

Trial generation

Trials are generated by sampling triplets of stimuli. The first stimulus in each triplet serves as the sample, while the second and third are the alternatives. One of the alternatives will match the sample (either identical or from a matching category).

Blank Duration

Duration in milliseconds to show a blank screen between trials. Set to 0 to turn this off. Default: 500 ms. Must be between 0 and 5000 ms.

Minimum Trial Duration

The stimuli will be displayed for at least this duration (in milliseconds), even if a response was given earlier. This ensures participants view the stimuli for a minimum amount of time. Default: 0 ms. Must be between 0 and 10,000 ms.

Cannot Confirm Trial Until All Audio/Video Stimuli Have Finished

If enabled, participants must wait for all audio or video stimuli to finish playing before they can confirm their selection. Default: False.

Wait Button Text

Caption of the submit button when the trial is not ready yet (e.g., minimum duration not reached, or media still playing). Default: "wait..". Max 20 characters.

Spatial configuration

Options for customizing the layout and size of stimuli on the screen.

Layout

How to arrange the stimuli on the screen. Options:

  • Centered (default): All stimuli are spread out evenly with the sample at the top and the two alternatives centered below it. This provides balanced spacing.
  • Justified: Stimuli are aligned with the edges of the screen. The sample is centered at the top, while alternatives are positioned at the bottom-left and bottom-right corners. This is most useful for large stimulus sizes to prevent overlap.
  • Sample Justified, Alternatives Centered: The sample is justified (centered at top edge), while the two alternatives remain centered below. This provides a hybrid layout.
Item Size

Height of the alternative stimuli. Default: 8.0. Must be between 0.2 and 40.0. The width is adapted according to the original aspect ratio of the stimulus.

Item Unit

The unit to use for the size of the stimuli. Options:

  • Percentage of the available width (default)
  • Centimeters - requires participant calibration
  • Visual angle in Degrees - requires participant calibration and distance measurement

See the documentation page "Dimensions, Units & Calibration" for more details.

Sample Size Ratio

Adjust the size of the sample (target) stimulus by this factor relative to the alternative stimuli. For example, a value of 1.5 makes the sample 50% larger than the alternatives, while 0.5 makes it half the size. Default: 1.0 (same size). Must be between 0.1 and 10.0.

Example

With Item Size set to 8.0 and Sample Size Ratio set to 1.5, the alternatives will have a height of 8.0 (in the chosen unit), while the sample will have a height of 12.0. This can help visually distinguish the sample from the alternatives.

Visual feedback

Target Outline Thickness

Width (in pixels) of the border displayed around the selected stimulus. Set to 0 for no outline. Default: 0. Must be between 0 and 50.

Target Outline Color

Color of the border around the selected stimulus. Options: Red, Green, Blue, Black, White. Default: Red.

Data

For general information about the various structures and file formats that you can download for your data see Downloads.

Trial-wise "annotations" (table rows). Each row represents one trial. Columns:

  • task Name of the task
  • participation Name of the experiment/participation
  • trial Numerical index of the trial (starting from 0)
  • time_trial_start Timestamp when the trial was displayed (seconds since 1/1/1970)
  • time_trial_response Timestamp when the participant responded (seconds since 1/1/1970)
  • stim1_id Meadows internal ID of the sample (target) stimulus
  • stim1_name Filename of the sample stimulus as uploaded
  • stim2_id Meadows internal ID of the first alternative stimulus
  • stim2_name Filename of the first alternative as uploaded
  • stim3_id Meadows internal ID of the second alternative stimulus
  • stim3_name Filename of the second alternative as uploaded
  • label ID of the stimulus that was selected by the participant

In the Tree structure, under the task object:

  • annotations An array with a key/value map for each trial:
    • trial Numerical index of the trial
    • start Timestamp (epoch time) of the start of the trial, in seconds since 1/1/1970
    • resp Timestamp (epoch time) of the response, in seconds since 1/1/1970
    • ids Array of three stimulus IDs: [sample, alternative1, alternative2]
    • label The ID of the stimulus selected by the participant
  • stimuli Array of stimulus objects with id and name fields

Analysis and Visualization

The match-to-sample task data can be analyzed to compute accuracy and reaction times, and to assess learning or discrimination performance across conditions.

Calculate Accuracy and Reaction Times

A response is correct when the participant selects the stimulus that matches the sample. This can be determined by comparing the selected stimulus ID with the sample ID (for identical matching) or by checking stimulus categories (for categorical matching).

import pandas as pd
import matplotlib.pyplot as plt

# Load the annotations data
df = pd.read_csv('Meadows_myExperiment_v1_annotations.csv')

# Calculate reaction time in milliseconds
df['rt_ms'] = (df['time_trial_response'] - df['time_trial_start']) * 1000

# Determine if response was correct
# For identical matching: check if selected stimulus matches sample
df['correct'] = (df['label'] == df['stim1_id']) | \
                (df['label'] == df['stim2_id']) & (df['stim2_id'] == df['stim1_id']) | \
                (df['label'] == df['stim3_id']) & (df['stim3_id'] == df['stim1_id'])

# Alternative: for categorical matching, you'd check if labels match
# df['correct'] = df['label'].str.contains(df['stim1_name'].str.split('_').str[0])

# Basic statistics
accuracy = df['correct'].mean() * 100
mean_rt = df['rt_ms'].mean()
mean_rt_correct = df[df['correct']]['rt_ms'].mean()
mean_rt_incorrect = df[~df['correct']]['rt_ms'].mean()

print(f"Overall accuracy: {accuracy:.1f}%")
print(f"Mean RT (all trials): {mean_rt:.2f} ms")
print(f"Mean RT (correct): {mean_rt_correct:.2f} ms")
print(f"Mean RT (incorrect): {mean_rt_incorrect:.2f} ms")

# Plot RT distributions for correct vs incorrect
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

ax1.hist(df[df['correct']]['rt_ms'], bins=30, alpha=0.7, 
         label='Correct', color='green', edgecolor='black')
ax1.hist(df[~df['correct']]['rt_ms'], bins=30, alpha=0.7, 
         label='Incorrect', color='red', edgecolor='black')
ax1.set_xlabel('Reaction Time (ms)')
ax1.set_ylabel('Frequency')
ax1.set_title('RT Distribution by Accuracy')
ax1.legend()

# Accuracy over trials (to see learning)
window = 10  # rolling window size
df['accuracy_rolling'] = df['correct'].rolling(window=window).mean()
ax2.plot(df['trial'], df['accuracy_rolling'])
ax2.axhline(y=0.5, color='gray', linestyle='--', label='Chance')
ax2.set_xlabel('Trial Number')
ax2.set_ylabel(f'Accuracy (rolling {window}-trial window)')
ax2.set_title('Learning Curve')
ax2.legend()

plt.tight_layout()
plt.show()
library(tidyverse)

# Load the annotations data
df <- read_csv('Meadows_myExperiment_v1_annotations.csv')

# Calculate reaction time in seconds
df <- df %>%
  mutate(
    rt_ms = (time_trial_response - time_trial_start) * 1000,
    # Determine correctness (for identical matching)
    correct = (label == stim1_id) | 
              (label == stim2_id & stim2_id == stim1_id) |
              (label == stim3_id & stim3_id == stim1_id)
  )

# Summary statistics
df %>%
  summarise(
    accuracy = mean(correct) * 100,
    mean_rt = mean(rt_ms),
    median_rt = median(rt_ms),
    sd_rt = sd(rt_ms)
  )

# Statistics by accuracy
df %>%
  group_by(correct) %>%
  summarise(
    n = n(),
    mean_rt = mean(rt_ms),
    sd_rt = sd(rt_ms)
  )

# Plot RT by accuracy
ggplot(df, aes(x = correct, y = rt_ms, fill = correct)) +
  geom_boxplot() +
  scale_fill_manual(values = c("TRUE" = "green", "FALSE" = "red"),
                   labels = c("Incorrect", "Correct")) +
  labs(x = "Response Accuracy", y = "Reaction Time (ms)",
       title = "Reaction Times by Accuracy") +
  theme_minimal() +
  theme(legend.title = element_blank())

For basic analysis in Excel, Google Sheets, or LibreOffice Calc:

  1. Calculate RT: In a new column, compute:

    =(time_trial_response - time_trial_start) * 1000
    

  2. Determine accuracy: Create a column to check if the response matches:

    =IF(label = stim1_id, 1, 0)
    
    Or for categorical matching:
    =IF(LEFT(label, 3) = LEFT(stim1_name, 3), 1, 0)
    

  3. Calculate statistics:

  4. Mean accuracy: =AVERAGE(correct_column)
  5. Mean RT: =AVERAGE(rt_column)
  6. Mean RT for correct: =AVERAGEIF(correct_column, 1, rt_column)

  7. Create a pivot table to analyze accuracy by stimulus or trial block.

% Load the data
data = readtable('Meadows_myExperiment_v1_annotations.csv');

% Calculate reaction time in milliseconds
data.rt_ms = (data.time_trial_response - data.time_trial_start) * 1000;

% Determine correctness
data.correct = strcmp(data.label, data.stim1_id) | ...
               (strcmp(data.label, data.stim2_id) & strcmp(data.stim2_id, data.stim1_id)) | ...
               (strcmp(data.label, data.stim3_id) & strcmp(data.stim3_id, data.stim1_id));

% Calculate statistics
accuracy = mean(data.correct) * 100;
mean_rt = mean(data.rt_ms);
mean_rt_correct = mean(data.rt_ms(data.correct));
mean_rt_incorrect = mean(data.rt_ms(~data.correct));

fprintf('Overall accuracy: %.1f%%\n', accuracy);
fprintf('Mean RT (all): %.2f ms\n', mean_rt);
fprintf('Mean RT (correct): %.2f ms\n', mean_rt_correct);
fprintf('Mean RT (incorrect): %.2f ms\n', mean_rt_incorrect);

% Plot RT distributions
figure('Position', [100, 100, 1200, 500]);

subplot(1, 2, 1);
histogram(data.rt_ms(data.correct), 30, 'FaceColor', 'g', 'FaceAlpha', 0.7);
hold on;
histogram(data.rt_ms(~data.correct), 30, 'FaceColor', 'r', 'FaceAlpha', 0.7);
xlabel('Reaction Time (ms)');
ylabel('Frequency');
title('RT Distribution by Accuracy');
legend({'Correct', 'Incorrect'});

% Learning curve
subplot(1, 2, 2);
window = 10;
accuracy_rolling = movmean(double(data.correct), window);
plot(data.trial, accuracy_rolling, 'LineWidth', 2);
hold on;
yline(0.5, '--', 'Color', [0.5 0.5 0.5], 'LineWidth', 1.5);
xlabel('Trial Number');
ylabel(sprintf('Accuracy (rolling %d-trial window)', window));
title('Learning Curve');
legend({'Accuracy', 'Chance'}, 'Location', 'best');

References


  1. Cumming, W. W., & Berryman, R. (1965). The complex discriminated operant: Studies of matching-to-sample and related problems. In D. I. Mostofsky (Ed.), Stimulus generalization (pp. 284-330). Stanford University Press.