diff --git a/Admin/rtbPublishReferenceData.m b/Admin/rtbPublishReferenceData.m index 7b376d0eb731c219e5398a195769129225b6e50d..9a8e08a4bcf99477899ada757c65a2aeb00f0360 100644 --- a/Admin/rtbPublishReferenceData.m +++ b/Admin/rtbPublishReferenceData.m @@ -24,14 +24,18 @@ function artifacts = rtbPublishReferenceData(varargin) parser = inputParser(); parser.addParameter('rdtConfig', 'render-toolbox'); +parser.addParameter('rdtUsername', ''); +parser.addParameter('rdtPassword', ''); parser.addParameter('referenceRoot', pwd(), @ischar); parser.addParameter('tempRoot', fullfile(tempdir(), 'rtbPublishReferenceData'), @ischar); parser.addParameter('referenceVersion', 'test', @ischar); parser.addParameter('remotePath', 'reference-data', @ischar); -parser.addParameter('deployToolboxes', true, @islogical); +parser.addParameter('deployToolboxes', false, @islogical); parser.addParameter('dryRun', true, @islogical); parser.parse(varargin{:}); rdtConfig = parser.Results.rdtConfig; +rdtUsername = parser.Results.rdtUsername; +rdtPassword = parser.Results.rdtPassword; referenceRoot = parser.Results.referenceRoot; tempRoot = parser.Results.tempRoot; referenceVersion = parser.Results.referenceVersion; @@ -39,6 +43,12 @@ remotePath = parser.Results.remotePath; deployToolboxes = parser.Results.deployToolboxes; dryRun = parser.Results.dryRun; +if ~isempty(rdtUsername) && ~isempty(rdtPassword) + rdtConfig = rdtConfiguration(rdtConfig); + rdtConfig.username = rdtUsername; + rdtConfig.password = rdtPassword; +end + if deployToolboxes tbUse({'RenderToolbox4', 'RemoteDataToolbox'}); end @@ -48,6 +58,7 @@ if 7 ~= exist(tempRoot, 'dir') end % iterate subfolders of referenceRoot for example names +fprintf('Looking for examples in <%s>:', referenceRoot); [exampleNames, nExamples] = subfolderNames(referenceRoot); artifactCell = cell(1, nExamples); for ee = 1:nExamples @@ -66,6 +77,7 @@ for ee = 1:nExamples end artifacts = [artifactCell{:}]; + function [names, nNames] = subfolderNames(parentPath) parentDir = dir(parentPath); parentDir = parentDir(3:end); @@ -77,7 +89,7 @@ function artifact = publishFile(rdtConfig, fileName, remotePath, exampleName, ve % describe the example artifactPath = fullfile(remotePath, exampleName); -description = sprintf('version <%s> example <%s>', versionName, exampleName); +description = sprintf(' version <%s> example <%s>', versionName, exampleName); disp(description); if dryRun diff --git a/Test/Automated/RtbExampleTests.m b/Test/Automated/RtbExampleTests.m index bd07c83d137b88db3831335fef131c00c8e543ce..a551e9687a9c5b0421f45b21f29612db2817d550 100644 --- a/Test/Automated/RtbExampleTests.m +++ b/Test/Automated/RtbExampleTests.m @@ -21,7 +21,7 @@ classdef RtbExampleTests < matlab.unittest.TestCase methods (Test) function testNotAnExample(testCase) - results = rtbRunEpicTest( ... + results = rtbRunEpicExamples( ... 'outputRoot', testCase.outputRoot, ... 'makeFunctions', {'notAnExample.m'}); testCase.assertFalse(results.isSuccess); @@ -29,7 +29,7 @@ classdef RtbExampleTests < matlab.unittest.TestCase end function testCoordinatesTest(testCase) - results = rtbRunEpicTest( ... + results = rtbRunEpicExamples( ... 'outputRoot', testCase.outputRoot, ... 'makeFunctions', {'rtbMakeCoordinatesTest.m'}); testCase.assertTrue(results.isSuccess); @@ -51,7 +51,7 @@ classdef RtbExampleTests < matlab.unittest.TestCase end function testDragon(testCase) - results = rtbRunEpicTest( ... + results = rtbRunEpicExamples( ... 'outputRoot', testCase.outputRoot, ... 'makeFunctions', {'rtbMakeDragon.m'}); testCase.assertTrue(results.isSuccess); @@ -70,7 +70,7 @@ classdef RtbExampleTests < matlab.unittest.TestCase end function testMaterialSphereBumps(testCase) - results = rtbRunEpicTest( ... + results = rtbRunEpicExamples( ... 'outputRoot', testCase.outputRoot, ... 'makeFunctions', {'rtbMakeMaterialSphereBumps.m'}); testCase.assertTrue(results.isSuccess); @@ -89,7 +89,7 @@ classdef RtbExampleTests < matlab.unittest.TestCase end function testMaterialSphereRemodeled(testCase) - results = rtbRunEpicTest( ... + results = rtbRunEpicExamples( ... 'outputRoot', testCase.outputRoot, ... 'makeFunctions', {'rtbMakeMaterialSphereRemodeled.m'}); testCase.assertTrue(results.isSuccess); diff --git a/Test/Interactive/Comparison/rtbRunEpicComparison.m b/Test/Interactive/Comparison/rtbRunEpicComparison.m index 5ea42c274ae7a849ec309c9de81cfe21a8fb674c..370e98a71e19cae6f084955ec19dcc514209d949 100644 --- a/Test/Interactive/Comparison/rtbRunEpicComparison.m +++ b/Test/Interactive/Comparison/rtbRunEpicComparison.m @@ -40,6 +40,7 @@ function [comparisons, matchInfo, figs] = rtbRunEpicComparison(folderA, folderB, %%% 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('plotSummary', true, @islogical); diff --git a/Test/Interactive/rtbEpicValidationExample.m b/Test/Interactive/rtbEpicValidationExample.m new file mode 100644 index 0000000000000000000000000000000000000000..ccc7643a1225dc1401714b7f7b3928e5bd98764f --- /dev/null +++ b/Test/Interactive/rtbEpicValidationExample.m @@ -0,0 +1,60 @@ +%% Run an "epic" example tests, and compare to published reference data. +% +% This script is an example of how to run through an "epic scene test" and +% comparison of results to reference data stored at Brainard Archiva. +% http://52.32.77.154/#browse~RenderToolbox/reference-data +% +% All the work is done by the function rtbRunEpicValidation(). But there +% are several parameters that you might want to configure. So here is a +% script with comments. +% +%%% 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. + +clear; +clc; + + +%% Parameters to pass to rtbRunEpicExamples(). + +% where to store locally generated results +localOutput = '/Users/ben/Deskop/rtb-epic'; + +% choose a few recipes for testing this out +makeFunctions = {'rtbMakeCoordinatesTest', 'rtbMakeDragon'}; + +% leave empty to run them all +% makeFunctions = {}; + + +%% Parameters to pass to rtbRunEpicComparison(). + +% where to store fetched reference data +rtbReference = '/Users/ben/Deskop/rtb-reference'; + +% where to save generated comparison figures +figureFolder = '/Users/ben/Deskop/rtb-figures'; + +% a name to use for this comparison run +summaryName = 'epic-validation-example'; + + +%% Run examples and do the comparison. +% You could pass in additional parameters for rtbRunEpicExamples() or +% rtbRunEpicComparison(), too. They will be forwarded along. The +% parameters above seem like a good bunch to start with. + +% This may take a long time. +% The outputs are: +% - exampleResults -- struct array with info for each example recipe run +% - comparisons -- struct array with info about comparisons to reference +% - matchInfo -- struct array about matching up local data vs reference +% - figures -- array of figure handles with comparison summary +[exampleResults, comparisons, matchInfo, figs] = rtbRunEpicValidation( ... + localOutput, ... + rtbReference, ... + 'makeFunctions', makeFunctions, ... + 'figureFolder', figureFolder, ... + 'summaryName', summaryName); + diff --git a/Test/Interactive/rtbRunEpicTest.m b/Test/Interactive/rtbRunEpicExamples.m similarity index 93% rename from Test/Interactive/rtbRunEpicTest.m rename to Test/Interactive/rtbRunEpicExamples.m index 68ba5ea8997032c0ed9af5247eb92f5e11dadcc3..b280a571e5d92c8bd2017dd976c3e8f72c8bafb5 100644 --- a/Test/Interactive/rtbRunEpicTest.m +++ b/Test/Interactive/rtbRunEpicExamples.m @@ -1,7 +1,7 @@ -function results = rtbRunEpicTest(varargin) +function results = rtbRunEpicExamples(varargin) %% Run all "rtbMake..." scripts in the ExampleScenes/ folder. % -% results = rtbRunEpicTest() renders example scenes by invoking +% results = rtbRunEpicExamples() renders example scenes by invoking % all of the "rtbMake..." executive sripts found within the ExampleScenes/ % folder % @@ -19,11 +19,11 @@ function results = rtbRunEpicTest(varargin) % have a name that that includes the name of this m-file, plus the date and % time. % -% rtbRunEpicTest( ... 'outputRoot', outputRoot) specifies the +% rtbRunEpicExamples( ... 'outputRoot', outputRoot) specifies the % working folder where to put rendering outputs. The default is from % rtbDefaultHints(). % -% rtbRunEpicTest( ... 'makeFunctions', makeFunctions) specifies a +% rtbRunEpicExamples( ... 'makeFunctions', makeFunctions) specifies a % cell array of executive functions to run. The default is to search the % ExampleScenes/ folder for m-files that begin with "rtbMake". % @@ -32,6 +32,7 @@ function results = rtbRunEpicTest(varargin) %%% RenderToolbox4 is released under the MIT License. See LICENSE file. parser = inputParser(); +parser.KeepUnmatched = true; parser.addParameter('outputRoot', rtbWorkingFolder(), @ischar); parser.addParameter('makeFunctions', {}, @iscellstr); parser.parse(varargin{:}); diff --git a/Test/Interactive/rtbRunEpicValidation.m b/Test/Interactive/rtbRunEpicValidation.m new file mode 100644 index 0000000000000000000000000000000000000000..946b82b96103593d47552b78e76507a1ece1ccaf --- /dev/null +++ b/Test/Interactive/rtbRunEpicValidation.m @@ -0,0 +1,40 @@ +function [results, comparisons, matchInfo, figs] = rtbRunEpicValidation(outputRoot, referenceRoot, varargin) +%% Run an "epic" example tests, and compare to published reference data. +% +% results = rtbRunEpicValidation(outputRoot, referenceRoot) renders example +% scenes by invoking all of the "rtbMake..." executive sripts found within +% the ExampleScenes/ folder and putting results into the given outputRoot +% folder. Then compares all rendered recipes to published reference data, +% using the given referenceRoot to store the reference data. +% +% Returns a struct with information about each recipe executed locally -- +% see rtbRunEpicExamples(). Also returns a struct with information about +% comparisons to reference data, a struct with information about how local +% and reference data files were matched up, and an array of figure handles +% that illustrate the comparisons -- see rtbRunEpicComparison(). +% +% rtbRunEpicValidation( ... name, value) passes additional name-value pairs +% to the functions rtbRunEpicExamples() and rtbRunEpicComparison(). +% +%%% 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.addRequired('outputRoot', @ischar); +parser.addRequired('referenceRoot', @ischar); +parser.parse(outputRoot, referenceRoot); +outputRoot = parser.Results.outputRoot; +referenceRoot = parser.Results.referenceRoot; + + +%% Run the epic example set. +results = rtbRunEpicExamples( ... + 'outputRoot', outputRoot, ... + varargin{:}); + + +%% Run the epic comparison. +[comparisons, matchInfo, figs] = rtbRunEpicComparison( ... + outputRoot, referenceRoot, ... + varargin{:}); diff --git a/Test/Interactive/rtbTestInstallation.m b/Test/Interactive/rtbTestInstallation.m index ada27c2e7035d2605d8dd2a6ea5cb2ae05658f4a..259f1058515a7cb677d255e87813b5a843be6998 100644 --- a/Test/Interactive/rtbTestInstallation.m +++ b/Test/Interactive/rtbTestInstallation.m @@ -77,7 +77,7 @@ end if doAll fprintf('\nTesting rendering with all example scripts.\n'); fprintf('This might take a while.\n'); - renderResults = rtbRunEpicTest([], []); + renderResults = rtbRunEpicExamples([], []); else testScenes = { ... @@ -88,7 +88,7 @@ else fprintf('\nTesting rendering with %d example scripts.\n', numel(testScenes)); fprintf('You should see several figures with rendered images.\n\n'); - renderResults = rtbRunEpicTest('makeFunctions', testScenes); + renderResults = rtbRunEpicExamples('makeFunctions', testScenes); end diff --git a/Utilities/rtbBuildDesription.m b/Utilities/rtbBuildDesription.m new file mode 100644 index 0000000000000000000000000000000000000000..fabaeda2bf01be47a843fd41c761ca8194d561a3 --- /dev/null +++ b/Utilities/rtbBuildDesription.m @@ -0,0 +1,45 @@ +%% Get a formatted struct describing a light, material, etc. +% @param category a scene element category like 'light', 'material', etc. +% @param type a scene element type like 'area', 'matte', etc. +% @param propertyNames cell aray of element property names like {'intensity', 'diffuseReflectance'} +% @param propertyValues cell aray of element property values like {'D65.spd, '255 0 0'} +% @param valueTypes cell aray of property values types like {'spectrum', 'rgb'} +% +% @details +% Builds a struct with standard formatting that describes some scene +% element. This struct will be suitable for writing to a RenderToolbox3 +% mappings file using utilities like AppendMappings(). +% +% @details +% @a category and @a type indicate the kind of scene element to describe, +% for example an area light or matte material. +% +% @details +% @a propertyNames, @a propertyValues, and @a valueTypes all should have +% n elements, and collectively specify n properties of the scene element. +% +% @details +% See <a +% href="https://github.com/DavidBrainard/RenderToolbox3/wiki/Generic-Scene-Elements">Generic-Scene-Elements</a> +% for examples of valid elements and properties. +% +% @details +% Returns a struct with standard formatting which describes a scene element +% and its properties. +% +% @details +% Usage: +% description = rtbBuildDesription(category, type, propertyNames, propertyValues, valueTypes) +% +% We should update the commenting style of this header someday. + +function description = rtbBuildDesription(category, type, propertyNames, propertyValues, valueTypes) +properties = struct( ... + 'propertyName', propertyNames, ... + 'propertyValue', propertyValues, ... + 'valueType', valueTypes); + +description = struct( ... + 'category', category, ... + 'type', type, ... + 'properties', properties); diff --git a/Utilities/rtbReadMetadata.m b/Utilities/rtbReadMetadata.m new file mode 100644 index 0000000000000000000000000000000000000000..e3b7ad8fa69210c53684f58e4a41bd7361cb44c1 --- /dev/null +++ b/Utilities/rtbReadMetadata.m @@ -0,0 +1,46 @@ +%% Read metadata about a VirtualScenes base scene or object. +% @param modelName the name of a VirtualScenes model like "RingToy" +% +% @details +% Reads a mat-file of metadata for a 3D Collada model that we previouslt +% registered in the VirtualScenes ModelRepository using WriteMetadata(). +% @a modelName must be the same name that was passed to WriteMetadata(), +% for example "RingToy". This must would correspond to the name of the +% Collada file in the VirtualScenes Toolbox ModelRepository, such as +% 'VirtualScenesToolbox/ModelRepository/Objects/Models/RingToy.dae'. +% +% @details +% Returns the struct metadata that was previously written by +% WriteMetadata(). +% +% @details +% Usage: +% metadata = ReadMetadata(modelName) +% +% @ingroup VirtualScenes +function metadata = rtbReadMetadata(modelName) +metadata = []; + +% locate the metadata file +metadataFile = [modelName '.mat']; +rootFolder = getpref('VirtualScenes', 'modelRepository'); +fileInfo = rtbResolveFilePath(metadataFile, rootFolder); + +if ~fileInfo.isRootFolderMatch + warning('VirtualScenes:NoSuchMetadata', ... + 'Could not find metadata for model named "%s" in %s', modelName, rootFolder); + return; +end + +metadataFullPath = fileInfo.absolutePath; +fprintf('\nFound model metadata:\n %s\n', metadataFullPath); + +fileData = load(fileInfo.absolutePath); + +if ~isfield(fileData, 'metadata') + warning('VirtualScenes:BadMetadata', ... + 'Metadata is missing from data file %s', metadataFullPath); + return; +end + +metadata = fileData.metadata;