-
Notifications
You must be signed in to change notification settings - Fork 1
/
fit_flow_density_with_GZ1961B_GaussSigCon.R
366 lines (344 loc) · 22.6 KB
/
fit_flow_density_with_GZ1961B_GaussSigCon.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
fit_flow_density_with_GZ1961B_GaussSigCon = function(traffic_data, ngrid, upper_density, output_files) {
# Description: This function fits a GAMLSS model to the flow-density values in "traffic_data", and it is designed to be called directly from the R
# script "FitFun.R". The model component for the functional form of the flow-density relationship is the Gazis model B (GZ1961B). The
# model component for the noise in the flow-density relationship is defined as independent observations that follow a Gaussian
# distribution with constant variance (GaussSigCon).
# The input parameters "ngrid" and "upper_density" are used to define an equally spaced grid of "ngrid" density values ranging from
# zero to "upper_density". The function employs this density grid to reconstruct the fitted model at the grid points for use in plots
# and for estimating certain properties of the fitted model that are not directly accessible from the fitted parameter values.
# The function creates various output files "output_files" including diagnostic plots (see "FitFun.R" for details). If the function
# finishes successfully, then it returns the corresponding GAMLSS model fit object.
#
# Authors:
#
# Dan Bramich (dan.bramich@hotmail.co.uk)
# Lukas Ambuhl (lukas.ambuehl@ivt.baug.ethz.ch)
#
# Configuration Parameters:
#
# NONE
# Define some useful variables
functional_form_model = 'GZ1961B'
noise_model = 'GaussSigCon'
# Report on the GAMLSS model and the data
cat('\n')
cat('>-----------------------------------------------------------------------------<\n')
cat('\n')
cat('The following GAMLSS model will be fit to the flow-density data:\n')
cat('\n')
cat('Model component for the functional form:\n')
cat(' Gazis\n')
cat(' Model B (GZ1961B)\n')
cat('\n')
cat('Model component for the noise:\n')
cat(' Independent observations\n')
cat(' Gaussian distribution\n')
cat(' Constant variance (GaussSigCon)\n')
cat('\n')
cat('Data properties:\n')
tryCatch(
{ ntraffic_data = nrow(traffic_data)
data_range_density = range(traffic_data$V2)
data_min_density = data_range_density[1]
data_max_density = data_range_density[2]
data_range_flow = range(traffic_data$V3)
data_min_flow = data_range_flow[1]
data_max_flow = data_range_flow[2] },
error = function(cond) { cat('ERROR - Failed to determine the data properties...\n')
q(save = 'no', status = 1) }
)
cat(' No. of flow-density measurement pairs (Ndat):', ntraffic_data, '\n')
cat(' Minimum density in the data: ', sprintf('%.8g', data_min_density), '\n')
cat(' Maximum density in the data: ', sprintf('%.8g', data_max_density), '\n')
cat(' Minimum flow in the data: ', sprintf('%.8g', data_min_flow), '\n')
cat(' Maximum flow in the data: ', sprintf('%.8g', data_max_flow), '\n')
cat('\n')
cat('Model reconstruction:\n')
tryCatch(
{ grid_density_step = upper_density/(ngrid - 1) },
error = function(cond) { cat('ERROR - Failed to compute the grid density step...\n')
q(save = 'no', status = 1) }
)
cat(' No. of density grid points:', ngrid, '\n')
cat(' Grid lower density: 0\n')
cat(' Grid upper density: ', sprintf('%.8g', upper_density), '\n')
cat(' Grid density step: ', sprintf('%.8g', grid_density_step), '\n')
# Fit the GAMLSS model to the data
cat('\n')
cat('Fitting the GAMLSS model...\n')
tryCatch(
{ model_obj = gamlss(V3 ~ 0 + V2 + I(V2^1.5), sigma.formula = ~ 1, family = NO(), data = traffic_data)
if (model_obj$converged != TRUE) {
cat('ERROR - The fit did not converge...\n')
q(save = 'no', status = 1)
} },
error = function(cond) { cat('ERROR - Failed to fit the GAMLSS model...\n')
q(save = 'no', status = 1) }
)
# Store the predicted values for the fitted model at the density values in the data in the data table
cat('\n')
cat('Storing the predicted values for the fitted model in the data table...\n')
tryCatch(
{ if (!all(is.finite(model_obj$mu.fv))) {
cat('ERROR - The predicted values for "mu" at the density values in the data include at least one value that is infinite...\n')
q(save = 'no', status = 1)
}
if (!all(is.finite(model_obj$sigma.fv))) {
cat('ERROR - The predicted values for "sigma" at the density values in the data include at least one value that is infinite...\n')
q(save = 'no', status = 1)
}
if (any(model_obj$sigma.fv <= 0.0)) {
cat('ERROR - The predicted values for "sigma" at the density values in the data include at least one value that is zero or negative...\n')
q(save = 'no', status = 1)
}
traffic_data[, fitted_values_mu := model_obj$mu.fv]
traffic_data[, fitted_values_sigma := model_obj$sigma.fv]
traffic_data[, fitted_values_nu := double(length = ntraffic_data)]
traffic_data[, fitted_values_tau := double(length = ntraffic_data)] },
error = function(cond) { cat('ERROR - Failed to store the predicted values for the fitted model...\n')
q(save = 'no', status = 1) }
)
# Compute the normalised quantile residuals and store them in the data table. Note that the normalised quantile residuals may include some "-Inf"
# or "Inf" values for particularly bad outliers.
cat('Computing the normalised quantile residuals...\n')
tryCatch(
{ cumulative_probs_lower = pNO(traffic_data$V3, mu = model_obj$mu.fv, sigma = model_obj$sigma.fv)
cumulative_probs_upper = pNO(traffic_data$V3, mu = model_obj$mu.fv, sigma = model_obj$sigma.fv, lower.tail = FALSE)
traffic_data[, normalised_quantile_residuals := calculate_normalised_quantile_residuals(cumulative_probs_lower, cumulative_probs_upper)] },
error = function(cond) { cat('ERROR - Failed to compute the normalised quantile residuals...\n')
q(save = 'no', status = 1) }
)
# Compute the percentiles for the fitted model at the density values in the data and store them in the data table
cat('Computing the percentiles for the fitted model at the density values in the data...\n')
tryCatch(
{ traffic_data[, percentile_m3sig := qNO(pNO(-3.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_m2sig := qNO(pNO(-2.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_m1sig := qNO(pNO(-1.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_0sig := qNO(0.5, mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_p1sig := qNO(pNO(1.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_p2sig := qNO(pNO(2.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)]
traffic_data[, percentile_p3sig := qNO(pNO(3.0), mu = traffic_data$fitted_values_mu, sigma = traffic_data$fitted_values_sigma)] },
error = function(cond) { cat('ERROR - Failed to compute the percentiles for the fitted model at the density values in the data...\n')
q(save = 'no', status = 1) }
)
# Compute a set of distributional measures for the fitted model at the density values in the data and store them in the data table
cat('Computing a set of distributional measures for the fitted model at the density values in the data...\n')
tryCatch(
{ traffic_data[, mean := traffic_data$fitted_values_mu]
traffic_data[, median := traffic_data$fitted_values_mu]
traffic_data[, mode := traffic_data$fitted_values_mu]
traffic_data[, standard_deviation := traffic_data$fitted_values_sigma]
traffic_data[, moment_skewness := traffic_data$fitted_values_nu]
traffic_data[, moment_excess_kurtosis := traffic_data$fitted_values_tau] },
error = function(cond) { cat('ERROR - Failed to compute a set of distributional measures for the fitted model at the density values in the data...\n')
q(save = 'no', status = 1) }
)
# Reconstruct the fitted model over the density range from zero to "upper_density"
cat('Reconstructing the fitted model over the density range from 0 to', sprintf('%.8g', upper_density), '...\n')
tryCatch(
{ reconstructed_model_fit = data.table(V2 = seq(from = 0.0, to = upper_density, length.out = ngrid))
predicted_values = predictAll(model_obj, newdata = reconstructed_model_fit, type = 'response', data = traffic_data)
if (!all(is.finite(predicted_values$mu))) {
cat('ERROR - The reconstructed fitted model for "mu" includes at least one value that is infinite...\n')
q(save = 'no', status = 1)
}
if (!all(is.finite(predicted_values$sigma))) {
cat('ERROR - The reconstructed fitted model for "sigma" includes at least one value that is infinite...\n')
q(save = 'no', status = 1)
}
if (any(predicted_values$sigma <= 0.0)) {
cat('ERROR - The reconstructed fitted model for "sigma" includes at least one value that is zero or negative...\n')
q(save = 'no', status = 1)
}
reconstructed_model_fit[, mu := predicted_values$mu]
reconstructed_model_fit[, sigma := predicted_values$sigma]
reconstructed_model_fit[, nu := double(length = ngrid)]
reconstructed_model_fit[, tau := double(length = ngrid)] },
error = function(cond) { cat('ERROR - Failed to reconstruct the fitted model over the required density range...\n')
q(save = 'no', status = 1) }
)
# Construct percentile curves for the fitted model over the density range from zero to "upper_density"
cat('Constructing percentile curves for the fitted model over the density range from 0 to', sprintf('%.8g', upper_density), '...\n')
tryCatch(
{ reconstructed_model_fit[, percentile_m3sig := qNO(pNO(-3.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_m2sig := qNO(pNO(-2.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_m1sig := qNO(pNO(-1.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_0sig := qNO(0.5, mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_p1sig := qNO(pNO(1.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_p2sig := qNO(pNO(2.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)]
reconstructed_model_fit[, percentile_p3sig := qNO(pNO(3.0), mu = reconstructed_model_fit$mu, sigma = reconstructed_model_fit$sigma)] },
error = function(cond) { cat('ERROR - Failed to construct percentile curves for the fitted model over the required density range...\n')
q(save = 'no', status = 1) }
)
# Construct curves of a set of distributional measures for the fitted model over the density range from zero to "upper_density"
cat('Constructing curves of a set of distributional measures for the fitted model over the density range from 0 to', sprintf('%.8g', upper_density), '...\n')
tryCatch(
{ reconstructed_model_fit[, mean := reconstructed_model_fit$mu]
reconstructed_model_fit[, median := reconstructed_model_fit$mu]
reconstructed_model_fit[, mode := reconstructed_model_fit$mu]
reconstructed_model_fit[, standard_deviation := reconstructed_model_fit$sigma]
reconstructed_model_fit[, moment_skewness := reconstructed_model_fit$nu]
reconstructed_model_fit[, moment_excess_kurtosis := reconstructed_model_fit$tau] },
error = function(cond) { cat('ERROR - Failed to construct curves of a set of distributional measures for the fitted model over the required density range...\n')
q(save = 'no', status = 1) }
)
# Estimate useful properties of the fitted model over the density range from zero to the maximum observed density using the reconstruction
cat('Estimating useful properties of the fitted model using the reconstruction...\n')
tryCatch(
{ selection = reconstructed_model_fit$V2 < (data_max_density + grid_density_step)
reconstructed_model_fit_selection = reconstructed_model_fit[selection]
curve_properties_for_mu_over_data_range = get_curve_properties_for_mu(reconstructed_model_fit_selection, 'Flow.Density')
curve_properties_for_sigma_over_data_range = get_curve_properties_for_sigma(reconstructed_model_fit_selection, curve_properties_for_mu_over_data_range)
curve_properties_for_nu_over_data_range = get_curve_properties_for_nu(reconstructed_model_fit_selection, curve_properties_for_mu_over_data_range)
curve_properties_for_tau_over_data_range = get_curve_properties_for_tau(reconstructed_model_fit_selection, curve_properties_for_mu_over_data_range) },
error = function(cond) { cat('ERROR - Failed to estimate useful properties of the fitted model over the density range from zero to the maximum observed density...\n')
q(save = 'no', status = 1) }
)
# Estimate useful properties of the fitted model over the density range from zero to "upper_density" using the reconstruction
tryCatch(
{ curve_properties_for_mu_over_full_range = get_curve_properties_for_mu(reconstructed_model_fit, 'Flow.Density')
curve_properties_for_sigma_over_full_range = get_curve_properties_for_sigma(reconstructed_model_fit, curve_properties_for_mu_over_full_range)
curve_properties_for_nu_over_full_range = get_curve_properties_for_nu(reconstructed_model_fit, curve_properties_for_mu_over_full_range)
curve_properties_for_tau_over_full_range = get_curve_properties_for_tau(reconstructed_model_fit, curve_properties_for_mu_over_full_range) },
error = function(cond) { cat('ERROR - Failed to estimate useful properties of the fitted model over the density range from zero to "upper_density"...\n')
q(save = 'no', status = 1) }
)
# Extract information from the model fit object for the fit summary
cat('Extracting information from the model fit object for the fit summary...\n')
tryCatch(
{ npar_mu = model_obj$mu.df
npar_sigma = model_obj$sigma.df
npar_nu = 0
npar_tau = 0
npar_all = model_obj$df.fit
gdev = model_obj$G.deviance
aic = model_obj$aic
bic = model_obj$sbc },
error = function(cond) { cat('ERROR - Failed to extract information from the model fit object for the fit summary...\n')
q(save = 'no', status = 1) }
)
# Where possible, extract physical parameter values from the model fit object for the fit summary
tryCatch(
{ q_0 = 0.0
v_ff = NA
dvdk_0 = NA
k_crit = NA
k_vmax = NA
q_cap = NA
v_max = NA
k_jam = NA
v_bw = NA
dvdk_kjam = NA
if (model_obj$mu.coefficients[1] > 0.0) {
v_ff = model_obj$mu.coefficients[1]
if (model_obj$mu.coefficients[2] < 0.0) {
k_jam = (model_obj$mu.coefficients[1]/model_obj$mu.coefficients[2])^2
k_crit = (4.0/9.0)*k_jam
k_vmax = 0.0
q_cap = v_ff*(k_crit/3.0)
v_max = v_ff
v_bw = 0.5*v_ff
dvdk_kjam = -v_bw/k_jam
}
} },
error = function(cond) { cat('ERROR - Failed to extract physical parameter values from the model fit object for the fit summary...\n')
q(save = 'no', status = 1) }
)
# Report a basic fit summary
cat('\n')
cat('Fit summary (abridged):\n')
cat('\n')
cat('Model parameter counts:\n')
cat(' No. of free parameters (mu): ', sprintf('%.6f', npar_mu), '\n')
cat(' No. of free parameters (sigma): ', sprintf('%.6f', npar_sigma), '\n')
cat(' No. of free parameters (nu): ', sprintf('%.6f', npar_nu), '\n')
cat(' No. of free parameters (tau): ', sprintf('%.6f', npar_tau), '\n')
cat(' Total no. of free parameters (Npar):', sprintf('%.6f', npar_all), '\n')
cat('\n')
cat('Fit quality:\n')
cat(' Global deviance [ -2*ln(Lmax) ]: ', sprintf('%.4f', gdev), '\n')
cat(' AIC [ -2*ln(Lmax) + 2*Npar ]: ', sprintf('%.4f', aic), '\n')
cat(' BIC [ -2*ln(Lmax) + Npar*ln(Ndat) ]:', sprintf('%.4f', bic), '\n')
cat('\n')
cat('Fitted physical parameters (where available):\n')
if (!is.na(q_0)) { cat(' Flow at zero density: ', sprintf('%.8g', q_0), '\n') }
if (!is.na(v_ff)) { cat(' Free-flow speed: ', sprintf('%.8g', v_ff), '\n') }
if (!is.na(dvdk_0)) { cat(' Gradient of the speed (w.r.t. density) at zero density:', sprintf('%.8g', dvdk_0), '\n') }
if (!is.na(k_crit)) { cat(' Critical density: ', sprintf('%.8g', k_crit), '\n') }
if (!is.na(k_vmax)) { cat(' Density at maximum speed: ', sprintf('%.8g', k_vmax), '\n') }
if (!is.na(q_cap)) { cat(' Capacity: ', sprintf('%.8g', q_cap), '\n') }
if (!is.na(v_max)) { cat(' Maximum speed: ', sprintf('%.8g', v_max), '\n') }
if (!is.na(k_jam)) { cat(' Jam density: ', sprintf('%.8g', k_jam), '\n') }
if (!is.na(v_bw)) { cat(' Back-propagating wave speed at jam density: ', sprintf('%.8g', v_bw), '\n') }
if (!is.na(dvdk_kjam)) { cat(' Gradient of the speed (w.r.t. density) at jam density: ', sprintf('%.8g', dvdk_kjam), '\n') }
cat('\n')
cat('Fitted model parameters (see the accompanying papers by Bramich, Menendez & Ambuhl for details):\n')
cat(' v_ff: ', sprintf('%.8g', model_obj$mu.coefficients[1]), '\n')
cat(' v_ff/sqrt(k_jam):', sprintf('%.8g', -model_obj$mu.coefficients[2]), '\n')
cat(' sigma_con: ', sprintf('%.8g', exp(model_obj$sigma.coefficients[1])), '\n')
# Write out the fit summary file "Fit.Summary.<fd_type>.<functional_form_model>.<noise_model>.txt"
cat('\n')
cat('Writing out the fit summary file: ', output_files[1], '\n')
tryCatch(
{ write_fit_summary(output_files[1], 'Flow.Density', ntraffic_data, data_min_density, data_max_density, data_min_flow, data_max_flow,
npar_mu, npar_sigma, npar_nu, npar_tau, npar_all, gdev, aic, bic,
q_0, v_ff, dvdk_0, k_crit, k_vmax, q_cap, v_max, k_jam, v_bw, dvdk_kjam,
curve_properties_for_mu_over_data_range, curve_properties_for_sigma_over_data_range,
curve_properties_for_nu_over_data_range, curve_properties_for_tau_over_data_range,
curve_properties_for_mu_over_full_range, curve_properties_for_sigma_over_full_range,
curve_properties_for_nu_over_full_range, curve_properties_for_tau_over_full_range)
cat('######################################################################################################################\n',
'# FITTED MODEL PARAMETERS (SEE THE ACCOMPANYING PAPERS BY BRAMICH, MENENDEZ & AMBUHL FOR DETAILS)\n',
'# N.B: FITTED COEFFICIENTS FOR ANY NON-PARAMETRIC SMOOTHING FUNCTIONS IN THE MODEL ARE NOT REPORTED HERE\n',
'######################################################################################################################\n',
sprintf('%.8g', model_obj$mu.coefficients[1]), ' # v_ff\n',
sprintf('%.8g', -model_obj$mu.coefficients[2]), ' # v_ff/sqrt(k_jam)\n',
sprintf('%.8g', exp(model_obj$sigma.coefficients[1])), ' # sigma_con\n',
file = output_files[1], sep = '', append = TRUE) },
error = function(cond) { cat('ERROR - Failed to write out the fit summary file...\n')
remove_file_list(output_files)
q(save = 'no', status = 1) }
)
# Write out the fit curves file "Fit.Curves.<fd_type>.<functional_form_model>.<noise_model>.txt"
cat('Writing out the fit curves file: ', output_files[2], '\n')
tryCatch(
{ cat('# Density : Mu : Sigma : Nu : Tau : 0.135 Percentile (Corresponding To -3*Sigma In A Normal Distribution) : 2.28 Percentile (Corresponding To -2*Sigma In A',
'Normal Distribution) : 15.87 Percentile (Corresponding To -1*Sigma In A Normal Distribution) : 50.00 Percentile (Median) : 84.13 Percentile (Corresponding',
'To 1*Sigma In A Normal Distribution) : 97.72 Percentile (Corresponding To 2*Sigma In A Normal Distribution) : 99.865 Percentile (Corresponding To 3*Sigma',
'In A Normal Distribution) : Mean : Median : Mode : Standard Deviation : Moment Skewness : Moment Excess Kurtosis\n', file = output_files[2])
write.table(reconstructed_model_fit, file = output_files[2], append = TRUE, quote = FALSE, row.names = FALSE, col.names = FALSE) },
error = function(cond) { cat('ERROR - Failed to write out the fit curves file...\n')
remove_file_list(output_files)
q(save = 'no', status = 1) }
)
# Write out the fit predictions file "Fit.Predictions.<fd_type>.<functional_form_model>.<noise_model>.txt"
cat('Writing out the fit predictions file:', output_files[3], '\n')
tryCatch(
{ cat('# Data Column 1 : Data Column 2 : Data Column 3 : Fitted Value For Mu : Fitted Value For Sigma : Fitted Value For Nu : Fitted Value For Tau :',
'Normalised Quantile Residual ("-Inf" Or "Inf" Values May Be Present) : 0.135 Percentile (Corresponding To -3*Sigma In A Normal Distribution) :',
'2.28 Percentile (Corresponding To -2*Sigma In A Normal Distribution) : 15.87 Percentile (Corresponding To -1*Sigma In A Normal Distribution) :',
'50.00 Percentile (Median) : 84.13 Percentile (Corresponding To 1*Sigma In A Normal Distribution) : 97.72 Percentile (Corresponding To 2*Sigma',
'In A Normal Distribution) : 99.865 Percentile (Corresponding To 3*Sigma In A Normal Distribution) : Mean : Median : Mode : Standard Deviation :',
'Moment Skewness : Moment Excess Kurtosis\n', file = output_files[3])
write.table(traffic_data, file = output_files[3], append = TRUE, quote = FALSE, row.names = FALSE, col.names = FALSE) },
error = function(cond) { cat('ERROR - Failed to write out the fit predictions file...\n')
remove_file_list(output_files)
q(save = 'no', status = 1) }
)
# If required, then create the plots for the GAMLSS model fit
if (length(output_files) > 3) {
cat('\n')
cat('Creating the plots for the GAMLSS model fit...\n')
tryCatch(
{ create_all_plots(traffic_data, ntraffic_data, data_max_density, upper_density, reconstructed_model_fit_selection, reconstructed_model_fit, ngrid,
'Flow.Density', functional_form_model, noise_model, output_files) },
error = function(cond) { cat('ERROR - Failed to create the plot...\n')
remove_file_list(output_files)
q(save = 'no', status = 1) }
)
}
# Return the GAMLSS model fit object
cat('\n')
cat('>-----------------------------------------------------------------------------<\n')
return(model_obj)
}