37 #include <cxmessages.h>
38 #include <cxstrutils.h>
40 #include <cpl_error.h>
55 _giraffe_model_set_flag(GiModel *
self, cxint idx, cxbool value)
58 cx_assert(
self != NULL);
60 if (self->parameters.flags == NULL) {
61 self->parameters.flags = cx_calloc(self->parameters.count,
66 if (self->parameters.flags[idx] == 0) {
67 self->parameters.flags[idx] = 1;
72 if (self->parameters.flags[idx] == 1) {
73 self->parameters.flags[idx] = 0;
84 _giraffe_model_get_flag(
const GiModel *
self, cxint idx)
87 cx_assert(
self != NULL);
89 if (self->parameters.flags == NULL) {
93 return self->parameters.flags[idx] == 0 ? FALSE : TRUE;
98 inline static cxdouble
99 _giraffe_compute_rsquare(cxdouble rss, cpl_matrix *y, cxint n)
104 register cxdouble my = 0.;
105 register cxdouble sy = 0.;
106 register cxdouble ss = 0.;
109 cxdouble *_y = cpl_matrix_get_data(y);
116 for (i = 0; i < n; i++) {
122 for (i = 0; i < n; i++) {
139 _giraffe_model_fit(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
140 cpl_matrix *sigma, cxint ndata, cxint start,
146 cxdouble _chisq = 0.;
151 if ((cpl_matrix_get_nrow(x) != cpl_matrix_get_nrow(y)) ||
152 (cpl_matrix_get_nrow(x) != cpl_matrix_get_nrow(sigma))) {
156 if (cpl_matrix_get_ncol(x) != self->arguments.count) {
165 if (cpl_matrix_get_nrow(y) <= start + stride * (ndata - 1)) {
174 setup.
iterations =
self->fit.setup.iterations;
175 setup.
tests =
self->fit.setup.tests;
176 setup.
dchisq =
self->fit.setup.delta;
178 if (self->fit.covariance != NULL) {
179 cpl_matrix_set_size(self->fit.covariance, self->parameters.count,
180 self->parameters.count);
181 cpl_matrix_fill(self->fit.covariance, 0.);
184 self->fit.covariance = cpl_matrix_new(self->parameters.count,
185 self->parameters.count);
193 giraffe_error_push();
195 status =
giraffe_nlfit(x, y, sigma, ndata, self->parameters.values,
196 self->parameters.limits, self->parameters.flags,
197 self->parameters.count, self->fit.covariance,
198 &_chisq, self->model, &setup);
202 if (cpl_error_get_code() == CPL_ERROR_NONE) {
210 if (cpl_error_get_code() != CPL_ERROR_NONE) {
216 self->fit.df = ndata -
self->fit.nfree;
217 self->fit.iterations = status;
218 self->fit.chisq = _chisq;
219 self->fit.rsquare = _giraffe_compute_rsquare(self->fit.chisq, y, ndata);
227 giraffe_model_new(
const cxchar *
name)
230 register cxint i = 0;
232 GiModel *
self = NULL;
239 while (giraffe_models[i].name != NULL) {
241 if (strcmp(name, giraffe_models[i].name) == 0) {
243 self = cx_calloc(1,
sizeof(GiModel));
245 giraffe_error_push();
247 giraffe_models[i].ctor(
self, &giraffe_models[i]);
249 if (cpl_error_get_code() != CPL_ERROR_NONE) {
251 giraffe_model_delete(
self);
266 self->fit.setup.iterations = 0;
267 self->fit.setup.tests = 0;
268 self->fit.setup.delta = 0.;
270 self->fit.iterations = 0;
273 self->fit.covariance = NULL;
281 giraffe_model_clone(
const GiModel *other)
284 GiModel *
self = NULL;
289 self = giraffe_model_new(other->name);
299 cpl_propertylist_delete(self->arguments.names);
300 self->arguments.names =
301 cpl_propertylist_duplicate(other->arguments.names);
303 cpl_matrix_delete(self->arguments.values);
304 self->arguments.values =
305 cpl_matrix_duplicate(other->arguments.values);
307 self->arguments.count = other->arguments.count;
309 cx_assert(cpl_propertylist_get_size(self->arguments.names) ==
310 self->arguments.count);
311 cx_assert(cpl_matrix_get_nrow(self->arguments.values) *
312 cpl_matrix_get_ncol(self->arguments.values) ==
313 self->arguments.count);
316 cpl_propertylist_delete(self->parameters.names);
317 self->parameters.names =
318 cpl_propertylist_duplicate(other->parameters.names);
320 cpl_matrix_delete(self->parameters.values);
321 self->parameters.values =
322 cpl_matrix_duplicate(other->parameters.values);
324 self->parameters.count = other->parameters.count;
326 cx_assert(cpl_propertylist_get_size(self->parameters.names) ==
327 self->parameters.count);
328 cx_assert(cpl_matrix_get_nrow(self->parameters.values) *
329 cpl_matrix_get_ncol(self->parameters.values) ==
330 self->parameters.count);
332 self->fit.setup = other->fit.setup;
333 self->fit.iterations = other->fit.iterations;
334 self->fit.nfree = other->fit.nfree;
335 self->fit.df = other->fit.df;
337 if (other->fit.covariance == NULL) {
338 self->fit.covariance = NULL;
341 self->fit.covariance =
342 cpl_matrix_duplicate(other->fit.covariance);
352 giraffe_model_delete(GiModel *
self)
357 register cxint i = 0;
359 while (giraffe_models[i].name != NULL) {
361 if (strcmp(self->name, giraffe_models[i].name) == 0) {
362 giraffe_models[i].dtor(
self);
380 giraffe_model_get_name(
const GiModel *
self)
383 cx_assert(
self != NULL);
390 giraffe_model_get_type(
const GiModel *
self)
393 cx_assert(
self != NULL);
400 giraffe_model_count_arguments(
const GiModel *
self)
403 cx_assert(
self != NULL);
404 return self->arguments.count;
410 giraffe_model_count_parameters(
const GiModel *
self)
413 cx_assert(
self != NULL);
414 return self->parameters.count;
420 giraffe_model_argument_name(
const GiModel*
self, cxsize position)
423 const cpl_property* p = NULL;
426 cx_assert(
self != NULL);
428 p = cpl_propertylist_get(self->arguments.names, position);
433 return cpl_property_get_name(p);
439 giraffe_model_parameter_name(
const GiModel*
self, cxsize position)
442 const cpl_property* p = NULL;
445 cx_assert(
self != NULL);
447 p = cpl_propertylist_get(self->parameters.names, position);
452 return cpl_property_get_name(p);
458 giraffe_model_set_argument(GiModel *
self,
const cxchar *name, cxdouble value)
461 const cxchar *
const fctid =
"giraffe_model_set_argument";
464 cx_assert(
self != NULL);
467 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
471 if (!cpl_propertylist_has(self->arguments.names, name)) {
472 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
477 register cxint idx = cpl_propertylist_get_int(self->arguments.names,
480 cpl_matrix_set(self->arguments.values, idx, 0, value);
490 giraffe_model_get_argument(
const GiModel *
self,
const cxchar *name)
493 const cxchar *
const fctid =
"giraffe_model_get_argument";
498 cx_assert(
self != NULL);
501 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
505 if (!cpl_propertylist_has(self->arguments.names, name)) {
506 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
511 idx = cpl_propertylist_get_int(self->arguments.names, name);
513 return cpl_matrix_get(self->arguments.values, idx, 0);
519 giraffe_model_set_parameter(GiModel *
self,
const cxchar *name,
523 const cxchar *
const fctid =
"giraffe_model_set_parameter";
526 cx_assert(
self != NULL);
529 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
533 if (!cpl_propertylist_has(self->parameters.names, name)) {
534 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
539 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
542 cpl_matrix_set(self->parameters.values, idx, 0, value);
552 giraffe_model_get_parameter(
const GiModel *
self,
const cxchar *name)
555 const cxchar *
const fctid =
"giraffe_model_get_parameter";
560 cx_assert(
self != NULL);
563 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
567 if (!cpl_propertylist_has(self->parameters.names, name)) {
568 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
573 idx = cpl_propertylist_get_int(self->parameters.names, name);
575 return cpl_matrix_get(self->parameters.values, idx, 0);
581 giraffe_model_freeze_parameter(GiModel *
self,
const cxchar *name)
584 const cxchar *
const fctid =
"giraffe_model_freeze_parameter";
588 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
593 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
597 if (!cpl_propertylist_has(self->parameters.names, name)) {
598 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
603 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
606 _giraffe_model_set_flag(
self, idx, FALSE);
616 giraffe_model_thaw_parameter(GiModel *
self,
const cxchar *name)
619 const cxchar *
const fctid =
"giraffe_model_thaw_parameter";
622 cx_assert(
self != NULL);
625 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
629 if (!cpl_propertylist_has(self->parameters.names, name)) {
630 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
635 register cxint idx = cpl_propertylist_get_int(self->parameters.names,
638 _giraffe_model_set_flag(
self, idx, TRUE);
648 giraffe_model_frozen_parameter(
const GiModel *
self,
const cxchar *name)
651 const cxchar *
const fctid =
"giraffe_model_frozen_parameter";
656 cx_assert(
self != NULL);
659 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
663 if (!cpl_propertylist_has(self->parameters.names, name)) {
664 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
669 idx = cpl_propertylist_get_int(self->parameters.names, name);
671 return _giraffe_model_get_flag(
self, idx) == FALSE;
677 giraffe_model_freeze(GiModel *
self)
683 cx_assert(
self != NULL);
685 for (i = 0; i < cpl_propertylist_get_size(self->parameters.names); i++) {
687 const cpl_property *p = cpl_propertylist_get(self->parameters.names,
694 _giraffe_model_set_flag(
self, cpl_property_get_int(p), FALSE);
704 giraffe_model_thaw(GiModel *
self)
710 cx_assert(
self != NULL);
712 for (i = 0; i < cpl_propertylist_get_size(self->parameters.names); i++) {
714 const cpl_property *p = cpl_propertylist_get(self->parameters.names,
721 _giraffe_model_set_flag(
self, cpl_property_get_int(p), TRUE);
731 giraffe_model_evaluate(
const GiModel *
self, cxdouble *result, cxint *status)
734 const cxchar *
const fctid =
"giraffe_model_evaluate";
736 cxdouble _result = 0.;
737 cxdouble *arg = NULL;
738 cxdouble *par = NULL;
741 cx_assert(
self != NULL);
743 arg = cpl_matrix_get_data(self->arguments.values);
746 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
750 par = cpl_matrix_get_data(self->parameters.values);
753 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
757 giraffe_error_push();
759 self->model(&_result, arg, par, self->parameters.count, NULL, NULL);
761 if (cpl_error_get_code() != CPL_ERROR_NONE) {
782 giraffe_model_set_iterations(GiModel *
self, cxint iterations)
785 cx_assert(
self != NULL);
787 if (iterations < 1) {
791 self->fit.setup.iterations = iterations;
799 giraffe_model_get_iterations(
const GiModel *
self)
802 cx_assert(
self != NULL);
804 return self->fit.setup.iterations;
810 giraffe_model_set_tests(GiModel *
self, cxint tests)
813 cx_assert(
self != NULL);
819 self->fit.setup.tests = tests;
827 giraffe_model_get_tests(
const GiModel *
self)
830 cx_assert(
self != NULL);
832 return self->fit.setup.tests;
838 giraffe_model_set_delta(GiModel *
self, cxdouble delta)
841 cx_assert(
self != NULL);
847 self->fit.setup.delta = delta;
855 giraffe_model_get_delta(
const GiModel *
self)
858 cx_assert(
self != NULL);
860 return self->fit.setup.delta;
866 giraffe_model_get_position(
const GiModel *
self)
869 cx_assert(
self != NULL);
871 if (self->fit.iterations <= 0) {
875 return self->fit.iterations;
881 giraffe_model_get_variance(
const GiModel *
self,
const cxchar *name)
884 const cxchar *
const fctid =
"giraffe_model_get_variance";
887 cxdouble variance = 0.;
890 cx_assert(
self != NULL);
893 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
897 if (!cpl_propertylist_has(self->parameters.names, name)) {
898 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
903 if (self->fit.covariance == NULL) {
904 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
910 cpl_propertylist_get_int(self->parameters.names, name);
912 variance = cpl_matrix_get(self->fit.covariance, idx, idx);
924 giraffe_model_get_sigma(
const GiModel *
self,
const cxchar *name)
927 const cxchar *
const fctid =
"giraffe_model_get_sigma";
933 cx_assert(
self != NULL);
936 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
940 if (!cpl_propertylist_has(self->parameters.names, name)) {
941 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
946 if (self->fit.covariance == NULL) {
947 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
953 cpl_propertylist_get_int(self->parameters.names, name);
955 sigma = cpl_matrix_get(self->fit.covariance, idx, idx);
957 if (isnan(sigma) || sigma < 0.) {
974 giraffe_model_get_df(
const GiModel *
self)
977 cx_assert(
self != NULL);
985 giraffe_model_get_chisq(
const GiModel *
self)
988 cx_assert(
self != NULL);
990 return self->fit.chisq;
996 giraffe_model_get_rsquare(
const GiModel *
self)
999 cx_assert(
self != NULL);
1001 return self->fit.rsquare;
1007 giraffe_model_fit(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
1014 cx_assert(
self != NULL);
1016 if (x == NULL || y == NULL) {
1020 if (sigma == NULL) {
1024 ndata = cpl_matrix_get_nrow(y);
1026 return _giraffe_model_fit(
self, x, y, sigma, ndata, 0, 1);
1032 giraffe_model_fit_sequence(GiModel *
self, cpl_matrix *x, cpl_matrix *y,
1033 cpl_matrix *sigma, cxint ndata, cxint start,
1037 cx_assert(
self != NULL);
1040 cx_assert((start == 0) || (stride == 1));
1043 if (x == NULL || y == NULL) {
1047 if (sigma == NULL) {
1051 if ((start < 0) || (stride < 0)) {
1055 return _giraffe_model_fit(
self, x, y, sigma, ndata, 0, 1);
Non-linear fit control parameters.
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.