28 #include <cxmessages.h>
29 #include <cxstrutils.h>
35 static GiModelData _gimodels[];
37 const GiModelData *
const giraffe_models = _gimodels;
84 static const cxint DW_DEGREE = 3;
85 static const cxdouble DW_LOG001 = 2.302585093;
100 inline static cxdouble
101 _giraffe_dydaweight(cxdouble x, cxdouble x0, cxdouble dx)
107 w = exp(-pow(fabs(x - x0), DW_DEGREE) / pow(dx, DW_DEGREE / DW_LOG001));
119 _giraffe_model_dtor(GiModel *
self)
128 self->arguments.count = 0;
130 if (self->arguments.names) {
131 cpl_propertylist_delete(self->arguments.names);
132 self->arguments.names = NULL;
135 if (self->arguments.values) {
136 cpl_matrix_delete(self->arguments.values);
137 self->arguments.values = NULL;
141 self->parameters.count = 0;
143 if (self->parameters.names) {
144 cpl_propertylist_delete(self->parameters.names);
145 self->parameters.names = NULL;
148 if (self->parameters.values) {
149 cpl_matrix_delete(self->parameters.values);
150 self->parameters.values = NULL;
153 if (self->parameters.limits) {
154 cpl_matrix_delete(self->parameters.limits);
155 self->parameters.limits = NULL;
158 if (self->parameters.flags) {
159 cx_free(self->parameters.flags);
160 self->parameters.flags = NULL;
164 self->fit.iterations = 0;
166 if (self->fit.covariance) {
167 cpl_matrix_delete(self->fit.covariance);
168 self->fit.covariance = NULL;
177 _giraffe_xoptmod_ctor(GiModel *
self,
const GiModelData *model)
180 cx_assert(
self != NULL);
181 cx_assert(model != NULL);
183 self->name = cx_strdup(model->name);
184 self->type = model->type;
186 self->model = model->eval;
193 self->arguments.names = cpl_propertylist_new();
195 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
196 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
197 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
199 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
200 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
207 self->parameters.names = cpl_propertylist_new();
209 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
211 cpl_propertylist_append_int(self->parameters.names,
"Order",
213 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
215 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
217 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
219 cpl_propertylist_append_int(self->parameters.names,
"Angle",
221 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
224 self->parameters.count =
225 cpl_propertylist_get_size(self->parameters.names);
226 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
234 _giraffe_xoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
235 cxdouble *dyda, cxdouble *r)
238 const cxchar *
const fctid =
"_giraffe_xoptmod_eval";
245 cxdouble pixsize, nx;
246 cxdouble fcoll, cfact;
247 cxdouble gtheta, gorder, gspace;
249 register cxdouble xccd, d, X;
250 register cxdouble yfibre2, tmp, tmp2, d2, X2, gspace2;
251 register cxdouble sqtmp, costheta, sintheta;
256 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
264 dyda[LMP_PXSIZ] = 0.;
265 dyda[LMP_FCOLL] = 0.;
266 dyda[LMP_CFACT] = 0.;
267 dyda[LMP_THETA] = 0.;
268 dyda[LMP_ORDER] = 0.;
269 dyda[LMP_SPACE] = 0.;
272 lambda = x[LMI_WLEN];
273 xfibre = x[LMI_XFIB];
274 yfibre = x[LMI_YFIB];
277 pixsize = a[LMP_PXSIZ];
278 fcoll = a[LMP_FCOLL];
279 cfact = a[LMP_CFACT];
280 gtheta = a[LMP_THETA];
281 gorder = a[LMP_ORDER];
282 gspace = a[LMP_SPACE];
285 lambda *= GI_NM_TO_MM;
287 yfibre2 = yfibre * yfibre;
288 gspace2 = gspace * gspace;
289 costheta = cos(gtheta);
290 sintheta = sin(gtheta);
292 d2 = xfibre * xfibre + yfibre2 + (fcoll * fcoll);
295 X = (-lambda * gorder / gspace) + (xfibre * costheta / d) +
296 (fcoll * sintheta / d);
299 sqtmp = sqrt(1.0 - yfibre2 / d2 - X2);
300 tmp = -sintheta * X + costheta * sqtmp;
302 xccd = (cfact * fcoll * (X * costheta + sintheta * sqtmp)) / tmp;
310 *y = xccd / pixsize - 0.5 * nx;
313 *y = -xccd / pixsize + 0.5 * nx;
325 dyda[LMP_PXSIZ] = 0.0;
327 dyda[LMP_FCOLL] = cfact * (costheta * X + sintheta * sqtmp) / tmp +
328 cfact * fcoll * (costheta * (-X * fcoll / d2 + sintheta / d -
329 gorder * lambda * fcoll /
330 (d2 * gspace)) + 0.5 * sintheta *
331 (-2.0 * X * (-X * fcoll / d2 + sintheta / d -
332 gorder * lambda * fcoll /
334 2.0 * yfibre2 * fcoll / (d2 * d2)) / sqtmp) /
335 tmp - cfact * fcoll * (costheta * X + sintheta * sqtmp) *
336 (-sintheta * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
337 fcoll / (d2 * gspace)) + 0.5 * costheta *
338 (-2.0 * X * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
339 fcoll / (d2 * gspace)) + 2.0 * yfibre2 * fcoll /
340 (d2 * d2)) / sqtmp) / tmp2;
342 dyda[LMP_FCOLL] /= pixsize;
343 dyda[LMP_CFACT] = (xccd / cfact) / pixsize;
345 dyda[LMP_THETA] = cfact * fcoll * ((-xfibre * sintheta / d + fcoll *
346 costheta / d) * costheta -
347 sintheta * X - sintheta * X *
348 (-xfibre * sintheta / d + fcoll *
349 costheta / d) / sqtmp +
350 costheta * sqtmp) / tmp -
351 cfact * fcoll * (costheta * X + sintheta * sqtmp) *
352 (-(-xfibre * sintheta / d + fcoll * costheta / d) * sintheta -
353 costheta * X - costheta * X * (-xfibre * sintheta / d + fcoll *
355 sqtmp - sintheta * sqtmp) / tmp2;
357 dyda[LMP_THETA] /= pixsize;
358 dyda[LMP_ORDER] = 0.0;
360 dyda[LMP_SPACE] = cfact * fcoll * (lambda * gorder * costheta /
361 gspace2 - sintheta * X * lambda *
362 gorder / (sqtmp * gspace2)) /
363 tmp - cfact * fcoll * (X * costheta + sintheta * sqtmp) *
364 (-lambda * gorder * sintheta / gspace2 - costheta * X * lambda *
365 gorder / (sqtmp * gspace2)) / tmp2;
367 dyda[LMP_SPACE] /= pixsize;
370 dyda[LMP_NX] = -dyda[LMP_NX];
371 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
372 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
373 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
374 dyda[LMP_THETA] = -dyda[LMP_THETA];
375 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
376 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
385 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
391 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
397 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
403 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
417 _giraffe_yoptmod_ctor(GiModel *
self,
const GiModelData *model)
420 cx_assert(
self != NULL);
421 cx_assert(model != NULL);
423 self->name = cx_strdup(model->name);
424 self->type = model->type;
426 self->model = model->eval;
433 self->arguments.names = cpl_propertylist_new();
435 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
436 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
437 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
439 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
440 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
447 self->parameters.names = cpl_propertylist_new();
449 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
451 cpl_propertylist_append_int(self->parameters.names,
"Order",
453 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
455 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
457 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
459 cpl_propertylist_append_int(self->parameters.names,
"Angle",
461 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
464 self->parameters.count =
465 cpl_propertylist_get_size(self->parameters.names);
466 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
474 _giraffe_yoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
475 cxdouble *dyda, cxdouble *r)
478 const cxchar *
const fctid =
"_giraffe_yoptmod_eval";
480 cxdouble lambda, xfibre, yfibre;
481 cxdouble pixsize, ny;
482 cxdouble fcoll,cfact;
483 cxdouble gtheta,gorder,gspace;
485 register cxdouble t2, t3, t4, t5, t6, t7, t8, t9;
486 register cxdouble t10, t12, t13, t15, t18;
487 register cxdouble t22, t24, t26, t27, t28, t29;
488 register cxdouble t30, t33;
489 register cxdouble t41, t45, t47;
490 register cxdouble t53, t56, t57;
491 register cxdouble t76;
492 register cxdouble t93, t94;
499 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
507 dyda[LMP_PXSIZ] = 0.;
508 dyda[LMP_FCOLL] = 0.;
509 dyda[LMP_CFACT] = 0.;
510 dyda[LMP_THETA] = 0.;
511 dyda[LMP_ORDER] = 0.;
512 dyda[LMP_SPACE] = 0.;
515 lambda = x[LMI_WLEN];
516 xfibre = x[LMI_XFIB];
517 yfibre = x[LMI_YFIB];
520 pixsize = a[LMP_PXSIZ];
521 fcoll = a[LMP_FCOLL];
522 cfact = a[LMP_CFACT];
523 gtheta = a[LMP_THETA];
524 gorder = a[LMP_ORDER];
525 gspace = a[LMP_SPACE];
527 lambda *= GI_NM_TO_MM;
529 t2 = cfact * fcoll * yfibre;
530 t3 = xfibre * xfibre;
531 t4 = yfibre * yfibre;
536 t9 = lambda * gorder;
541 t18 = -t9 * t10 + t13 * t8 + fcoll * t15 * t8;
543 t24 = sqrt(1.0 - t4 / t6 - t22);
544 t26 = -t18 * t15 + t12 * t24;
549 t33 = pixsize * pixsize;
553 t53 = -t13 * t41 * fcoll + t15 * t8 - t5 * t15 * t41;
556 t76 = -xfibre * t15 * t8 + fcoll * t12 * t8;
557 t93 = gspace * gspace;
560 *y = -t2 * t30 + 0.5 * ny;
571 dyda[LMP_PXSIZ] = t2 * t28 / t33;
572 dyda[LMP_FCOLL] = -cfact * yfibre * t30 + cfact * t5 *
573 yfibre * t41 * t27 * t29 + t2 * t47 * t29 *
574 (-t53 * t15 + t56 * (2.0 * t4 / t57 * fcoll -
575 2.0 * t18 * t53) / 2.0);
576 dyda[LMP_CFACT] = -fcoll * yfibre * t30;
577 dyda[LMP_THETA] = t2 * t47 * t29 * (-t76 * t15 - t18 * t12 -
578 t15 * t24 - t56 * t18 * t76);
579 dyda[LMP_ORDER] = t2 * t47 *t29 *(lambda * t10 * t15 + t56 *
581 dyda[LMP_SPACE] = t2 * t47 * t29 * (-t9 * t94 * t15 -
582 t56 * t18 * t9 * t94);
592 _giraffe_xoptmod2_ctor(GiModel *
self,
const GiModelData *model)
595 cx_assert(
self != NULL);
596 cx_assert(model != NULL);
598 self->name = cx_strdup(model->name);
599 self->type = model->type;
601 self->model = model->eval;
608 self->arguments.names = cpl_propertylist_new();
610 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
611 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
612 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
614 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
615 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
622 self->parameters.names = cpl_propertylist_new();
624 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
626 cpl_propertylist_append_int(self->parameters.names,
"Order",
628 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
630 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
632 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
634 cpl_propertylist_append_int(self->parameters.names,
"Angle",
636 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
638 cpl_propertylist_append_int(self->parameters.names,
"Sdx",
640 cpl_propertylist_append_int(self->parameters.names,
"Sdy",
642 cpl_propertylist_append_int(self->parameters.names,
"Sphi",
645 self->parameters.count =
646 cpl_propertylist_get_size(self->parameters.names);
647 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
655 _giraffe_xoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
656 cxdouble *dyda, cxdouble *r)
659 const cxchar *
const fctid =
"_giraffe_xoptmod2_eval";
666 cxdouble pixsize, nx;
667 cxdouble fcoll, cfact;
668 cxdouble gtheta, gorder, gspace;
669 cxdouble slitdx, slitdy, slitphi;
671 register cxdouble t1, t2, t3, t4, t9;
672 register cxdouble t10, t11, t12, t14, t16, t17, t18, t19;
673 register cxdouble t20, t21, t23, t24, t26, t27, t28;
674 register cxdouble t30, t32, t33, t34, t35, t36, t37, t38, t39;
675 register cxdouble t40, t44, t49;
676 register cxdouble t52, t58;
677 register cxdouble t60, t61, t62, t64, t68;
678 register cxdouble t75, t76, t78;
679 register cxdouble t80;
680 register cxdouble t91, t93;
681 register cxdouble t104, t107;
682 register cxdouble t113, t119;
683 register cxdouble t120, t121, t124;
684 register cxdouble t136, t137, t138;
685 register cxdouble t143, t148;
686 register cxdouble t161, t162, t166, t168;
687 register cxdouble t173;
688 register cxdouble t191, t195, t196;
689 register cxdouble t201, t210;
693 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
701 dyda[LMP_PXSIZ] = 0.;
702 dyda[LMP_FCOLL] = 0.;
703 dyda[LMP_CFACT] = 0.;
704 dyda[LMP_THETA] = 0.;
705 dyda[LMP_ORDER] = 0.;
706 dyda[LMP_SPACE] = 0.;
707 dyda[LMP_SOFFX] = 0.;
708 dyda[LMP_SOFFY] = 0.;
712 lambda = x[LMI_WLEN];
713 xfibre = x[LMI_XFIB];
714 yfibre = x[LMI_YFIB];
717 pixsize = a[LMP_PXSIZ];
718 fcoll = a[LMP_FCOLL];
719 cfact = a[LMP_CFACT];
720 gtheta = a[LMP_THETA];
721 gorder = a[LMP_ORDER];
722 gspace = a[LMP_SPACE];
723 slitdx = a[LMP_SOFFX];
724 slitdy = a[LMP_SOFFY];
725 slitphi = a[LMP_SPHI];
727 lambda *= GI_NM_TO_MM;
731 t3 = lambda * gorder;
733 t9 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
736 t12 = slitphi * slitphi;
737 t14 = sqrt(1.0 - t12);
738 t16 = yfibre * t14 + slitdy;
741 t19 = t11 + t17 + t18;
746 t26 = -t3 * t4 + t10 * t21 + t24 * t21;
750 t32 = sqrt(1.0 - t17 * t28 - t30);
759 t44 = pixsize * pixsize;
761 t52 = 1.0 / t20 / t19;
762 t58 = -t10 * t52 * fcoll + t23 * t21 - t18 * t23 * t52;
767 t68 = 2.0 * t64 * fcoll - 2.0 * t26 * t58;
770 t78 = 1.0 / t76 * t40;
772 t91 = -t9 * t23 * t21 + fcoll * t2 * t21;
775 t107 = t26 * lambda * t4;
777 t119 = gspace * gspace;
779 t121 = gorder * t120;
784 t143 = t136 - t10 * t138 / 2.0 - t24 * t138 / 2.0;
785 t148 = t64 * t137 - 2.0 * t26 * t143;
788 t166 = -t10 * t162 / 2.0 - t24 * t162 / 2.0;
790 t173 = -2.0 * t168 + t64 * t161 - 2.0 * t26 * t166;
792 t195 = 2.0 * t9 * xfibre * yfibre - 2.0 * t16 * yfibre * t191 * slitphi;
794 t201 = xfibre * yfibre * t136 - t10 * t196 / 2.0 - t24 * t196 / 2.0;
795 t210 = 2.0 * t168 * yfibre * t191 * slitphi + t64 * t195 -
804 *y = t1 * t39 * t40 - 0.5 * nx;
807 *y = -t1 * t39 * t40 + 0.5 * nx;
819 dyda[LMP_PXSIZ] = -t1 * t39 / t44;
820 dyda[LMP_FCOLL] = cfact * t34 * t49 + t1 *
821 (t2 * t58 + t61 * t68 / 2.0) * t38 * t40 -
822 t75 * t78 * (-t23 * t58 + t80 * t68 / 2.0);
823 dyda[LMP_CFACT] = fcoll * t34 * t49;
824 dyda[LMP_THETA] = t1 * (-t35 + t2 * t91 + t36 - t61 * t93) * t38 *
825 t40 - t75 * t78 * (-t27 - t23 * t91 - t33 - t80 * t93);
826 dyda[LMP_ORDER] = t1 * (-t104 * t4 + t61 * t107) * t38 * t40 - t75 *
827 t78 * (t113 * t4 + t80 * t107);
828 dyda[LMP_SPACE] = t1 * (t104 * t121 - t61 * t26 * t124) * t38 * t40 -
829 t75 * t78 * (-t113 * t121 - t80 * t26 * t124);
830 dyda[LMP_SOFFX] = t1 * (t2 * t143 + t61 * t148 / 2.0) * t38 * t40 -
831 t75 * t78 * (-t23 * t143 + t80 * t148 / 2.0);
832 dyda[LMP_SOFFY] = t1 * (t2 * t166 + t61 * t173 / 2.0) * t38 * t40 -
833 t75 * t78 * (-t23 * t166 + t80 * t173 / 2.0);
834 dyda[LMP_SPHI] = t1 * (t2 * t201 + t61 * t210 / 2.0) * t38 * t40 -
835 t75 * t78 * (-t23 * t201 + t80 * t210 / 2.0);
838 dyda[LMP_NX] = -dyda[LMP_NX];
839 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
840 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
841 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
842 dyda[LMP_THETA] = -dyda[LMP_THETA];
843 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
844 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
845 dyda[LMP_SOFFX] = -dyda[LMP_SOFFX];
846 dyda[LMP_SOFFY] = -dyda[LMP_SOFFY];
847 dyda[LMP_SPHI] = -dyda[LMP_SPHI];
857 dyda[LMP_PXSIZ] *= _giraffe_dydaweight(a[LMP_PXSIZ], r[k],
863 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
869 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
875 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
881 dyda[LMP_ORDER] *= _giraffe_dydaweight(a[LMP_ORDER], r[k],
887 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
893 dyda[LMP_SOFFX] *= _giraffe_dydaweight(a[LMP_SOFFX], r[k],
899 dyda[LMP_SOFFY] *= _giraffe_dydaweight(a[LMP_SOFFY], r[k],
905 dyda[LMP_SPHI] *= _giraffe_dydaweight(a[LMP_SPHI], r[k],
919 _giraffe_yoptmod2_ctor(GiModel *
self,
const GiModelData *model)
922 cx_assert(
self != NULL);
923 cx_assert(model != NULL);
925 self->name = cx_strdup(model->name);
926 self->type = model->type;
928 self->model = model->eval;
935 self->arguments.names = cpl_propertylist_new();
937 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
938 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
939 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
941 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
942 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
949 self->parameters.names = cpl_propertylist_new();
951 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
953 cpl_propertylist_append_int(self->parameters.names,
"Order",
955 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
957 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
959 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
961 cpl_propertylist_append_int(self->parameters.names,
"Angle",
963 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
965 cpl_propertylist_append_int(self->parameters.names,
"Sdx",
967 cpl_propertylist_append_int(self->parameters.names,
"Sdy",
969 cpl_propertylist_append_int(self->parameters.names,
"Sphi",
972 self->parameters.count =
973 cpl_propertylist_get_size(self->parameters.names);
974 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
982 _giraffe_yoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
983 cxdouble *dyda, cxdouble *r)
986 const cxchar *
const fctid =
"_giraffe_yoptmod2_eval";
989 cxdouble lambda, xfibre, yfibre;
990 cxdouble pixsize, ny;
991 cxdouble fcoll, cfact;
992 cxdouble gtheta, gorder, gspace;
993 cxdouble slitdx, slitdy, slitphi;
995 register cxdouble t1, t2, t4, t6, t7;
996 register cxdouble t11, t12, t13, t14, t15, t16, t17, t18, t19;
997 register cxdouble t21, t22, t24, t25, t27, t29;
998 register cxdouble t31, t33, t35, t36, t37, t38, t39;
999 register cxdouble t42, t50, t51, t54, t56;
1000 register cxdouble t62, t65, t66, t68;
1001 register cxdouble t85;
1002 register cxdouble t102, t103;
1003 register cxdouble t112, t117, t118;
1004 register cxdouble t123;
1005 register cxdouble t136;
1006 register cxdouble t141, t145, t147;
1007 register cxdouble t159;
1008 register cxdouble t160;
1009 register cxdouble t172, t179;
1010 register cxdouble t184;
1017 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1025 dyda[LMP_PXSIZ] = 0.;
1026 dyda[LMP_FCOLL] = 0.;
1027 dyda[LMP_CFACT] = 0.;
1028 dyda[LMP_THETA] = 0.;
1029 dyda[LMP_ORDER] = 0.;
1030 dyda[LMP_SPACE] = 0.;
1031 dyda[LMP_SOFFX] = 0.;
1032 dyda[LMP_SOFFY] = 0.;
1033 dyda[LMP_SPHI] = 0.;
1036 lambda = x[LMI_WLEN];
1037 xfibre = x[LMI_XFIB];
1038 yfibre = x[LMI_YFIB];
1041 pixsize = a[LMP_PXSIZ];
1042 fcoll = a[LMP_FCOLL];
1043 cfact = a[LMP_CFACT];
1044 gtheta = a[LMP_THETA];
1045 gorder = a[LMP_ORDER];
1046 gspace = a[LMP_SPACE];
1047 slitdx = a[LMP_SOFFX];
1048 slitdy = a[LMP_SOFFY];
1049 slitphi = a[LMP_SPHI];
1051 lambda *= GI_NM_TO_MM;
1054 t2 = slitphi * slitphi;
1055 t4 = sqrt(1.0 - t2);
1056 t6 = yfibre * t4 + slitdy;
1058 t11 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
1061 t14 = fcoll * fcoll;
1062 t15 = t12 + t13 + t14;
1065 t18 = lambda * gorder;
1071 t27 = -t18 * t19 + t22 * t17 + t25 * t17;
1074 t33 = sqrt(1.0 - t13 * t29 - t31);
1075 t35 = -t27 * t24 + t21 * t33;
1080 t42 = pixsize * pixsize;
1081 t50 = 1 / t16 / t15;
1085 t62 = -t22 * t50 * fcoll + t24 * t17 - t14 * t24 * t50;
1089 t85 = -t11 * t24 * t17 + fcoll * t21 * t17;
1090 t102 = gspace * gspace;
1095 t123 = t117 - t22 * t118 / 2.0 - t25 * t118 / 2.0;
1098 t145 = -t22 * t141 / 2.0 - t25 * t141 / 2.0;
1101 t160 = yfibre * t159;
1102 t172 = 2.0 * t11 * xfibre * yfibre - 2.0 * t6 * yfibre * t159 * slitphi;
1104 t184 = xfibre * yfibre * t117 - t22 * t179 / 2.0 - t25 * t179 / 2.0;
1106 *y = -t7 * t39 + 0.5 * ny;
1111 dyda[LMP_PXSIZ] = t7 * t37 / t42;
1112 dyda[LMP_FCOLL] = -cfact * t6 * t39 + cfact * t14 * t6 * t51 * t38 +
1113 t7 * t56 * t38 * (-t62 * t24 + t65 * (2.0 * t68 * fcoll -
1114 2.0 * t27 * t62) / 2.0);
1115 dyda[LMP_CFACT] = -fcoll * t6 * t39;
1116 dyda[LMP_THETA] = t7 * t56 * t38 * (-t85 * t24 - t27 * t21 - t24 *
1117 t33 - t65 * t27 * t85);
1118 dyda[LMP_ORDER] = t7 * t56 * t38 * (lambda * t19 * t24 + t65 * t27 *
1120 dyda[LMP_SPACE] = t7 * t56 * t38 * (-t18 * t103 * t24 - t65 * t27 *
1122 dyda[LMP_SOFFX] = t7 * t51 * t38 * t112 / 2.0 + t7 * t56 * t38 *
1123 (-t123 * t24 + t65 * (t68 * t112 - 2.0 * t27 * t123) / 2.0);
1124 dyda[LMP_SOFFY] = -t1 * t39 + t7 * t51 * t38 * t136 / 2.0 + t7 *
1125 t56 * t38 * (-t145 * t24 + t65 * (-2.0 * t147 + t68 * t136 -
1126 2.0 * t27 * t145) / 2.0);
1127 dyda[LMP_SPHI] = t1 * t160 * slitphi * t17 * t36 * t38 + t7 * t51 *
1128 t38 * t172 / 2.0 + t7 * t56 * t38 *
1129 (-t184 * t24 + t65 * (2.0 * t147 * t160 * slitphi + t68 * t172 -
1130 2.0 * t27 * t184) / 2.0);
1140 _giraffe_gaussian_ctor(GiModel *
self,
const GiModelData *model)
1143 cx_assert(
self != NULL);
1144 cx_assert(model != NULL);
1146 self->name = cx_strdup(model->name);
1147 self->type = model->type;
1149 self->model = model->eval;
1156 self->arguments.names = cpl_propertylist_new();
1158 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1160 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1161 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1168 self->parameters.names = cpl_propertylist_new();
1170 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1172 cpl_propertylist_append_int(self->parameters.names,
"Center",
1174 cpl_propertylist_append_int(self->parameters.names,
"Background",
1176 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1179 self->parameters.count =
1180 cpl_propertylist_get_size(self->parameters.names);
1181 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1189 _giraffe_gaussian_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1190 cxdouble *dyda, cxdouble *r)
1193 const cxchar *
const fctid =
"_giraffe_gaussian_eval";
1209 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1216 dyda[LMP_AMPL] = 0.;
1217 dyda[LMP_CENT] = 0.;
1218 dyda[LMP_BACK] = 0.;
1219 dyda[LMP_WID1] = 0.;
1223 amplitude = a[LMP_AMPL];
1224 center = a[LMP_CENT];
1225 backg = a[LMP_BACK];
1226 width = a[LMP_WID1];
1228 xred = (x[0] - center) / width;
1230 ex = exp(-xred * xred / 2.);
1231 fac = amplitude * xred * ex;
1233 *y = amplitude * ex + backg;
1243 dyda[LMP_AMPL] = ex;
1244 dyda[LMP_CENT] = fac / width;
1245 dyda[LMP_BACK] = 1.;
1246 dyda[LMP_WID1] = (fac * xred) / width;
1256 _giraffe_psfcos_ctor(GiModel *
self,
const GiModelData *model)
1259 cx_assert(
self != NULL);
1260 cx_assert(model != NULL);
1262 self->name = cx_strdup(model->name);
1263 self->type = model->type;
1265 self->model = model->eval;
1272 self->arguments.names = cpl_propertylist_new();
1274 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1276 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1277 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1284 self->parameters.names = cpl_propertylist_new();
1286 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1288 cpl_propertylist_append_int(self->parameters.names,
"Center",
1290 cpl_propertylist_append_int(self->parameters.names,
"Background",
1292 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1294 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1297 self->parameters.count =
1298 cpl_propertylist_get_size(self->parameters.names);
1299 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1307 _giraffe_psfcos_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1308 cxdouble *dyda, cxdouble *r)
1311 const cxchar *
const fctid =
"_giraffe_psfcos_eval";
1316 cxdouble background;
1320 cxdouble t1, t2, t3, t4, t5, t6, t7, t8, t9;
1321 cxdouble t10, t13, t14, t15, t16;
1329 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1336 dyda[LMP_AMPL] = 0.;
1337 dyda[LMP_CENT] = 0.;
1338 dyda[LMP_BACK] = 0.;
1339 dyda[LMP_WID1] = 0.;
1340 dyda[LMP_WID2] = 0.;
1343 amplitude = a[LMP_AMPL];
1344 center = a[LMP_CENT];
1345 background = a[LMP_BACK];
1346 width1 = a[LMP_WID1];
1347 width2 = a[LMP_WID2];
1353 t5 = pow(t4, width1);
1359 t13 = amplitude * t9;
1363 t26 = t1 > 0.0 ? 1.0 : -1.0;
1369 dyda[LMP_WID2] = 1.0;
1373 *y = amplitude * t10 / 8.0 + background;
1377 dyda[LMP_AMPL] = t10 / 8.0;
1378 dyda[LMP_CENT] = 3.0 / 8.0 * t13 * t14 * CX_PI * t5 *
1380 dyda[LMP_BACK] = 1.0;
1381 dyda[LMP_WID1] = -3.0 / 8.0 * t15 * t6 * t16;
1382 dyda[LMP_WID2] = 3.0 / 8.0 * t15 * t6 * width1 * t3;
1393 _giraffe_psfexp_ctor(GiModel *
self,
const GiModelData *model)
1396 cx_assert(
self != NULL);
1397 cx_assert(model != NULL);
1399 self->name = cx_strdup(model->name);
1400 self->type = model->type;
1402 self->model = model->eval;
1409 self->arguments.names = cpl_propertylist_new();
1411 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1413 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1414 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1421 self->parameters.names = cpl_propertylist_new();
1423 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1425 cpl_propertylist_append_int(self->parameters.names,
"Center",
1427 cpl_propertylist_append_int(self->parameters.names,
"Background",
1429 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1431 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1434 self->parameters.count =
1435 cpl_propertylist_get_size(self->parameters.names);
1436 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1444 _giraffe_psfexp_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1445 cxdouble *dyda, cxdouble *r)
1448 const cxchar *
const fctid =
"_giraffe_psfexp_eval";
1452 cxdouble background;
1456 cxdouble t1, t2, t3, t4, t6, t8;
1457 cxdouble t10, t15, t18;
1463 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1470 dyda[LMP_AMPL] = 0.;
1471 dyda[LMP_CENT] = 0.;
1472 dyda[LMP_BACK] = 0.;
1473 dyda[LMP_WID1] = 0.;
1474 dyda[LMP_WID2] = 0.;
1477 amplitude = a[LMP_AMPL];
1478 center = a[LMP_CENT];
1479 background = a[LMP_BACK];
1480 width1 = a[LMP_WID1];
1481 width2 = a[LMP_WID2];
1494 t3 = pow(t2, width2);
1497 t8 = amplitude * t3;
1498 t15 = width1 * width1;
1501 *y = amplitude * t6 + background;
1504 dyda[LMP_AMPL] = t6;
1505 dyda[LMP_BACK] = 1.0;
1507 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t4 * t6;
1509 if (isnan(dyda[LMP_CENT])) {
1510 dyda[LMP_CENT] = 0.;
1513 dyda[LMP_WID1] = t8 / t15 * t6;
1515 if (isnan(dyda[LMP_WID1])) {
1516 dyda[LMP_WID1] = 0.;
1519 dyda[LMP_WID2] = -t8 * t18 * t4 * t6;
1521 if (isnan(dyda[LMP_WID2])) {
1522 dyda[LMP_WID2] = 0.;
1531 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
1537 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
1543 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
1549 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
1563 _giraffe_psfexp2_ctor(GiModel *
self,
const GiModelData *model)
1566 cx_assert(
self != NULL);
1567 cx_assert(model != NULL);
1569 self->name = cx_strdup(model->name);
1570 self->type = model->type;
1572 self->model = model->eval;
1579 self->arguments.names = cpl_propertylist_new();
1581 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1583 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1584 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1591 self->parameters.names = cpl_propertylist_new();
1593 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1595 cpl_propertylist_append_int(self->parameters.names,
"Center",
1597 cpl_propertylist_append_int(self->parameters.names,
"Background",
1599 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1601 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1604 self->parameters.count =
1605 cpl_propertylist_get_size(self->parameters.names);
1606 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1614 _giraffe_psfexp2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1615 cxdouble *dyda, cxdouble *r)
1618 const cxchar *
const fctid =
"_giraffe_psfexp2_eval";
1622 cxdouble background;
1626 cxdouble t1, t2, t3, t4, t5, t6, t8;
1633 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1640 dyda[LMP_AMPL] = 0.;
1641 dyda[LMP_CENT] = 0.;
1642 dyda[LMP_BACK] = 0.;
1643 dyda[LMP_WID1] = 0.;
1644 dyda[LMP_WID2] = 0.;
1647 amplitude = a[LMP_AMPL];
1648 center = a[LMP_CENT];
1649 background = a[LMP_BACK];
1650 width1 = a[LMP_WID1];
1651 width2 = a[LMP_WID2];
1666 t5 = pow(t4, width2);
1668 t8 = amplitude * t5;
1671 *y = amplitude * t6 + background;
1675 dyda[LMP_AMPL] = t6;
1677 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t6;
1679 if (isnan(dyda[LMP_CENT])) {
1680 dyda[LMP_CENT] = 0.0;
1683 dyda[LMP_BACK] = 1.0;
1684 dyda[LMP_WID1] = t8 * width2 * t3 * t6;
1686 dyda[LMP_WID2] = -t8 * t16 * t6;
1688 if (isnan(dyda[LMP_WID2])) {
1689 dyda[LMP_WID2] = 0.0;
1698 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
1704 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
1710 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
1716 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
1730 _giraffe_test_ctor(GiModel *
self,
const GiModelData *model)
1733 cx_assert(
self != NULL);
1734 cx_assert(model != NULL);
1736 self->name = cx_strdup(model->name);
1737 self->type = model->type;
1739 self->model = model->eval;
1746 self->arguments.names = cpl_propertylist_new();
1748 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1750 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1751 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1758 self->parameters.names = cpl_propertylist_new();
1760 cpl_propertylist_append_int(self->parameters.names,
"Slope", 0);
1761 cpl_propertylist_append_int(self->parameters.names,
"Intercept", 1);
1763 self->parameters.count =
1764 cpl_propertylist_get_size(self->parameters.names);
1765 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1773 _giraffe_test_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1774 cxdouble *dyda, cxdouble *r)
1777 const cxchar *
const fctid =
"_giraffe_test_eval";
1788 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1802 *y = a1 * x[0] + b1;
1820 static GiModelData _gimodels[] = {
1821 {
"xoptmod", GI_MODEL_XOPT,
1822 _giraffe_xoptmod_ctor, _giraffe_model_dtor, _giraffe_xoptmod_eval},
1823 {
"yoptmod", GI_MODEL_YOPT,
1824 _giraffe_yoptmod_ctor, _giraffe_model_dtor, _giraffe_yoptmod_eval},
1825 {
"xoptmod2", GI_MODEL_XOPT,
1826 _giraffe_xoptmod2_ctor, _giraffe_model_dtor, _giraffe_xoptmod2_eval},
1827 {
"yoptmod2", GI_MODEL_XOPT,
1828 _giraffe_yoptmod2_ctor, _giraffe_model_dtor, _giraffe_yoptmod2_eval},
1829 {
"gaussian", GI_MODEL_LINE,
1830 _giraffe_gaussian_ctor, _giraffe_model_dtor, _giraffe_gaussian_eval},
1831 {
"psfcos", GI_MODEL_LINE,
1832 _giraffe_psfcos_ctor, _giraffe_model_dtor, _giraffe_psfcos_eval},
1833 {
"psfexp", GI_MODEL_LINE,
1834 _giraffe_psfexp_ctor, _giraffe_model_dtor, _giraffe_psfexp_eval},
1835 {
"psfexp2", GI_MODEL_LINE,
1836 _giraffe_psfexp2_ctor, _giraffe_model_dtor, _giraffe_psfexp2_eval},
1837 {
"test", GI_MODEL_LINE,
1838 _giraffe_test_ctor, _giraffe_model_dtor, _giraffe_test_eval},
1839 {NULL, 0, NULL, NULL, NULL}