From d75db7c63f2d90a2c4f0bed58d9778376c212186 Mon Sep 17 00:00:00 2001 From: Ben Heasly <benjamin.heasly@gmail.com> Date: Mon, 6 Feb 2017 11:39:22 -0500 Subject: [PATCH] refactor match renderings between folders to separate function --- Test/Interactive/rtbCompareManyRenderings.m | 111 ++++++++++++++++++ Test/Interactive/rtbCompareRenderings.m | 1 + Test/Interactive/rtbFetchReferenceData.m | 17 ++- Test/Interactive/rtbFindRenderings.m | 1 + Test/Interactive/rtbPlotRenderingComparison.m | 6 +- 5 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 Test/Interactive/rtbCompareManyRenderings.m diff --git a/Test/Interactive/rtbCompareManyRenderings.m b/Test/Interactive/rtbCompareManyRenderings.m new file mode 100644 index 0000000..2052022 --- /dev/null +++ b/Test/Interactive/rtbCompareManyRenderings.m @@ -0,0 +1,111 @@ +function [comparisons, matchInfo] = rtbCompareManyRenderings(folderA, folderB, varargin) +%% Compare paris of renderings across two folders. +% +% comparisons = rtbCompareManyRenderings(folderA, folderB) finds rendering +% data files in the given folderA and folderB and attempts to match up +% pairs of renderings that came from the same recipe and renderer. +% For each pair, computes difference images and statistics. +% +% Returns a struct array of image comparisons, as returned from +% rtbCompareRenderings(). +% +% rtbCompareManyRenderings( ... 'fetchReferenceData', fetchReferenceData) +% specify whether to use Remote Data Toolbox to fetch reference data for +% comparison. The default is true, fetch reference data when there is a +% recipe in folderA that was not found in folderB, and cache the fetched +% data in folderB. +% +%%% RenderToolbox4 Copyright (c) 2012-2017 The RenderToolbox Team. +%%% About Us://github.com/RenderToolbox/RenderToolbox4/wiki/About-Us +%%% RenderToolbox4 is released under the MIT License. See LICENSE file. + +parser = inputParser(); +parser.KeepUnmatched = true; +parser.addRequired('folderA', @ischar); +parser.addRequired('folderB', @ischar); +parser.addParameter('fetchReferenceData', true, @islogical); +parser.parse(folderA, folderB, varargin{:}); +folderA = parser.Results.folderA; +folderB = parser.Results.folderB; +fetchReferenceData = parser.Results.fetchReferenceData; + + +%% Identify renderings and recipes to compare. +renderingsA = rtbFindRenderings(folderA, varargin{:}); +recipeNames = unique({renderingsA.recipeName}); +nRecipes = numel(recipeNames); + +renderingsB = rtbFindRenderings(folderB, varargin{:}); + +%% Compare one recipe at a time, fetch data as necessary. +comparisonsCell = cell(1, nRecipes); +matchInfoCell = cell(1, nRecipes); +for rr = 1:nRecipes + recipeName = recipeNames{rr}; + fprintf('Comparing renderings for recipe <%s>.\n', recipeName); + + isRecipeA = strcmp({renderingsA.recipeName}, recipeName); + recipeRenderingsA = renderingsA(isRecipeA); + + % fetch missing recipe for B? + isRecipeB = strcmp({renderingsB.recipeName}, recipeName); + if any(isRecipeB) + recipeRenderingsB = renderingsB(isRecipeB); + elseif fetchReferenceData + recipeRenderingsB = rtbFetchReferenceData(recipeName, varargin{:}); + if isempty(recipeRenderingsB) + fprintf(' Could not fetch reference data for set B, skipping this recipe.\n'); + continue; + end + else + fprintf(' Could not find local data for set B. Skipping this recipe.\n'); + continue; + end + + % match pairs of renderings for recipes A and B + info = matchRenderingPairs(recipeRenderingsA, recipeRenderingsB); + fprintf(' Found %d matched pairs of renderings.\n', info.nPairs); + + % run a comparison for each matched pair + pairsCell = cell(1, info.nPairs); + for pp = 1:info.nPairs + fprintf(' %s.\n', info.matchedA(pp).identifier); + pairsCell{pp} = rtbCompareRenderings(info.matchedA(pp), info.matchedB(pp), varargin{:}); + end + comparisonsCell{rr} = [pairsCell{:}]; + matchInfoCell{rr} = info; + + % report on unmatched renderings + if ~isempty(info.unmatchedA) + nUnmatched = info.unmatchedA; + fprintf(' %d renderings in A were not matched in B:\n', nUnmatched); + for uu = 1:nUnmatched + fprintf(' %s\n', info.info.unmatchedA(uu).identifier); + end + end + + if ~isempty(info.unmatchedB) + nUnmatched = info.unmatchedB; + fprintf(' %d renderings in B were not matched in A:\n', nUnmatched); + for uu = 1:nUnmatched + fprintf(' %s\n', info.info.unmatchedB(uu).identifier); + end + end +end +comparisons = [comparisonsCell{:}]; +matchInfo = [matchInfoCell{:}]; + + +%% For pairs of comparable renderings from two sets. +function info = matchRenderingPairs(renderingsA, renderingsB) +identifiersA = {renderingsA.identifier}; +identifiersB = {renderingsB.identifier}; +[~, indexA, indexB] = intersect(identifiersA, identifiersB, 'stable'); +[~, unmatchedIndexA] = setdiff(identifiersA, identifiersB); +[~, unmatchedIndexB] = setdiff(identifiersB, identifiersA); + +info.nPairs = numel(indexA); +info.matchedA = renderingsA(indexA); +info.matchedB = renderingsB(indexB); +info.unmatchedA = renderingsA(unmatchedIndexA); +info.unmatchedB = renderingsB(unmatchedIndexB); diff --git a/Test/Interactive/rtbCompareRenderings.m b/Test/Interactive/rtbCompareRenderings.m index d9e7a28..471a7fb 100644 --- a/Test/Interactive/rtbCompareRenderings.m +++ b/Test/Interactive/rtbCompareRenderings.m @@ -28,6 +28,7 @@ function comparison = rtbCompareRenderings(renderingA, renderingB, varargin) %%% RenderToolbox4 is released under the MIT License. See LICENSE file. parser = inputParser(); +parser.KeepUnmatched = true; parser.addRequired('renderingA', @isstruct); parser.addRequired('renderingB', @isstruct); parser.addParameter('denominatorThreshold', 0.2, @isnumeric); diff --git a/Test/Interactive/rtbFetchReferenceData.m b/Test/Interactive/rtbFetchReferenceData.m index 8b400f6..adca969 100644 --- a/Test/Interactive/rtbFetchReferenceData.m +++ b/Test/Interactive/rtbFetchReferenceData.m @@ -30,6 +30,7 @@ function [renderings, referenceRoot, artifact] = rtbFetchReferenceData(recipeNam %%% RenderToolbox4 is released under the MIT License. See LICENSE file. parser = inputParser(); +parser.KeepUnmatched = true; parser.addRequired('recipeName', @ischar); parser.addParameter('rdtConfig', 'render-toolbox'); parser.addParameter('remotePath', 'reference-data', @ischar); @@ -42,12 +43,17 @@ remotePath = parser.Results.remotePath; referenceVersion = parser.Results.referenceVersion; referenceRoot = parser.Results.referenceRoot; - %% Get a whole recipe from the server. artifactPath = fullfile(remotePath, recipeName); -[fileName, artifact] = rdtReadArtifact(rdtConfig, artifactPath, recipeName, ... - 'version', referenceVersion, ... - 'type', 'zip'); +try + [fileName, artifact] = rdtReadArtifact(rdtConfig, artifactPath, recipeName, ... + 'version', referenceVersion, ... + 'type', 'zip'); +catch err + renderings = []; + artifact = []; + return; +end if isempty(fileName) renderings = []; @@ -58,6 +64,9 @@ end %% Explode renderings it into the destination folder. destination = fullfile(referenceRoot, recipeName); +if 7 ~= exist(destination, 'dir') + mkdir(destination); +end unzip(fileName, destination); % scan for rendering records diff --git a/Test/Interactive/rtbFindRenderings.m b/Test/Interactive/rtbFindRenderings.m index cdde19c..d6b7b22 100644 --- a/Test/Interactive/rtbFindRenderings.m +++ b/Test/Interactive/rtbFindRenderings.m @@ -32,6 +32,7 @@ function renderings = rtbFindRenderings(rootFolder, varargin) %%% RenderToolbox4 is released under the MIT License. See LICENSE file. parser = inputParser(); +parser.KeepUnmatched = true; parser.addRequired('rootFolder', @ischar); parser.addParameter('filter', '\.mat$', @ischar); parser.addParameter('renderingsFolderName', 'renderings', @ischar); diff --git a/Test/Interactive/rtbPlotRenderingComparison.m b/Test/Interactive/rtbPlotRenderingComparison.m index 60a8974..b5526fa 100644 --- a/Test/Interactive/rtbPlotRenderingComparison.m +++ b/Test/Interactive/rtbPlotRenderingComparison.m @@ -10,6 +10,7 @@ function fig = rtbPlotRenderingComparison(comparison, varargin) %%% RenderToolbox4 is released under the MIT License. See LICENSE file. parser = inputParser(); +parser.KeepUnmatched = true; parser.addRequired('comparison', @isstruct); parser.addParameter('isScale', true, @islogical); parser.addParameter('toneMapFactor', 0, @isnumeric); @@ -34,7 +35,10 @@ rgbBminusA = rtbMultispectralToSRGB(comparison.bMinusA, S, ... %% Make the plot. -name = sprintf('RGB isScale %d toneMapFactor %.2f', isScale, toneMapFactor); +name = sprintf('%s isScale %d toneMapFactor %.2f', ... + comparison.renderingA.identifier, ... + isScale, ... + toneMapFactor); set(fig, 'Name', name, ... 'NumberTitle', 'off'); -- GitLab