00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <math.h>
00033
00034 #include <cxtypes.h>
00035 #include <cxmemory.h>
00036 #include <cxmessages.h>
00037 #include <cxstrutils.h>
00038
00039 #include "gimacros.h"
00040 #include "gimodels.h"
00041
00042
00043 static GiModelData _gimodels[];
00044
00045 const GiModelData *const giraffe_models = _gimodels;
00046
00047
00048
00049
00050
00051
00052 enum {
00053 LMI_WLEN = 0,
00054 LMI_XFIB = 1,
00055 LMI_YFIB = 2
00056 };
00057
00058
00059
00060
00061
00062
00063 enum {
00064 LMP_NX = 0,
00065 LMP_NY = 0,
00066 LMP_PXSIZ = 1,
00067 LMP_FCOLL = 2,
00068 LMP_CFACT = 3,
00069 LMP_THETA = 4,
00070 LMP_ORDER = 5,
00071 LMP_SPACE = 6,
00072 LMP_SOFFX = 7,
00073 LMP_SOFFY = 8,
00074 LMP_SPHI = 9
00075 };
00076
00077
00078
00079
00080
00081
00082 enum {
00083 LMP_AMPL = 0,
00084 LMP_CENT = 1,
00085 LMP_BACK = 2,
00086 LMP_WID1 = 3,
00087 LMP_WID2 = 4
00088 };
00089
00090
00091
00092 static const cxint DW_DEGREE = 3;
00093 static const cxdouble DW_LOG001 = 2.302585093;
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 inline static cxdouble
00109 _giraffe_dydaweight(cxdouble x, cxdouble x0, cxdouble dx)
00110 {
00111
00112 register cxdouble w;
00113
00114
00115 w = exp(-pow(fabs(x - x0), DW_DEGREE) / pow(dx, DW_DEGREE / DW_LOG001));
00116
00117 if (isnan(w)) {
00118 w = 1;
00119 }
00120
00121 return w;
00122
00123 }
00124
00125
00126 inline static void
00127 _giraffe_model_dtor(GiModel *self)
00128 {
00129
00130 if (self->name) {
00131 cx_free(self->name);
00132 self->name = NULL;
00133 }
00134
00135
00136 self->arguments.count = 0;
00137
00138 if (self->arguments.names) {
00139 cpl_propertylist_delete(self->arguments.names);
00140 self->arguments.names = NULL;
00141 }
00142
00143 if (self->arguments.values) {
00144 cpl_matrix_delete(self->arguments.values);
00145 self->arguments.values = NULL;
00146 }
00147
00148
00149 self->parameters.count = 0;
00150
00151 if (self->parameters.names) {
00152 cpl_propertylist_delete(self->parameters.names);
00153 self->parameters.names = NULL;
00154 }
00155
00156 if (self->parameters.values) {
00157 cpl_matrix_delete(self->parameters.values);
00158 self->parameters.values = NULL;
00159 }
00160
00161 if (self->parameters.limits) {
00162 cpl_matrix_delete(self->parameters.limits);
00163 self->parameters.limits = NULL;
00164 }
00165
00166 if (self->parameters.flags) {
00167 cx_free(self->parameters.flags);
00168 self->parameters.flags = NULL;
00169 }
00170
00171
00172 self->fit.iterations = 0;
00173
00174 if (self->fit.covariance) {
00175 cpl_matrix_delete(self->fit.covariance);
00176 self->fit.covariance = NULL;
00177 }
00178
00179 return;
00180
00181 }
00182
00183
00184 inline static void
00185 _giraffe_xoptmod_ctor(GiModel *self, const GiModelData *model)
00186 {
00187
00188 cx_assert(self != NULL);
00189 cx_assert(model != NULL);
00190
00191 self->name = cx_strdup(model->name);
00192 self->type = model->type;
00193
00194 self->model = model->eval;
00195
00196
00197
00198
00199
00200
00201 self->arguments.names = cpl_propertylist_new();
00202
00203 cpl_propertylist_append_int(self->arguments.names, "xf", LMI_XFIB);
00204 cpl_propertylist_append_int(self->arguments.names, "yf", LMI_YFIB);
00205 cpl_propertylist_append_int(self->arguments.names, "lambda", LMI_WLEN);
00206
00207 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
00208 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
00209
00210
00211
00212
00213
00214
00215 self->parameters.names = cpl_propertylist_new();
00216
00217 cpl_propertylist_append_int(self->parameters.names, "Orientation",
00218 LMP_NX);
00219 cpl_propertylist_append_int(self->parameters.names, "Order",
00220 LMP_ORDER);
00221 cpl_propertylist_append_int(self->parameters.names, "PixelSize",
00222 LMP_PXSIZ);
00223 cpl_propertylist_append_int(self->parameters.names, "FocalLength",
00224 LMP_FCOLL);
00225 cpl_propertylist_append_int(self->parameters.names, "Magnification",
00226 LMP_CFACT);
00227 cpl_propertylist_append_int(self->parameters.names, "Angle",
00228 LMP_THETA);
00229 cpl_propertylist_append_int(self->parameters.names, "Spacing",
00230 LMP_SPACE);
00231
00232 self->parameters.count =
00233 cpl_propertylist_get_size(self->parameters.names);
00234 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
00235
00236 return;
00237
00238 }
00239
00240
00241 inline static void
00242 _giraffe_xoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
00243 cxdouble *dyda, cxdouble *r)
00244 {
00245
00246 const cxchar *const fctid = "_giraffe_xoptmod_eval";
00247
00248
00249 cxdouble lambda;
00250 cxdouble xfibre;
00251 cxdouble yfibre;
00252
00253 cxdouble pixsize, nx;
00254 cxdouble fcoll, cfact;
00255 cxdouble gtheta, gorder, gspace;
00256
00257 register cxdouble xccd, d, X;
00258 register cxdouble yfibre2, tmp, tmp2, d2, X2, gspace2;
00259 register cxdouble sqtmp, costheta, sintheta;
00260
00261
00262
00263 if (na != 7) {
00264 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00265 return;
00266 }
00267
00268 *y = 0.0;
00269
00270 if (dyda != NULL) {
00271 dyda[LMP_NX] = 0.;
00272 dyda[LMP_PXSIZ] = 0.;
00273 dyda[LMP_FCOLL] = 0.;
00274 dyda[LMP_CFACT] = 0.;
00275 dyda[LMP_THETA] = 0.;
00276 dyda[LMP_ORDER] = 0.;
00277 dyda[LMP_SPACE] = 0.;
00278 }
00279
00280 lambda = x[LMI_WLEN];
00281 xfibre = x[LMI_XFIB];
00282 yfibre = x[LMI_YFIB];
00283
00284 nx = a[LMP_NX];
00285 pixsize = a[LMP_PXSIZ];
00286 fcoll = a[LMP_FCOLL];
00287 cfact = a[LMP_CFACT];
00288 gtheta = a[LMP_THETA];
00289 gorder = a[LMP_ORDER];
00290 gspace = a[LMP_SPACE];
00291
00292
00293 lambda *= GI_NM_TO_MM;
00294
00295 yfibre2 = yfibre * yfibre;
00296 gspace2 = gspace * gspace;
00297 costheta = cos(gtheta);
00298 sintheta = sin(gtheta);
00299
00300 d2 = xfibre * xfibre + yfibre2 + (fcoll * fcoll);
00301 d = sqrt(d2);
00302
00303 X = (-lambda * gorder / gspace) + (xfibre * costheta / d) +
00304 (fcoll * sintheta / d);
00305 X2 = X * X;
00306
00307 sqtmp = sqrt(1.0 - yfibre2 / d2 - X2);
00308 tmp = -sintheta * X + costheta * sqtmp;
00309 tmp2 = tmp * tmp;
00310 xccd = (cfact * fcoll * (X * costheta + sintheta * sqtmp)) / tmp;
00311
00312
00313
00314
00315
00316
00317 if (nx < 0.0) {
00318 *y = xccd / pixsize - 0.5 * nx;
00319 }
00320 else {
00321 *y = -xccd / pixsize + 0.5 * nx;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 if (dyda != NULL) {
00331
00332 dyda[LMP_NX] = 0.5;
00333 dyda[LMP_PXSIZ] = 0.0;
00334
00335 dyda[LMP_FCOLL] = cfact * (costheta * X + sintheta * sqtmp) / tmp +
00336 cfact * fcoll * (costheta * (-X * fcoll / d2 + sintheta / d -
00337 gorder * lambda * fcoll /
00338 (d2 * gspace)) + 0.5 * sintheta *
00339 (-2.0 * X * (-X * fcoll / d2 + sintheta / d -
00340 gorder * lambda * fcoll /
00341 (d2 * gspace)) +
00342 2.0 * yfibre2 * fcoll / (d2 * d2)) / sqtmp) /
00343 tmp - cfact * fcoll * (costheta * X + sintheta * sqtmp) *
00344 (-sintheta * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
00345 fcoll / (d2 * gspace)) + 0.5 * costheta *
00346 (-2.0 * X * (-X * fcoll / d2 + sintheta / d - gorder * lambda *
00347 fcoll / (d2 * gspace)) + 2.0 * yfibre2 * fcoll /
00348 (d2 * d2)) / sqtmp) / tmp2;
00349
00350 dyda[LMP_FCOLL] /= pixsize;
00351 dyda[LMP_CFACT] = (xccd / cfact) / pixsize;
00352
00353 dyda[LMP_THETA] = cfact * fcoll * ((-xfibre * sintheta / d + fcoll *
00354 costheta / d) * costheta -
00355 sintheta * X - sintheta * X *
00356 (-xfibre * sintheta / d + fcoll *
00357 costheta / d) / sqtmp +
00358 costheta * sqtmp) / tmp -
00359 cfact * fcoll * (costheta * X + sintheta * sqtmp) *
00360 (-(-xfibre * sintheta / d + fcoll * costheta / d) * sintheta -
00361 costheta * X - costheta * X * (-xfibre * sintheta / d + fcoll *
00362 costheta / d) /
00363 sqtmp - sintheta * sqtmp) / tmp2;
00364
00365 dyda[LMP_THETA] /= pixsize;
00366 dyda[LMP_ORDER] = 0.0;
00367
00368 dyda[LMP_SPACE] = cfact * fcoll * (lambda * gorder * costheta /
00369 gspace2 - sintheta * X * lambda *
00370 gorder / (sqtmp * gspace2)) /
00371 tmp - cfact * fcoll * (X * costheta + sintheta * sqtmp) *
00372 (-lambda * gorder * sintheta / gspace2 - costheta * X * lambda *
00373 gorder / (sqtmp * gspace2)) / tmp2;
00374
00375 dyda[LMP_SPACE] /= pixsize;
00376
00377 if (nx > 0.) {
00378 dyda[LMP_NX] = -dyda[LMP_NX];
00379 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
00380 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
00381 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
00382 dyda[LMP_THETA] = -dyda[LMP_THETA];
00383 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
00384 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
00385 }
00386
00387 if (r != NULL) {
00388
00389 register cxint k;
00390
00391 k = LMP_FCOLL << 1;
00392 if (r[k+1] > 0) {
00393 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
00394 r[k + 1]);
00395 }
00396
00397 k = LMP_CFACT << 1;
00398 if (r[k+1] > 0) {
00399 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
00400 r[k + 1]);
00401 }
00402
00403 k = LMP_THETA << 1;
00404 if (r[k+1] > 0) {
00405 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
00406 r[k + 1]);
00407 }
00408
00409 k = LMP_SPACE << 1;
00410 if (r[k+1] > 0) {
00411 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
00412 r[k + 1]);
00413 }
00414
00415 }
00416
00417 }
00418
00419 return;
00420
00421 }
00422
00423
00424 inline static void
00425 _giraffe_yoptmod_ctor(GiModel *self, const GiModelData *model)
00426 {
00427
00428 cx_assert(self != NULL);
00429 cx_assert(model != NULL);
00430
00431 self->name = cx_strdup(model->name);
00432 self->type = model->type;
00433
00434 self->model = model->eval;
00435
00436
00437
00438
00439
00440
00441 self->arguments.names = cpl_propertylist_new();
00442
00443 cpl_propertylist_append_int(self->arguments.names, "xf", LMI_XFIB);
00444 cpl_propertylist_append_int(self->arguments.names, "yf", LMI_YFIB);
00445 cpl_propertylist_append_int(self->arguments.names, "lambda", LMI_WLEN);
00446
00447 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
00448 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
00449
00450
00451
00452
00453
00454
00455 self->parameters.names = cpl_propertylist_new();
00456
00457 cpl_propertylist_append_int(self->parameters.names, "Orientation",
00458 LMP_NY);
00459 cpl_propertylist_append_int(self->parameters.names, "Order",
00460 LMP_ORDER);
00461 cpl_propertylist_append_int(self->parameters.names, "PixelSize",
00462 LMP_PXSIZ);
00463 cpl_propertylist_append_int(self->parameters.names, "FocalLength",
00464 LMP_FCOLL);
00465 cpl_propertylist_append_int(self->parameters.names, "Magnification",
00466 LMP_CFACT);
00467 cpl_propertylist_append_int(self->parameters.names, "Angle",
00468 LMP_THETA);
00469 cpl_propertylist_append_int(self->parameters.names, "Spacing",
00470 LMP_SPACE);
00471
00472 self->parameters.count =
00473 cpl_propertylist_get_size(self->parameters.names);
00474 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
00475
00476 return;
00477
00478 }
00479
00480
00481 inline static void
00482 _giraffe_yoptmod_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
00483 cxdouble *dyda, cxdouble *r)
00484 {
00485
00486 const cxchar *const fctid = "_giraffe_yoptmod_eval";
00487
00488 cxdouble lambda, xfibre, yfibre;
00489 cxdouble pixsize, ny;
00490 cxdouble fcoll,cfact;
00491 cxdouble gtheta,gorder,gspace;
00492
00493 register cxdouble t2, t3, t4, t5, t6, t7, t8, t9;
00494 register cxdouble t10, t12, t13, t15, t18;
00495 register cxdouble t22, t24, t26, t27, t28, t29;
00496 register cxdouble t30, t33;
00497 register cxdouble t41, t45, t47;
00498 register cxdouble t53, t56, t57;
00499 register cxdouble t76;
00500 register cxdouble t93, t94;
00501
00502
00503
00504 r = NULL;
00505
00506 if (na != 7) {
00507 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00508 return;
00509 }
00510
00511 *y = 0.;
00512
00513 if (dyda != NULL) {
00514 dyda[LMP_NY] = 0.;
00515 dyda[LMP_PXSIZ] = 0.;
00516 dyda[LMP_FCOLL] = 0.;
00517 dyda[LMP_CFACT] = 0.;
00518 dyda[LMP_THETA] = 0.;
00519 dyda[LMP_ORDER] = 0.;
00520 dyda[LMP_SPACE] = 0.;
00521 }
00522
00523 lambda = x[LMI_WLEN];
00524 xfibre = x[LMI_XFIB];
00525 yfibre = x[LMI_YFIB];
00526
00527 ny = a[LMP_NY];
00528 pixsize = a[LMP_PXSIZ];
00529 fcoll = a[LMP_FCOLL];
00530 cfact = a[LMP_CFACT];
00531 gtheta = a[LMP_THETA];
00532 gorder = a[LMP_ORDER];
00533 gspace = a[LMP_SPACE];
00534
00535 lambda *= GI_NM_TO_MM;
00536
00537 t2 = cfact * fcoll * yfibre;
00538 t3 = xfibre * xfibre;
00539 t4 = yfibre * yfibre;
00540 t5 = fcoll * fcoll;
00541 t6 = t3 + t4 + t5;
00542 t7 = sqrt(t6);
00543 t8 = 1.0 / t7;
00544 t9 = lambda * gorder;
00545 t10 = 1.0 / gspace;
00546 t12 = cos(gtheta);
00547 t13 = xfibre * t12;
00548 t15 = sin(gtheta);
00549 t18 = -t9 * t10 + t13 * t8 + fcoll * t15 * t8;
00550 t22 = t18 * t18;
00551 t24 = sqrt(1.0 - t4 / t6 - t22);
00552 t26 = -t18 * t15 + t12 * t24;
00553 t27 = 1.0 / t26;
00554 t28 = t8 * t27;
00555 t29 = 1.0 / pixsize;
00556 t30 = t28 * t29;
00557 t33 = pixsize * pixsize;
00558 t41 = 1.0 / t7 / t6;
00559 t45 = t26 * t26;
00560 t47 = t8 / t45;
00561 t53 = -t13 * t41 * fcoll + t15 * t8 - t5 * t15 * t41;
00562 t56 = t12 / t24;
00563 t57 = t6 * t6;
00564 t76 = -xfibre * t15 * t8 + fcoll * t12 * t8;
00565 t93 = gspace * gspace;
00566 t94 = 1.0 / t93;
00567
00568 *y = -t2 * t30 + 0.5 * ny;
00569
00570
00571
00572
00573
00574
00575
00576 if (dyda != NULL) {
00577
00578 dyda[LMP_NY] = 0.5;
00579 dyda[LMP_PXSIZ] = t2 * t28 / t33;
00580 dyda[LMP_FCOLL] = -cfact * yfibre * t30 + cfact * t5 *
00581 yfibre * t41 * t27 * t29 + t2 * t47 * t29 *
00582 (-t53 * t15 + t56 * (2.0 * t4 / t57 * fcoll -
00583 2.0 * t18 * t53) / 2.0);
00584 dyda[LMP_CFACT] = -fcoll * yfibre * t30;
00585 dyda[LMP_THETA] = t2 * t47 * t29 * (-t76 * t15 - t18 * t12 -
00586 t15 * t24 - t56 * t18 * t76);
00587 dyda[LMP_ORDER] = t2 * t47 *t29 *(lambda * t10 * t15 + t56 *
00588 t18 * lambda * t10);
00589 dyda[LMP_SPACE] = t2 * t47 * t29 * (-t9 * t94 * t15 -
00590 t56 * t18 * t9 * t94);
00591
00592 }
00593
00594 return;
00595
00596 }
00597
00598
00599 inline static void
00600 _giraffe_xoptmod2_ctor(GiModel *self, const GiModelData *model)
00601 {
00602
00603 cx_assert(self != NULL);
00604 cx_assert(model != NULL);
00605
00606 self->name = cx_strdup(model->name);
00607 self->type = model->type;
00608
00609 self->model = model->eval;
00610
00611
00612
00613
00614
00615
00616 self->arguments.names = cpl_propertylist_new();
00617
00618 cpl_propertylist_append_int(self->arguments.names, "xf", LMI_XFIB);
00619 cpl_propertylist_append_int(self->arguments.names, "yf", LMI_YFIB);
00620 cpl_propertylist_append_int(self->arguments.names, "lambda", LMI_WLEN);
00621
00622 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
00623 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
00624
00625
00626
00627
00628
00629
00630 self->parameters.names = cpl_propertylist_new();
00631
00632 cpl_propertylist_append_int(self->parameters.names, "Orientation",
00633 LMP_NX);
00634 cpl_propertylist_append_int(self->parameters.names, "Order",
00635 LMP_ORDER);
00636 cpl_propertylist_append_int(self->parameters.names, "PixelSize",
00637 LMP_PXSIZ);
00638 cpl_propertylist_append_int(self->parameters.names, "FocalLength",
00639 LMP_FCOLL);
00640 cpl_propertylist_append_int(self->parameters.names, "Magnification",
00641 LMP_CFACT);
00642 cpl_propertylist_append_int(self->parameters.names, "Angle",
00643 LMP_THETA);
00644 cpl_propertylist_append_int(self->parameters.names, "Spacing",
00645 LMP_SPACE);
00646 cpl_propertylist_append_int(self->parameters.names, "Sdx",
00647 LMP_SOFFX);
00648 cpl_propertylist_append_int(self->parameters.names, "Sdy",
00649 LMP_SOFFY);
00650 cpl_propertylist_append_int(self->parameters.names, "Sphi",
00651 LMP_SPHI);
00652
00653 self->parameters.count =
00654 cpl_propertylist_get_size(self->parameters.names);
00655 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
00656
00657 return;
00658
00659 }
00660
00661
00662 inline static void
00663 _giraffe_xoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
00664 cxdouble *dyda, cxdouble *r)
00665 {
00666
00667 const cxchar *const fctid = "_giraffe_xoptmod2_eval";
00668
00669
00670 cxdouble lambda;
00671 cxdouble xfibre;
00672 cxdouble yfibre;
00673
00674 cxdouble pixsize, nx;
00675 cxdouble fcoll, cfact;
00676 cxdouble gtheta, gorder, gspace;
00677 cxdouble slitdx, slitdy, slitphi;
00678
00679 register cxdouble t1, t2, t3, t4, t9;
00680 register cxdouble t10, t11, t12, t14, t16, t17, t18, t19;
00681 register cxdouble t20, t21, t23, t24, t26, t27, t28;
00682 register cxdouble t30, t32, t33, t34, t35, t36, t37, t38, t39;
00683 register cxdouble t40, t44, t49;
00684 register cxdouble t52, t58;
00685 register cxdouble t60, t61, t62, t64, t68;
00686 register cxdouble t75, t76, t78;
00687 register cxdouble t80;
00688 register cxdouble t91, t93;
00689 register cxdouble t104, t107;
00690 register cxdouble t113, t119;
00691 register cxdouble t120, t121, t124;
00692 register cxdouble t136, t137, t138;
00693 register cxdouble t143, t148;
00694 register cxdouble t161, t162, t166, t168;
00695 register cxdouble t173;
00696 register cxdouble t191, t195, t196;
00697 register cxdouble t201, t210;
00698
00699
00700 if (na != 10) {
00701 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00702 return;
00703 }
00704
00705 *y = 0.0;
00706
00707 if (dyda != NULL) {
00708 dyda[LMP_NX] = 0.;
00709 dyda[LMP_PXSIZ] = 0.;
00710 dyda[LMP_FCOLL] = 0.;
00711 dyda[LMP_CFACT] = 0.;
00712 dyda[LMP_THETA] = 0.;
00713 dyda[LMP_ORDER] = 0.;
00714 dyda[LMP_SPACE] = 0.;
00715 dyda[LMP_SOFFX] = 0.;
00716 dyda[LMP_SOFFY] = 0.;
00717 dyda[LMP_SPHI] = 0.;
00718 }
00719
00720 lambda = x[LMI_WLEN];
00721 xfibre = x[LMI_XFIB];
00722 yfibre = x[LMI_YFIB];
00723
00724 nx = a[LMP_NX];
00725 pixsize = a[LMP_PXSIZ];
00726 fcoll = a[LMP_FCOLL];
00727 cfact = a[LMP_CFACT];
00728 gtheta = a[LMP_THETA];
00729 gorder = a[LMP_ORDER];
00730 gspace = a[LMP_SPACE];
00731 slitdx = a[LMP_SOFFX];
00732 slitdy = a[LMP_SOFFY];
00733 slitphi = a[LMP_SPHI];
00734
00735 lambda *= GI_NM_TO_MM;
00736
00737 t1 = cfact * fcoll;
00738 t2 = cos(gtheta);
00739 t3 = lambda * gorder;
00740 t4 = 1.0 / gspace;
00741 t9 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
00742 t10 = t9 * t2;
00743 t11 = t9 * t9;
00744 t12 = slitphi * slitphi;
00745 t14 = sqrt(1.0 - t12);
00746 t16 = yfibre * t14 + slitdy;
00747 t17 = t16 * t16;
00748 t18 = fcoll * fcoll;
00749 t19 = t11 + t17 + t18;
00750 t20 = sqrt(t19);
00751 t21 = 1.0 / t20;
00752 t23 = sin(gtheta);
00753 t24 = fcoll * t23;
00754 t26 = -t3 * t4 + t10 * t21 + t24 * t21;
00755 t27 = t2 * t26;
00756 t28 = 1.0 / t19;
00757 t30 = t26 * t26;
00758 t32 = sqrt(1.0 - t17 * t28 - t30);
00759 t33 = t23 * t32;
00760 t34 = t27 + t33;
00761 t35 = t23 * t26;
00762 t36 = t2 * t32;
00763 t37 = -t35 + t36;
00764 t38 = 1.0 / t37;
00765 t39 = t34 * t38;
00766 t40 = 1.0 / pixsize;
00767 t44 = pixsize * pixsize;
00768 t49 = t38 * t40;
00769 t52 = 1.0 / t20 / t19;
00770 t58 = -t10 * t52 * fcoll + t23 * t21 - t18 * t23 * t52;
00771 t60 = 1.0 / t32;
00772 t61 = t23 * t60;
00773 t62 = t19 * t19;
00774 t64 = t17 / t62;
00775 t68 = 2.0 * t64 * fcoll - 2.0 * t26 * t58;
00776 t75 = t1 * t34;
00777 t76 = t37 * t37;
00778 t78 = 1.0 / t76 * t40;
00779 t80 = t2 * t60;
00780 t91 = -t9 * t23 * t21 + fcoll * t2 * t21;
00781 t93 = t26 * t91;
00782 t104 = t2 * lambda;
00783 t107 = t26 * lambda * t4;
00784 t113 = t23 * lambda;
00785 t119 = gspace * gspace;
00786 t120 = 1.0 / t119;
00787 t121 = gorder * t120;
00788 t124 = t3 * t120;
00789 t136 = t2 * t21;
00790 t137 = 2.0 * t9;
00791 t138 = t52 * t137;
00792 t143 = t136 - t10 * t138 / 2.0 - t24 * t138 / 2.0;
00793 t148 = t64 * t137 - 2.0 * t26 * t143;
00794 t161 = 2.0 * t16;
00795 t162 = t52 * t161;
00796 t166 = -t10 * t162 / 2.0 - t24 * t162 / 2.0;
00797 t168 = t16 * t28;
00798 t173 = -2.0 * t168 + t64 * t161 - 2.0 * t26 * t166;
00799 t191 = 1.0 / t14;
00800 t195 = 2.0 * t9 * xfibre * yfibre - 2.0 * t16 * yfibre * t191 * slitphi;
00801 t196 = t52 * t195;
00802 t201 = xfibre * yfibre * t136 - t10 * t196 / 2.0 - t24 * t196 / 2.0;
00803 t210 = 2.0 * t168 * yfibre * t191 * slitphi + t64 * t195 -
00804 2.0 * t26 * t201;
00805
00806
00807
00808
00809
00810
00811 if (nx < 0.0) {
00812 *y = t1 * t39 * t40 - 0.5 * nx;
00813 }
00814 else {
00815 *y = -t1 * t39 * t40 + 0.5 * nx;
00816 }
00817
00818
00819
00820
00821
00822
00823
00824 if (dyda != NULL) {
00825
00826 dyda[LMP_NX] = 0.5;
00827 dyda[LMP_PXSIZ] = -t1 * t39 / t44;
00828 dyda[LMP_FCOLL] = cfact * t34 * t49 + t1 *
00829 (t2 * t58 + t61 * t68 / 2.0) * t38 * t40 -
00830 t75 * t78 * (-t23 * t58 + t80 * t68 / 2.0);
00831 dyda[LMP_CFACT] = fcoll * t34 * t49;
00832 dyda[LMP_THETA] = t1 * (-t35 + t2 * t91 + t36 - t61 * t93) * t38 *
00833 t40 - t75 * t78 * (-t27 - t23 * t91 - t33 - t80 * t93);
00834 dyda[LMP_ORDER] = t1 * (-t104 * t4 + t61 * t107) * t38 * t40 - t75 *
00835 t78 * (t113 * t4 + t80 * t107);
00836 dyda[LMP_SPACE] = t1 * (t104 * t121 - t61 * t26 * t124) * t38 * t40 -
00837 t75 * t78 * (-t113 * t121 - t80 * t26 * t124);
00838 dyda[LMP_SOFFX] = t1 * (t2 * t143 + t61 * t148 / 2.0) * t38 * t40 -
00839 t75 * t78 * (-t23 * t143 + t80 * t148 / 2.0);
00840 dyda[LMP_SOFFY] = t1 * (t2 * t166 + t61 * t173 / 2.0) * t38 * t40 -
00841 t75 * t78 * (-t23 * t166 + t80 * t173 / 2.0);
00842 dyda[LMP_SPHI] = t1 * (t2 * t201 + t61 * t210 / 2.0) * t38 * t40 -
00843 t75 * t78 * (-t23 * t201 + t80 * t210 / 2.0);
00844
00845 if (nx > 0.0) {
00846 dyda[LMP_NX] = -dyda[LMP_NX];
00847 dyda[LMP_PXSIZ] = -dyda[LMP_PXSIZ];
00848 dyda[LMP_FCOLL] = -dyda[LMP_FCOLL];
00849 dyda[LMP_CFACT] = -dyda[LMP_CFACT];
00850 dyda[LMP_THETA] = -dyda[LMP_THETA];
00851 dyda[LMP_ORDER] = -dyda[LMP_ORDER];
00852 dyda[LMP_SPACE] = -dyda[LMP_SPACE];
00853 dyda[LMP_SOFFX] = -dyda[LMP_SOFFX];
00854 dyda[LMP_SOFFY] = -dyda[LMP_SOFFY];
00855 dyda[LMP_SPHI] = -dyda[LMP_SPHI];
00856 }
00857
00858 if (r != NULL) {
00859
00860 register cxint k;
00861
00862
00863 k = LMP_PXSIZ << 1;
00864 if (r[k + 1] > 0) {
00865 dyda[LMP_PXSIZ] *= _giraffe_dydaweight(a[LMP_PXSIZ], r[k],
00866 r[k + 1]);
00867 }
00868
00869 k = LMP_FCOLL << 1;
00870 if (r[k + 1] > 0) {
00871 dyda[LMP_FCOLL] *= _giraffe_dydaweight(a[LMP_FCOLL], r[k],
00872 r[k + 1]);
00873 }
00874
00875 k = LMP_CFACT << 1;
00876 if (r[k + 1] > 0) {
00877 dyda[LMP_CFACT] *= _giraffe_dydaweight(a[LMP_CFACT], r[k],
00878 r[k + 1]);
00879 }
00880
00881 k = LMP_THETA << 1;
00882 if (r[k + 1] > 0) {
00883 dyda[LMP_THETA] *= _giraffe_dydaweight(a[LMP_THETA], r[k],
00884 r[k + 1]);
00885 }
00886
00887 k = LMP_ORDER << 1;
00888 if (r[k + 1] > 0) {
00889 dyda[LMP_ORDER] *= _giraffe_dydaweight(a[LMP_ORDER], r[k],
00890 r[k + 1]);
00891 }
00892
00893 k = LMP_SPACE << 1;
00894 if (r[k + 1] > 0) {
00895 dyda[LMP_SPACE] *= _giraffe_dydaweight(a[LMP_SPACE], r[k],
00896 r[k + 1]);
00897 }
00898
00899 k = LMP_SOFFX << 1;
00900 if (r[k + 1] > 0) {
00901 dyda[LMP_SOFFX] *= _giraffe_dydaweight(a[LMP_SOFFX], r[k],
00902 r[k + 1]);
00903 }
00904
00905 k = LMP_SOFFY << 1;
00906 if (r[k + 1] > 0) {
00907 dyda[LMP_SOFFY] *= _giraffe_dydaweight(a[LMP_SOFFY], r[k],
00908 r[k + 1]);
00909 }
00910
00911 k = LMP_SPHI << 1;
00912 if (r[k + 1] > 0) {
00913 dyda[LMP_SPHI] *= _giraffe_dydaweight(a[LMP_SPHI], r[k],
00914 r[k + 1]);
00915 }
00916
00917 }
00918
00919 }
00920
00921 return;
00922
00923 }
00924
00925
00926 inline static void
00927 _giraffe_yoptmod2_ctor(GiModel *self, const GiModelData *model)
00928 {
00929
00930 cx_assert(self != NULL);
00931 cx_assert(model != NULL);
00932
00933 self->name = cx_strdup(model->name);
00934 self->type = model->type;
00935
00936 self->model = model->eval;
00937
00938
00939
00940
00941
00942
00943 self->arguments.names = cpl_propertylist_new();
00944
00945 cpl_propertylist_append_int(self->arguments.names, "xf", LMI_XFIB);
00946 cpl_propertylist_append_int(self->arguments.names, "yf", LMI_YFIB);
00947 cpl_propertylist_append_int(self->arguments.names, "lambda", LMI_WLEN);
00948
00949 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
00950 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
00951
00952
00953
00954
00955
00956
00957 self->parameters.names = cpl_propertylist_new();
00958
00959 cpl_propertylist_append_int(self->parameters.names, "Orientation",
00960 LMP_NY);
00961 cpl_propertylist_append_int(self->parameters.names, "Order",
00962 LMP_ORDER);
00963 cpl_propertylist_append_int(self->parameters.names, "PixelSize",
00964 LMP_PXSIZ);
00965 cpl_propertylist_append_int(self->parameters.names, "FocalLength",
00966 LMP_FCOLL);
00967 cpl_propertylist_append_int(self->parameters.names, "Magnification",
00968 LMP_CFACT);
00969 cpl_propertylist_append_int(self->parameters.names, "Angle",
00970 LMP_THETA);
00971 cpl_propertylist_append_int(self->parameters.names, "Spacing",
00972 LMP_SPACE);
00973 cpl_propertylist_append_int(self->parameters.names, "Sdx",
00974 LMP_SOFFX);
00975 cpl_propertylist_append_int(self->parameters.names, "Sdy",
00976 LMP_SOFFY);
00977 cpl_propertylist_append_int(self->parameters.names, "Sphi",
00978 LMP_SPHI);
00979
00980 self->parameters.count =
00981 cpl_propertylist_get_size(self->parameters.names);
00982 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
00983
00984 return;
00985
00986 }
00987
00988
00989 inline static void
00990 _giraffe_yoptmod2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
00991 cxdouble *dyda, cxdouble *r)
00992 {
00993
00994 const cxchar *const fctid = "_giraffe_yoptmod2_eval";
00995
00996
00997 cxdouble lambda, xfibre, yfibre;
00998 cxdouble pixsize, ny;
00999 cxdouble fcoll, cfact;
01000 cxdouble gtheta, gorder, gspace;
01001 cxdouble slitdx, slitdy, slitphi;
01002
01003 register cxdouble t1, t2, t4, t6, t7;
01004 register cxdouble t11, t12, t13, t14, t15, t16, t17, t18, t19;
01005 register cxdouble t21, t22, t24, t25, t27, t29;
01006 register cxdouble t31, t33, t35, t36, t37, t38, t39;
01007 register cxdouble t42, t50, t51, t54, t56;
01008 register cxdouble t62, t65, t66, t68;
01009 register cxdouble t85;
01010 register cxdouble t102, t103;
01011 register cxdouble t112, t117, t118;
01012 register cxdouble t123;
01013 register cxdouble t136;
01014 register cxdouble t141, t145, t147;
01015 register cxdouble t159;
01016 register cxdouble t160;
01017 register cxdouble t172, t179;
01018 register cxdouble t184;
01019
01020
01021
01022 r = NULL;
01023
01024 if (na != 10) {
01025 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01026 return;
01027 }
01028
01029 *y = 0.0;
01030
01031 if (dyda != NULL) {
01032 dyda[LMP_NY] = 0.;
01033 dyda[LMP_PXSIZ] = 0.;
01034 dyda[LMP_FCOLL] = 0.;
01035 dyda[LMP_CFACT] = 0.;
01036 dyda[LMP_THETA] = 0.;
01037 dyda[LMP_ORDER] = 0.;
01038 dyda[LMP_SPACE] = 0.;
01039 dyda[LMP_SOFFX] = 0.;
01040 dyda[LMP_SOFFY] = 0.;
01041 dyda[LMP_SPHI] = 0.;
01042 }
01043
01044 lambda = x[LMI_WLEN];
01045 xfibre = x[LMI_XFIB];
01046 yfibre = x[LMI_YFIB];
01047
01048 ny = a[LMP_NY];
01049 pixsize = a[LMP_PXSIZ];
01050 fcoll = a[LMP_FCOLL];
01051 cfact = a[LMP_CFACT];
01052 gtheta = a[LMP_THETA];
01053 gorder = a[LMP_ORDER];
01054 gspace = a[LMP_SPACE];
01055 slitdx = a[LMP_SOFFX];
01056 slitdy = a[LMP_SOFFY];
01057 slitphi = a[LMP_SPHI];
01058
01059 lambda *= GI_NM_TO_MM;
01060
01061 t1 = cfact * fcoll;
01062 t2 = slitphi * slitphi;
01063 t4 = sqrt(1.0 - t2);
01064 t6 = yfibre * t4 + slitdy;
01065 t7 = t1 * t6;
01066 t11 = xfibre * (1.0 + slitphi * yfibre) + slitdx;
01067 t12 = t11 * t11;
01068 t13 = t6 * t6;
01069 t14 = fcoll * fcoll;
01070 t15 = t12 + t13 + t14;
01071 t16 = sqrt(t15);
01072 t17 = 1 / t16;
01073 t18 = lambda * gorder;
01074 t19 = 1 / gspace;
01075 t21 = cos(gtheta);
01076 t22 = t11 * t21;
01077 t24 = sin(gtheta);
01078 t25 = fcoll * t24;
01079 t27 = -t18 * t19 + t22 * t17 + t25 * t17;
01080 t29 = 1 / t15;
01081 t31 = t27 * t27;
01082 t33 = sqrt(1.0 - t13 * t29 - t31);
01083 t35 = -t27 * t24 + t21 * t33;
01084 t36 = 1 / t35;
01085 t37 = t17 * t36;
01086 t38 = 1 / pixsize;
01087 t39 = t37 * t38;
01088 t42 = pixsize * pixsize;
01089 t50 = 1 / t16 / t15;
01090 t51 = t50 * t36;
01091 t54 = t35 * t35;
01092 t56 = t17 / t54;
01093 t62 = -t22 * t50 * fcoll + t24 * t17 - t14 * t24 * t50;
01094 t65 = t21 / t33;
01095 t66 = t15 * t15;
01096 t68 = t13 / t66;
01097 t85 = -t11 * t24 * t17 + fcoll * t21 * t17;
01098 t102 = gspace * gspace;
01099 t103 = 1 / t102;
01100 t112 = 2.0 * t11;
01101 t117 = t21 * t17;
01102 t118 = t50 * t112;
01103 t123 = t117 - t22 * t118 / 2.0 - t25 * t118 / 2.0;
01104 t136 = 2.0 * t6;
01105 t141 = t50 * t136;
01106 t145 = -t22 * t141 / 2.0 - t25 * t141 / 2.0;
01107 t147 = t6 * t29;
01108 t159 = 1 / t4;
01109 t160 = yfibre * t159;
01110 t172 = 2.0 * t11 * xfibre * yfibre - 2.0 * t6 * yfibre * t159 * slitphi;
01111 t179 = t50 * t172;
01112 t184 = xfibre * yfibre * t117 - t22 * t179 / 2.0 - t25 * t179 / 2.0;
01113
01114 *y = -t7 * t39 + 0.5 * ny;
01115
01116 if (dyda != NULL) {
01117
01118 dyda[LMP_NY] = 0.5;
01119 dyda[LMP_PXSIZ] = t7 * t37 / t42;
01120 dyda[LMP_FCOLL] = -cfact * t6 * t39 + cfact * t14 * t6 * t51 * t38 +
01121 t7 * t56 * t38 * (-t62 * t24 + t65 * (2.0 * t68 * fcoll -
01122 2.0 * t27 * t62) / 2.0);
01123 dyda[LMP_CFACT] = -fcoll * t6 * t39;
01124 dyda[LMP_THETA] = t7 * t56 * t38 * (-t85 * t24 - t27 * t21 - t24 *
01125 t33 - t65 * t27 * t85);
01126 dyda[LMP_ORDER] = t7 * t56 * t38 * (lambda * t19 * t24 + t65 * t27 *
01127 lambda * t19);
01128 dyda[LMP_SPACE] = t7 * t56 * t38 * (-t18 * t103 * t24 - t65 * t27 *
01129 t18 * t103);
01130 dyda[LMP_SOFFX] = t7 * t51 * t38 * t112 / 2.0 + t7 * t56 * t38 *
01131 (-t123 * t24 + t65 * (t68 * t112 - 2.0 * t27 * t123) / 2.0);
01132 dyda[LMP_SOFFY] = -t1 * t39 + t7 * t51 * t38 * t136 / 2.0 + t7 *
01133 t56 * t38 * (-t145 * t24 + t65 * (-2.0 * t147 + t68 * t136 -
01134 2.0 * t27 * t145) / 2.0);
01135 dyda[LMP_SPHI] = t1 * t160 * slitphi * t17 * t36 * t38 + t7 * t51 *
01136 t38 * t172 / 2.0 + t7 * t56 * t38 *
01137 (-t184 * t24 + t65 * (2.0 * t147 * t160 * slitphi + t68 * t172 -
01138 2.0 * t27 * t184) / 2.0);
01139
01140 }
01141
01142 return;
01143
01144 }
01145
01146
01147 inline static void
01148 _giraffe_gaussian_ctor(GiModel *self, const GiModelData *model)
01149 {
01150
01151 cx_assert(self != NULL);
01152 cx_assert(model != NULL);
01153
01154 self->name = cx_strdup(model->name);
01155 self->type = model->type;
01156
01157 self->model = model->eval;
01158
01159
01160
01161
01162
01163
01164 self->arguments.names = cpl_propertylist_new();
01165
01166 cpl_propertylist_append_int(self->arguments.names, "x", 0);
01167
01168 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
01169 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
01170
01171
01172
01173
01174
01175
01176 self->parameters.names = cpl_propertylist_new();
01177
01178 cpl_propertylist_append_int(self->parameters.names, "Amplitude",
01179 LMP_AMPL);
01180 cpl_propertylist_append_int(self->parameters.names, "Center",
01181 LMP_CENT);
01182 cpl_propertylist_append_int(self->parameters.names, "Background",
01183 LMP_BACK);
01184 cpl_propertylist_append_int(self->parameters.names, "Width1",
01185 LMP_WID1);
01186
01187 self->parameters.count =
01188 cpl_propertylist_get_size(self->parameters.names);
01189 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
01190
01191 return;
01192
01193 }
01194
01195
01196 inline static void
01197 _giraffe_gaussian_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
01198 cxdouble *dyda, cxdouble *r)
01199 {
01200
01201 const cxchar *const fctid = "_giraffe_gaussian_eval";
01202
01203
01204 cxdouble fac;
01205 cxdouble ex;
01206 cxdouble amplitude;
01207 cxdouble center;
01208 cxdouble backg;
01209 cxdouble width;
01210 cxdouble xred;
01211
01212
01213
01214 r = NULL;
01215
01216 if (na != 4) {
01217 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01218 return;
01219 }
01220
01221 *y = 0.0;
01222
01223 if (dyda != NULL) {
01224 dyda[LMP_AMPL] = 0.;
01225 dyda[LMP_CENT] = 0.;
01226 dyda[LMP_BACK] = 0.;
01227 dyda[LMP_WID1] = 0.;
01228 }
01229
01230
01231 amplitude = a[LMP_AMPL];
01232 center = a[LMP_CENT];
01233 backg = a[LMP_BACK];
01234 width = a[LMP_WID1];
01235
01236 xred = (x[0] - center) / width;
01237
01238 ex = exp(-xred * xred / 2.);
01239 fac = amplitude * xred * ex;
01240
01241 *y = amplitude * ex + backg;
01242
01243
01244
01245
01246
01247
01248
01249 if (dyda != NULL) {
01250
01251 dyda[LMP_AMPL] = ex;
01252 dyda[LMP_CENT] = fac / width;
01253 dyda[LMP_BACK] = 1.;
01254 dyda[LMP_WID1] = (fac * xred) / width;
01255
01256 }
01257
01258 return;
01259
01260 }
01261
01262
01263 inline static void
01264 _giraffe_psfcos_ctor(GiModel *self, const GiModelData *model)
01265 {
01266
01267 cx_assert(self != NULL);
01268 cx_assert(model != NULL);
01269
01270 self->name = cx_strdup(model->name);
01271 self->type = model->type;
01272
01273 self->model = model->eval;
01274
01275
01276
01277
01278
01279
01280 self->arguments.names = cpl_propertylist_new();
01281
01282 cpl_propertylist_append_int(self->arguments.names, "x", 0);
01283
01284 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
01285 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
01286
01287
01288
01289
01290
01291
01292 self->parameters.names = cpl_propertylist_new();
01293
01294 cpl_propertylist_append_int(self->parameters.names, "Amplitude",
01295 LMP_AMPL);
01296 cpl_propertylist_append_int(self->parameters.names, "Center",
01297 LMP_CENT);
01298 cpl_propertylist_append_int(self->parameters.names, "Background",
01299 LMP_BACK);
01300 cpl_propertylist_append_int(self->parameters.names, "Width1",
01301 LMP_WID1);
01302 cpl_propertylist_append_int(self->parameters.names, "Width2",
01303 LMP_WID2);
01304
01305 self->parameters.count =
01306 cpl_propertylist_get_size(self->parameters.names);
01307 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
01308
01309 return;
01310
01311 }
01312
01313
01314 inline static void
01315 _giraffe_psfcos_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
01316 cxdouble *dyda, cxdouble *r)
01317 {
01318
01319 const cxchar *const fctid = "_giraffe_psfcos_eval";
01320
01321
01322 cxdouble amplitude;
01323 cxdouble center;
01324 cxdouble background;
01325 cxdouble width1;
01326 cxdouble width2;
01327
01328 cxdouble t1, t2, t3, t4, t5, t6, t7, t8, t9;
01329 cxdouble t10, t13, t14, t15, t16;
01330 cxdouble t26;
01331
01332
01333
01334 r = NULL;
01335
01336 if (na != 5) {
01337 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01338 return;
01339 }
01340
01341 *y = 0.0;
01342
01343 if (dyda != NULL) {
01344 dyda[LMP_AMPL] = 0.;
01345 dyda[LMP_CENT] = 0.;
01346 dyda[LMP_BACK] = 0.;
01347 dyda[LMP_WID1] = 0.;
01348 dyda[LMP_WID2] = 0.;
01349 }
01350
01351 amplitude = a[LMP_AMPL];
01352 center = a[LMP_CENT];
01353 background = a[LMP_BACK];
01354 width1 = a[LMP_WID1];
01355 width2 = a[LMP_WID2];
01356
01357 t1 = x[0] - center;
01358 t2 = fabs(t1);
01359 t3 = 1.0 / width2;
01360 t4 = t2 * t3;
01361 t5 = pow(t4, width1);
01362 t6 = CX_PI * t5;
01363 t7 = cos(t6);
01364 t8 = 1.0 + t7;
01365 t9 = t8 * t8;
01366 t10 = t9 * t8;
01367 t13 = amplitude * t9;
01368 t14 = sin(t6);
01369 t15 = t13 * t14;
01370 t16 = log(t4);
01371 t26 = t1 > 0.0 ? 1.0 : -1.0;
01372
01373 if (t2 > width2) {
01374 *y = background;
01375
01376 if (dyda != NULL) {
01377 dyda[LMP_WID2] = 1.0;
01378 }
01379 }
01380 else {
01381 *y = amplitude * t10 / 8.0 + background;
01382
01383 if (dyda != NULL) {
01384
01385 dyda[LMP_AMPL] = t10 / 8.0;
01386 dyda[LMP_CENT] = 3.0 / 8.0 * t13 * t14 * CX_PI * t5 *
01387 width1 * t26 / t2;
01388 dyda[LMP_BACK] = 1.0;
01389 dyda[LMP_WID1] = -3.0 / 8.0 * t15 * t6 * t16;
01390 dyda[LMP_WID2] = 3.0 / 8.0 * t15 * t6 * width1 * t3;
01391
01392 }
01393 }
01394
01395 return;
01396
01397 }
01398
01399
01400 inline static void
01401 _giraffe_psfexp_ctor(GiModel *self, const GiModelData *model)
01402 {
01403
01404 cx_assert(self != NULL);
01405 cx_assert(model != NULL);
01406
01407 self->name = cx_strdup(model->name);
01408 self->type = model->type;
01409
01410 self->model = model->eval;
01411
01412
01413
01414
01415
01416
01417 self->arguments.names = cpl_propertylist_new();
01418
01419 cpl_propertylist_append_int(self->arguments.names, "x", 0);
01420
01421 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
01422 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
01423
01424
01425
01426
01427
01428
01429 self->parameters.names = cpl_propertylist_new();
01430
01431 cpl_propertylist_append_int(self->parameters.names, "Amplitude",
01432 LMP_AMPL);
01433 cpl_propertylist_append_int(self->parameters.names, "Center",
01434 LMP_CENT);
01435 cpl_propertylist_append_int(self->parameters.names, "Background",
01436 LMP_BACK);
01437 cpl_propertylist_append_int(self->parameters.names, "Width1",
01438 LMP_WID1);
01439 cpl_propertylist_append_int(self->parameters.names, "Width2",
01440 LMP_WID2);
01441
01442 self->parameters.count =
01443 cpl_propertylist_get_size(self->parameters.names);
01444 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
01445
01446 return;
01447
01448 }
01449
01450
01451 inline static void
01452 _giraffe_psfexp_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
01453 cxdouble *dyda, cxdouble *r)
01454 {
01455
01456 const cxchar *const fctid = "_giraffe_psfexp_eval";
01457
01458 cxdouble amplitude;
01459 cxdouble center;
01460 cxdouble background;
01461 cxdouble width1;
01462 cxdouble width2;
01463
01464 cxdouble t1, t2, t3, t4, t6, t8;
01465 cxdouble t10, t15, t18;
01466
01467
01468
01469 r = NULL;
01470
01471 if (na != 5) {
01472 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01473 return;
01474 }
01475
01476 *y = 0.0;
01477
01478 if (dyda != NULL) {
01479 dyda[LMP_AMPL] = 0.;
01480 dyda[LMP_CENT] = 0.;
01481 dyda[LMP_BACK] = 0.;
01482 dyda[LMP_WID1] = 0.;
01483 dyda[LMP_WID2] = 0.;
01484 }
01485
01486 amplitude = a[LMP_AMPL];
01487 center = a[LMP_CENT];
01488 background = a[LMP_BACK];
01489 width1 = a[LMP_WID1];
01490 width2 = a[LMP_WID2];
01491
01492 t1 = x[0] - center;
01493
01494 if (t1 > 0.0) {
01495 t2 = t1;
01496 t10 = 1.0;
01497 }
01498 else {
01499 t2 = -t1;
01500 t10 = -1.0;
01501 }
01502
01503 t3 = pow(t2, width2);
01504 t4 = 1.0 / width1;
01505 t6 = exp(-t3 * t4);
01506 t8 = amplitude * t3;
01507 t15 = width1 * width1;
01508 t18 = log(t2);
01509
01510 *y = amplitude * t6 + background;
01511
01512 if (dyda != NULL) {
01513 dyda[LMP_AMPL] = t6;
01514 dyda[LMP_BACK] = 1.0;
01515
01516 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t4 * t6;
01517
01518 if (isnan(dyda[LMP_CENT])) {
01519 dyda[LMP_CENT] = 0.;
01520 }
01521
01522 dyda[LMP_WID1] = t8 / t15 * t6;
01523
01524 if (isnan(dyda[LMP_WID1])) {
01525 dyda[LMP_WID1] = 0.;
01526 }
01527
01528 dyda[LMP_WID2] = -t8 * t18 * t4 * t6;
01529
01530 if (isnan(dyda[LMP_WID2])) {
01531 dyda[LMP_WID2] = 0.;
01532 }
01533
01534 if (r != NULL) {
01535
01536 register cxint k;
01537
01538 k = LMP_AMPL << 1;
01539 if (r[k + 1] > 0) {
01540 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
01541 r[k + 1]);
01542 }
01543
01544 k = LMP_CENT << 1;
01545 if (r[k + 1] > 0) {
01546 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
01547 r[k + 1]);
01548 }
01549
01550 k = LMP_WID1 << 1;
01551 if (r[k + 1] > 0) {
01552 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
01553 r[k + 1]);
01554 }
01555
01556 k = LMP_WID2 << 1;
01557 if (r[k + 1] > 0) {
01558 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
01559 r[k + 1]);
01560 }
01561
01562 }
01563
01564 }
01565
01566 return;
01567
01568 }
01569
01570
01571 inline static void
01572 _giraffe_psfexp2_ctor(GiModel *self, const GiModelData *model)
01573 {
01574
01575 cx_assert(self != NULL);
01576 cx_assert(model != NULL);
01577
01578 self->name = cx_strdup(model->name);
01579 self->type = model->type;
01580
01581 self->model = model->eval;
01582
01583
01584
01585
01586
01587
01588 self->arguments.names = cpl_propertylist_new();
01589
01590 cpl_propertylist_append_int(self->arguments.names, "x", 0);
01591
01592 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
01593 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
01594
01595
01596
01597
01598
01599
01600 self->parameters.names = cpl_propertylist_new();
01601
01602 cpl_propertylist_append_int(self->parameters.names, "Amplitude",
01603 LMP_AMPL);
01604 cpl_propertylist_append_int(self->parameters.names, "Center",
01605 LMP_CENT);
01606 cpl_propertylist_append_int(self->parameters.names, "Background",
01607 LMP_BACK);
01608 cpl_propertylist_append_int(self->parameters.names, "Width1",
01609 LMP_WID1);
01610 cpl_propertylist_append_int(self->parameters.names, "Width2",
01611 LMP_WID2);
01612
01613 self->parameters.count =
01614 cpl_propertylist_get_size(self->parameters.names);
01615 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
01616
01617 return;
01618
01619 }
01620
01621
01622 inline static void
01623 _giraffe_psfexp2_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
01624 cxdouble *dyda, cxdouble *r)
01625 {
01626
01627 const cxchar *const fctid = "_giraffe_psfexp2_eval";
01628
01629 cxdouble amplitude;
01630 cxdouble center;
01631 cxdouble background;
01632 cxdouble width1;
01633 cxdouble width2;
01634
01635 cxdouble t1, t2, t3, t4, t5, t6, t8;
01636 cxdouble t10, t16;
01637
01638
01639
01640 r = NULL;
01641
01642 if (na != 5) {
01643 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01644 return;
01645 }
01646
01647 *y = 0.0;
01648
01649 if (dyda != NULL) {
01650 dyda[LMP_AMPL] = 0.;
01651 dyda[LMP_CENT] = 0.;
01652 dyda[LMP_BACK] = 0.;
01653 dyda[LMP_WID1] = 0.;
01654 dyda[LMP_WID2] = 0.;
01655 }
01656
01657 amplitude = a[LMP_AMPL];
01658 center = a[LMP_CENT];
01659 background = a[LMP_BACK];
01660 width1 = a[LMP_WID1];
01661 width2 = a[LMP_WID2];
01662
01663 t1 = x[0] - center;
01664
01665 if (t1 > 0.0) {
01666 t2 = t1;
01667 t10 = 1.0;
01668 }
01669 else {
01670 t2 = -t1;
01671 t10 = -1.0;
01672 }
01673
01674 t3 = 1.0 / width1;
01675 t4 = t2 * t3;
01676 t5 = pow(t4, width2);
01677 t6 = exp(-t5);
01678 t8 = amplitude * t5;
01679 t16 = log(t4);
01680
01681 *y = amplitude * t6 + background;
01682
01683 if (dyda != NULL) {
01684
01685 dyda[LMP_AMPL] = t6;
01686
01687 dyda[LMP_CENT] = t8 * width2 * t10 / t2 * t6;
01688
01689 if (isnan(dyda[LMP_CENT])) {
01690 dyda[LMP_CENT] = 0.0;
01691 }
01692
01693 dyda[LMP_BACK] = 1.0;
01694 dyda[LMP_WID1] = t8 * width2 * t3 * t6;
01695
01696 dyda[LMP_WID2] = -t8 * t16 * t6;
01697
01698 if (isnan(dyda[LMP_WID2])) {
01699 dyda[LMP_WID2] = 0.0;
01700 }
01701
01702 if (r != NULL) {
01703
01704 register cxint k;
01705
01706 k = LMP_AMPL << 1;
01707 if (r[k + 1] > 0) {
01708 dyda[LMP_AMPL] *= _giraffe_dydaweight(a[LMP_AMPL], r[k],
01709 r[k + 1]);
01710 }
01711
01712 k = LMP_CENT << 1;
01713 if (r[k + 1] > 0) {
01714 dyda[LMP_CENT] *= _giraffe_dydaweight(a[LMP_CENT], r[k],
01715 r[k + 1]);
01716 }
01717
01718 k = LMP_WID1 << 1;
01719 if (r[k + 1] > 0) {
01720 dyda[LMP_WID1] *= _giraffe_dydaweight(a[LMP_WID1], r[k],
01721 r[k + 1]);
01722 }
01723
01724 k = LMP_WID2 << 1;
01725 if (r[k + 1] > 0) {
01726 dyda[LMP_WID2] *= _giraffe_dydaweight(a[LMP_WID2], r[k],
01727 r[k + 1]);
01728 }
01729
01730 }
01731
01732 }
01733
01734 return;
01735
01736 }
01737
01738
01739 inline static void
01740 _giraffe_test_ctor(GiModel *self, const GiModelData *model)
01741 {
01742
01743 cx_assert(self != NULL);
01744 cx_assert(model != NULL);
01745
01746 self->name = cx_strdup(model->name);
01747 self->type = model->type;
01748
01749 self->model = model->eval;
01750
01751
01752
01753
01754
01755
01756 self->arguments.names = cpl_propertylist_new();
01757
01758 cpl_propertylist_append_int(self->arguments.names, "x", 0);
01759
01760 self->arguments.count = cpl_propertylist_get_size(self->arguments.names);
01761 self->arguments.values = cpl_matrix_new(self->arguments.count, 1);
01762
01763
01764
01765
01766
01767
01768 self->parameters.names = cpl_propertylist_new();
01769
01770 cpl_propertylist_append_int(self->parameters.names, "Slope", 0);
01771 cpl_propertylist_append_int(self->parameters.names, "Intercept", 1);
01772
01773 self->parameters.count =
01774 cpl_propertylist_get_size(self->parameters.names);
01775 self->parameters.values = cpl_matrix_new(self->parameters.count, 1);
01776
01777 return;
01778
01779 }
01780
01781
01782 inline static void
01783 _giraffe_test_eval(cxdouble *y, cxdouble *x, cxdouble *a, cxint na,
01784 cxdouble *dyda, cxdouble *r)
01785 {
01786
01787 const cxchar *const fctid = "_giraffe_test_eval";
01788
01789
01790 cxdouble a1;
01791 cxdouble b1;
01792
01793
01794
01795 r = NULL;
01796
01797 if (na != 2) {
01798 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
01799 return;
01800 }
01801
01802 *y = 0.0;
01803
01804 if (dyda != NULL) {
01805 dyda[0] = 0.;
01806 dyda[1] = 0.;
01807 }
01808
01809 a1 = a[0];
01810 b1 = a[1];
01811
01812 *y = a1 * x[0] + b1;
01813
01814 if (dyda != NULL) {
01815
01816 dyda[0] = x[0];
01817 dyda[1] = 0.0;
01818
01819 }
01820
01821 return;
01822
01823 }
01824
01825
01826
01827
01828
01829
01830 static GiModelData _gimodels[] = {
01831 {"xoptmod", GI_MODEL_XOPT,
01832 _giraffe_xoptmod_ctor, _giraffe_model_dtor, _giraffe_xoptmod_eval},
01833 {"yoptmod", GI_MODEL_YOPT,
01834 _giraffe_yoptmod_ctor, _giraffe_model_dtor, _giraffe_yoptmod_eval},
01835 {"xoptmod2", GI_MODEL_XOPT,
01836 _giraffe_xoptmod2_ctor, _giraffe_model_dtor, _giraffe_xoptmod2_eval},
01837 {"yoptmod2", GI_MODEL_XOPT,
01838 _giraffe_yoptmod2_ctor, _giraffe_model_dtor, _giraffe_yoptmod2_eval},
01839 {"gaussian", GI_MODEL_LINE,
01840 _giraffe_gaussian_ctor, _giraffe_model_dtor, _giraffe_gaussian_eval},
01841 {"psfcos", GI_MODEL_LINE,
01842 _giraffe_psfcos_ctor, _giraffe_model_dtor, _giraffe_psfcos_eval},
01843 {"psfexp", GI_MODEL_LINE,
01844 _giraffe_psfexp_ctor, _giraffe_model_dtor, _giraffe_psfexp_eval},
01845 {"psfexp2", GI_MODEL_LINE,
01846 _giraffe_psfexp2_ctor, _giraffe_model_dtor, _giraffe_psfexp2_eval},
01847 {"test", GI_MODEL_LINE,
01848 _giraffe_test_ctor, _giraffe_model_dtor, _giraffe_test_eval},
01849 {NULL, 0, NULL, NULL, NULL}
01850 };