Why is there no matching of timing data when trying to match partic... (2024)

Hello!

I want to analyze synchronization data. I have the timing of note onsets in seconds of a 30s long audio file in an xlsx file. I also have the timestamps of a participant's taps in relation to a stimuli in a separate xlsx file. The experiment is thus: the participant will listen to a 30s long audio stimulus where a C4 note is played at different rhythms. There will be 6 different audio files - a file will be randomly selected from the list for the participant to synchronize to by tapping along. This will happen 24 times as each stimuli has to be selected 4 times.

In my participant's data file there are several columns of interest to me. The most important being the column "keyTap.rt" as this is the column that contains the timestamps of each trial. Each row of this column will contain all the tap timestamps of one trial. Another column is the "Rhythmsequence" column, which designates what audio file was playing at the time of the trial. Hence, each row of this column tells me what audio file was playing at that particular trial. Rows of keyTap.rt and rows of Rhythmsequence have to match up. They also have to match up to the data in the note onsets file (RPTiming.xls), which has a column that called "Rhythmsequence" which says what audiofile and another column called "Notetiming" which has the timing of the note onset. So I have a multi-level matching task I have to perform prior to analysis.

So the problem is that I don't think I am matching the data properly.

As a result, I am unable to generate the circular histogram plots that I need.

Here is my code:

% Load participant data

participant_data = readtable('945386.xlsx');

keyTap_rt = participant_data.keyTap_rt;

Rhythmsequence = participant_data.Rhythmsequence;

trials_thisN = participant_data.trials_thisN;

% Display Rhythmsequence for debugging

disp('Rhythmsequence:');

disp(Rhythmsequence);

% Load note onset data

note_onset_data = readtable('RPTiming.xls');

note_onset_Rhythmsequence = note_onset_data.Rhythmsequence;

note_onset_Notetiming = note_onset_data.Notetiming;

% Define durations for different audio stimuli

file_duration_data = { ...

'44_neutral_eighths.mp3', 33; ...

'44_prosody_eighths.mp3', 33; ...

'44_reverse_eighths.mp3', 33; ...

'78_neutral_eighths.mp3', 30; ...

'78_prosody_eighths.mp3', 30; ...

'78_reverse_eighths.mp3', 30 ...

};

% Initialize duration_map

duration_map = containers.Map();

% Populate duration_map

for i = 1:size(file_duration_data, 1)

filename = file_duration_data{i, 1};

duration = file_duration_data{i, 2};

duration_map(filename) = duration;

end

% Initialize matched data arrays

matched_keyTap_rt = [];

matched_Notetiming = [];

% Store results for each trial

trial_results = struct('filename', {}, 'circular_mean', {}, 'circular_variance', {});

% Initialize a map to store results per audio file

audiofile_results = containers.Map('KeyType', 'char', 'ValueType', 'any');

% Define the list of relevant audio files

relevant_files = {'44_neutral_eighths.mp3', '44_prosody_eighths.mp3', '44_reverse_eighths.mp3', '78_neutral_eighths.mp3', '78_prosody_eighths.mp3', '78_reverse_eighths.mp3'};

% Iterate through each trial in the participant data from rows 7 to 30

for i = 7:30

% Get the full filename from the Rhythmsequence

full_filename = Rhythmsequence{i};

% Check if full_filename or keyTap_rt is empty

if isempty(full_filename) || isempty(keyTap_rt{i})

warning('Empty full_filename or keyTap_rt at index %d', i);

continue;

end

% Debugging statement to check the full_filename

disp('Full filename:');

disp(full_filename);

% Remove 'resources/' prefix if it exists

filename_without_prefix = strrep(full_filename, 'resources/', '');

% Debugging statement to check the filename without the prefix

disp('Filename without prefix:');

disp(filename_without_prefix);

% Check if the filename without prefix is in the list of relevant files

if ~ismember(filename_without_prefix, relevant_files)

continue; % Skip this trial if the file is not relevant

end

% Check if the filename without prefix is present in the duration map

if isKey(duration_map, filename_without_prefix)

% Retrieve duration from duration_map

duration_of_audio_stimulus = duration_map(filename_without_prefix);

% Debugging statement to check the duration

disp('Duration of audio stimulus:');

disp(duration_of_audio_stimulus);

else

warning('Duration not found for audio file: %s', filename_without_prefix);

continue; % Skip this trial if duration is not found

end

% Find the index of the matching Rhythmsequence in the note onset data

matching_idx = find(strcmp(note_onset_Rhythmsequence, full_filename));

% Match keyTap.rt with corresponding Notetiming based on Rhythmsequence

for j = 1:numel(matching_idx)

% Extract note onset timings for the current Rhythmsequence

note_onset_times = note_onset_Notetiming{matching_idx(j)};

% Convert note onset timings to numeric array

note_onset_times = str2double(strsplit(note_onset_times, ','));

% Check if the trial index is within the range of available keyTap_rt values

if i <= numel(keyTap_rt)

% Iterate over each note onset and find the closest tapping event

for k = 1:numel(note_onset_times)

% Find the index of the closest tapping timestamp to the current note onset timestamp

[~, closest_idx] = min(abs(keyTap_rt{i} - note_onset_times(k)));

% Match participant's tapping timestamp with note onset timestamp

matched_keyTap_rt = [matched_keyTap_rt; keyTap_rt{i}(closest_idx)];

matched_Rhythmsequence = [matched_Rhythmsequence; full_filename];

% For the first note, set the timestamp to 0.0

if k == 1

matched_Notetiming = [matched_Notetiming; 0.0];

else

matched_Notetiming = [matched_Notetiming; note_onset_times(k)];

end

end

% Convert timestamps to angles for current trial

angles = mod(2*pi * matched_keyTap_rt / duration_of_audio_stimulus, 2*pi);

% Calculate circular mean and variance for current trial

trial_circular_mean = circ_mean(angles);

trial_circular_variance = circ_var(angles);

% Perform Rayleigh test for circular mean

p_mean = circ_rtest(angles);

% Perform Rayleigh test for circular variance

p_variance = circ_rtest(angles);

% Store results for current trial

trial_results(end+1).filename = full_filename;

trial_results(end).circular_mean = trial_circular_mean;

trial_results(end).circular_variance = trial_circular_variance;

% Retrieve or initialize results for the current audio file

if isKey(audiofile_results, filename_without_prefix)

results = audiofile_results(filename_without_prefix);

else

results = struct('means', [], 'variances', []);

end

% Append current trial results to the audio file results

results.means(end+1) = trial_circular_mean;

results.variances(end+1) = trial_circular_variance;

% Update the audio file results in the map

audiofile_results(filename_without_prefix) = results;

end

end

end

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 44_neutral_eighths.mp3

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 44_prosody_eighths.mp3

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 44_reverse_eighths.mp3

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 78_neutral_eighths.mp3

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 78_prosody_eighths.mp3

Full filename:

resources/44_prosody_eighths.mp3

Index of matching Rhythmsequence:

2

Index of matching Rhythmsequence:

No matching Rhythmsequence found for 78_reverse_eighths.mp3

>>

So what I expect and actually did manage to get is an overall comparison of synchronization data across 24 trials, as well as the comparison of trials of specific audio files. I end up getting something like this

Summary for all trials combined: Circular Mean: 2.109612 radians Circular Variance: 0.058917

Audio File: 78_neutral_eighths.mp3 Trial 1 - Circular Mean: 2.918635 radians, Circular Variance: 0.059712 Trial 2 - Circular Mean: 2.918385 radians, Circular Variance: 0.060746 Trial 3 - Circular Mean: 2.918424 radians, Circular Variance: 0.060585 Trial 4 - Circular Mean: 2.918635 radians, Circular Variance: 0.059712

Trial Number: 24 Filename: resources/44_prosody_eighths.mp3 Circular Mean: 2.109612 radians Circular Variance: 0.058917

And so I want this on a circular histogram for each audio file (I didn't include the plotting section), showing the tapping data in different colors (e.g. for audio file n we have tapping data for trial n1 in green, trial n2, in blue, etc.)

The plots are unfortunately not generating and I suspect it's cause there is an issue with the index? Is there a way to fix this?

Why is there no matching of timing data when trying to match partic... (2024)

References

Top Articles
Latest Posts
Article information

Author: Golda Nolan II

Last Updated:

Views: 5715

Rating: 4.8 / 5 (78 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Golda Nolan II

Birthday: 1998-05-14

Address: Suite 369 9754 Roberts Pines, West Benitaburgh, NM 69180-7958

Phone: +522993866487

Job: Sales Executive

Hobby: Worldbuilding, Shopping, Quilting, Cooking, Homebrewing, Leather crafting, Pet

Introduction: My name is Golda Nolan II, I am a thoughtful, clever, cute, jolly, brave, powerful, splendid person who loves writing and wants to share my knowledge and understanding with you.