29#include <cxmessages.h>
30#include <cxstrutils.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;
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);
219giraffe_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;
273giraffe_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);
344giraffe_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);
372giraffe_model_get_name(
const GiModel *self)
375 cx_assert(self != NULL);
382giraffe_model_get_type(
const GiModel *self)
385 cx_assert(self != NULL);
392giraffe_model_count_arguments(
const GiModel *self)
395 cx_assert(self != NULL);
396 return self->arguments.count;
402giraffe_model_count_parameters(
const GiModel *self)
405 cx_assert(self != NULL);
406 return self->parameters.count;
412giraffe_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);
431giraffe_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);
450giraffe_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);
482giraffe_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);
511giraffe_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);
544giraffe_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);
573giraffe_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);
608giraffe_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);
640giraffe_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;
669giraffe_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);
696giraffe_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);
723giraffe_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) {
774giraffe_model_set_iterations(GiModel *self, cxint iterations)
777 cx_assert(self != NULL);
779 if (iterations < 1) {
783 self->fit.setup.iterations = iterations;
791giraffe_model_get_iterations(
const GiModel *self)
794 cx_assert(self != NULL);
796 return self->fit.setup.iterations;
802giraffe_model_set_tests(GiModel *self, cxint tests)
805 cx_assert(self != NULL);
811 self->fit.setup.tests = tests;
819giraffe_model_get_tests(
const GiModel *self)
822 cx_assert(self != NULL);
824 return self->fit.setup.tests;
830giraffe_model_set_delta(GiModel *self, cxdouble delta)
833 cx_assert(self != NULL);
839 self->fit.setup.delta = delta;
847giraffe_model_get_delta(
const GiModel *self)
850 cx_assert(self != NULL);
852 return self->fit.setup.delta;
858giraffe_model_get_position(
const GiModel *self)
861 cx_assert(self != NULL);
863 if (self->fit.iterations <= 0) {
867 return self->fit.iterations;
873giraffe_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);
916giraffe_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.) {
966giraffe_model_get_df(
const GiModel *self)
969 cx_assert(self != NULL);
977giraffe_model_get_chisq(
const GiModel *self)
980 cx_assert(self != NULL);
982 return self->fit.chisq;
988giraffe_model_get_rsquare(
const GiModel *self)
991 cx_assert(self != NULL);
993 return self->fit.rsquare;
999giraffe_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);
1024giraffe_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.