36 #include <cxmessages.h>
37 #include <cxstrutils.h>
43 static GiModelData _gimodels[];
45 const GiModelData *
const giraffe_models = _gimodels;
92 static const cxint DW_DEGREE = 3;
93 static const cxdouble DW_LOG001 = 2.302585093;
108 inline static cxdouble
109 _giraffe_dydaweight(cxdouble x, cxdouble x0, cxdouble dx)
115 w = exp(-pow(fabs(x - x0), DW_DEGREE) / pow(dx, DW_DEGREE / DW_LOG001));
127 _giraffe_model_dtor(GiModel *
self)
136 self->arguments.count = 0;
138 if (self->arguments.names) {
139 cpl_propertylist_delete(self->arguments.names);
140 self->arguments.names = NULL;
143 if (self->arguments.values) {
144 cpl_matrix_delete(self->arguments.values);
145 self->arguments.values = NULL;
149 self->parameters.count = 0;
151 if (self->parameters.names) {
152 cpl_propertylist_delete(self->parameters.names);
153 self->parameters.names = NULL;
156 if (self->parameters.values) {
157 cpl_matrix_delete(self->parameters.values);
158 self->parameters.values = NULL;
161 if (self->parameters.limits) {
162 cpl_matrix_delete(self->parameters.limits);
163 self->parameters.limits = NULL;
166 if (self->parameters.flags) {
167 cx_free(self->parameters.flags);
168 self->parameters.flags = NULL;
172 self->fit.iterations = 0;
174 if (self->fit.covariance) {
175 cpl_matrix_delete(self->fit.covariance);
176 self->fit.covariance = NULL;
185 _giraffe_xoptmod_ctor(GiModel *
self,
const GiModelData *model)
188 cx_assert(
self != NULL);
189 cx_assert(model != NULL);
191 self->name = cx_strdup(model->name);
192 self->type = model->type;
194 self->model = model->eval;
201 self->arguments.names = cpl_propertylist_new();
203 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
204 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
205 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
207 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
208 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
215 self->parameters.names = cpl_propertylist_new();
217 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
219 cpl_propertylist_append_int(self->parameters.names,
"Order",
221 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
223 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
225 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
227 cpl_propertylist_append_int(self->parameters.names,
"Angle",
229 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
232 self->parameters.count =
233 cpl_propertylist_get_size(self->parameters.names);
234 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
242 _giraffe_xoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
243 cxdouble *dyda, cxdouble *r)
246 const cxchar *
const fctid =
"_giraffe_xoptmod_eval";
253 cxdouble pixsize, nx;
254 cxdouble fcoll, cfact;
255 cxdouble gtheta, gorder, gspace;
257 register cxdouble xccd, d, X;
258 register cxdouble yfibre2, tmp, tmp2, d2, X2, gspace2;
259 register cxdouble sqtmp, costheta, sintheta;
264 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
272 dyda[LMP_PXSIZ] = 0.;
273 dyda[LMP_FCOLL] = 0.;
274 dyda[LMP_CFACT] = 0.;
275 dyda[LMP_THETA] = 0.;
276 dyda[LMP_ORDER] = 0.;
277 dyda[LMP_SPACE] = 0.;
280 lambda = x[LMI_WLEN];
281 xfibre = x[LMI_XFIB];
282 yfibre = x[LMI_YFIB];
285 pixsize = a[LMP_PXSIZ];
286 fcoll = a[LMP_FCOLL];
287 cfact = a[LMP_CFACT];
288 gtheta = a[LMP_THETA];
289 gorder = a[LMP_ORDER];
290 gspace = a[LMP_SPACE];
293 lambda *= GI_NM_TO_MM;
295 yfibre2 = yfibre * yfibre;
296 gspace2 = gspace * gspace;
297 costheta = cos(gtheta);
298 sintheta = sin(gtheta);
300 d2 = xfibre * xfibre + yfibre2 + (fcoll * fcoll);
303 X = (-lambda * gorder / gspace) + (xfibre * costheta / d) +
304 (fcoll * sintheta / d);
307 sqtmp = sqrt(1.0 - yfibre2 / d2 - X2);
308 tmp = -sintheta * X + costheta * sqtmp;
310 xccd = (cfact * fcoll * (X * costheta + sintheta * sqtmp)) / tmp;
318 *y = xccd / pixsize - 0.5 * nx;
321 *y = -xccd / pixsize + 0.5 * nx;
333 dyda[LMP_PXSIZ] = 0.0;
335 dyda[LMP_FCOLL] = cfact * (costheta * X + sintheta * sqtmp) / tmp +
336 cfact * fcoll * (costheta * (-X * fcoll / d2 + sintheta / d -
337 gorder * lambda * fcoll /
338 (d2 * gspace)) + 0.5 * sintheta *
339 (-2.0 * X * (-X * fcoll / d2 + sintheta / d -
340 gorder * lambda * fcoll /
342 2.0 * yfibre2 * fcoll / (d2 * d2)) / sqtmp) /
343 tmp - cfact * fcoll * (costheta * X + sintheta * sqtmp) *
344 (-sintheta * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
345 fcoll / (d2 * gspace)) + 0.5 * costheta *
346 (-2.0 * X * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
347 fcoll / (d2 * gspace)) + 2.0 * yfibre2 * fcoll /
348 (d2 * d2)) / sqtmp) / tmp2;
350 dyda[LMP_FCOLL] /= pixsize;
351 dyda[LMP_CFACT] = (xccd / cfact) / pixsize;
353 dyda[LMP_THETA] = cfact * fcoll * ((-xfibre * sintheta / d + fcoll *
354 costheta / d) * costheta -
355 sintheta * X - sintheta * X *
356 (-xfibre * sintheta / d + fcoll *
357 costheta / d) / sqtmp +
358 costheta * sqtmp) / tmp -
359 cfact * fcoll * (costheta * X + sintheta * sqtmp) *
360 (-(-xfibre * sintheta / d + fcoll * costheta / d) * sintheta -
361 costheta * X - costheta * X * (-xfibre * sintheta / d + fcoll *
363 sqtmp - sintheta * sqtmp) / tmp2;
365 dyda[LMP_THETA] /= pixsize;
366 dyda[LMP_ORDER] = 0.0;
368 dyda[LMP_SPACE] = cfact * fcoll * (lambda * gorder * costheta /
369 gspace2 - sintheta * X * lambda *
370 gorder / (sqtmp * gspace2)) /
371 tmp - cfact * fcoll * (X * costheta + sintheta * sqtmp) *
372 (-lambda * gorder * sintheta / gspace2 - costheta * X * lambda *
373 gorder / (sqtmp * gspace2)) / tmp2;
375 dyda[LMP_SPACE] /= pixsize;
378 dyda[LMP_NX] = -dyda[LMP_NX];
379 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
380 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
381 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
382 dyda[LMP_THETA] = -dyda[LMP_THETA];
383 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
384 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
393 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
399 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
405 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
411 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
425 _giraffe_yoptmod_ctor(GiModel *
self,
const GiModelData *model)
428 cx_assert(
self != NULL);
429 cx_assert(model != NULL);
431 self->name = cx_strdup(model->name);
432 self->type = model->type;
434 self->model = model->eval;
441 self->arguments.names = cpl_propertylist_new();
443 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
444 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
445 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
447 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
448 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
455 self->parameters.names = cpl_propertylist_new();
457 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
459 cpl_propertylist_append_int(self->parameters.names,
"Order",
461 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
463 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
465 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
467 cpl_propertylist_append_int(self->parameters.names,
"Angle",
469 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
472 self->parameters.count =
473 cpl_propertylist_get_size(self->parameters.names);
474 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
482 _giraffe_yoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
483 cxdouble *dyda, cxdouble *r)
486 const cxchar *
const fctid =
"_giraffe_yoptmod_eval";
488 cxdouble lambda, xfibre, yfibre;
489 cxdouble pixsize, ny;
490 cxdouble fcoll,cfact;
491 cxdouble gtheta,gorder,gspace;
493 register cxdouble t2, t3, t4, t5, t6, t7, t8, t9;
494 register cxdouble t10, t12, t13, t15, t18;
495 register cxdouble t22, t24, t26, t27, t28, t29;
496 register cxdouble t30, t33;
497 register cxdouble t41, t45, t47;
498 register cxdouble t53, t56, t57;
499 register cxdouble t76;
500 register cxdouble t93, t94;
507 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
515 dyda[LMP_PXSIZ] = 0.;
516 dyda[LMP_FCOLL] = 0.;
517 dyda[LMP_CFACT] = 0.;
518 dyda[LMP_THETA] = 0.;
519 dyda[LMP_ORDER] = 0.;
520 dyda[LMP_SPACE] = 0.;
523 lambda = x[LMI_WLEN];
524 xfibre = x[LMI_XFIB];
525 yfibre = x[LMI_YFIB];
528 pixsize = a[LMP_PXSIZ];
529 fcoll = a[LMP_FCOLL];
530 cfact = a[LMP_CFACT];
531 gtheta = a[LMP_THETA];
532 gorder = a[LMP_ORDER];
533 gspace = a[LMP_SPACE];
535 lambda *= GI_NM_TO_MM;
537 t2 = cfact * fcoll * yfibre;
538 t3 = xfibre * xfibre;
539 t4 = yfibre * yfibre;
544 t9 = lambda * gorder;
549 t18 = -t9 * t10 + t13 * t8 + fcoll * t15 * t8;
551 t24 = sqrt(1.0 - t4 / t6 - t22);
552 t26 = -t18 * t15 + t12 * t24;
557 t33 = pixsize * pixsize;
561 t53 = -t13 * t41 * fcoll + t15 * t8 - t5 * t15 * t41;
564 t76 = -xfibre * t15 * t8 + fcoll * t12 * t8;
565 t93 = gspace * gspace;
568 *y = -t2 * t30 + 0.5 * ny;
579 dyda[LMP_PXSIZ] = t2 * t28 / t33;
580 dyda[LMP_FCOLL] = -cfact * yfibre * t30 + cfact * t5 *
581 yfibre * t41 * t27 * t29 + t2 * t47 * t29 *
582 (-t53 * t15 + t56 * (2.0 * t4 / t57 * fcoll -
583 2.0 * t18 * t53) / 2.0);
584 dyda[LMP_CFACT] = -fcoll * yfibre * t30;
585 dyda[LMP_THETA] = t2 * t47 * t29 * (-t76 * t15 - t18 * t12 -
586 t15 * t24 - t56 * t18 * t76);
587 dyda[LMP_ORDER] = t2 * t47 *t29 *(lambda * t10 * t15 + t56 *
589 dyda[LMP_SPACE] = t2 * t47 * t29 * (-t9 * t94 * t15 -
590 t56 * t18 * t9 * t94);
600 _giraffe_xoptmod2_ctor(GiModel *
self,
const GiModelData *model)
603 cx_assert(
self != NULL);
604 cx_assert(model != NULL);
606 self->name = cx_strdup(model->name);
607 self->type = model->type;
609 self->model = model->eval;
616 self->arguments.names = cpl_propertylist_new();
618 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
619 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
620 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
622 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
623 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
630 self->parameters.names = cpl_propertylist_new();
632 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
634 cpl_propertylist_append_int(self->parameters.names,
"Order",
636 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
638 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
640 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
642 cpl_propertylist_append_int(self->parameters.names,
"Angle",
644 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
646 cpl_propertylist_append_int(self->parameters.names,
"Sdx",
648 cpl_propertylist_append_int(self->parameters.names,
"Sdy",
650 cpl_propertylist_append_int(self->parameters.names,
"Sphi",
653 self->parameters.count =
654 cpl_propertylist_get_size(self->parameters.names);
655 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
663 _giraffe_xoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
664 cxdouble *dyda, cxdouble *r)
667 const cxchar *
const fctid =
"_giraffe_xoptmod2_eval";
674 cxdouble pixsize, nx;
675 cxdouble fcoll, cfact;
676 cxdouble gtheta, gorder, gspace;
677 cxdouble slitdx, slitdy, slitphi;
679 register cxdouble t1, t2, t3, t4, t9;
680 register cxdouble t10, t11, t12, t14, t16, t17, t18, t19;
681 register cxdouble t20, t21, t23, t24, t26, t27, t28;
682 register cxdouble t30, t32, t33, t34, t35, t36, t37, t38, t39;
683 register cxdouble t40, t44, t49;
684 register cxdouble t52, t58;
685 register cxdouble t60, t61, t62, t64, t68;
686 register cxdouble t75, t76, t78;
687 register cxdouble t80;
688 register cxdouble t91, t93;
689 register cxdouble t104, t107;
690 register cxdouble t113, t119;
691 register cxdouble t120, t121, t124;
692 register cxdouble t136, t137, t138;
693 register cxdouble t143, t148;
694 register cxdouble t161, t162, t166, t168;
695 register cxdouble t173;
696 register cxdouble t191, t195, t196;
697 register cxdouble t201, t210;
701 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
709 dyda[LMP_PXSIZ] = 0.;
710 dyda[LMP_FCOLL] = 0.;
711 dyda[LMP_CFACT] = 0.;
712 dyda[LMP_THETA] = 0.;
713 dyda[LMP_ORDER] = 0.;
714 dyda[LMP_SPACE] = 0.;
715 dyda[LMP_SOFFX] = 0.;
716 dyda[LMP_SOFFY] = 0.;
720 lambda = x[LMI_WLEN];
721 xfibre = x[LMI_XFIB];
722 yfibre = x[LMI_YFIB];
725 pixsize = a[LMP_PXSIZ];
726 fcoll = a[LMP_FCOLL];
727 cfact = a[LMP_CFACT];
728 gtheta = a[LMP_THETA];
729 gorder = a[LMP_ORDER];
730 gspace = a[LMP_SPACE];
731 slitdx = a[LMP_SOFFX];
732 slitdy = a[LMP_SOFFY];
733 slitphi = a[LMP_SPHI];
735 lambda *= GI_NM_TO_MM;
739 t3 = lambda * gorder;
741 t9 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
744 t12 = slitphi * slitphi;
745 t14 = sqrt(1.0 - t12);
746 t16 = yfibre * t14 + slitdy;
749 t19 = t11 + t17 + t18;
754 t26 = -t3 * t4 + t10 * t21 + t24 * t21;
758 t32 = sqrt(1.0 - t17 * t28 - t30);
767 t44 = pixsize * pixsize;
769 t52 = 1.0 / t20 / t19;
770 t58 = -t10 * t52 * fcoll + t23 * t21 - t18 * t23 * t52;
775 t68 = 2.0 * t64 * fcoll - 2.0 * t26 * t58;
778 t78 = 1.0 / t76 * t40;
780 t91 = -t9 * t23 * t21 + fcoll * t2 * t21;
783 t107 = t26 * lambda * t4;
785 t119 = gspace * gspace;
787 t121 = gorder * t120;
792 t143 = t136 - t10 * t138 / 2.0 - t24 * t138 / 2.0;
793 t148 = t64 * t137 - 2.0 * t26 * t143;
796 t166 = -t10 * t162 / 2.0 - t24 * t162 / 2.0;
798 t173 = -2.0 * t168 + t64 * t161 - 2.0 * t26 * t166;
800 t195 = 2.0 * t9 * xfibre * yfibre - 2.0 * t16 * yfibre * t191 * slitphi;
802 t201 = xfibre * yfibre * t136 - t10 * t196 / 2.0 - t24 * t196 / 2.0;
803 t210 = 2.0 * t168 * yfibre * t191 * slitphi + t64 * t195 -
812 *y = t1 * t39 * t40 - 0.5 * nx;
815 *y = -t1 * t39 * t40 + 0.5 * nx;
827 dyda[LMP_PXSIZ] = -t1 * t39 / t44;
828 dyda[LMP_FCOLL] = cfact * t34 * t49 + t1 *
829 (t2 * t58 + t61 * t68 / 2.0) * t38 * t40 -
830 t75 * t78 * (-t23 * t58 + t80 * t68 / 2.0);
831 dyda[LMP_CFACT] = fcoll * t34 * t49;
832 dyda[LMP_THETA] = t1 * (-t35 + t2 * t91 + t36 - t61 * t93) * t38 *
833 t40 - t75 * t78 * (-t27 - t23 * t91 - t33 - t80 * t93);
834 dyda[LMP_ORDER] = t1 * (-t104 * t4 + t61 * t107) * t38 * t40 - t75 *
835 t78 * (t113 * t4 + t80 * t107);
836 dyda[LMP_SPACE] = t1 * (t104 * t121 - t61 * t26 * t124) * t38 * t40 -
837 t75 * t78 * (-t113 * t121 - t80 * t26 * t124);
838 dyda[LMP_SOFFX] = t1 * (t2 * t143 + t61 * t148 / 2.0) * t38 * t40 -
839 t75 * t78 * (-t23 * t143 + t80 * t148 / 2.0);
840 dyda[LMP_SOFFY] = t1 * (t2 * t166 + t61 * t173 / 2.0) * t38 * t40 -
841 t75 * t78 * (-t23 * t166 + t80 * t173 / 2.0);
842 dyda[LMP_SPHI] = t1 * (t2 * t201 + t61 * t210 / 2.0) * t38 * t40 -
843 t75 * t78 * (-t23 * t201 + t80 * t210 / 2.0);
846 dyda[LMP_NX] = -dyda[LMP_NX];
847 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
848 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
849 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
850 dyda[LMP_THETA] = -dyda[LMP_THETA];
851 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
852 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
853 dyda[LMP_SOFFX] = -dyda[LMP_SOFFX];
854 dyda[LMP_SOFFY] = -dyda[LMP_SOFFY];
855 dyda[LMP_SPHI] = -dyda[LMP_SPHI];
865 dyda[LMP_PXSIZ] *= _giraffe_dydaweight(a[LMP_PXSIZ], r[k],
871 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
877 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
883 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
889 dyda[LMP_ORDER] *= _giraffe_dydaweight(a[LMP_ORDER], r[k],
895 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
901 dyda[LMP_SOFFX] *= _giraffe_dydaweight(a[LMP_SOFFX], r[k],
907 dyda[LMP_SOFFY] *= _giraffe_dydaweight(a[LMP_SOFFY], r[k],
913 dyda[LMP_SPHI] *= _giraffe_dydaweight(a[LMP_SPHI], r[k],
927 _giraffe_yoptmod2_ctor(GiModel *
self,
const GiModelData *model)
930 cx_assert(
self != NULL);
931 cx_assert(model != NULL);
933 self->name = cx_strdup(model->name);
934 self->type = model->type;
936 self->model = model->eval;
943 self->arguments.names = cpl_propertylist_new();
945 cpl_propertylist_append_int(self->arguments.names,
"xf", LMI_XFIB);
946 cpl_propertylist_append_int(self->arguments.names,
"yf", LMI_YFIB);
947 cpl_propertylist_append_int(self->arguments.names,
"lambda", LMI_WLEN);
949 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
950 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
957 self->parameters.names = cpl_propertylist_new();
959 cpl_propertylist_append_int(self->parameters.names,
"Orientation",
961 cpl_propertylist_append_int(self->parameters.names,
"Order",
963 cpl_propertylist_append_int(self->parameters.names,
"PixelSize",
965 cpl_propertylist_append_int(self->parameters.names,
"FocalLength",
967 cpl_propertylist_append_int(self->parameters.names,
"Magnification",
969 cpl_propertylist_append_int(self->parameters.names,
"Angle",
971 cpl_propertylist_append_int(self->parameters.names,
"Spacing",
973 cpl_propertylist_append_int(self->parameters.names,
"Sdx",
975 cpl_propertylist_append_int(self->parameters.names,
"Sdy",
977 cpl_propertylist_append_int(self->parameters.names,
"Sphi",
980 self->parameters.count =
981 cpl_propertylist_get_size(self->parameters.names);
982 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
990 _giraffe_yoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
991 cxdouble *dyda, cxdouble *r)
994 const cxchar *
const fctid =
"_giraffe_yoptmod2_eval";
997 cxdouble lambda, xfibre, yfibre;
998 cxdouble pixsize, ny;
999 cxdouble fcoll, cfact;
1000 cxdouble gtheta, gorder, gspace;
1001 cxdouble slitdx, slitdy, slitphi;
1003 register cxdouble t1, t2, t4, t6, t7;
1004 register cxdouble t11, t12, t13, t14, t15, t16, t17, t18, t19;
1005 register cxdouble t21, t22, t24, t25, t27, t29;
1006 register cxdouble t31, t33, t35, t36, t37, t38, t39;
1007 register cxdouble t42, t50, t51, t54, t56;
1008 register cxdouble t62, t65, t66, t68;
1009 register cxdouble t85;
1010 register cxdouble t102, t103;
1011 register cxdouble t112, t117, t118;
1012 register cxdouble t123;
1013 register cxdouble t136;
1014 register cxdouble t141, t145, t147;
1015 register cxdouble t159;
1016 register cxdouble t160;
1017 register cxdouble t172, t179;
1018 register cxdouble t184;
1025 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1033 dyda[LMP_PXSIZ] = 0.;
1034 dyda[LMP_FCOLL] = 0.;
1035 dyda[LMP_CFACT] = 0.;
1036 dyda[LMP_THETA] = 0.;
1037 dyda[LMP_ORDER] = 0.;
1038 dyda[LMP_SPACE] = 0.;
1039 dyda[LMP_SOFFX] = 0.;
1040 dyda[LMP_SOFFY] = 0.;
1041 dyda[LMP_SPHI] = 0.;
1044 lambda = x[LMI_WLEN];
1045 xfibre = x[LMI_XFIB];
1046 yfibre = x[LMI_YFIB];
1049 pixsize = a[LMP_PXSIZ];
1050 fcoll = a[LMP_FCOLL];
1051 cfact = a[LMP_CFACT];
1052 gtheta = a[LMP_THETA];
1053 gorder = a[LMP_ORDER];
1054 gspace = a[LMP_SPACE];
1055 slitdx = a[LMP_SOFFX];
1056 slitdy = a[LMP_SOFFY];
1057 slitphi = a[LMP_SPHI];
1059 lambda *= GI_NM_TO_MM;
1062 t2 = slitphi * slitphi;
1063 t4 = sqrt(1.0 - t2);
1064 t6 = yfibre * t4 + slitdy;
1066 t11 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
1069 t14 = fcoll * fcoll;
1070 t15 = t12 + t13 + t14;
1073 t18 = lambda * gorder;
1079 t27 = -t18 * t19 + t22 * t17 + t25 * t17;
1082 t33 = sqrt(1.0 - t13 * t29 - t31);
1083 t35 = -t27 * t24 + t21 * t33;
1088 t42 = pixsize * pixsize;
1089 t50 = 1 / t16 / t15;
1093 t62 = -t22 * t50 * fcoll + t24 * t17 - t14 * t24 * t50;
1097 t85 = -t11 * t24 * t17 + fcoll * t21 * t17;
1098 t102 = gspace * gspace;
1103 t123 = t117 - t22 * t118 / 2.0 - t25 * t118 / 2.0;
1106 t145 = -t22 * t141 / 2.0 - t25 * t141 / 2.0;
1109 t160 = yfibre * t159;
1110 t172 = 2.0 * t11 * xfibre * yfibre - 2.0 * t6 * yfibre * t159 * slitphi;
1112 t184 = xfibre * yfibre * t117 - t22 * t179 / 2.0 - t25 * t179 / 2.0;
1114 *y = -t7 * t39 + 0.5 * ny;
1119 dyda[LMP_PXSIZ] = t7 * t37 / t42;
1120 dyda[LMP_FCOLL] = -cfact * t6 * t39 + cfact * t14 * t6 * t51 * t38 +
1121 t7 * t56 * t38 * (-t62 * t24 + t65 * (2.0 * t68 * fcoll -
1122 2.0 * t27 * t62) / 2.0);
1123 dyda[LMP_CFACT] = -fcoll * t6 * t39;
1124 dyda[LMP_THETA] = t7 * t56 * t38 * (-t85 * t24 - t27 * t21 - t24 *
1125 t33 - t65 * t27 * t85);
1126 dyda[LMP_ORDER] = t7 * t56 * t38 * (lambda * t19 * t24 + t65 * t27 *
1128 dyda[LMP_SPACE] = t7 * t56 * t38 * (-t18 * t103 * t24 - t65 * t27 *
1130 dyda[LMP_SOFFX] = t7 * t51 * t38 * t112 / 2.0 + t7 * t56 * t38 *
1131 (-t123 * t24 + t65 * (t68 * t112 - 2.0 * t27 * t123) / 2.0);
1132 dyda[LMP_SOFFY] = -t1 * t39 + t7 * t51 * t38 * t136 / 2.0 + t7 *
1133 t56 * t38 * (-t145 * t24 + t65 * (-2.0 * t147 + t68 * t136 -
1134 2.0 * t27 * t145) / 2.0);
1135 dyda[LMP_SPHI] = t1 * t160 * slitphi * t17 * t36 * t38 + t7 * t51 *
1136 t38 * t172 / 2.0 + t7 * t56 * t38 *
1137 (-t184 * t24 + t65 * (2.0 * t147 * t160 * slitphi + t68 * t172 -
1138 2.0 * t27 * t184) / 2.0);
1148 _giraffe_gaussian_ctor(GiModel *
self,
const GiModelData *model)
1151 cx_assert(
self != NULL);
1152 cx_assert(model != NULL);
1154 self->name = cx_strdup(model->name);
1155 self->type = model->type;
1157 self->model = model->eval;
1164 self->arguments.names = cpl_propertylist_new();
1166 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1168 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1169 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1176 self->parameters.names = cpl_propertylist_new();
1178 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1180 cpl_propertylist_append_int(self->parameters.names,
"Center",
1182 cpl_propertylist_append_int(self->parameters.names,
"Background",
1184 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1187 self->parameters.count =
1188 cpl_propertylist_get_size(self->parameters.names);
1189 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1197 _giraffe_gaussian_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1198 cxdouble *dyda, cxdouble *r)
1201 const cxchar *
const fctid =
"_giraffe_gaussian_eval";
1217 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1224 dyda[LMP_AMPL] = 0.;
1225 dyda[LMP_CENT] = 0.;
1226 dyda[LMP_BACK] = 0.;
1227 dyda[LMP_WID1] = 0.;
1231 amplitude = a[LMP_AMPL];
1232 center = a[LMP_CENT];
1233 backg = a[LMP_BACK];
1234 width = a[LMP_WID1];
1236 xred = (x[0] - center) / width;
1238 ex = exp(-xred * xred / 2.);
1239 fac = amplitude * xred * ex;
1241 *y = amplitude * ex + backg;
1251 dyda[LMP_AMPL] = ex;
1252 dyda[LMP_CENT] = fac / width;
1253 dyda[LMP_BACK] = 1.;
1254 dyda[LMP_WID1] = (fac * xred) / width;
1264 _giraffe_psfcos_ctor(GiModel *
self,
const GiModelData *model)
1267 cx_assert(
self != NULL);
1268 cx_assert(model != NULL);
1270 self->name = cx_strdup(model->name);
1271 self->type = model->type;
1273 self->model = model->eval;
1280 self->arguments.names = cpl_propertylist_new();
1282 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1284 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1285 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1292 self->parameters.names = cpl_propertylist_new();
1294 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1296 cpl_propertylist_append_int(self->parameters.names,
"Center",
1298 cpl_propertylist_append_int(self->parameters.names,
"Background",
1300 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1302 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1305 self->parameters.count =
1306 cpl_propertylist_get_size(self->parameters.names);
1307 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1315 _giraffe_psfcos_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1316 cxdouble *dyda, cxdouble *r)
1319 const cxchar *
const fctid =
"_giraffe_psfcos_eval";
1324 cxdouble background;
1328 cxdouble t1, t2, t3, t4, t5, t6, t7, t8, t9;
1329 cxdouble t10, t13, t14, t15, t16;
1337 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1344 dyda[LMP_AMPL] = 0.;
1345 dyda[LMP_CENT] = 0.;
1346 dyda[LMP_BACK] = 0.;
1347 dyda[LMP_WID1] = 0.;
1348 dyda[LMP_WID2] = 0.;
1351 amplitude = a[LMP_AMPL];
1352 center = a[LMP_CENT];
1353 background = a[LMP_BACK];
1354 width1 = a[LMP_WID1];
1355 width2 = a[LMP_WID2];
1361 t5 = pow(t4, width1);
1367 t13 = amplitude * t9;
1371 t26 = t1 > 0.0 ? 1.0 : -1.0;
1377 dyda[LMP_WID2] = 1.0;
1381 *y = amplitude * t10 / 8.0 + background;
1385 dyda[LMP_AMPL] = t10 / 8.0;
1386 dyda[LMP_CENT] = 3.0 / 8.0 * t13 * t14 * CX_PI * t5 *
1388 dyda[LMP_BACK] = 1.0;
1389 dyda[LMP_WID1] = -3.0 / 8.0 * t15 * t6 * t16;
1390 dyda[LMP_WID2] = 3.0 / 8.0 * t15 * t6 * width1 * t3;
1401 _giraffe_psfexp_ctor(GiModel *
self,
const GiModelData *model)
1404 cx_assert(
self != NULL);
1405 cx_assert(model != NULL);
1407 self->name = cx_strdup(model->name);
1408 self->type = model->type;
1410 self->model = model->eval;
1417 self->arguments.names = cpl_propertylist_new();
1419 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1421 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1422 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1429 self->parameters.names = cpl_propertylist_new();
1431 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1433 cpl_propertylist_append_int(self->parameters.names,
"Center",
1435 cpl_propertylist_append_int(self->parameters.names,
"Background",
1437 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1439 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1442 self->parameters.count =
1443 cpl_propertylist_get_size(self->parameters.names);
1444 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1452 _giraffe_psfexp_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1453 cxdouble *dyda, cxdouble *r)
1456 const cxchar *
const fctid =
"_giraffe_psfexp_eval";
1460 cxdouble background;
1464 cxdouble t1, t2, t3, t4, t6, t8;
1465 cxdouble t10, t15, t18;
1471 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1478 dyda[LMP_AMPL] = 0.;
1479 dyda[LMP_CENT] = 0.;
1480 dyda[LMP_BACK] = 0.;
1481 dyda[LMP_WID1] = 0.;
1482 dyda[LMP_WID2] = 0.;
1485 amplitude = a[LMP_AMPL];
1486 center = a[LMP_CENT];
1487 background = a[LMP_BACK];
1488 width1 = a[LMP_WID1];
1489 width2 = a[LMP_WID2];
1502 t3 = pow(t2, width2);
1505 t8 = amplitude * t3;
1506 t15 = width1 * width1;
1509 *y = amplitude * t6 + background;
1512 dyda[LMP_AMPL] = t6;
1513 dyda[LMP_BACK] = 1.0;
1515 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t4 * t6;
1517 if (isnan(dyda[LMP_CENT])) {
1518 dyda[LMP_CENT] = 0.;
1521 dyda[LMP_WID1] = t8 / t15 * t6;
1523 if (isnan(dyda[LMP_WID1])) {
1524 dyda[LMP_WID1] = 0.;
1527 dyda[LMP_WID2] = -t8 * t18 * t4 * t6;
1529 if (isnan(dyda[LMP_WID2])) {
1530 dyda[LMP_WID2] = 0.;
1539 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
1545 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
1551 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
1557 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
1571 _giraffe_psfexp2_ctor(GiModel *
self,
const GiModelData *model)
1574 cx_assert(
self != NULL);
1575 cx_assert(model != NULL);
1577 self->name = cx_strdup(model->name);
1578 self->type = model->type;
1580 self->model = model->eval;
1587 self->arguments.names = cpl_propertylist_new();
1589 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1591 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1592 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1599 self->parameters.names = cpl_propertylist_new();
1601 cpl_propertylist_append_int(self->parameters.names,
"Amplitude",
1603 cpl_propertylist_append_int(self->parameters.names,
"Center",
1605 cpl_propertylist_append_int(self->parameters.names,
"Background",
1607 cpl_propertylist_append_int(self->parameters.names,
"Width1",
1609 cpl_propertylist_append_int(self->parameters.names,
"Width2",
1612 self->parameters.count =
1613 cpl_propertylist_get_size(self->parameters.names);
1614 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1622 _giraffe_psfexp2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1623 cxdouble *dyda, cxdouble *r)
1626 const cxchar *
const fctid =
"_giraffe_psfexp2_eval";
1630 cxdouble background;
1634 cxdouble t1, t2, t3, t4, t5, t6, t8;
1641 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1648 dyda[LMP_AMPL] = 0.;
1649 dyda[LMP_CENT] = 0.;
1650 dyda[LMP_BACK] = 0.;
1651 dyda[LMP_WID1] = 0.;
1652 dyda[LMP_WID2] = 0.;
1655 amplitude = a[LMP_AMPL];
1656 center = a[LMP_CENT];
1657 background = a[LMP_BACK];
1658 width1 = a[LMP_WID1];
1659 width2 = a[LMP_WID2];
1674 t5 = pow(t4, width2);
1676 t8 = amplitude * t5;
1679 *y = amplitude * t6 + background;
1683 dyda[LMP_AMPL] = t6;
1685 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t6;
1687 if (isnan(dyda[LMP_CENT])) {
1688 dyda[LMP_CENT] = 0.0;
1691 dyda[LMP_BACK] = 1.0;
1692 dyda[LMP_WID1] = t8 * width2 * t3 * t6;
1694 dyda[LMP_WID2] = -t8 * t16 * t6;
1696 if (isnan(dyda[LMP_WID2])) {
1697 dyda[LMP_WID2] = 0.0;
1706 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
1712 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
1718 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
1724 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
1738 _giraffe_test_ctor(GiModel *
self,
const GiModelData *model)
1741 cx_assert(
self != NULL);
1742 cx_assert(model != NULL);
1744 self->name = cx_strdup(model->name);
1745 self->type = model->type;
1747 self->model = model->eval;
1754 self->arguments.names = cpl_propertylist_new();
1756 cpl_propertylist_append_int(self->arguments.names,
"x", 0);
1758 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
1759 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
1766 self->parameters.names = cpl_propertylist_new();
1768 cpl_propertylist_append_int(self->parameters.names,
"Slope", 0);
1769 cpl_propertylist_append_int(self->parameters.names,
"Intercept", 1);
1771 self->parameters.count =
1772 cpl_propertylist_get_size(self->parameters.names);
1773 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
1781 _giraffe_test_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
1782 cxdouble *dyda, cxdouble *r)
1785 const cxchar *
const fctid =
"_giraffe_test_eval";
1796 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1810 *y = a1 * x[0] + b1;
1828 static GiModelData _gimodels[] = {
1829 {
"xoptmod", GI_MODEL_XOPT,
1830 _giraffe_xoptmod_ctor, _giraffe_model_dtor, _giraffe_xoptmod_eval},
1831 {
"yoptmod", GI_MODEL_YOPT,
1832 _giraffe_yoptmod_ctor, _giraffe_model_dtor, _giraffe_yoptmod_eval},
1833 {
"xoptmod2", GI_MODEL_XOPT,
1834 _giraffe_xoptmod2_ctor, _giraffe_model_dtor, _giraffe_xoptmod2_eval},
1835 {
"yoptmod2", GI_MODEL_XOPT,
1836 _giraffe_yoptmod2_ctor, _giraffe_model_dtor, _giraffe_yoptmod2_eval},
1837 {
"gaussian", GI_MODEL_LINE,
1838 _giraffe_gaussian_ctor, _giraffe_model_dtor, _giraffe_gaussian_eval},
1839 {
"psfcos", GI_MODEL_LINE,
1840 _giraffe_psfcos_ctor, _giraffe_model_dtor, _giraffe_psfcos_eval},
1841 {
"psfexp", GI_MODEL_LINE,
1842 _giraffe_psfexp_ctor, _giraffe_model_dtor, _giraffe_psfexp_eval},
1843 {
"psfexp2", GI_MODEL_LINE,
1844 _giraffe_psfexp2_ctor, _giraffe_model_dtor, _giraffe_psfexp2_eval},
1845 {
"test", GI_MODEL_LINE,
1846 _giraffe_test_ctor, _giraffe_model_dtor, _giraffe_test_eval},
1847 {NULL, 0, NULL, NULL, NULL}