visir_spc_optmod.c

00001 /* $Id: visir_spc_optmod.c,v 1.24 2012/01/31 08:16:58 llundin Exp $
00002  *
00003  * This file is part of the VISIR Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2012/01/31 08:16:58 $
00024  * $Revision: 1.24 $
00025  * $Name: visir-3_5_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
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                                    Type definition
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_MSWN,
00071     VISIR_SPC_M_MLWN,
00072     VISIR_SPC_M_MSWQ,
00073     VISIR_SPC_M_MLWQ,
00074     VISIR_SPC_M_GHR01,
00075     VISIR_SPC_M_GHR02,
00076     VISIR_SPC_M_GHR03,
00077     VISIR_SPC_M_GHR04,
00078     VISIR_SPC_M_GHR05,
00079     VISIR_SPC_M_GHR06,
00080     VISIR_SPC_M_GHR07,
00081     VISIR_SPC_M_GHR08,
00082     VISIR_SPC_M_GHR09,
00083     VISIR_SPC_M_GHR10,
00084     VISIR_SPC_M_GHR11,
00085     VISIR_SPC_M_GHR12,
00086     VISIR_SPC_M_GHR13,
00087     VISIR_SPC_M_GHR14,
00088     VISIR_SPC_M_GHR15,
00089     VISIR_SPC_M_GHR16,
00090     VISIR_SPC_M_GHR17,
00091     VISIR_SPC_M_GHR18,
00092     VISIR_SPC_M_GHR19,
00093     VISIR_SPC_M_GHR20,
00094     VISIR_SPC_M_GHR21,
00095     VISIR_SPC_M_GHR22,
00096     VISIR_SPC_M_GHR23,
00097     VISIR_SPC_M_GHR24,
00098     VISIR_SPC_M_GHR25,
00099     VISIR_SPC_M_GHR26,
00100     VISIR_SPC_M_GHR27,
00101     VISIR_SPC_M_HR01,
00102     VISIR_SPC_M_HR02,
00103     VISIR_SPC_M_HR03,
00104     VISIR_SPC_M_HR04,
00105     VISIR_SPC_M_HR05,
00106     VISIR_SPC_M_HR06,
00107     VISIR_SPC_M_HR07,
00108     VISIR_SPC_M_HR08,
00109     VISIR_SPC_M_HR09,
00110     VISIR_SPC_M_HR10
00111 };
00112 
00113 typedef enum visir_spc_mode_ visir_spc_mode;
00114 
00115 struct visir_optmod_private_ {
00116     /* The Central Wavelength of the settings */
00117     double wlen;
00118 
00119     /* Angles are in radians */
00120     double angle_a;    /* Angle in 1st term */
00121     double angle_b0;   /* Angle in 2nd term, center of 1st pixel */
00122     double angle_bm;   /* Angle in 2nd term, center of spectral range */
00123     double angle_b1;   /* Angle in 2nd term, center of last pixel */
00124 
00125     double angle_scan; /* Scan-angle */
00126     double sinus_sum;  /* sin(a + scan-angle) + sin(b + scan-angle) */
00127 
00128     /* The unit of d has to be equal to that of the wavelength */
00129     double d;         /* Echelle groove spacing @30K [m] */
00130 
00131     /* These settings are only defined in High Resolution Grism mode, i.e. when
00132        mode == VISIR_SPC_R_GHR */
00133     double gg;        /* grism groove spacing @ 30K [m] */
00134     double w;         /* grism wedge [radians] */
00135     double offset;    /* Parameter for grism cross-dispersion */
00136     double factor;    /* Parameter for grism cross-dispersion */
00137 
00138     double dcolbeam;  /* Diameter of collimated beam */
00139     double ld;        /* The (unit-less) Linear Dispersion factor */
00140 
00141     /* The spectroscopy resolution corresponding to the settings */
00142     visir_spc_resol resolution;
00143 
00144     /* The spectroscopy mode corresponding to the settings */
00145     visir_spc_mode mode;
00146 
00147     int    m;         /* Echelle order (1, 2, ..., 18) */
00148 
00149     /* These settings are only defined in High Resolution, i.e. when
00150        mode == VISIR_SPC_R_GHR || mode == VISIR_SPC_R_HR */
00151     int side_is_A;    /* 1 if side is 'A', 0 if side is 'B' */
00152 
00153 };
00154 
00155 typedef struct visir_optmod_private_ visir_optmod_private;
00156 
00157 /*-----------------------------------------------------------------------------
00158                             Functions prototypes
00159  -----------------------------------------------------------------------------*/
00160 
00161 static double visir_spc_optmod_krs5(double);
00162 static void visir_spc_optmod_scan_angle(visir_optmod_private *);
00163 
00166 /*-----------------------------------------------------------------------------
00167                             Function codes
00168  -----------------------------------------------------------------------------*/
00169 
00170 /*----------------------------------------------------------------------------*/
00183 /*----------------------------------------------------------------------------*/
00184 int visir_spc_optmod_init(visir_spc_resol resol, double wlen,
00185                           visir_optmod * pins)
00186 {
00187 
00188     visir_optmod_private * self = (visir_optmod_private*)pins;
00189 
00190     /* The angles are coded in degrees and then converted to radians */
00191     const double rad_per_deg = atan(1)/45;
00192 
00193     visir_spc_mode mode = VISIR_SPC_M_ERR;
00194 
00195 
00196     /* Ensure that the public struct has the proper size */
00197     assert( sizeof(visir_optmod_private) == sizeof(visir_optmod) );
00198 
00199     if (self == NULL) return -1;
00200 
00201     /* Switch on the resolution
00202        Constants here are coded in micron - convert to m */
00203     wlen *= 1e6;
00204     switch (resol) {
00205         case VISIR_SPC_R_LR:
00206           {
00207                  if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_LSWN;
00208             else if (10.2 <  wlen && wlen <= 14.5) mode = VISIR_SPC_M_LLWN;
00209             else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_LSWQ;
00210             else if (20.4 <  wlen && wlen <= 28.0) mode = VISIR_SPC_M_LLWQ;
00211             break;
00212           }
00213 
00214         case VISIR_SPC_R_MR:
00215           {
00216                  if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_MSWN;
00217             else if (10.2 <  wlen && wlen <= 14.0) mode = VISIR_SPC_M_MLWN;
00218             else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_MSWQ;
00219             else if (20.4 <  wlen && wlen <= 28.0) mode = VISIR_SPC_M_MLWQ;
00220             break;
00221           }
00222 
00223         case VISIR_SPC_R_GHR:
00224           {
00225                  if ( 7.6 <= wlen && wlen <=  7.8 ) mode = VISIR_SPC_M_GHR01;
00226             else if ( 7.8  < wlen && wlen <=  8.03) mode = VISIR_SPC_M_GHR02;
00227             else if ( 8.03 < wlen && wlen <=  8.26) mode = VISIR_SPC_M_GHR03;
00228             else if ( 8.26 < wlen && wlen <=  8.52) mode = VISIR_SPC_M_GHR04;
00229             else if ( 8.52 < wlen && wlen <=  8.78) mode = VISIR_SPC_M_GHR05;
00230             else if ( 8.78 < wlen && wlen <=  9.07) mode = VISIR_SPC_M_GHR06;
00231             else if ( 9.07 < wlen && wlen <=  9.36) mode = VISIR_SPC_M_GHR07;
00232             else if ( 9.36 < wlen && wlen <=  9.69) mode = VISIR_SPC_M_GHR08;
00233             else if ( 9.69 < wlen && wlen <= 10.03) mode = VISIR_SPC_M_GHR09;
00234             else if (10.03 < wlen && wlen <= 10.20) mode = VISIR_SPC_M_GHR10;
00235             else if (10.2  < wlen && wlen <= 10.41) mode = VISIR_SPC_M_GHR11;
00236             else if (10.41 < wlen && wlen <= 10.80) mode = VISIR_SPC_M_GHR12;
00237             else if (10.80 < wlen && wlen <= 11.24) mode = VISIR_SPC_M_GHR13;
00238             else if (11.24 < wlen && wlen <= 11.70) mode = VISIR_SPC_M_GHR14;
00239             else if (11.70 < wlen && wlen <= 12.21) mode = VISIR_SPC_M_GHR15;
00240             else if (12.21 < wlen && wlen <= 12.76) mode = VISIR_SPC_M_GHR16;
00241             else if (12.76 < wlen && wlen <= 13.37) mode = VISIR_SPC_M_GHR17;
00242             else if (13.37 < wlen && wlen <= 14.04) mode = VISIR_SPC_M_GHR18;
00243             else if (14.04 < wlen && wlen <= 14.77) mode = VISIR_SPC_M_GHR19;
00244             else if (15.60 < wlen && wlen <= 16.49) mode = VISIR_SPC_M_GHR20;
00245             else if (16.49 < wlen && wlen <= 17.55) mode = VISIR_SPC_M_GHR21;
00246             else if (17.55 < wlen && wlen <= 18.67) mode = VISIR_SPC_M_GHR22;
00247             else if (18.67 < wlen && wlen <= 20.06) mode = VISIR_SPC_M_GHR23;
00248             else if (20.06 < wlen && wlen <= 21.49) mode = VISIR_SPC_M_GHR24;
00249             else if (21.49 < wlen && wlen <= 23.40) mode = VISIR_SPC_M_GHR25;
00250             else if (23.40 < wlen && wlen <= 25.32) mode = VISIR_SPC_M_GHR26;
00251             else if (25.32 < wlen && wlen <= 28.08) mode = VISIR_SPC_M_GHR27;
00252             break;
00253           }
00254         case VISIR_SPC_R_HR:
00255           {
00256                  if ( 7.97 <= wlen && wlen <=  8.27) mode = VISIR_SPC_M_HR01;
00257             else if ( 8.83 <= wlen && wlen <=  9.05) mode = VISIR_SPC_M_HR02;
00258             else if ( 9.52 <= wlen && wlen <=  9.72) mode = VISIR_SPC_M_HR03;
00259                  /* FIXME: VISIR_SPC_M_HR04 really goes up to 12.21 */
00260             else if (11.85 <= wlen && wlen <  12.19) mode = VISIR_SPC_M_HR04;
00261             else if (12.19 <= wlen && wlen <= 12.37) mode = VISIR_SPC_M_HR05;
00262             else if (12.37 <  wlen && wlen <= 12.71) mode = VISIR_SPC_M_HR06;
00263             else if (12.71 <  wlen && wlen <= 12.91) mode = VISIR_SPC_M_HR07;
00264             else if (16.80 <= wlen && wlen <= 17.20) mode = VISIR_SPC_M_HR08;
00265             else if (18.32 <= wlen && wlen <= 18.67) mode = VISIR_SPC_M_HR09;
00266             else if (18.67 <  wlen && wlen <= 19.18) mode = VISIR_SPC_M_HR10;
00267             break;
00268           }
00269         default:;
00270     }
00271     wlen *= 1e-6;
00272 
00273     if (mode == VISIR_SPC_M_ERR) return -2;
00274 
00275     self->resolution = resol;
00276     self->mode = mode;
00277     self->wlen = wlen;
00278     self->m = 0;
00279 
00280     self->angle_a  = 0;
00281     self->angle_b0 = 0;
00282     self->angle_bm = 0;
00283     self->angle_b1 = 0;
00284 
00285     /* Switch on the resolution */
00286     switch (resol) {
00287     case VISIR_SPC_R_LR:
00288         {
00289             self->angle_a  = 6.708;
00290             self->angle_bm = 1.291;
00291             self->angle_b0 = 0.586;
00292             self->angle_b1 = 2.0;
00293             self->dcolbeam = 53000; /* [micron] */
00294             self->ld = 10332;
00295 
00296             /* Switch on the (LR)-mode */
00297             switch (mode) {
00298             case VISIR_SPC_M_LSWN:
00299                 {
00300                     self->d = 129.162;
00301                     self->m = 2;
00302                     break;
00303                 }
00304             case VISIR_SPC_M_LLWN:
00305                 {
00306                     self->d = 172.308;
00307                     self->m = 2;
00308                     break;
00309                 }
00310             case VISIR_SPC_M_LSWQ:
00311                 {
00312                     self->d = 129.162;
00313                     self->m = 1;
00314                     break;
00315                 }
00316             case VISIR_SPC_M_LLWQ:
00317                 {
00318                     self->d = 172.308;
00319                     self->m = 1;
00320                     break;
00321                 }
00322             default:;
00323             }
00324             break;
00325         }
00326     case VISIR_SPC_R_MR:
00327         {
00328             self->angle_a  = 34.208;
00329             self->angle_bm = 28.791;
00330             self->angle_b0 = 28.086;
00331             self->angle_b1 = 29.500;
00332             self->dcolbeam = 53000; /* [micron] */
00333             self->ld = 10332;
00334 
00335             /* Switch on the (MR)-mode */
00336             switch (mode) {
00337             case VISIR_SPC_M_MSWN:
00338                 {
00339                     self->d = 17.1478;
00340                     self->m = 2;
00341                     break;
00342                 }
00343             case VISIR_SPC_M_MLWN:
00344                 {
00345                     self->d = 22.9560;
00346                     self->m = 2;
00347                     break;
00348                 }
00349             case VISIR_SPC_M_MSWQ:
00350                 {
00351                     self->d = 17.1478;
00352                     self->m = 1;
00353                     break;
00354                 }
00355             case VISIR_SPC_M_MLWQ:
00356                 {
00357                     self->d = 22.9560;
00358                     self->m = 1;
00359                     break;
00360                 }
00361             default:;
00362             }
00363             break;
00364         }
00365     case VISIR_SPC_R_GHR:
00366         {
00367             /* Switch on the (HR Grism)-mode */
00368             self->side_is_A = 0;
00369             self->dcolbeam = 125000; /* [micron] */
00370             self->ld = 23403;
00371 
00372             switch (mode) {
00373             case VISIR_SPC_M_GHR01:
00374                 {
00375                     self->d=77.16526;
00376                     self->m=18;
00377                     self->gg=36.8906;
00378                     self->w=9.8;
00379                     self->offset=166.9;
00380                     self->factor=2940;
00381                     break;
00382                 }
00383 
00384             case VISIR_SPC_M_GHR02:
00385                 {
00386                     self->side_is_A = 1;
00387                     self->d=79.93104;
00388                     self->m=18;
00389                     self->gg=36.8906;
00390                     self->w=9.8;
00391                     self->offset=178;
00392                     self->factor=2940;
00393                     break;
00394                 }
00395 
00396             case VISIR_SPC_M_GHR03:
00397                 {
00398                     self->d=77.16526;
00399                     self->m=17;
00400                     self->gg=36.8906;
00401                     self->w=9.8;
00402                     self->offset=166.9;
00403                     self->factor=2940;
00404                     break;
00405                 }
00406 
00407             case VISIR_SPC_M_GHR04:
00408                 {
00409                     self->side_is_A = 1;
00410                     self->d=79.93104;
00411                     self->m=17;
00412                     self->gg=36.8906;
00413                     self->w=9.8;
00414                     self->offset=178;
00415                     self->factor=2940;
00416                     break;
00417                 }
00418 
00419             case VISIR_SPC_M_GHR05:
00420                 {
00421                     self->d=77.16526;
00422                     self->m=16;
00423                     self->gg=36.8906;
00424                     self->w=9.8;
00425                     self->offset=166.9;
00426                     self->factor=2940;
00427                     break;
00428                 }
00429 
00430             case VISIR_SPC_M_GHR06:
00431                 {
00432                     self->side_is_A = 1;
00433                     self->d=79.93104;
00434                     self->m=16;
00435                     self->gg=36.8906;
00436                     self->w=9.8;
00437                     self->offset=178;
00438                     self->factor=2940;
00439                     break;
00440                 }
00441 
00442             case VISIR_SPC_M_GHR07:
00443                 {
00444                     self->d=77.16526;
00445                     self->m=15;
00446                     self->gg=36.8906;
00447                     self->w=9.8;
00448                     self->offset=166.9;
00449                     self->factor=2940;
00450                     break;
00451                 }
00452 
00453             case VISIR_SPC_M_GHR08:
00454                 {
00455                     self->side_is_A = 1;
00456                     self->d=79.93104;
00457                     self->m=15;
00458                     self->gg=36.8906;
00459                     self->w=9.8;
00460                     self->offset=178;
00461                     self->factor=2940;
00462                     break;
00463                 }
00464 
00465             case VISIR_SPC_M_GHR09:
00466                 {
00467                     self->d=77.16526;
00468                     self->m=14;
00469                     self->gg=36.8906;
00470                     self->w=9.8;
00471                     self->offset=166.9;
00472                     self->factor=2940;
00473                     break;
00474                 }
00475 
00476             case VISIR_SPC_M_GHR10:
00477                 {
00478                     self->side_is_A = 1;
00479                     self->d=79.93104;
00480                     self->m=14;
00481                     self->gg=36.8906;
00482                     self->w=9.8;
00483                     self->offset=178;
00484                     self->factor=2940;
00485                     break;
00486                 }
00487 
00488             case VISIR_SPC_M_GHR11:
00489                 {
00490                     self->side_is_A = 1;
00491                     self->d=79.93104;
00492                     self->m=14;
00493                     self->gg=63.5470;
00494                     self->w=7.6;
00495                     self->offset=143.1;
00496                     self->factor=3004;
00497                     break;
00498                 }
00499 
00500             case VISIR_SPC_M_GHR12:
00501                 {
00502                     self->d=77.16526;
00503                     self->m=13;
00504                     self->gg=63.5470;
00505                     self->w=7.6;
00506                     self->offset=131.6;
00507                     self->factor=3004;
00508                     break;
00509                 }
00510 
00511             case VISIR_SPC_M_GHR13:
00512                 {
00513                     self->side_is_A = 1;
00514                     self->d=79.93104;
00515                     self->m=13;
00516                     self->gg=63.5470;
00517                     self->w=7.6;
00518                     self->offset=143.1;
00519                     self->factor=3004;
00520                     break;
00521                 }
00522 
00523             case VISIR_SPC_M_GHR14:
00524                 {
00525                     self->d=77.16526;
00526                     self->m=12;
00527                     self->gg=63.5470;
00528                     self->w=7.6;
00529                     self->offset=131.6;
00530                     self->factor=3004;
00531                     break;
00532                 }
00533 
00534             case VISIR_SPC_M_GHR15:
00535                 {
00536                     self->side_is_A = 1;
00537                     self->d=79.93104;
00538                     self->m=12;
00539                     self->gg=63.5470;
00540                     self->w=7.6;
00541                     self->offset=143.1;
00542                     self->factor=3004;
00543                     break;
00544                 }
00545 
00546             case VISIR_SPC_M_GHR16:
00547                 {
00548                     self->d=77.16526;
00549                     self->m=11;
00550                     self->gg=63.5470;
00551                     self->w=7.6;
00552                     self->offset=131.6;
00553                     self->factor=3004;
00554                     break;
00555                 }
00556 
00557             case VISIR_SPC_M_GHR17:
00558                 {
00559                     self->side_is_A = 1;
00560                     self->d=79.93104;
00561                     self->m=11;
00562                     self->gg=63.5470;
00563                     self->w=7.6;
00564                     self->offset=143.1;
00565                     self->factor=3004;
00566                     break;
00567                 }
00568 
00569             case VISIR_SPC_M_GHR18:
00570                 {
00571                     self->d=77.16526;
00572                     self->m=10;
00573                     self->gg=63.5470;
00574                     self->w=7.6;
00575                     self->offset=131.6;
00576                     self->factor=3004;
00577                     break;
00578                 }
00579 
00580             case VISIR_SPC_M_GHR19:
00581                 {
00582                     self->side_is_A = 1;
00583                     self->d=79.93104;
00584                     self->m=10;
00585                     self->gg=63.5470;
00586                     self->w=7.6;
00587                     self->offset=143.1;
00588                     self->factor=3004;
00589                     break;
00590                 }
00591 
00592             case VISIR_SPC_M_GHR20:
00593                 {
00594                     self->side_is_A = 1;
00595                     self->d=79.93104;
00596                     self->m=9;
00597                     self->gg=217.8772;
00598                     self->w=4.1;
00599                     self->offset=120.3;
00600                     self->factor=2980;
00601                     break;
00602                 }
00603 
00604             case VISIR_SPC_M_GHR21:
00605                 {
00606                     self->d=77.16526;
00607                     self->m=8;
00608                     self->gg=217.8772;
00609                     self->w=4.1;
00610                     self->offset=108.7;
00611                     self->factor=2980;
00612                     break;
00613                 }
00614 
00615             case VISIR_SPC_M_GHR22:
00616                 {
00617                     self->side_is_A = 1;
00618                     self->d=79.93104;
00619                     self->m=8;
00620                     self->gg=217.8772;
00621                     self->w=4.1;
00622                     self->offset=120.3;
00623                     self->factor=2980;
00624                     break;
00625                 }
00626 
00627             case VISIR_SPC_M_GHR23:
00628                 {
00629                     self->d=77.16526;
00630                     self->m=7;
00631                     self->gg=217.8772;
00632                     self->w=4.1;
00633                     self->offset=108.7;
00634                     self->factor=2980;
00635                     break;
00636                 }
00637 
00638             case VISIR_SPC_M_GHR24:
00639                 {
00640                     self->side_is_A = 1;
00641                     self->d=79.93104;
00642                     self->m=7;
00643                     self->gg=217.8772;
00644                     self->w=4.1;
00645                     self->offset=120.3;
00646                     self->factor=2980;
00647                     break;
00648                 }
00649 
00650             case VISIR_SPC_M_GHR25:
00651                 {
00652                     self->d=77.16526;
00653                     self->m=6;
00654                     self->gg=217.8772;
00655                     self->w=4.1;
00656                     self->offset=108.7;
00657                     self->factor=2980;
00658                     break;
00659                 }
00660 
00661             case VISIR_SPC_M_GHR26:
00662                 {
00663                     self->side_is_A = 1;
00664                     self->d=79.93104;
00665                     self->m=6;
00666                     self->gg=217.8772;
00667                     self->w=4.1;
00668                     self->offset=120.3;
00669                     self->factor=2980;
00670                     break;
00671                 }
00672 
00673             case VISIR_SPC_M_GHR27:
00674                 {
00675                     self->d=77.16526;
00676                     self->m=5;
00677                     self->gg=217.8772;
00678                     self->w=4.1;
00679                     self->offset=108.7;
00680                     self->factor=2980;
00681                     break;
00682                 }
00683             default:;
00684             }
00685 
00686             if (self->side_is_A) {
00687                 /* side 'A' */
00688                 self->angle_a  = 62.1299;
00689                 self->angle_bm = 64.8519;
00690                 self->angle_b0 = 64.5393;
00691                 self->angle_b1 = 65.1641;
00692             } else {
00693                 /* side 'B' */
00694                 self->angle_a  = 64.8701;
00695                 self->angle_bm = 62.1483;
00696                 self->angle_b0 = 62.4609;
00697                 self->angle_b1 = 61.8361;
00698             }
00699             self->w *= rad_per_deg;
00700 
00701             /* Length constants are coded in micron - convert to m */
00702             self->gg *= 1e-6;
00703             break;
00704         }
00705     case VISIR_SPC_R_HR:
00706         {
00707             /* Switch on the (HR Long Slit)-mode */
00708             self->side_is_A = 0;
00709             self->dcolbeam = 125000; /* [micron] */
00710             self->ld = 23403;
00711 
00712             switch (mode) {
00713             case VISIR_SPC_M_HR01:
00714                 {
00715                     self->m=17;
00716                     break;
00717                 }
00718             case VISIR_SPC_M_HR02:
00719                 {
00720                     self->side_is_A = 1;
00721                     self->m=16;
00722                     break;
00723                 }
00724             case VISIR_SPC_M_HR03:
00725                 {
00726                     self->side_is_A = 1;
00727                     self->m=15;
00728                     break;
00729                 }
00730             case VISIR_SPC_M_HR04:
00731                 {
00732                     self->side_is_A = 1;
00733                     self->m=12;
00734                     break;
00735                 }
00736             case VISIR_SPC_M_HR05:
00737                 {
00738                     self->m=11;
00739                     break;
00740                 }
00741             case VISIR_SPC_M_HR06:
00742                 {
00743                     self->m=11;
00744                     break;
00745                 }
00746             case VISIR_SPC_M_HR07:
00747                 {
00748                     self->side_is_A = 1;
00749                     self->m=11;
00750                     break;
00751                 }
00752             case VISIR_SPC_M_HR08:
00753                 {
00754                     self->m=8;
00755                     break;
00756                 }
00757             case VISIR_SPC_M_HR09:
00758                 {
00759                     self->side_is_A = 1;
00760                     self->m=8;
00761                     break;
00762                 }
00763             case VISIR_SPC_M_HR10:
00764                 {
00765                     self->m=7;
00766                     break;
00767                 }
00768             default:;
00769             }
00770             if (self->side_is_A) {
00771                 /* side 'A' */
00772                 self->d=79.93104;
00773                 self->angle_a  = 62.1299;
00774                 self->angle_bm = 64.8519;
00775                 self->angle_b0 = 64.5393;
00776                 self->angle_b1 = 65.1641;
00777             } else {
00778                 /* side 'B' */
00779                 self->d=77.16526;
00780                 self->angle_a  = 64.8701;
00781                 self->angle_bm = 62.1483;
00782                 self->angle_b0 = 62.4609;
00783                 self->angle_b1 = 61.8361;
00784             }
00785             break;
00786         }
00787     default:;
00788     }
00789 
00790     self->angle_a  *= rad_per_deg;
00791     self->angle_b0 *= rad_per_deg;
00792     self->angle_bm *= rad_per_deg;
00793     self->angle_b1 *= rad_per_deg;
00794 
00795     /* Length constants are coded in micron - convert to m */
00796     self->d        *= 1e-6;
00797     self->dcolbeam *= 1e-6;
00798 
00799     assert( self->m > 0);
00800 
00801     visir_spc_optmod_scan_angle(self);
00802 
00803     self->sinus_sum = sin(self->angle_a  + self->angle_scan)
00804                     + sin(self->angle_bm + self->angle_scan);
00805 
00806     return 0;
00807 
00808 }
00809 
00810 
00811 /*----------------------------------------------------------------------------*/
00825 /*----------------------------------------------------------------------------*/
00826 double visir_spc_optmod_wlen(const visir_optmod * pins, double * pwl0, 
00827                              double * pwl1)
00828 {
00829 
00830     const visir_optmod_private * self = (const visir_optmod_private*)pins;
00831 
00832     if (self == NULL) return -1;
00833 
00834     /* The wavelength on the center of the 1st pixel */
00835     if (pwl0) *pwl0 = self->d/self->m*( sin(self->angle_a  + self->angle_scan)
00836                                       + sin(self->angle_b0 + self->angle_scan));
00837   
00838     /* The wavelength on the center of the last pixel */
00839     if (pwl1) *pwl1 = self->d/self->m*( sin(self->angle_a  + self->angle_scan)
00840                                       + sin(self->angle_b1 + self->angle_scan));
00841 
00842     /* The wavelength on the detector-center according to the model */
00843     return self->d / self->m * self->sinus_sum;
00844 
00845 }
00846 
00847 /*----------------------------------------------------------------------------*/
00866 /*----------------------------------------------------------------------------*/
00867 double visir_spc_optmod_cross_dispersion(const visir_optmod * pins, double wlen)
00868 {
00869 
00870     double sinbeta;
00871     double rf_index;
00872     const visir_optmod_private * self = (const visir_optmod_private*)pins;
00873 
00874     if (self == NULL) return -1;
00875 
00876     if (self->resolution != VISIR_SPC_R_GHR) return -2;
00877     if (wlen <= 0) return -3;
00878 
00879     assert( self->gg != 0 );
00880 
00881     rf_index = visir_spc_optmod_krs5(wlen);
00882 
00883     if (rf_index < 1) return -8;
00884 
00885     sinbeta = sin(self->w) * rf_index - wlen / self->gg;
00886 
00887     /* Correct any rounding errors */
00888     if (sinbeta < -1) return -9;
00889     if (sinbeta >  1) return -10;
00890 
00891     return self->offset + self->factor * tan(asin(sinbeta) - self->w);
00892 
00893 }
00894 
00895 
00896 /*----------------------------------------------------------------------------*/
00919 /*----------------------------------------------------------------------------*/
00920 double visir_spc_optmod_echelle(const visir_optmod * pins, double wlen,
00921                                 int ioffset)
00922 {
00923 
00924     int order;
00925     const visir_optmod_private * self = (const visir_optmod_private*)pins;
00926 
00927     if (self == NULL) return -1;
00928     if (self->resolution != VISIR_SPC_R_GHR) return -2;
00929     if (wlen <= 0) return -3;
00930     if (ioffset < -4) return -4;
00931     if (ioffset >  4) return -5;
00932 
00933     order = ioffset + self->m;
00934 
00935     /* There are 18 echelle orders */
00936     if (order <    1) return -6;
00937     if (order >   18) return -7;
00938 
00939     return wlen * self->m / (double) order;
00940 
00941 }
00942 
00943 /*----------------------------------------------------------------------------*/
00958 /*----------------------------------------------------------------------------*/
00959 int visir_spc_optmod_side_is_A(const visir_optmod * pins)
00960 {
00961     const visir_optmod_private * self = (const visir_optmod_private*)pins;
00962 
00963     if (self == NULL) return -1;
00964 
00965     if (self->resolution != VISIR_SPC_R_GHR &&
00966         self->resolution != VISIR_SPC_R_HR) return -2;
00967 
00968     return self->side_is_A;
00969 
00970 }
00971 
00972 /*----------------------------------------------------------------------------*/
00987 /*----------------------------------------------------------------------------*/
00988 int visir_spc_optmod_get_echelle_order(const visir_optmod * pins)
00989 {
00990     const visir_optmod_private * self = (const visir_optmod_private*)pins;
00991 
00992     if (self == NULL) return -1;
00993 
00994     if (self->resolution != VISIR_SPC_R_GHR &&
00995         self->resolution != VISIR_SPC_R_HR) return -2;
00996 
00997     return self->m;
00998 }
00999 
01000 
01001 /*----------------------------------------------------------------------------*/
01013 /*----------------------------------------------------------------------------*/
01014 
01015 double visir_spc_optmod_resolution(const visir_optmod * pins)
01016 {
01017     const visir_optmod_private * self = (const visir_optmod_private*)pins;
01018 
01019     if (self == NULL) return -1;
01020 
01021     return self->dcolbeam * self->sinus_sum
01022         /(2.0 * self->wlen * cos(self->angle_a  + self->angle_scan));
01023 }
01024 
01025 /*----------------------------------------------------------------------------*/
01038 /*----------------------------------------------------------------------------*/
01039 
01040 double visir_spc_optmod_dispersion(const visir_optmod * pins)
01041 {
01042     const visir_optmod_private * self = (const visir_optmod_private*)pins;
01043 
01044     if (self == NULL) return -1;
01045 
01046     return self->ld * self->sinus_sum
01047         /(self->wlen * cos(self->angle_bm + self->angle_scan));
01048 }
01049 
01052 /*----------------------------------------------------------------------------*/
01059 /*----------------------------------------------------------------------------*/
01060 static double visir_spc_optmod_krs5(double wlen) {
01061 
01062     const double a0 =  5.96032159;
01063     const double a1 = -5.36135205e-4;
01064     const double a2 =  1.77047634;
01065     const double a3 = -2.79310980e1;
01066     const double a4 = -1.28684883;
01067     const double a5 = -4.34541795e-2;
01068 
01069     double n2 = 0;
01070 
01071 
01072     assert( wlen > 0 );
01073 
01074     /* The above constants are for a wavelength in microns */
01075     wlen *= 1e6;
01076 
01077     wlen *= wlen;
01078 
01079     n2 = a0 + a1 * wlen + (((a5/wlen + a4)/wlen + a3)/ wlen + a2)/wlen;
01080 
01081     /* The refractive index is greater than 1 */
01082     return n2 > 1 ? sqrt(n2) : -1;
01083 
01084 }
01085 
01086 /*----------------------------------------------------------------------------*/
01093 /*----------------------------------------------------------------------------*/
01094 static void visir_spc_optmod_scan_angle(visir_optmod_private * self)
01095 {
01096 
01097     /* Determine the Scan-angle from Mode and Central Wavelength */
01098 
01099     const double mld = self->m * self->wlen / self->d;
01100     const double sab = sin(self->angle_bm) + sin(self->angle_a);
01101     const double cab = cos(self->angle_bm) + cos(self->angle_a);
01102     const double A = sab * sab + cab * cab;
01103     /*
01104       const double B = -2 * mld * cab;
01105     */
01106     const double C = mld * mld - sab * sab;
01107 
01108     double D = A - mld * mld; /* D = B^2 - 4 * A * C */
01109     double u1, u2;
01110 
01111     /* D can only become negative due to rounding errors */
01112     D = D > 0 ? sqrt(D) : 0;
01113     D *= fabs(sab);
01114 
01115     /* A, cab, mld & D are all positive */
01116     u1 = (cab * mld + D) / A;
01117 
01118     /* u2 may be a lot smaller than both D/A and cab * mld/A, so subtraction
01119        of those two terms may lead to loss of precision. u2 is instead
01120        computed by use of the fact that C = A * u1 * u2 */
01121     u2 = C / A / u1;           
01122 
01123     /* u1 is not a physically meaningful solution, it is just an
01124        intermediate result */
01125 
01126     self->angle_scan = asin(u2);
01127 
01128 }

Generated on Mon Feb 6 15:23:49 2012 for VISIR Pipeline Reference Manual by  doxygen 1.5.8