function reorganize_data() basePath = '../'; rawDataPath = fullfile(basePath, 'raw_data'); % Initialize maps to track run files and transient run numbers runFilesMap = containers.Map('KeyType', 'char', 'ValueType', 'any'); transientRunMap = containers.Map('KeyType', 'char', 'ValueType', 'double'); files = dir(fullfile(rawDataPath, '**/*.mat')); % Process files to categorize runs and identify transient runs for i = 1:length(files) data = load(fullfile(files(i).folder, files(i).name)); if isfield(data, 'tireid') && isfield(data, 'testid') tireid = data.tireid; testType = formatTestType(data.testid); runNumber = extractRunNumber(files(i).name); key = sprintf('%s_%s', tireid, testType); if ~runFilesMap.isKey(key) runFilesMap(key) = {}; end runFiles = runFilesMap(key); runFiles{end+1} = struct('path', fullfile(files(i).folder, files(i).name), 'runNumber', runNumber); runFilesMap(key) = runFiles; % Identify the transient run for cornering if strcmpi(testType, 'cornering') if transientRunMap.isKey(tireid) transientRunMap(tireid) = min(transientRunMap(tireid), runNumber); else transientRunMap(tireid) = runNumber; end end end end % Create directories for each tireid if they don't exist mapKeys = runFilesMap.keys(); tireids = unique(cellfun(@(x) strtok(x, '_'), mapKeys, 'UniformOutput', false)); for i = 1:length(tireids) newDir = fullfile('../sorted_data', tireids{i}); if ~exist(newDir, 'dir') mkdir(newDir); end end % Merge files in ascending order of run number and handle transient runs for i = 1:length(mapKeys) key = mapKeys{i}; runFiles = runFilesMap(key); [tireid, testType] = strtok(key, '_'); testType = testType(2:end); % Remove leading underscore % Extract run numbers and sort runs by run number runNumbers = arrayfun(@(x) x.runNumber, [runFiles{:}]); [~, idx] = sort(runNumbers); sortedRuns = runFiles(idx); newDir = fullfile('../sorted_data', tireid); for j = 1:length(sortedRuns) if strcmpi(testType, 'cornering') && sortedRuns{j}.runNumber == transientRunMap(tireid) % Handle transient cornering run separately newFilePath = fullfile(newDir, 'cornering_transient.mat'); copyfile(sortedRuns{j}.path, newFilePath); else % Regular file processing newFilePath = fullfile(newDir, sprintf('%s.mat', testType)); if j == 1 || ~exist(newFilePath, 'file') copyfile(sortedRuns{j}.path, newFilePath); else mergeData(newFilePath, sortedRuns{j}.path); end end end end end function testType = formatTestType(testid) switch lower(testid) case 'cornering' testType = 'cornering'; case 'drive/brake/combined' testType = 'drivebrake'; otherwise error('Unknown testid: %s', testid); end end function mergeData(mergedFilePath, newFilePath) % Load existing and new data existingData = load(mergedFilePath); newData = load(newFilePath); % Merge logic with error checking for singular values fieldNames = fieldnames(newData); for i = 1:length(fieldNames) fieldName = fieldNames{i}; if isnumeric(newData.(fieldName)) || islogical(newData.(fieldName)) if numel(newData.(fieldName)) == 1 % Singular value if isfield(existingData, fieldName) && existingData.(fieldName) ~= newData.(fieldName) error('Mismatch in singular value for field "%s" between existing and new data.', fieldName); end elseif isfield(existingData, fieldName) existingData.(fieldName) = [existingData.(fieldName); newData.(fieldName)]; else existingData.(fieldName) = newData.(fieldName); end elseif ~strcmp(fieldName, 'tireid') && ~strcmp(fieldName, 'testid') if isfield(existingData, fieldName) && ~isequal(existingData.(fieldName), newData.(fieldName)) error('Mismatch in non-array field "%s" between existing and new data.', fieldName); end existingData.(fieldName) = newData.(fieldName); end end % Save the merged data save(mergedFilePath, '-struct', 'existingData'); end function runNumber = extractRunNumber(fileName) num = sscanf(fileName, 'B2356run%d'); if isempty(num) runNumber = NaN; % Indicate missing or invalid run number else runNumber = num; end end