add result button making plot
This commit is contained in:
@@ -4,6 +4,7 @@ classdef EDFMAppController < handle
|
||||
Config struct = struct()
|
||||
Results struct = struct()
|
||||
ProjectRoot char
|
||||
CurrentPlotAction string = ""
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -48,6 +49,9 @@ classdef EDFMAppController < handle
|
||||
obj.Config = load_case_template(caseId);
|
||||
obj.refreshUIFromConfig();
|
||||
obj.refreshResults();
|
||||
if strlength(obj.CurrentPlotAction) ~= 0
|
||||
obj.refreshCasePlotControls(obj.CurrentPlotAction);
|
||||
end
|
||||
obj.appendLog(sprintf('Loaded template: %s', string(caseId)));
|
||||
obj.setStatus(sprintf('Template %s loaded', string(caseId)));
|
||||
end
|
||||
@@ -95,6 +99,9 @@ classdef EDFMAppController < handle
|
||||
obj.appendLog(logText);
|
||||
end
|
||||
obj.refreshResults();
|
||||
if strlength(obj.CurrentPlotAction) ~= 0
|
||||
obj.refreshCasePlotControls(obj.CurrentPlotAction);
|
||||
end
|
||||
obj.setRunProgress('Completed');
|
||||
obj.setStatus('Run completed');
|
||||
catch ME
|
||||
@@ -117,6 +124,9 @@ classdef EDFMAppController < handle
|
||||
end
|
||||
obj.Results = load_results_mat(fullfile(folder, fileName));
|
||||
obj.refreshResults();
|
||||
if strlength(obj.CurrentPlotAction) ~= 0
|
||||
obj.refreshCasePlotControls(obj.CurrentPlotAction);
|
||||
end
|
||||
obj.appendLog(sprintf('Imported results: %s', fullfile(folder, fileName)));
|
||||
obj.setStatus('Results imported');
|
||||
end
|
||||
@@ -135,6 +145,63 @@ classdef EDFMAppController < handle
|
||||
obj.setStatus('Results exported');
|
||||
end
|
||||
|
||||
function actions = getCasePlotActions(obj)
|
||||
obj.pushUIToConfig();
|
||||
actions = get_case_plot_actions(obj.Config);
|
||||
end
|
||||
|
||||
function activateCasePlot(obj, actionId)
|
||||
obj.pushUIToConfig();
|
||||
obj.CurrentPlotAction = string(actionId);
|
||||
obj.refreshCasePlotControls(actionId);
|
||||
if ~isempty(fieldnames(obj.Results))
|
||||
obj.runCasePlot(actionId);
|
||||
end
|
||||
end
|
||||
|
||||
function onPlotOptionChanged(obj)
|
||||
if strlength(obj.CurrentPlotAction) == 0
|
||||
return;
|
||||
end
|
||||
if ~isempty(fieldnames(obj.Results))
|
||||
obj.runCasePlot(obj.CurrentPlotAction);
|
||||
end
|
||||
end
|
||||
|
||||
function refreshCasePlotControls(obj, actionId)
|
||||
obj.pushUIToConfig();
|
||||
obj.configurePlotControls(actionId);
|
||||
end
|
||||
|
||||
function runCasePlot(obj, actionId)
|
||||
if isempty(fieldnames(obj.Results))
|
||||
uialert(obj.App.UIFigure, 'Run or import results before plotting.', 'Plot');
|
||||
return;
|
||||
end
|
||||
|
||||
obj.pushUIToConfig();
|
||||
try
|
||||
obj.CurrentPlotAction = string(actionId);
|
||||
obj.configurePlotControls(actionId);
|
||||
if isprop(obj.App, 'ResultAxes') && ~isempty(obj.App.ResultAxes)
|
||||
options = obj.getCurrentPlotOptions(actionId);
|
||||
render_case_plot_in_axes(obj.App.ResultAxes, obj.Config, obj.Results, actionId, options);
|
||||
else
|
||||
run_case_plot(obj.Config, obj.Results, actionId);
|
||||
end
|
||||
obj.appendLog(sprintf('Executed plot action: %s', string(actionId)));
|
||||
obj.setStatus(sprintf('Plot: %s', string(actionId)));
|
||||
catch ME
|
||||
errorReport = getReport(ME, 'extended', 'hyperlinks', 'off');
|
||||
errorSummary = obj.formatExceptionSummary(ME);
|
||||
obj.publishExceptionToBase(ME, errorReport);
|
||||
fprintf(2, '\n[EDFM GUI Plot Error]\n%s\n', errorReport);
|
||||
obj.appendLog(errorSummary);
|
||||
obj.appendLog(errorReport);
|
||||
uialert(obj.App.UIFigure, errorSummary, 'Plot Failed', 'Interpreter', 'none');
|
||||
end
|
||||
end
|
||||
|
||||
function plotResults(obj)
|
||||
if isempty(fieldnames(obj.Results))
|
||||
obj.refreshResults();
|
||||
@@ -596,6 +663,51 @@ classdef EDFMAppController < handle
|
||||
end
|
||||
end
|
||||
|
||||
function configurePlotControls(obj, actionId)
|
||||
actionId = lower(string(actionId));
|
||||
|
||||
layerItems = obj.buildLayerItems();
|
||||
wellItems = obj.buildWellItems();
|
||||
metricItems = obj.buildMetricItems();
|
||||
propertyItems = obj.buildPropertyItems(actionId);
|
||||
[stepMin, stepMax, stepValue] = obj.buildTimeStepRange(actionId);
|
||||
|
||||
obj.setControlVisible('PlotLayerDropDown', ismember(actionId, ["plot_2d_layer", "plot_sp_dp", "plot_perm"]));
|
||||
obj.setControlVisible('PlotLayerDropDownLabel', ismember(actionId, ["plot_2d_layer", "plot_sp_dp", "plot_perm"]));
|
||||
obj.setControlVisible('PlotTimeStepSlider', ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]));
|
||||
obj.setControlVisible('PlotTimeStepSliderLabel', ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]));
|
||||
obj.setControlVisible('PlotTimeStepValueLabel', ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]));
|
||||
obj.setControlVisible('PlotPropertyDropDown', ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]));
|
||||
obj.setControlVisible('PlotPropertyDropDownLabel', ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]));
|
||||
obj.setControlVisible('PlotWellDropDown', actionId == "plot_well_response");
|
||||
obj.setControlVisible('PlotWellDropDownLabel', actionId == "plot_well_response");
|
||||
obj.setControlVisible('PlotMetricDropDown', actionId == "plot_well_response");
|
||||
obj.setControlVisible('PlotMetricDropDownLabel', actionId == "plot_well_response");
|
||||
|
||||
obj.setDropDownItems('PlotLayerDropDown', layerItems, layerItems{1});
|
||||
obj.setDropDownItems('PlotWellDropDown', wellItems, wellItems{1});
|
||||
obj.setDropDownItems('PlotMetricDropDown', metricItems, metricItems{1});
|
||||
obj.setDropDownItems('PlotPropertyDropDown', propertyItems, propertyItems{1});
|
||||
obj.configureTimeStepControl(stepMin, stepMax, stepValue);
|
||||
end
|
||||
|
||||
function options = getCurrentPlotOptions(obj, actionId)
|
||||
options = struct();
|
||||
actionId = lower(string(actionId));
|
||||
|
||||
if ismember(actionId, ["plot_2d_layer", "plot_sp_dp", "plot_perm"])
|
||||
options.layer_index = obj.getNumericDropDownValue('PlotLayerDropDown', 1);
|
||||
end
|
||||
if ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"])
|
||||
options.time_step = obj.getTimeStepControlValue();
|
||||
options.property_id = obj.getDropDownValue('PlotPropertyDropDown', 'pressure');
|
||||
end
|
||||
if actionId == "plot_well_response"
|
||||
options.well_index = obj.getNumericDropDownValue('PlotWellDropDown', 1);
|
||||
options.metric = obj.getDropDownValue('PlotMetricDropDown', 'BHP');
|
||||
end
|
||||
end
|
||||
|
||||
function setDropDownValue(obj, propName, value)
|
||||
if ~isprop(obj.App, propName)
|
||||
return;
|
||||
@@ -629,6 +741,30 @@ classdef EDFMAppController < handle
|
||||
end
|
||||
end
|
||||
|
||||
function configureTimeStepControl(obj, minValue, maxValue, currentValue)
|
||||
if isprop(obj.App, 'PlotTimeStepSlider')
|
||||
slider = obj.App.PlotTimeStepSlider;
|
||||
slider.Limits = [minValue, maxValue];
|
||||
slider.MajorTicks = minValue:maxValue;
|
||||
slider.MinorTicks = [];
|
||||
slider.Value = currentValue;
|
||||
end
|
||||
if isprop(obj.App, 'PlotTimeStepValueLabel')
|
||||
obj.App.PlotTimeStepValueLabel.Text = sprintf('Step: %d', currentValue);
|
||||
end
|
||||
end
|
||||
|
||||
function value = getTimeStepControlValue(obj)
|
||||
value = 1;
|
||||
if isprop(obj.App, 'PlotTimeStepSlider')
|
||||
value = max(1, round(obj.App.PlotTimeStepSlider.Value));
|
||||
obj.App.PlotTimeStepSlider.Value = value;
|
||||
end
|
||||
if isprop(obj.App, 'PlotTimeStepValueLabel')
|
||||
obj.App.PlotTimeStepValueLabel.Text = sprintf('Step: %d', value);
|
||||
end
|
||||
end
|
||||
|
||||
function setNumericFieldValue(obj, propName, value)
|
||||
if ~isprop(obj.App, propName)
|
||||
return;
|
||||
@@ -738,6 +874,99 @@ classdef EDFMAppController < handle
|
||||
end
|
||||
end
|
||||
|
||||
function setControlVisible(obj, propName, isVisible)
|
||||
if ~isprop(obj.App, propName)
|
||||
return;
|
||||
end
|
||||
component = obj.App.(propName);
|
||||
if isprop(component, 'Visible')
|
||||
if isVisible
|
||||
component.Visible = 'on';
|
||||
else
|
||||
component.Visible = 'off';
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function items = buildLayerItems(obj)
|
||||
layerCount = 1;
|
||||
if isfield(obj.Config, 'grid') && isfield(obj.Config.grid, 'dz') && ~isempty(obj.Config.grid.dz)
|
||||
layerCount = numel(obj.Config.grid.dz);
|
||||
elseif ~isempty(fieldnames(obj.Results)) && isfield(obj.Results, 'r') && isfield(obj.Results.r, 'nz')
|
||||
layerCount = obj.Results.r.nz;
|
||||
end
|
||||
items = cellstr(string(1:layerCount));
|
||||
end
|
||||
|
||||
function items = buildWellItems(obj)
|
||||
wellCount = 1;
|
||||
if ~isempty(fieldnames(obj.Results)) && isfield(obj.Results, 'Wellpara') && ~isempty(obj.Results.Wellpara)
|
||||
wellCount = size(obj.Results.Wellpara{1}, 2);
|
||||
else
|
||||
wellCount = size(obj.Config.wells.well1, 1) + size(obj.Config.wells.well2, 1);
|
||||
wellCount = max(wellCount, 1);
|
||||
end
|
||||
items = cellstr(string(1:wellCount));
|
||||
end
|
||||
|
||||
function items = buildMetricItems(obj)
|
||||
metricList = ["BHP", "dPWF"];
|
||||
if ~isempty(fieldnames(obj.Results)) && isfield(obj.Results, 'Wellpara') && ~isempty(obj.Results.Wellpara)
|
||||
sampleWell = obj.Results.Wellpara{1}{1, 1};
|
||||
metricList = "BHP";
|
||||
if isfield(sampleWell, 'qg')
|
||||
metricList(end + 1) = "GPR"; %#ok<AGROW>
|
||||
end
|
||||
if isfield(sampleWell, 'qo')
|
||||
metricList(end + 1) = "OPR"; %#ok<AGROW>
|
||||
end
|
||||
if isfield(sampleWell, 'qw')
|
||||
metricList(end + 1) = "WPR"; %#ok<AGROW>
|
||||
end
|
||||
if isfield(sampleWell, 'pwf')
|
||||
metricList(end + 1) = "dPWF"; %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
items = cellstr(unique(metricList, 'stable'));
|
||||
end
|
||||
|
||||
function items = buildPropertyItems(obj, actionId)
|
||||
if ~isfield(obj.Results, 'OutputRs') || isempty(obj.Results.OutputRs)
|
||||
items = {'pressure', 'water_saturation'};
|
||||
return;
|
||||
end
|
||||
output = obj.Results.OutputRs{end};
|
||||
propertyList = "pressure";
|
||||
if isfield(output, 'sw')
|
||||
propertyList(end + 1) = "water_saturation"; %#ok<AGROW>
|
||||
if obj.Config.model.flow_model == 2
|
||||
propertyList(end + 1) = "oil_saturation"; %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
if isfield(output, 'sg')
|
||||
propertyList(end + 1) = "gas_saturation"; %#ok<AGROW>
|
||||
elseif obj.Config.model.flow_model == 1 && isfield(output, 'sw')
|
||||
propertyList(end + 1) = "gas_saturation"; %#ok<AGROW>
|
||||
end
|
||||
|
||||
if ~ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"])
|
||||
items = {'pressure'};
|
||||
else
|
||||
items = cellstr(unique(propertyList, 'stable'));
|
||||
end
|
||||
end
|
||||
|
||||
function [minValue, maxValue, currentValue] = buildTimeStepRange(obj, actionId)
|
||||
minValue = 1;
|
||||
maxValue = 1;
|
||||
currentValue = 1;
|
||||
if ismember(actionId, ["plot_2d_layer", "plot_3d_distribution"]) ...
|
||||
&& isfield(obj.Results, 'OutputRs') && ~isempty(obj.Results.OutputRs)
|
||||
maxValue = numel(obj.Results.OutputRs);
|
||||
currentValue = maxValue;
|
||||
end
|
||||
end
|
||||
|
||||
function textValue = formatExceptionSummary(~, ME)
|
||||
lines = {
|
||||
sprintf('Error: %s', ME.message)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user