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
00033
00034
00035
00036 #include "visir_spc_optmod.h"
00037
00038 #include <stddef.h>
00039 #include <math.h>
00040 #include <assert.h>
00041
00042
00058
00059
00060
00061
00062
00063
00064 enum visir_spc_mode_ {
00065 VISIR_SPC_M_ERR = 0,
00066 VISIR_SPC_M_LSWN,
00067 VISIR_SPC_M_LLWN,
00068 VISIR_SPC_M_LSWQ,
00069 VISIR_SPC_M_LLWQ,
00070 VISIR_SPC_M_LRP,
00071 VISIR_SPC_M_MSWN,
00072 VISIR_SPC_M_MLWN,
00073 VISIR_SPC_M_MSWQ,
00074 VISIR_SPC_M_MLWQ,
00075 VISIR_SPC_M_GHR01,
00076 VISIR_SPC_M_GHR02,
00077 VISIR_SPC_M_GHR03,
00078 VISIR_SPC_M_GHR04,
00079 VISIR_SPC_M_GHR05,
00080 VISIR_SPC_M_GHR06,
00081 VISIR_SPC_M_GHR07,
00082 VISIR_SPC_M_GHR08,
00083 VISIR_SPC_M_GHR09,
00084 VISIR_SPC_M_GHR10,
00085 VISIR_SPC_M_GHR11,
00086 VISIR_SPC_M_GHR12,
00087 VISIR_SPC_M_GHR13,
00088 VISIR_SPC_M_GHR14,
00089 VISIR_SPC_M_GHR15,
00090 VISIR_SPC_M_GHR16,
00091 VISIR_SPC_M_GHR17,
00092 VISIR_SPC_M_GHR18,
00093 VISIR_SPC_M_GHR19,
00094 VISIR_SPC_M_GHR20,
00095 VISIR_SPC_M_GHR21,
00096 VISIR_SPC_M_GHR22,
00097 VISIR_SPC_M_GHR23,
00098 VISIR_SPC_M_GHR24,
00099 VISIR_SPC_M_GHR25,
00100 VISIR_SPC_M_GHR26,
00101 VISIR_SPC_M_GHR27,
00102 VISIR_SPC_M_HR01,
00103 VISIR_SPC_M_HR02,
00104 VISIR_SPC_M_HR03,
00105 VISIR_SPC_M_HR04,
00106 VISIR_SPC_M_HR05,
00107 VISIR_SPC_M_HR06,
00108 VISIR_SPC_M_HR07,
00109 VISIR_SPC_M_HR08,
00110 VISIR_SPC_M_HR09,
00111 VISIR_SPC_M_HR10
00112 };
00113
00114 typedef enum visir_spc_mode_ visir_spc_mode;
00115
00116 struct visir_optmod_private_ {
00117
00118 double wlen;
00119
00120
00121 double angle_a;
00122 double angle_b0;
00123 double angle_bm;
00124 double angle_b1;
00125
00126 double angle_scan;
00127 double sinus_sum;
00128
00129
00130 double d;
00131
00132
00133
00134 double gg;
00135 double w;
00136 double offset;
00137 double factor;
00138
00139 double dcolbeam;
00140 double ld;
00141
00142
00143 visir_spc_resol resolution;
00144
00145
00146 visir_spc_mode mode;
00147
00148 int m;
00149
00150
00151
00152 int side_is_A;
00153
00154 };
00155
00156 typedef struct visir_optmod_private_ visir_optmod_private;
00157
00158
00159
00160
00161
00162 static double visir_spc_optmod_krs5(double);
00163 static void visir_spc_optmod_scan_angle(visir_optmod_private *);
00164
00167
00168
00169
00170
00171
00185
00186 int visir_spc_optmod_init(visir_spc_resol resol, double wlen,
00187 visir_optmod * pins, int is_aqu)
00188 {
00189
00190 visir_optmod_private * self = (visir_optmod_private*)pins;
00191
00192
00193 const double rad_per_deg = atan(1)/45;
00194
00195 visir_spc_mode mode = VISIR_SPC_M_ERR;
00196
00197
00198
00199 assert( sizeof(visir_optmod_private) == sizeof(visir_optmod) );
00200
00201 if (self == NULL) return -1;
00202
00203
00204
00205 wlen *= 1e6;
00206 switch (resol) {
00207 case VISIR_SPC_R_LRP:
00208 {
00209 mode = VISIR_SPC_M_LRP;
00210 wlen = VISIR_SPC_LRP_CWLEN;
00211 break;
00212 }
00213
00214 case VISIR_SPC_R_LR:
00215 {
00216 if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_LSWN;
00217 else if (10.2 < wlen && wlen <= 14.5) mode = VISIR_SPC_M_LLWN;
00218 else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_LSWQ;
00219 else if (20.4 < wlen && wlen <= 28.0) mode = VISIR_SPC_M_LLWQ;
00220 break;
00221 }
00222
00223 case VISIR_SPC_R_MR:
00224 {
00225 if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_MSWN;
00226 else if (10.2 < wlen && wlen <= 14.0) mode = VISIR_SPC_M_MLWN;
00227 else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_MSWQ;
00228 else if (20.4 < wlen && wlen <= 28.0) mode = VISIR_SPC_M_MLWQ;
00229 break;
00230 }
00231
00232 case VISIR_SPC_R_GHR:
00233 {
00234 if ( 7.6 <= wlen && wlen <= 7.8 ) mode = VISIR_SPC_M_GHR01;
00235 else if ( 7.8 < wlen && wlen <= 8.03) mode = VISIR_SPC_M_GHR02;
00236 else if ( 8.03 < wlen && wlen <= 8.26) mode = VISIR_SPC_M_GHR03;
00237 else if ( 8.26 < wlen && wlen <= 8.52) mode = VISIR_SPC_M_GHR04;
00238 else if ( 8.52 < wlen && wlen <= 8.78) mode = VISIR_SPC_M_GHR05;
00239 else if ( 8.78 < wlen && wlen <= 9.07) mode = VISIR_SPC_M_GHR06;
00240 else if ( 9.07 < wlen && wlen <= 9.36) mode = VISIR_SPC_M_GHR07;
00241 else if ( 9.36 < wlen && wlen <= 9.69) mode = VISIR_SPC_M_GHR08;
00242 else if ( 9.69 < wlen && wlen <= 10.03) mode = VISIR_SPC_M_GHR09;
00243 else if (10.03 < wlen && wlen <= 10.20) mode = VISIR_SPC_M_GHR10;
00244 else if (10.2 < wlen && wlen <= 10.41) mode = VISIR_SPC_M_GHR11;
00245 else if (10.41 < wlen && wlen <= 10.80) mode = VISIR_SPC_M_GHR12;
00246 else if (10.80 < wlen && wlen <= 11.24) mode = VISIR_SPC_M_GHR13;
00247 else if (11.24 < wlen && wlen <= 11.70) mode = VISIR_SPC_M_GHR14;
00248 else if (11.70 < wlen && wlen <= 12.21) mode = VISIR_SPC_M_GHR15;
00249 else if (12.21 < wlen && wlen <= 12.76) mode = VISIR_SPC_M_GHR16;
00250 else if (12.76 < wlen && wlen <= 13.37) mode = VISIR_SPC_M_GHR17;
00251 else if (13.37 < wlen && wlen <= 14.04) mode = VISIR_SPC_M_GHR18;
00252 else if (14.04 < wlen && wlen <= 14.77) mode = VISIR_SPC_M_GHR19;
00253 else if (15.60 < wlen && wlen <= 16.49) mode = VISIR_SPC_M_GHR20;
00254 else if (16.49 < wlen && wlen <= 17.55) mode = VISIR_SPC_M_GHR21;
00255 else if (17.55 < wlen && wlen <= 18.67) mode = VISIR_SPC_M_GHR22;
00256 else if (18.67 < wlen && wlen <= 20.06) mode = VISIR_SPC_M_GHR23;
00257 else if (20.06 < wlen && wlen <= 21.49) mode = VISIR_SPC_M_GHR24;
00258 else if (21.49 < wlen && wlen <= 23.40) mode = VISIR_SPC_M_GHR25;
00259 else if (23.40 < wlen && wlen <= 25.32) mode = VISIR_SPC_M_GHR26;
00260 else if (25.32 < wlen && wlen <= 28.08) mode = VISIR_SPC_M_GHR27;
00261 break;
00262 }
00263 case VISIR_SPC_R_HR:
00264 {
00265 if ( 7.97 <= wlen && wlen <= 8.27) mode = VISIR_SPC_M_HR01;
00266 else if ( 8.83 <= wlen && wlen <= 9.05) mode = VISIR_SPC_M_HR02;
00267 else if ( 9.52 <= wlen && wlen <= 9.72) mode = VISIR_SPC_M_HR03;
00268
00269 else if (11.85 <= wlen && wlen < 12.19) mode = VISIR_SPC_M_HR04;
00270 else if (12.19 <= wlen && wlen <= 12.37) mode = VISIR_SPC_M_HR05;
00271 else if (12.37 < wlen && wlen <= 12.71) mode = VISIR_SPC_M_HR06;
00272 else if (12.71 < wlen && wlen <= 12.91) mode = VISIR_SPC_M_HR07;
00273 else if (16.80 <= wlen && wlen <= 17.20) mode = VISIR_SPC_M_HR08;
00274 else if (18.32 <= wlen && wlen <= 18.67) mode = VISIR_SPC_M_HR09;
00275 else if (18.67 < wlen && wlen <= 19.18) mode = VISIR_SPC_M_HR10;
00276 break;
00277 }
00278 default:;
00279 }
00280 wlen *= 1e-6;
00281
00282 if (mode == VISIR_SPC_M_ERR) return -2;
00283
00284 self->resolution = resol;
00285 self->mode = mode;
00286 self->wlen = wlen;
00287 self->m = 0;
00288
00289 self->angle_a = 0;
00290 self->angle_b0 = 0;
00291 self->angle_bm = 0;
00292 self->angle_b1 = 0;
00293
00294
00295 switch (resol) {
00296 case VISIR_SPC_R_LRP:
00297 {
00298 break;
00299 }
00300 case VISIR_SPC_R_LR:
00301 {
00302 self->angle_a = 6.708;
00303 self->angle_bm = 1.291;
00304 self->angle_b0 = 0.586;
00305 self->angle_b1 = 2.0;
00306 self->dcolbeam = 53000;
00307 self->ld = 10332;
00308
00309
00310 switch (mode) {
00311 case VISIR_SPC_M_LSWN:
00312 {
00313 self->d = 129.162;
00314 self->m = 2;
00315 break;
00316 }
00317 case VISIR_SPC_M_LLWN:
00318 {
00319 self->d = 172.308;
00320 self->m = 2;
00321 break;
00322 }
00323 case VISIR_SPC_M_LSWQ:
00324 {
00325 self->d = 129.162;
00326 self->m = 1;
00327 break;
00328 }
00329 case VISIR_SPC_M_LLWQ:
00330 {
00331 self->d = 172.308;
00332 self->m = 1;
00333 break;
00334 }
00335 default:;
00336 }
00337 break;
00338 }
00339 case VISIR_SPC_R_MR:
00340 {
00341 self->angle_a = 34.208;
00342 self->angle_bm = 28.791;
00343 self->angle_b0 = 28.086;
00344 self->angle_b1 = 29.500;
00345 self->dcolbeam = 53000;
00346 self->ld = 10332;
00347
00348
00349 switch (mode) {
00350 case VISIR_SPC_M_MSWN:
00351 {
00352 self->d = 17.1478;
00353 self->m = 2;
00354 break;
00355 }
00356 case VISIR_SPC_M_MLWN:
00357 {
00358 self->d = 22.9560;
00359 self->m = 2;
00360 break;
00361 }
00362 case VISIR_SPC_M_MSWQ:
00363 {
00364 self->d = 17.1478;
00365 self->m = 1;
00366 break;
00367 }
00368 case VISIR_SPC_M_MLWQ:
00369 {
00370 self->d = 22.9560;
00371 self->m = 1;
00372 break;
00373 }
00374 default:;
00375 }
00376 break;
00377 }
00378 case VISIR_SPC_R_GHR:
00379 {
00380
00381 self->side_is_A = 0;
00382 self->dcolbeam = 125000;
00383 self->ld = 23403;
00384
00385 switch (mode) {
00386 case VISIR_SPC_M_GHR01:
00387 {
00388 self->d=77.16526;
00389 self->m=18;
00390 self->gg=36.8906;
00391 self->w=9.8;
00392 self->offset=166.9;
00393 self->factor=2940;
00394 break;
00395 }
00396
00397 case VISIR_SPC_M_GHR02:
00398 {
00399 self->side_is_A = 1;
00400 self->d=79.93104;
00401 self->m=18;
00402 self->gg=36.8906;
00403 self->w=9.8;
00404 self->offset=178;
00405 self->factor=2940;
00406 break;
00407 }
00408
00409 case VISIR_SPC_M_GHR03:
00410 {
00411 self->d=77.16526;
00412 self->m=17;
00413 self->gg=36.8906;
00414 self->w=9.8;
00415 self->offset=166.9;
00416 self->factor=2940;
00417 break;
00418 }
00419
00420 case VISIR_SPC_M_GHR04:
00421 {
00422 self->side_is_A = 1;
00423 self->d=79.93104;
00424 self->m=17;
00425 self->gg=36.8906;
00426 self->w=9.8;
00427 self->offset=178;
00428 self->factor=2940;
00429 break;
00430 }
00431
00432 case VISIR_SPC_M_GHR05:
00433 {
00434 self->d=77.16526;
00435 self->m=16;
00436 self->gg=36.8906;
00437 self->w=9.8;
00438 self->offset=166.9;
00439 self->factor=2940;
00440 break;
00441 }
00442
00443 case VISIR_SPC_M_GHR06:
00444 {
00445 self->side_is_A = 1;
00446 self->d=79.93104;
00447 self->m=16;
00448 self->gg=36.8906;
00449 self->w=9.8;
00450 self->offset=178;
00451 self->factor=2940;
00452 break;
00453 }
00454
00455 case VISIR_SPC_M_GHR07:
00456 {
00457 self->d=77.16526;
00458 self->m=15;
00459 self->gg=36.8906;
00460 self->w=9.8;
00461 self->offset=166.9;
00462 self->factor=2940;
00463 break;
00464 }
00465
00466 case VISIR_SPC_M_GHR08:
00467 {
00468 self->side_is_A = 1;
00469 self->d=79.93104;
00470 self->m=15;
00471 self->gg=36.8906;
00472 self->w=9.8;
00473 self->offset=178;
00474 self->factor=2940;
00475 break;
00476 }
00477
00478 case VISIR_SPC_M_GHR09:
00479 {
00480 self->d=77.16526;
00481 self->m=14;
00482 self->gg=36.8906;
00483 self->w=9.8;
00484 self->offset=166.9;
00485 self->factor=2940;
00486 break;
00487 }
00488
00489 case VISIR_SPC_M_GHR10:
00490 {
00491 self->side_is_A = 1;
00492 self->d=79.93104;
00493 self->m=14;
00494 self->gg=36.8906;
00495 self->w=9.8;
00496 self->offset=178;
00497 self->factor=2940;
00498 break;
00499 }
00500
00501 case VISIR_SPC_M_GHR11:
00502 {
00503 self->side_is_A = 1;
00504 self->d=79.93104;
00505 self->m=14;
00506 self->gg=63.5470;
00507 self->w=7.6;
00508 self->offset=143.1;
00509 self->factor=3004;
00510 break;
00511 }
00512
00513 case VISIR_SPC_M_GHR12:
00514 {
00515 self->d=77.16526;
00516 self->m=13;
00517 self->gg=63.5470;
00518 self->w=7.6;
00519 self->offset=131.6;
00520 self->factor=3004;
00521 break;
00522 }
00523
00524 case VISIR_SPC_M_GHR13:
00525 {
00526 self->side_is_A = 1;
00527 self->d=79.93104;
00528 self->m=13;
00529 self->gg=63.5470;
00530 self->w=7.6;
00531 self->offset=143.1;
00532 self->factor=3004;
00533 break;
00534 }
00535
00536 case VISIR_SPC_M_GHR14:
00537 {
00538 self->d=77.16526;
00539 self->m=12;
00540 self->gg=63.5470;
00541 self->w=7.6;
00542 self->offset=131.6;
00543 self->factor=3004;
00544 break;
00545 }
00546
00547 case VISIR_SPC_M_GHR15:
00548 {
00549 self->side_is_A = 1;
00550 self->d=79.93104;
00551 self->m=12;
00552 self->gg=63.5470;
00553 self->w=7.6;
00554 self->offset=143.1;
00555 self->factor=3004;
00556 break;
00557 }
00558
00559 case VISIR_SPC_M_GHR16:
00560 {
00561 self->d=77.16526;
00562 self->m=11;
00563 self->gg=63.5470;
00564 self->w=7.6;
00565 self->offset=131.6;
00566 self->factor=3004;
00567 break;
00568 }
00569
00570 case VISIR_SPC_M_GHR17:
00571 {
00572 self->side_is_A = 1;
00573 self->d=79.93104;
00574 self->m=11;
00575 self->gg=63.5470;
00576 self->w=7.6;
00577 self->offset=143.1;
00578 self->factor=3004;
00579 break;
00580 }
00581
00582 case VISIR_SPC_M_GHR18:
00583 {
00584 self->d=77.16526;
00585 self->m=10;
00586 self->gg=63.5470;
00587 self->w=7.6;
00588 self->offset=131.6;
00589 self->factor=3004;
00590 break;
00591 }
00592
00593 case VISIR_SPC_M_GHR19:
00594 {
00595 self->side_is_A = 1;
00596 self->d=79.93104;
00597 self->m=10;
00598 self->gg=63.5470;
00599 self->w=7.6;
00600 self->offset=143.1;
00601 self->factor=3004;
00602 break;
00603 }
00604
00605 case VISIR_SPC_M_GHR20:
00606 {
00607 self->side_is_A = 1;
00608 self->d=79.93104;
00609 self->m=9;
00610 self->gg=217.8772;
00611 self->w=4.1;
00612 self->offset=120.3;
00613 self->factor=2980;
00614 break;
00615 }
00616
00617 case VISIR_SPC_M_GHR21:
00618 {
00619 self->d=77.16526;
00620 self->m=8;
00621 self->gg=217.8772;
00622 self->w=4.1;
00623 self->offset=108.7;
00624 self->factor=2980;
00625 break;
00626 }
00627
00628 case VISIR_SPC_M_GHR22:
00629 {
00630 self->side_is_A = 1;
00631 self->d=79.93104;
00632 self->m=8;
00633 self->gg=217.8772;
00634 self->w=4.1;
00635 self->offset=120.3;
00636 self->factor=2980;
00637 break;
00638 }
00639
00640 case VISIR_SPC_M_GHR23:
00641 {
00642 self->d=77.16526;
00643 self->m=7;
00644 self->gg=217.8772;
00645 self->w=4.1;
00646 self->offset=108.7;
00647 self->factor=2980;
00648 break;
00649 }
00650
00651 case VISIR_SPC_M_GHR24:
00652 {
00653 self->side_is_A = 1;
00654 self->d=79.93104;
00655 self->m=7;
00656 self->gg=217.8772;
00657 self->w=4.1;
00658 self->offset=120.3;
00659 self->factor=2980;
00660 break;
00661 }
00662
00663 case VISIR_SPC_M_GHR25:
00664 {
00665 self->d=77.16526;
00666 self->m=6;
00667 self->gg=217.8772;
00668 self->w=4.1;
00669 self->offset=108.7;
00670 self->factor=2980;
00671 break;
00672 }
00673
00674 case VISIR_SPC_M_GHR26:
00675 {
00676 self->side_is_A = 1;
00677 self->d=79.93104;
00678 self->m=6;
00679 self->gg=217.8772;
00680 self->w=4.1;
00681 self->offset=120.3;
00682 self->factor=2980;
00683 break;
00684 }
00685
00686 case VISIR_SPC_M_GHR27:
00687 {
00688 self->d=77.16526;
00689 self->m=5;
00690 self->gg=217.8772;
00691 self->w=4.1;
00692 self->offset=108.7;
00693 self->factor=2980;
00694 break;
00695 }
00696 default:;
00697 }
00698
00699 if (self->side_is_A) {
00700
00701 self->angle_a = 62.1299;
00702 self->angle_bm = 64.8519;
00703 self->angle_b0 = 64.5393;
00704 self->angle_b1 = 65.1641;
00705
00706 } else {
00707
00708 self->angle_a = 64.8701;
00709 self->angle_bm = 62.1483;
00710 self->angle_b0 = 62.4609;
00711 self->angle_b1 = 61.8361;
00712 }
00713 self->w *= rad_per_deg;
00714
00715
00716 self->gg *= 1e-6;
00717 break;
00718 }
00719 case VISIR_SPC_R_HR:
00720 {
00721
00722 self->side_is_A = 0;
00723 self->dcolbeam = 125000;
00724 self->ld = 23403;
00725
00726 switch (mode) {
00727 case VISIR_SPC_M_HR01:
00728 {
00729 self->m=17;
00730 break;
00731 }
00732 case VISIR_SPC_M_HR02:
00733 {
00734 self->side_is_A = 1;
00735 self->m=16;
00736 break;
00737 }
00738 case VISIR_SPC_M_HR03:
00739 {
00740 self->side_is_A = 1;
00741 self->m=15;
00742 break;
00743 }
00744 case VISIR_SPC_M_HR04:
00745 {
00746 self->side_is_A = 1;
00747 self->m=12;
00748 break;
00749 }
00750 case VISIR_SPC_M_HR05:
00751 {
00752 self->m=11;
00753 break;
00754 }
00755 case VISIR_SPC_M_HR06:
00756 {
00757 self->m=11;
00758 break;
00759 }
00760 case VISIR_SPC_M_HR07:
00761 {
00762 self->side_is_A = 1;
00763 self->m=11;
00764 break;
00765 }
00766 case VISIR_SPC_M_HR08:
00767 {
00768 self->m=8;
00769 break;
00770 }
00771 case VISIR_SPC_M_HR09:
00772 {
00773 self->side_is_A = 1;
00774 self->m=8;
00775 break;
00776 }
00777 case VISIR_SPC_M_HR10:
00778 {
00779 self->m=7;
00780 break;
00781 }
00782 default:;
00783 }
00784 if (self->side_is_A) {
00785
00786 self->d=79.93104;
00787 self->angle_a = 62.1299;
00788 self->angle_bm = 64.8519;
00789 self->angle_b0 = 64.5393;
00790 self->angle_b1 = 65.1641;
00791 } else {
00792
00793 self->d=77.16526;
00794 self->angle_a = 64.8701;
00795 self->angle_bm = 62.1483;
00796 self->angle_b0 = 62.4609;
00797 self->angle_b1 = 61.8361;
00798 }
00799 break;
00800 }
00801 default:;
00802 }
00803
00804 if (is_aqu && (resol == VISIR_SPC_R_HR || resol == VISIR_SPC_R_GHR)) {
00805
00806
00807 self->factor *= 0.127 / 0.0757;
00808 self->ld *= 0.127 / 0.0757;
00809
00810
00811
00812 if (self->angle_b0 < self->angle_bm) {
00813 self->angle_b0 = self->angle_bm - (self->angle_bm - self->angle_b0) * 2.377;
00814 self->angle_b1 = self->angle_bm + (self->angle_b1 - self->angle_bm) * 2.377;
00815 }
00816 else {
00817 self->angle_b0 = self->angle_bm + (self->angle_b0 - self->angle_bm) * 2.377;
00818 self->angle_b1 = self->angle_bm - (self->angle_bm - self->angle_b1) * 2.377;
00819 }
00820 self->offset += 162;
00821 }
00822
00823 if (resol != VISIR_SPC_R_LRP) {
00824 self->angle_a *= rad_per_deg;
00825 self->angle_b0 *= rad_per_deg;
00826 self->angle_bm *= rad_per_deg;
00827 self->angle_b1 *= rad_per_deg;
00828
00829
00830 self->d *= 1e-6;
00831 self->dcolbeam *= 1e-6;
00832
00833 assert( self->m > 0);
00834
00835 visir_spc_optmod_scan_angle(self);
00836
00837 self->sinus_sum = sin(self->angle_a + self->angle_scan)
00838 + sin(self->angle_bm + self->angle_scan);
00839 }
00840
00841 return 0;
00842
00843 }
00844
00845
00846
00860
00861 double visir_spc_optmod_wlen(const visir_optmod * pins, double * pwl0,
00862 double * pwl1)
00863 {
00864
00865 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00866
00867 if (self == NULL) return -1;
00868
00869 if (self->mode == VISIR_SPC_M_LRP) {
00870 if (pwl0) *pwl0 = VISIR_SPC_LRP_WLEN0;
00871 if (pwl1) *pwl1 = VISIR_SPC_LRP_WLEN1;
00872 return VISIR_SPC_LRP_CWLEN;
00873 }
00874
00875
00876 if (pwl0) *pwl0 = self->d/self->m*( sin(self->angle_a + self->angle_scan)
00877 + sin(self->angle_b0 + self->angle_scan));
00878
00879
00880 if (pwl1) *pwl1 = self->d/self->m*( sin(self->angle_a + self->angle_scan)
00881 + sin(self->angle_b1 + self->angle_scan));
00882
00883
00884 return self->d / self->m * self->sinus_sum;
00885
00886 }
00887
00888
00907
00908 double visir_spc_optmod_cross_dispersion(const visir_optmod * pins, double wlen)
00909 {
00910
00911 double sinbeta;
00912 double rf_index;
00913 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00914
00915 if (self == NULL) return -1;
00916
00917 if (self->resolution != VISIR_SPC_R_GHR) return -2;
00918 if (wlen <= 0) return -3;
00919
00920 assert( self->gg != 0 );
00921
00922 rf_index = visir_spc_optmod_krs5(wlen);
00923
00924 if (rf_index < 1) return -8;
00925
00926 sinbeta = sin(self->w) * rf_index - wlen / self->gg;
00927
00928
00929 if (sinbeta < -1) return -9;
00930 if (sinbeta > 1) return -10;
00931
00932 return self->offset + self->factor * tan(asin(sinbeta) - self->w);
00933
00934 }
00935
00936
00937
00960
00961 double visir_spc_optmod_echelle(const visir_optmod * pins, double wlen,
00962 int ioffset)
00963 {
00964
00965 int order;
00966 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00967
00968 if (self == NULL) return -1;
00969 if (self->resolution != VISIR_SPC_R_GHR) return -2;
00970 if (wlen <= 0) return -3;
00971 if (ioffset < -4) return -4;
00972 if (ioffset > 4) return -5;
00973
00974 order = ioffset + self->m;
00975
00976
00977 if (order < 1) return -6;
00978 if (order > 18) return -7;
00979
00980 return wlen * self->m / (double) order;
00981
00982 }
00983
00984
00999
01000 int visir_spc_optmod_side_is_A(const visir_optmod * pins)
01001 {
01002 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01003
01004 if (self == NULL) return -1;
01005
01006 if (self->resolution != VISIR_SPC_R_GHR &&
01007 self->resolution != VISIR_SPC_R_HR) return -2;
01008
01009 return self->side_is_A;
01010
01011 }
01012
01013
01028
01029 int visir_spc_optmod_get_echelle_order(const visir_optmod * pins)
01030 {
01031 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01032
01033 if (self == NULL) return -1;
01034
01035 if (self->resolution != VISIR_SPC_R_GHR &&
01036 self->resolution != VISIR_SPC_R_HR) return -2;
01037
01038 return self->m;
01039 }
01040
01041
01042
01054
01055
01056 double visir_spc_optmod_resolution(const visir_optmod * pins)
01057 {
01058 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01059
01060 if (self == NULL) return -1;
01061
01062 return self->mode == VISIR_SPC_M_LRP
01063 ? VISIR_SPC_LRP_RESOL
01064 : self->dcolbeam * self->sinus_sum
01065 / (2.0 * self->wlen * cos(self->angle_a + self->angle_scan));
01066 }
01067
01068
01081
01082
01083 double visir_spc_optmod_dispersion(const visir_optmod * pins)
01084 {
01085 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01086
01087 if (self == NULL) return -1;
01088
01089 return self->mode == VISIR_SPC_M_LRP
01090 ? VISIR_SPC_LRP_RESOL_DISP
01091 : self->ld * self->sinus_sum
01092 / (self->wlen * cos(self->angle_bm + self->angle_scan));
01093 }
01094
01097
01104
01105 static double visir_spc_optmod_krs5(double wlen) {
01106
01107 const double a0 = 5.96032159;
01108 const double a1 = -5.36135205e-4;
01109 const double a2 = 1.77047634;
01110 const double a3 = -2.79310980e1;
01111 const double a4 = -1.28684883;
01112 const double a5 = -4.34541795e-2;
01113
01114 double n2 = 0;
01115
01116
01117 assert( wlen > 0 );
01118
01119
01120 wlen *= 1e6;
01121
01122 wlen *= wlen;
01123
01124 n2 = a0 + a1 * wlen + (((a5/wlen + a4)/wlen + a3)/ wlen + a2)/wlen;
01125
01126
01127 return n2 > 1 ? sqrt(n2) : -1;
01128
01129 }
01130
01131
01138
01139 static void visir_spc_optmod_scan_angle(visir_optmod_private * self)
01140 {
01141
01142
01143
01144 const double mld = self->m * self->wlen / self->d;
01145 const double sab = sin(self->angle_bm) + sin(self->angle_a);
01146 const double cab = cos(self->angle_bm) + cos(self->angle_a);
01147 const double A = sab * sab + cab * cab;
01148
01149
01150
01151 const double C = mld * mld - sab * sab;
01152
01153 double D = A - mld * mld;
01154 double u1, u2;
01155
01156
01157 D = D > 0 ? sqrt(D) : 0;
01158 D *= fabs(sab);
01159
01160
01161 u1 = (cab * mld + D) / A;
01162
01163
01164
01165
01166 u2 = C / A / u1;
01167
01168
01169
01170
01171 self->angle_scan = asin(u2);
01172
01173 }