From c95c85401e894f59313bddb8034c6a6df02c57ea Mon Sep 17 00:00:00 2001 From: Stephen Nneji Date: Wed, 13 May 2026 15:41:18 +0100 Subject: [PATCH 1/2] Check fitted parameter range and remove if too small --- API/checkRange.m | 36 ++++++++++++++++++++++++++++++++++++ API/parseClassToStructs.m | 3 +++ API/parseOutToProjectClass.m | 14 +++++++------- 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 API/checkRange.m diff --git a/API/checkRange.m b/API/checkRange.m new file mode 100644 index 000000000..5ffce380f --- /dev/null +++ b/API/checkRange.m @@ -0,0 +1,36 @@ +function problemStruct = checkRange(problemStruct, limits) + % Check the range of fitted parameters, remove parameter from fit if range is too small. + % + % Parameters + % ---------- + % problemStruct : struct + % The project struct. + % limits : struct + % The limits for each parameter. + % + % Returns + % ------- + % problemStruct : struct + % The project struct with fit information. + fields = {"params", "backgroundParams", "scalefactors", "bulkIns",... + "bulkOuts", "resolutionParams", "domainRatios"}; + titles = {"Parameter", "Background parameter", "Scalefactor", "Bulk in",... + "Bulk out", "Resolution parameter", "Domain ratio"}; + + for i = 1:length(fields) + fitIndices = find(problemStruct.checks.(fields{i})); + + for j = 1:length(fitIndices) + lower = limits.(fields{i})(fitIndices(j),1); + upper = limits.(fields{i})(fitIndices(j),2); + + if (upper - lower) < 1e-10 + paramName = problemStruct.names.(fields{i}){fitIndices(j)}; + warning('%s "%s" was removed from the fit because its range is too small (< 1e-10).', titles{i}, paramName); + problemStruct.checks.(fields{i})(fitIndices(j)) = 0; + end + end + end + +end + diff --git a/API/parseClassToStructs.m b/API/parseClassToStructs.m index 553571b1e..ff58997d2 100644 --- a/API/parseClassToStructs.m +++ b/API/parseClassToStructs.m @@ -290,6 +290,9 @@ problemStruct.checks.domainRatios = ones(1,0); end +if ~strcmpi(inputControls.procedure, procedures.Calculate.value) + problemStruct = checkRange(problemStruct, limits); +end % Make sure the indices cannot lie outside of the arrays checkIndices(problemStruct, inputStruct.files); diff --git a/API/parseOutToProjectClass.m b/API/parseOutToProjectClass.m index 6b157a409..3e6f80b0c 100644 --- a/API/parseOutToProjectClass.m +++ b/API/parseOutToProjectClass.m @@ -6,43 +6,43 @@ %(1) Parameters params = problemStruct.params; for i = 1:length(params) - project.setParameter(i, 'value', params(i)); + project.setParameter(i, 'value', params(i), 'fit', logical(problemStruct.checks.params(i))); end %(2) Backgrounds backgroundParams = problemStruct.backgroundParams; for i = 1:length(backgroundParams) - project.setBackgroundParam(i, 'value', backgroundParams(i)); + project.setBackgroundParam(i, 'value', backgroundParams(i), 'fit', logical(problemStruct.checks.backgroundParams(i))); end %(3) Scalefactors scalefactors = problemStruct.scalefactors; for i = 1:length(scalefactors) - project.setScalefactor(i,'value',scalefactors(i)); + project.setScalefactor(i,'value',scalefactors(i), 'fit', logical(problemStruct.checks.scalefactors(i))); end %(4) Bulk In bulkIns = problemStruct.bulkIns; for i = 1:length(bulkIns) - project.setBulkIn(i,'value',bulkIns(i)); + project.setBulkIn(i,'value',bulkIns(i), 'fit', logical(problemStruct.checks.bulkIns(i))); end %(5) Bulk Out bulkOuts = problemStruct.bulkOuts; for i = 1:length(bulkOuts) - project.setBulkOut(i,'value',bulkOuts(i)); + project.setBulkOut(i,'value',bulkOuts(i), 'fit', logical(problemStruct.checks.bulkOuts(i))); end %(6) Resolutions resolutionParams = problemStruct.resolutionParams; for i = 1:length(resolutionParams) - project.setResolutionParam(i,'value',resolutionParams(i)); + project.setResolutionParam(i,'value',resolutionParams(i), 'fit', logical(problemStruct.checks.resolutionParams(i))); end % (7) Domain ratio if strcmpi(problemStruct.TF, calculationTypes.Domains.value) domainRatios = problemStruct.domainRatios; for i = 1:length(domainRatios) - project.setDomainRatio(i,'value',domainRatios(i)); + project.setDomainRatio(i,'value',domainRatios(i), 'fit', logical(problemStruct.checks.domainRatios(i))); end end From 60cdb0e292308d6169a86f8c13193ab91bf4b2b5 Mon Sep 17 00:00:00 2001 From: Stephen Nneji Date: Tue, 4 Aug 2026 15:57:01 +0100 Subject: [PATCH 2/2] Changed range heuristics --- API/checkRange.m | 10 +++++++--- .../standardLayers/standardLayersDSPCScript.m | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/API/checkRange.m b/API/checkRange.m index 5ffce380f..ecdd8b4f0 100644 --- a/API/checkRange.m +++ b/API/checkRange.m @@ -23,10 +23,14 @@ for j = 1:length(fitIndices) lower = limits.(fields{i})(fitIndices(j),1); upper = limits.(fields{i})(fitIndices(j),2); - - if (upper - lower) < 1e-10 + minRange = abs(problemStruct.(fields{i})(fitIndices(j))) * 1e-6; + if minRange == 0 + minRange = 1e-6; + end + + if (upper - lower) < minRange paramName = problemStruct.names.(fields{i}){fitIndices(j)}; - warning('%s "%s" was removed from the fit because its range is too small (< 1e-10).', titles{i}, paramName); + warning('%s "%s" was removed from the fit because its range is too small (< %g).', titles{i}, paramName, minRange); problemStruct.checks.(fields{i})(fitIndices(j)) = 0; end end diff --git a/examples/normalReflectivity/standardLayers/standardLayersDSPCScript.m b/examples/normalReflectivity/standardLayers/standardLayersDSPCScript.m index 7a660f9d8..4cb0880e6 100644 --- a/examples/normalReflectivity/standardLayers/standardLayersDSPCScript.m +++ b/examples/normalReflectivity/standardLayers/standardLayersDSPCScript.m @@ -15,7 +15,7 @@ {'Sam tails hydration', 1, 5.253, 50, true, 'uniform', 0, Inf}; {'Sam rough', 1, 5.64, 15, true, 'uniform', 0, Inf}; {'cw thick', 10, 17.12, 28, true, 'uniform', 0, Inf}; - {'cw SLD', 0, 0, 1e-09, false, 'uniform', 0, Inf}; + {'cw SLD', 0, 0, 0, false, 'uniform', 0, Inf}; {'SAM head thick', 5, 8.56, 17, true, 'gaussian', 10, 2}; {'SAM head SLD', 1e-07, 1.75e-06, 2e-06, false, 'uniform', 0, Inf}; {'SAM head hydration', 10, 45.45, 50, true, 'uniform', 0, Inf};