29 #include <cxmessages.h>
30 #include <cxstrutils.h>
32 #include <cpl_error.h>
47 _giraffe_model_set_flag(GiModel *
self, cxint idx, cxbool value)
50 cx_assert(
self != NULL);
52 if (self->parameters.flags == NULL) {
53 self->parameters.flags = cx_calloc(self->parameters.count,
58 if (self->parameters.flags[idx] == 0) {
59 self->parameters.flags[idx] = 1;
64 if (self->parameters.flags[idx] == 1) {
65 self->parameters.flags[idx] = 0;
76 _giraffe_model_get_flag(
const GiModel *
self, cxint idx)
79 cx_assert(
self != NULL);
81 if (self->parameters.flags == NULL) {
85 return self->parameters.flags[idx] == 0 ? FALSE : TRUE;
90 inline static cxdouble
91 _giraffe_compute_rsquare(cxdouble rss, cpl_matrix *y, cxint n)
96 register cxdouble my = 0.;
97 register cxdouble sy = 0.;
98 register cxdouble ss = 0.;
101 cxdouble *_y = cpl_matrix_get_data(y);
108 for (i = 0; i < n; i++) {
114 for (i = 0; i < n; i++) {
131 _giraffe_model_fit(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
132 cpl_matrix *sigma, cxint ndata, cxint start,
138 cxdouble _chisq = 0.;
143 if ((cpl_matrix_get_nrow(x) != cpl_matrix_get_nrow(y)) ||
144 (cpl_matrix_get_nrow(x) != cpl_matrix_get_nrow(sigma))) {
148 if (cpl_matrix_get_ncol(x) != self->arguments.count) {
157 if (cpl_matrix_get_nrow(y) <= start + stride * (ndata - 1)) {
166 setup.
iterations =
self->fit.setup.iterations;
167 setup.
tests =
self->fit.setup.tests;
168 setup.
dchisq =
self->fit.setup.delta;
170 if (self->fit.covariance != NULL) {
171 cpl_matrix_set_size(self->fit.covariance, self->parameters.count,
172 self->parameters.count);
173 cpl_matrix_fill(self->fit.covariance, 0.);
176 self->fit.covariance = cpl_matrix_new(self->parameters.count,
177 self->parameters.count);
185 giraffe_error_push();
187 status =
giraffe_nlfit(x, y, sigma, ndata, self->parameters.values,
188 self->parameters.limits, self->parameters.flags,
189 self->parameters.count, self->fit.covariance,
190 &_chisq, self->model, &setup);
194 if (cpl_error_get_code() == CPL_ERROR_NONE) {
202 if (cpl_error_get_code() != CPL_ERROR_NONE) {
208 self->fit.df = ndata -
self->fit.nfree;
209 self->fit.iterations = status;
210 self->fit.chisq = _chisq;
211 self->fit.rsquare = _giraffe_compute_rsquare(self->fit.chisq, y, ndata);
219 giraffe_model_new(
const cxchar *name)
222 register cxint i = 0;
224 GiModel *
self = NULL;
231 while (giraffe_models[i].name != NULL) {
233 if (strcmp(name, giraffe_models[i].name) == 0) {
235 self = cx_calloc(1,
sizeof(GiModel));
237 giraffe_error_push();
239 giraffe_models[i].ctor(
self, &giraffe_models[i]);
241 if (cpl_error_get_code() != CPL_ERROR_NONE) {
243 giraffe_model_delete(
self);
258 self->fit.setup.iterations = 0;
259 self->fit.setup.tests = 0;
260 self->fit.setup.delta = 0.;
262 self->fit.iterations = 0;
265 self->fit.covariance = NULL;
273 giraffe_model_clone(
const GiModel *other)
276 GiModel *
self = NULL;
281 self = giraffe_model_new(other->name);
291 cpl_propertylist_delete(self->arguments.names);
292 self->arguments.names =
293 cpl_propertylist_duplicate(other->arguments.names);
295 cpl_matrix_delete(self->arguments.values);
296 self->arguments.values =
297 cpl_matrix_duplicate(other->arguments.values);
299 self->arguments.count = other->arguments.count;
301 cx_assert(cpl_propertylist_get_size(self->arguments.names) ==
302 self->arguments.count);
303 cx_assert(cpl_matrix_get_nrow(self->arguments.values) *
304 cpl_matrix_get_ncol(self->arguments.values) ==
305 self->arguments.count);
308 cpl_propertylist_delete(self->parameters.names);
309 self->parameters.names =
310 cpl_propertylist_duplicate(other->parameters.names);
312 cpl_matrix_delete(self->parameters.values);
313 self->parameters.values =
314 cpl_matrix_duplicate(other->parameters.values);
316 self->parameters.count = other->parameters.count;
318 cx_assert(cpl_propertylist_get_size(self->parameters.names) ==
319 self->parameters.count);
320 cx_assert(cpl_matrix_get_nrow(self->parameters.values) *
321 cpl_matrix_get_ncol(self->parameters.values) ==
322 self->parameters.count);
324 self->fit.setup = other->fit.setup;
325 self->fit.iterations = other->fit.iterations;
326 self->fit.nfree = other->fit.nfree;
327 self->fit.df = other->fit.df;
329 if (other->fit.covariance == NULL) {
330 self->fit.covariance = NULL;
333 self->fit.covariance =
334 cpl_matrix_duplicate(other->fit.covariance);
344 giraffe_model_delete(GiModel *
self)
349 register cxint i = 0;
351 while (giraffe_models[i].name != NULL) {
353 if (strcmp(self->name, giraffe_models[i].name) == 0) {
354 giraffe_models[i].dtor(
self);
372 giraffe_model_get_name(
const GiModel *
self)
375 cx_assert(
self != NULL);
382 giraffe_model_get_type(
const GiModel *
self)
385 cx_assert(
self != NULL);
392 giraffe_model_count_arguments(
const GiModel *
self)
395 cx_assert(
self != NULL);
396 return self->arguments.count;
402 giraffe_model_count_parameters(
const GiModel *
self)
405 cx_assert(
self != NULL);
406 return self->parameters.count;
412 giraffe_model_argument_name(
const GiModel*
self, cxsize position)
415 const cpl_property* p = NULL;
418 cx_assert(
self != NULL);
420 p = cpl_propertylist_get(self->arguments.names, position);
425 return cpl_property_get_name(p);
431 giraffe_model_parameter_name(
const GiModel*
self, cxsize position)
434 const cpl_property* p = NULL;
437 cx_assert(
self != NULL);
439 p = cpl_propertylist_get(self->parameters.names, position);
444 return cpl_property_get_name(p);
450 giraffe_model_set_argument(GiModel *
self,
const cxchar *name, cxdouble value)
453 const cxchar *
const fctid =
"giraffe_model_set_argument";
456 cx_assert(
self != NULL);
459 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
463 if (!cpl_propertylist_has(self->arguments.names, name)) {
464 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
469 register cxint idx = cpl_propertylist_get_int(self->arguments.names,
472 cpl_matrix_set(self->arguments.values, idx, 0, value);
482 giraffe_model_get_argument(
const GiModel *
self,
const cxchar *name)
485 const cxchar *
const fctid =
"giraffe_model_get_argument";
490 cx_assert(
self != NULL);
493 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
497 if (!cpl_propertylist_has(self->arguments.names, name)) {
498 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
503 idx = cpl_propertylist_get_int(self->arguments.names, name);
505 return cpl_matrix_get(self->arguments.values, idx, 0);
511 giraffe_model_set_parameter(GiModel *
self,
const cxchar *name,
515 const cxchar *
const fctid =
"giraffe_model_set_parameter";
518 cx_assert(
self != NULL);
521 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
525 if (!cpl_propertylist_has(self->parameters.names, name)) {
526 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
531 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
534 cpl_matrix_set(self->parameters.values, idx, 0, value);
544 giraffe_model_get_parameter(
const GiModel *
self,
const cxchar *name)
547 const cxchar *
const fctid =
"giraffe_model_get_parameter";
552 cx_assert(
self != NULL);
555 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
559 if (!cpl_propertylist_has(self->parameters.names, name)) {
560 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
565 idx = cpl_propertylist_get_int(self->parameters.names, name);
567 return cpl_matrix_get(self->parameters.values, idx, 0);
573 giraffe_model_freeze_parameter(GiModel *
self,
const cxchar *name)
576 const cxchar *
const fctid =
"giraffe_model_freeze_parameter";
580 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
585 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
589 if (!cpl_propertylist_has(self->parameters.names, name)) {
590 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
595 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
598 _giraffe_model_set_flag(
self, idx, FALSE);
608 giraffe_model_thaw_parameter(GiModel *
self,
const cxchar *name)
611 const cxchar *
const fctid =
"giraffe_model_thaw_parameter";
614 cx_assert(
self != NULL);
617 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
621 if (!cpl_propertylist_has(self->parameters.names, name)) {
622 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
627 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
630 _giraffe_model_set_flag(
self, idx, TRUE);
640 giraffe_model_frozen_parameter(
const GiModel *
self,
const cxchar *name)
643 const cxchar *
const fctid =
"giraffe_model_frozen_parameter";
648 cx_assert(
self != NULL);
651 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
655 if (!cpl_propertylist_has(self->parameters.names, name)) {
656 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
661 idx = cpl_propertylist_get_int(self->parameters.names, name);
663 return _giraffe_model_get_flag(
self, idx) == FALSE;
669 giraffe_model_freeze(GiModel *
self)
675 cx_assert(
self != NULL);
677 for (i = 0; i < cpl_propertylist_get_size(self->parameters.names); i++) {
679 const cpl_property *p = cpl_propertylist_get(self->parameters.names,
686 _giraffe_model_set_flag(
self, cpl_property_get_int(p), FALSE);
696 giraffe_model_thaw(GiModel *
self)
702 cx_assert(
self != NULL);
704 for (i = 0; i < cpl_propertylist_get_size(self->parameters.names); i++) {
706 const cpl_property *p = cpl_propertylist_get(self->parameters.names,
713 _giraffe_model_set_flag(
self, cpl_property_get_int(p), TRUE);
723 giraffe_model_evaluate(
const GiModel *
self, cxdouble *result, cxint *status)
726 const cxchar *
const fctid =
"giraffe_model_evaluate";
728 cxdouble _result = 0.;
729 cxdouble *arg = NULL;
730 cxdouble *par = NULL;
733 cx_assert(
self != NULL);
735 arg = cpl_matrix_get_data(self->arguments.values);
738 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
742 par = cpl_matrix_get_data(self->parameters.values);
745 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
749 giraffe_error_push();
751 self->model(&_result, arg, par, self->parameters.count, NULL, NULL);
753 if (cpl_error_get_code() != CPL_ERROR_NONE) {
774 giraffe_model_set_iterations(GiModel *
self, cxint iterations)
777 cx_assert(
self != NULL);
779 if (iterations < 1) {
783 self->fit.setup.iterations = iterations;
791 giraffe_model_get_iterations(
const GiModel *
self)
794 cx_assert(
self != NULL);
796 return self->fit.setup.iterations;
802 giraffe_model_set_tests(GiModel *
self, cxint tests)
805 cx_assert(
self != NULL);
811 self->fit.setup.tests = tests;
819 giraffe_model_get_tests(
const GiModel *
self)
822 cx_assert(
self != NULL);
824 return self->fit.setup.tests;
830 giraffe_model_set_delta(GiModel *
self, cxdouble delta)
833 cx_assert(
self != NULL);
839 self->fit.setup.delta = delta;
847 giraffe_model_get_delta(
const GiModel *
self)
850 cx_assert(
self != NULL);
852 return self->fit.setup.delta;
858 giraffe_model_get_position(
const GiModel *
self)
861 cx_assert(
self != NULL);
863 if (self->fit.iterations <= 0) {
867 return self->fit.iterations;
873 giraffe_model_get_variance(
const GiModel *
self,
const cxchar *name)
876 const cxchar *
const fctid =
"giraffe_model_get_variance";
879 cxdouble variance = 0.;
882 cx_assert(
self != NULL);
885 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
889 if (!cpl_propertylist_has(self->parameters.names, name)) {
890 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
895 if (self->fit.covariance == NULL) {
896 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
902 cpl_propertylist_get_int(self->parameters.names, name);
904 variance = cpl_matrix_get(self->fit.covariance, idx, idx);
916 giraffe_model_get_sigma(
const GiModel *
self,
const cxchar *name)
919 const cxchar *
const fctid =
"giraffe_model_get_sigma";
925 cx_assert(
self != NULL);
928 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
932 if (!cpl_propertylist_has(self->parameters.names, name)) {
933 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
938 if (self->fit.covariance == NULL) {
939 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
945 cpl_propertylist_get_int(self->parameters.names, name);
947 sigma = cpl_matrix_get(self->fit.covariance, idx, idx);
949 if (isnan(sigma) || sigma < 0.) {
966 giraffe_model_get_df(
const GiModel *
self)
969 cx_assert(
self != NULL);
977 giraffe_model_get_chisq(
const GiModel *
self)
980 cx_assert(
self != NULL);
982 return self->fit.chisq;
988 giraffe_model_get_rsquare(
const GiModel *
self)
991 cx_assert(
self != NULL);
993 return self->fit.rsquare;
999 giraffe_model_fit(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
1006 cx_assert(
self != NULL);
1008 if (x == NULL || y == NULL) {
1012 if (sigma == NULL) {
1016 ndata = cpl_matrix_get_nrow(y);
1018 return _giraffe_model_fit(
self, x, y, sigma, ndata, 0, 1);
1024 giraffe_model_fit_sequence(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
1025 cpl_matrix *sigma, cxint ndata, cxint start,
1029 cx_assert(
self != NULL);
1032 cx_assert((start == 0) || (stride == 1));
1035 if (x == NULL || y == NULL) {
1039 if (sigma == NULL) {
1043 if ((start < 0) || (stride < 0)) {
1047 return _giraffe_model_fit(
self, x, y, sigma, ndata, 0, 1);
cxint giraffe_nlfit(cpl_matrix *x, cpl_matrix *y, cpl_matrix *sigma, cxint ndata, cpl_matrix *a, cpl_matrix *delta, cxint *ia, cxint ma, cpl_matrix *alpha, cxdouble *chisq, GiFitFunc funcs, const GiFitParams *setup)
Levenberg-Marquardt non-linear fit driver.
Non-linear fit control parameters.