Skip to content

Commit 4b8f74b

Browse files
committed
Rename Fit variables consistently, cleanup
1 parent 7400308 commit 4b8f74b

File tree

11 files changed

+78
-83
lines changed

11 files changed

+78
-83
lines changed

appPy/cli/fit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
@click.command()
1818
@click.argument('compound1')
1919
@click.argument('compound2')
20-
@click.option('-m', '--model', help=f'Which model to fit, enter one of: {model_list}')
20+
@click.argument('model')
2121
@click.option('-d', '--datasets', help='Comma-separated exact dataset names, otherwise do all datasets of the system')
2222
@click.option('-p', '--params', help='Comma-separated initial parameters, will ignore params saved in file')
2323
@click.option('-c', '--consts', help='Comma-separated names of parameters to be kept constant')

appPy/src/fit/Fit.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,16 @@ def __init__(self, supported_models, model_name, params0, const_param_names=None
1515
const_param_names (list of str): names of parameter names to be kept constant during optimization.
1616
"""
1717
super().__init__()
18-
self.keys_to_serialize = [
19-
'is_optimized', 'nparams', 'nparams0', 'RMS_init', 'RMS_final', 'AAD_init', 'AAD_final'
20-
]
18+
self.keys_to_serialize = ['nparams0', 'RMS0', 'AAD0']
2119
self.supported_models = supported_models
22-
self.is_optimized = False # whether optimization has been performed
2320

2421
self.model = get_model_by_name(supported_models, model_name)
2522
self.params0, self.nparams0 = self.__parse_params0(params0) # initial params as np.array, and as dict
26-
self.params = self.params0 # optimization result params as np.array
27-
self.nparams = self.nparams0
2823

2924
self.const_param_names = self.__parse_const_param_names(const_param_names)
3025

31-
# initial and final objective function values
32-
self.RMS_init = None
33-
self.AAD_init = None
34-
self.RMS_final = None
35-
self.AAD_final = None
26+
# initial objective function values
27+
self.RMS0 = self.AAD0 = None
3628

3729
def set_named_params(self, params):
3830
"""Compose vector of ordered params into an ordered dict of named params."""
@@ -44,12 +36,12 @@ def __parse_params0(self, params0):
4436
params0: either ordered list of float, or named params as ordered key:value dict
4537
"""
4638
model = self.model
47-
if not params0: return model.params0, dict(zip(model.param_names, model.params0))
39+
if not params0: return model.params0, self.set_named_params(model.params0)
4840
if isinstance(params0, dict):
4941
nparams0 = params0
5042
params0 = [params0[key] for key in model.param_names]
5143
else:
52-
nparams0 = dict(zip(model.param_names, params0))
44+
nparams0 = self.set_named_params(params0)
5345
if len(params0) != model.n_params:
5446
raise AppException(f'{model.display_name} model expects {model.n_params} parameters, got {len(params0)}!')
5547
return params0, nparams0

appPy/src/fit/Fit_VLE.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __init__(self, compound1, compound2, model_name, datasets, params0, const_pa
2727
const_param_names (list of str): names of parameters to be kept constant during optimization.
2828
"""
2929
super().__init__(supported_models, model_name, params0, const_param_names)
30-
self.keys_to_serialize.extend(['tabulated_datasets'])
30+
self.keys_to_serialize.extend(['is_optimized', 'tabulated_datasets', 'nparams', 'RMS_final', 'AAD_final'])
3131
self.compound1 = compound1
3232
self.compound2 = compound2
3333

@@ -43,8 +43,13 @@ def __init__(self, compound1, compound2, model_name, datasets, params0, const_pa
4343
self.gamma_1 = squash(self.dataset_VLEs, 'gamma_1')
4444
self.gamma_2 = squash(self.dataset_VLEs, 'gamma_2')
4545

46-
self.RMS_init = RMS(self.get_residual(self.params0))
47-
self.AAD_init = AAD(self.get_residual(self.params0))
46+
self.params = self.params0 # optimization result params as np.array
47+
self.nparams = self.nparams0
48+
49+
self.is_optimized = False # whether optimization has been performed
50+
self.RMS_final = self.AAD_final = None
51+
self.RMS0 = RMS(self.get_residual(self.params0))
52+
self.AAD0 = AAD(self.get_residual(self.params0))
4853

4954
def __check_model_suitability(self):
5055
"""Check if the model is appropriate for given datasets."""
@@ -88,8 +93,8 @@ def report(self):
8893
echo(f' {name} = {value:.4g}')
8994

9095
echo('')
91-
echo(f'Initial RMS = {self.RMS_init:.3g}')
92-
echo(f'Initial AAD = {self.AAD_init:.3g}')
96+
echo(f'Initial RMS = {self.RMS0:.3g}')
97+
echo(f'Initial AAD = {self.AAD0:.3g}')
9398
if self.is_optimized:
9499
echo(f'Final RMS = {self.RMS_final:.3g}')
95100
echo(f'Final AAD = {self.AAD_final:.3g}')

appPy/src/fit/Fit_Vapor.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,28 @@ def __init__(self, compound, model_name, p_data, T_data, params0):
2020
p_data (list of float): vector of pressure data.
2121
T_data (list of float): vector of temperature data.
2222
params0 (list of float): initial estimate of model parameters (ordered).
23-
skip_T_p_optimization (bool): if True, only p residuals will be optimized.
2423
"""
2524
super().__init__(supported_models, model_name, params0)
26-
self.keys_to_serialize.extend(
27-
['is_T_p_optimized', 'odr_messages', 'RMS_inter', 'AAD_inter', 'nparams_inter', 'T_min', 'T_max'])
25+
self.keys_to_serialize.extend([
26+
'is_p_optimized', 'is_T_p_optimized', 'odr_messages', 'nparams_p', 'nparams_T_p', 'RMS_p', 'AAD_p',
27+
'RMS_T_p', 'AAD_T_p', 'T_min', 'T_max'
28+
])
2829
self.compound = compound
2930
self.p_data = np.array(p_data)
3031
self.T_data = np.array(T_data)
3132
# will be offered as model T_min & T_max
3233
self.T_min = np.min(T_data)
3334
self.T_max = np.max(T_data)
3435

35-
self.T_tab = self.p_tab_inter = self.p_tab_final = None
36-
self.nparams_inter = self.params_inter = None
37-
self.RMS_inter = self.AAD_inter = None
38-
self.is_T_p_optimized = False # in case of Fit_Vapor, Fit.is_optimized means is_p_optimized
36+
self.nparams_p = self.params_p = self.params_T_p = self.nparams_T_p = None
37+
self.RMS_p = self.AAD_p = self.RMS_T_p = self.AAD_T_p = None
38+
self.T_tab = self.p_tab_p = self.p_tab_T_p = None
39+
self.is_p_optimized = self.is_T_p_optimized = False
3940
self.odr_messages = [] # scipy.ODR has an unusual output format, as array of messages, but no status
4041

4142
# even for ODR, only p residuals are calculated for simplicity, so they may actually increase after ODR
42-
self.RMS_init = RMS(self.get_p_residuals(self.params0))
43-
self.AAD_init = AAD(self.get_p_residuals(self.params0))
43+
self.RMS0 = RMS(self.get_p_residuals(self.params0))
44+
self.AAD0 = AAD(self.get_p_residuals(self.params0))
4445

4546
def get_p_residuals(self, params):
4647
"""With given params, calculate residuals only of the dependent variable (p)."""
@@ -55,15 +56,15 @@ def optimize_p(self):
5556
if result.status <= 0:
5657
self.warn(f'p-optimization failed! Status {result.status}: {result.message}')
5758
return
58-
self.is_optimized = True
59-
self.params_inter = merge_params(result.x)
60-
self.nparams_inter = self.set_named_params(self.params_inter)
61-
self.RMS_inter = RMS(self.get_p_residuals(self.params_inter))
62-
self.AAD_inter = AAD(self.get_p_residuals(self.params_inter))
59+
self.is_p_optimized = True
60+
self.params_p = merge_params(result.x)
61+
self.nparams_p = self.set_named_params(self.params_p)
62+
self.RMS_p = RMS(self.get_p_residuals(self.params_p))
63+
self.AAD_p = AAD(self.get_p_residuals(self.params_p))
6364

6465
def optimize_T_p(self):
6566
"""Optimize the model params, considering errors of both dependent (p) & independent (T) variables."""
66-
full_params0 = self.params_inter if self.is_optimized else self.params # use intermediate params if available
67+
full_params0 = self.params_p if self.is_p_optimized else self.params0 # use intermediate params if available
6768
fun2wrap = lambda params, x: self.model.fun(x, *params) # swap the order of params and x
6869
var_params0, wrapped_fun, merge_params = const_param_wrappers(fun2wrap, full_params0, self.const_param_names,
6970
self.model.param_names)
@@ -76,19 +77,19 @@ def optimize_T_p(self):
7677
self.warn(f'T,p-optimization failed with error: {e}')
7778
return
7879
self.is_T_p_optimized = True
79-
self.params = merge_params(odr_result.beta)
80-
self.nparams = self.set_named_params(self.params)
81-
self.RMS_final = RMS(self.get_p_residuals(self.params))
82-
self.AAD_final = AAD(self.get_p_residuals(self.params))
80+
self.params_T_p = merge_params(odr_result.beta)
81+
self.nparams_T_p = self.set_named_params(self.params_T_p)
82+
self.RMS_T_p = RMS(self.get_p_residuals(self.params_T_p))
83+
self.AAD_T_p = AAD(self.get_p_residuals(self.params_T_p))
8384
self.odr_messages = odr_result.stopreason
8485
self.odr_messages = self.odr_messages if isinstance(self.odr_messages, list) else [self.odr_messages]
8586

8687
def tabulate(self):
8788
self.T_tab = np.linspace(self.T_min, self.T_max, cst.x_points_smooth_plot)
88-
if self.is_optimized:
89-
self.p_tab_inter = self.model.fun(self.T_tab, *self.params_inter)
89+
if self.is_p_optimized:
90+
self.p_tab_p = self.model.fun(self.T_tab, *self.params_p)
9091
if self.is_T_p_optimized:
91-
self.p_tab_final = self.model.fun(self.T_tab, *self.params)
92+
self.p_tab_T_p = self.model.fun(self.T_tab, *self.params_T_p)
9293

9394
def report(self):
9495
underline_echo(self.get_title())
@@ -98,14 +99,14 @@ def report(self):
9899
echo('')
99100

100101
echo('Optimized parameters as intermediate & final value:')
101-
for (name, p_inter, p_final) in zip(self.model.param_names, self.params_inter, self.params):
102-
echo(f' {name} = {p_inter:7.4g} {p_final:9.4g}')
102+
for (name, p_p, p_T_p) in zip(self.model.param_names, self.params_p, self.params_T_p):
103+
echo(f' {name} = {p_p:7.4g} {p_T_p:9.4g}')
103104

104105
echo('')
105-
echo(f'Initial RMS = {self.RMS_init:.3g}')
106-
echo(f'Initial AAD = {self.AAD_init:.3g}')
107-
echo(f'Final RMS = {self.RMS_final:.3g}')
108-
echo(f'Final AAD = {self.AAD_final:.3g}')
106+
echo(f'Initial RMS = {self.RMS0:.3g}')
107+
echo(f'Initial AAD = {self.AAD0:.3g}')
108+
echo(f'Final RMS = {self.RMS_T_p:.3g}')
109+
echo(f'Final AAD = {self.AAD_T_p:.3g}')
109110

110111
def get_title(self):
111112
return f'Regression of {self.model.display_name} on {self.compound}'

appPy/src/plot/Fit_Vapor_plot.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ def decorate(self):
2020

2121
def plot_p(self, mode):
2222
"""Overlay p-fitted model over vapor pressure data."""
23-
if not self.is_optimized: return None
23+
if not self.is_p_optimized: return None
2424
init_plot(mode)
2525
self.draw_data()
2626

2727
T_tab_disp = convert_T(self.T_tab)
28-
p_tab_inter_disp = convert_p(self.p_tab_inter)
29-
plt.plot(T_tab_disp, p_tab_inter_disp, '-k', label='p-fitted model')
28+
p_tab_p_disp = convert_p(self.p_tab_p)
29+
plt.plot(T_tab_disp, p_tab_p_disp, '-k', label='p-fitted model')
3030

3131
self.decorate()
3232
return finish_plot(mode)
@@ -38,8 +38,8 @@ def plot_T_p(self, mode):
3838
self.draw_data()
3939

4040
T_tab_disp = convert_T(self.T_tab)
41-
p_tab_final_disp = convert_p(self.p_tab_final)
42-
plt.plot(T_tab_disp, p_tab_final_disp, '-k', label='T,p-fitted model')
41+
p_tab_T_p_disp = convert_p(self.p_tab_T_p)
42+
plt.plot(T_tab_disp, p_tab_T_p_disp, '-k', label='T,p-fitted model')
4343

4444
self.decorate()
4545
return finish_plot(mode)

appUI/src/actions/FitVLE/FitVLEResultsDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const FitVLEResultsDialog: FC<FitResultsDialogProps> = ({ open, handleClo
5050
}, [data]);
5151

5252
const metricsSpreadsheetData = useMemo(() => {
53-
const rows = [[data.RMS_init, data.AAD_init]];
53+
const rows = [[data.RMS0, data.AAD0]];
5454
if (optimized) rows.push([data.RMS_final!, data.AAD_final!]);
5555
return makeReadOnly(spreadsheetToSigDgts(matrixToSpreadsheetData(rows), sigDgtsMetrics));
5656
}, [data]);

appUI/src/actions/FitVapor/FitVaporResultsDialog.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ export const FitVaporResultsDialog: FC<FitVaporResultsDialogProps> = ({
3434
}) => {
3535
const [infoOpen, setInfoOpen] = useState(false);
3636

37-
const optimizedP = data.is_optimized;
37+
const optimizedP = data.is_p_optimized;
3838
const optimizedTP = data.is_T_p_optimized;
3939
const paramNames = useMemo(() => fromNamedParams(data.nparams0)[0], [data]);
4040
const params0 = fromNamedParams(data.nparams0)[1];
41-
const paramsP = fromNamedParams(data.nparams_inter)[1];
42-
const paramsTP = fromNamedParams(data.nparams)[1];
41+
const paramsP = fromNamedParams(data.nparams_p)[1];
42+
const paramsTP = fromNamedParams(data.nparams_T_p)[1];
4343

4444
const rowLabels = useMemo(() => {
4545
const rows = ['initial'];
@@ -49,9 +49,9 @@ export const FitVaporResultsDialog: FC<FitVaporResultsDialogProps> = ({
4949
}, [data]);
5050

5151
const metricsSpreadsheetData = useMemo(() => {
52-
const rows = [[data.RMS_init, data.AAD_init]];
53-
if (optimizedP) rows.push([data.RMS_inter!, data.AAD_inter!]);
54-
if (optimizedTP) rows.push([data.RMS_final!, data.AAD_final!]);
52+
const rows = [[data.RMS0, data.AAD0]];
53+
if (optimizedP) rows.push([data.RMS_p!, data.AAD_p!]);
54+
if (optimizedTP) rows.push([data.RMS_T_p!, data.AAD_T_p!]);
5555
return makeReadOnly(spreadsheetToSigDgts(matrixToSpreadsheetData(rows), sigDgtsMetrics));
5656
}, [data]);
5757

appUI/src/adapters/api/types/fitTypes.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,17 @@ export type PlottedDataset = AnalysisResult & {
4444
gamma_plot: string;
4545
};
4646

47-
type FitMetrics = AnalysisResult & {
47+
export type FitAnalysisResponse = AnalysisResult & {
4848
is_optimized: boolean;
49-
RMS_init: number;
50-
RMS_final: number | null;
51-
AAD_init: number;
52-
AAD_final: number | null;
53-
};
49+
tabulated_datasets: PlottedDataset[];
5450

55-
export type FitAnalysisResponse = FitMetrics & {
5651
nparams0: NamedParams;
5752
nparams: NamedParams;
58-
tabulated_datasets: PlottedDataset[];
53+
54+
RMS0: number;
55+
RMS_final: number | null;
56+
AAD0: number;
57+
AAD_final: number | null;
5958
};
6059

6160
export type FitTabulateRequest = SystemIdentifier & { model_name: string; p: number };
@@ -77,7 +76,7 @@ export type VaporFitRequest = CompoundIdentifier & {
7776
};
7877

7978
export type VaporFitResponse = AnalysisResult & {
80-
is_optimized: boolean;
79+
is_p_optimized: boolean;
8180
is_T_p_optimized: boolean;
8281
odr_messages: string[];
8382
T_min: number;
@@ -86,13 +85,13 @@ export type VaporFitResponse = AnalysisResult & {
8685
plot_T_p?: string;
8786

8887
nparams0: NamedParams;
89-
nparams_inter?: NamedParams;
90-
nparams?: NamedParams;
88+
nparams_p?: NamedParams;
89+
nparams_T_p?: NamedParams;
9190

92-
RMS_init: number;
93-
RMS_inter: number | null;
94-
RMS_final: number | null;
95-
AAD_init: number;
96-
AAD_inter: number | null;
97-
AAD_final: number | null;
91+
RMS0: number;
92+
RMS_p: number | null;
93+
RMS_T_p: number | null;
94+
AAD0: number;
95+
AAD_p: number | null;
96+
AAD_T_p: number | null;
9897
};

dev/notes_VLizard.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/appPy.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ pipenv run cli\gamma CHF CHOL -d 25kPa --plot
5555
pipenv run cli\rk CHF CHOL -d 25kPa,40kPa --plot
5656
pipenv run cli\herington CHF CHOL -d 25kPa,40kPa
5757
pipenv run cli\fredenslund CHF CHOL -d 25kPa --ge --res
58-
pipenv run cli\fit CPF CPOL -m vanLaar -d 25kPa --txy --persist
58+
pipenv run cli\fit CPF CPOL vanLaar -d 25kPa --txy --persist
5959
pipenv run cli\tabulate CPOL CPF vanLaar 33 --txy
6060
pipenv run cli\vn CPOL CPF vanLaar -d 25kPa --plot
61-
pipenv run cli\fit CHOL CHF -d 10kPa,25kPa,40kPa --xy --txy --gamma -c c_12
62-
pipenv run cli\fit EtOH H2O -m UNIQUAC --skip -d Kamihama2012,Voutsas2011 --xy --gamma -p 1.972,1.4,2.10547,0.92,2.0046,-2.4936,-728.9705,756.9477
61+
pipenv run cli\fit CHOL CHF NRTL -d 10kPa,25kPa,40kPa --xy --txy --gamma -c c_12
62+
pipenv run cli\fit EtOH H2O UNIQUAC --skip -d Kamihama2012,Voutsas2011 --xy --gamma -p 1.972,1.4,2.10547,0.92,2.0046,-2.4936,-728.9705,756.9477
6363
```
6464
See [appPy/cli](../appPy/cli), where filenames correspond to commands;
6565
calling with `--help` will instruct you further.

http/fit.http

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Accept: application/json
77
POST http://localhost:37137/fit/vle
88
Content-Type: application/json
99

10-
{"compound1": "EtOH", "compound2": "H2O", "model_name": "vanLaar", "datasets": ["1939vac"],
10+
{"compound1": "EtOH", "compound2": "H2O", "model_name": "vanLaar", "datasets": ["Voutsas2011"],
1111
"skip_optimization": false, "nparams0": {"A_12": 0.4, "A_21": 0.1}}
1212

1313
###
@@ -35,8 +35,7 @@ Content-Type: application/json
3535
"model_name": "Wagner",
3636
"p_data": [9.98, 11.52, 14.39, 25.01, 25.95, 39.91, 40.05, 52.5, 60.41, 78.21, 89.63, 100.05],
3737
"T_data": [363.95, 367.65, 373.55, 389.25, 390.25, 403.35, 403.55, 412.45, 417.15, 426.25, 431.25, 435.35],
38-
"nparams0": {"A": -7.898313, "B": 1.997515, "C": -2.448405, "D": -1.880206, "T_c": 647, "p_c": 22071},
39-
"skip_T_p_optimization": false
38+
"nparams0": {"A": -7.898313, "B": 1.997515, "C": -2.448405, "D": -1.880206, "T_c": 647, "p_c": 22071}
4039
}
4140

4241
###

0 commit comments

Comments
 (0)