Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions API/controlsClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,8 @@
fwrite(fileID, true, 'uchar');
fclose(fileID);
end
end

%------------------------- Display Methods --------------------------
methods (Access = protected)
function groups = getPropertyGroups(obj)

function dispPropList = getAvailableFields(obj)
masterPropList = struct('parallel', {obj.parallel},...
'procedure', {obj.procedure},...
'display', {obj.display},...
Expand Down Expand Up @@ -499,20 +496,29 @@
'boundHandling',...
'adaptPCR'};


dispPropList = masterPropList;
if strcmpi(obj.procedure, 'calculate')
dispPropList = rmfield(masterPropList, [deCell, simplexCell, nsCell, dreamCell, {'updatePlotFreq','updateFreq'}]);
elseif strcmpi(obj.procedure, 'simplex')
dispPropList = rmfield(masterPropList, [deCell, nsCell, dreamCell]);
elseif strcmpi(obj.procedure, 'de')
dispPropList = rmfield(masterPropList, [simplexCell, nsCell, dreamCell]);
% Add the update back...
elseif strcmpi(obj.procedure, 'ns')
dispPropList = rmfield(masterPropList, [simplexCell, deCell, dreamCell, {'updatePlotFreq','updateFreq'}]);
elseif strcmpi(obj.procedure, 'dream')
dispPropList = rmfield(masterPropList, [simplexCell, deCell, nsCell, {'updatePlotFreq','updateFreq'}]);
end
end
end

%------------------------- Display Methods --------------------------
methods (Access = protected)
function groups = getPropertyGroups(obj)

if isscalar(obj)
dispPropList = masterPropList;
if strcmpi(obj.procedure, 'calculate')
dispPropList = rmfield(masterPropList, [deCell, simplexCell, nsCell, dreamCell, {'updatePlotFreq','updateFreq'}]);
elseif strcmpi(obj.procedure, 'simplex')
dispPropList = rmfield(masterPropList, [deCell, nsCell, dreamCell]);
elseif strcmpi(obj.procedure, 'de')
dispPropList = rmfield(masterPropList, [simplexCell, nsCell, dreamCell]);
% Add the update back...
elseif strcmpi(obj.procedure, 'ns')
dispPropList = rmfield(masterPropList, [simplexCell, deCell, dreamCell, {'updatePlotFreq','updateFreq'}]);
elseif strcmpi(obj.procedure, 'dream')
dispPropList = rmfield(masterPropList, [simplexCell, deCell, nsCell, {'updatePlotFreq','updateFreq'}]);
end
dispPropList = obj.getAvailableFields();
groups = matlab.mixin.util.PropertyGroup(dispPropList);
else
groups = getPropertyGroups@matlab.mixin.CustomDisplay(obj);
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions tests/testJsonToProject/result_bayes_dream.json

Large diffs are not rendered by default.

70 changes: 61 additions & 9 deletions tests/testJsonToProject/testJsonToProject.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,24 @@
'DSPC_standard_layers'}

resultFile = {'result', ...
'result_bayes'}
'result_bayes_dream', ...
'result_bayes_ns'}

controlsParams = {{'calculate', 'numSimulationPoints', 100},...
{'simplex' 'xTolerance', 19},...
{'de' 'populationSize', 200},...
{'ns' 'nLive', 19},...
{'dream' 'nSamples', 200}}
r2Tests = {{'normalReflectivity', 'standardLayers', 'standardLayersDSPCScript'},...
{'domains', 'customLayers', 'domainsCustomLayersScript'},...
{'domains', 'customXY', 'domainsCustomXYScript'}}
end

methods(TestClassSetup)
function addDataPath(testCase)
import matlab.unittest.fixtures.PathFixture
path = fullfile(getappdata(0, 'root'), 'tests', 'testJsonToProject');
testCase.applyFixture(PathFixture(path))
testCase.applyFixture(PathFixture(path));
end
function setWorkingFolder(testCase)
import matlab.unittest.fixtures.WorkingFolderFixture;
Expand All @@ -48,19 +58,15 @@ function testJsonResultConversion(testCase, resultFile)
resultsToJson(result, "test.json");
result2 = jsonToResults("test.json");

props = properties(result);
props = fieldnames(result);
for i = 1:length(props)
testCase.verifyEqual(result.(props{i}), result2.(props{i}));
end
end

function testJsonControlsConversion(testCase)
function testJsonControlsConversion(testCase, controlsParams)
controls = controlsClass();
controls.numSimulationPoints = 100;
controls.xTolerance = 19;
controls.populationSize = 200;
controls.nLive = 140;
controls.nSamples = 200;
controls.setProcedure(controlsParams{1}, controlsParams{2:end});

controlsToJson(controls, "test.json");
controls2 = jsonToControls("test.json");
Expand All @@ -69,6 +75,52 @@ function testJsonControlsConversion(testCase)
for i = 1:length(props)
testCase.verifyEqual(controls.(props{i}), controls2.(props{i}));
end
end

function testR2Conversion(testCase, r2Tests)
scriptName = r2Tests{3};
outFolder = ['save_' scriptName];

copyfile(fullfile(getappdata(0, 'root'), 'examples', r2Tests{1}, r2Tests{2}), ...
fullfile(pwd))
evalc(scriptName);

controls = controlsClass();
controls.display = 'off';
[project, result] = RAT(problem, controls);

saveR2(outFolder, project, result, controls)
testCase.verifyEqual(exist(fullfile(pwd, outFolder, 'results.json'), 'file'), 2)
testCase.verifyEqual(exist(fullfile(pwd, outFolder, 'project.json'), 'file'), 2)
testCase.verifyEqual(exist(fullfile(pwd, outFolder, 'controls.json'), 'file'), 2)
for i=1:project.customFile.rowCount
customFile = project.customFile.varTable{i, 2};
testCase.verifyEqual(exist(fullfile(pwd, outFolder, customFile), 'file'), 2)
end

[project2, result2] = loadR2(outFolder);
% verifies the problem name, model type and geometry
testCase.verifyEqual(project.experimentName, project2.experimentName);
testCase.verifyEqual(project.modelType, project2.modelType);
testCase.verifyEqual(project.geometry, project2.geometry);

% verifies the count of problem properties
testCase.verifyEqual(project.contrasts.numberOfContrasts, project2.contrasts.numberOfContrasts);
testCase.verifyEqual(project.parameters.rowCount, project2.parameters.rowCount);
testCase.verifyEqual(project.bulkOut.rowCount, project2.bulkOut.rowCount);
testCase.verifyEqual(project.background.backgrounds.rowCount, project2.background.backgrounds.rowCount);
testCase.verifyEqual(project.data.rowCount, project2.data.rowCount);
testCase.verifyEqual(project.scalefactors.rowCount, project2.scalefactors.rowCount);
if isa(project.layers, 'layersClass')
testCase.verifyEqual(project.layers.rowCount, project2.layers.rowCount);
end
testCase.verifyEqual(project.bulkIn.rowCount, project2.bulkIn.rowCount);

props = fieldnames(result);
for i = 1:length(props)
testCase.verifyEqual(result.(props{i}), result2.(props{i}));
end
close all
end
end

Expand Down
2 changes: 1 addition & 1 deletion utilities/misc/controlsToJson.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
function controlsToJson(controls,filename)

% Saves the current controls block as a json..
encoded = jsonencode(controls,ConvertInfAndNaN=false);
encoded = jsonencode(controls.getAvailableFields(),ConvertInfAndNaN=false);

[path,filename,~] = fileparts(filename);
fid = fullfile(path, append(filename, '.json'));
Expand Down
57 changes: 24 additions & 33 deletions utilities/misc/jsonToResults.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
results.shiftedData = dataArray2Cells(jsonRes.shiftedData);
results.backgrounds = simArray2Cells(jsonRes.backgrounds);
results.resolutions = simArray2Cells(jsonRes.resolutions);
results.sldProfiles = sldArray2Cells(jsonRes.sldProfiles,numel(results.reflectivity));
results.layers = sldArray2Cells(jsonRes.layers,numel(results.reflectivity)); % Layers array is in the same format as the SLDs
results.resampledLayers = sldArray2Cells(jsonRes.resampledLayers,numel(results.reflectivity));
results.sldProfiles = sldArray2Cells(jsonRes.sldProfiles);
results.layers = sldArray2Cells(jsonRes.layers); % Layers array is in the same format as the SLDs
results.resampledLayers = sldArray2Cells(jsonRes.resampledLayers);

% These correctly load in as structs or arrays....
results.calculationResults = jsonRes.calculationResults;
Expand All @@ -35,7 +35,7 @@
if isfield(jsonRes,'predictionIntervals')
results.predictionIntervals = jsonRes.predictionIntervals;
results.predictionIntervals.reflectivity = simArray2Cells(results.predictionIntervals.reflectivity);
results.predictionIntervals.sld = simArray2Cells(results.predictionIntervals.sld);
results.predictionIntervals.sld = sldArray2Cells(results.predictionIntervals.sld);

results.confidenceIntervals = jsonRes.confidenceIntervals;
results.dreamParams = jsonRes.dreamParams;
Expand All @@ -49,42 +49,33 @@

% ----------------------------------------------------------

function outCell = sldArray2Cells(inArray,nContrasts)
function outCell = sldArray2Cells(inArray)

% Check we don't already have cells..
if iscell(inArray)
nArrays = numel(inArray);
if nArrays == nContrasts % (not domains)
outCell = inArray;
else % ..domains - [n x 2] cell array
outCell = reshape(inArray,nContrasts,2);
row = size(inArray, 1);
if iscell(inArray{1})
col = size(inArray{1}, 1);
else
col = size(inArray(1),1);
end
else

% Get number of profiles...
nProfiles = size(inArray,1);

% Make them into cells....
for i = 1:nProfiles
thisSLD = inArray(i,:,:,:);
thisSLD = squeeze(thisSLD); % Collapse singleton dims....
outCell{i,1} = thisSLD;
outCell = cell(row, col);
for i=1:row
for j=1:col
outCell{i, j} = squeeze(inArray{i}{j});
end
end

% If domains, reorganise the cells...
if nProfiles > nContrasts
outCell = transpose(reshape(outCell,nContrasts,2));
end
end

% We have an annoying automatic reshape of single layers into columns.
% Fix this...
for i = 1:numel(outCell)
if iscolumn(outCell{i})
outCell{i} = transpose(outCell{i});
else
dims = size(inArray);
row = dims(1);
col = dims(2);
outCell = cell(row, col);
for i=1:row
for j=1:col
outCell{i, j} = reshape(inArray(i, j, :, :), dims(3:end));
end
end
end

end

% --------------------------------------------------------------
Expand Down
40 changes: 40 additions & 0 deletions utilities/misc/loadR2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

function [problem,varargout] = loadR2(dirName)
% Loads in a RasCAL2 project.
%
% Examples
% --------
% >>> project = loadR2("r2_example"); % Load project from a given directory
% >>> [project, results] = loadR2("r2_example"); % Load project and result
%
% Parameters
% ----------
% dirName : string or char array
% The path of the R2 project folder.
%
% Returns
% -------
% project : projectClass
% An instance of the ``projectClass`` which should be equivalent to the given R2 problem.
% results : struct
% An optional output. A struct which contains the R2 results if present.

arguments
dirName {mustBeTextScalar, mustBeNonempty}
end
% Load the project.
projectFile = fullfile(dirName,'project.json');
problem = jsonToProject(projectFile);

% If there is a second output, also load results.
if nargout > 1
resultsFile = fullfile(dirName, 'results.json');
if exist(resultsFile, 'file') == 2
varargout{1} = jsonToResults(resultsFile);
else
varargout{1} = struct();
warning("result.json was not found in the project.");
end
end

end
73 changes: 72 additions & 1 deletion utilities/misc/resultsToJson.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,84 @@
function resultsToJson(results,filename)

% Encodes the results into a json file...
tmpResults = struct();
for fn = fieldnames(results)'
tmpResults.(fn{1}) = results.(fn{1});
end

encoded = jsonencode(results,ConvertInfAndNaN=false);
tmpResults.reflectivity = correctCellArray(tmpResults.reflectivity);
tmpResults.simulation = correctCellArray(tmpResults.simulation);
tmpResults.shiftedData = correctCellArray(tmpResults.shiftedData);
tmpResults.backgrounds = correctCellArray(tmpResults.backgrounds);
tmpResults.resolutions = correctCellArray(tmpResults.resolutions );
tmpResults.sldProfiles = makeCellJson(tmpResults.sldProfiles);
tmpResults.layers = makeCellJson(tmpResults.layers);
tmpResults.resampledLayers = makeCellJson(tmpResults.resampledLayers);

for prop = {'dreamOutput', 'nestedSamplerOutput', 'confidenceIntervals'}
if isfield(tmpResults, prop{1})
for fn = fieldnames(tmpResults.(prop{1}))'
tmpResults.(prop{1}).(fn{1}) = correctRowArray(tmpResults.(prop{1}).(fn{1}));
end
end
end

if isfield(tmpResults,'predictionIntervals')
tmpResults.predictionIntervals.reflectivity = correctCellArray(tmpResults.predictionIntervals.reflectivity);
tmpResults.predictionIntervals.sld = makeCellJson(tmpResults.predictionIntervals.sld);
tmpResults.predictionIntervals.sampleChi = correctRowArray(tmpResults.predictionIntervals.sampleChi);
end

encoded = jsonencode(tmpResults,ConvertInfAndNaN=false);
encoded = strrep(encoded, ']"', ']');
encoded = strrep(encoded, '"[', '[');

[path,filename,~] = fileparts(filename);
fid = fullfile(path, append(filename, '.json'));
fid = fopen(fid,'w');
fprintf(fid,'%s',encoded);
fclose(fid);

end

function outputArray = makeCellJson(cellArray)
% The jsonencode function flattens 2d cell arrays this is a workaround to
% avoid flattening by converting to a string array with is not flattened.
[row, col] = size(cellArray, [1, 2]);
outputArray = strings([row, col]);
for i=1:row
for j=1:col
entry = cellArray{i, j};
if size(entry, 1) == 1
entry = {entry};
end
if col == 1
entry = {entry};
end
outputArray(i, j) = jsonencode(entry);
end
end
if row == 1
outputArray = {outputArray};
end

end

function array = correctRowArray(array)
% Corrects row array so its written as 2D array in json
if isa(array, "double") && size(array, 1) == 1 && size(array, 2) > 1
array = {array};
end
end

function cellArray = correctCellArray(cellArray)
% Corrects array with single row so its written as 2D array in json
[row, col] = size(cellArray, [1, 2]);
for i=1:row
for j=1:col
if size(cellArray{i, j}, 1) == 1
cellArray{i, j} = {cellArray{i, j}};
end
end
end
end
Loading