LCOV - code coverage report
Current view: top level - air_casawvr/src - radiometermeasure.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 68 153 44.4 %
Date: 2024-12-11 20:54:31 Functions: 8 21 38.1 %

          Line data    Source code
       1             : /**
       2             :    \file radiometermeasure.cpp
       3             :    Bojan Nikolic <bn204@mrao.cam.ac.uk>, <bojan@bnikolic.co.uk>
       4             :    
       5             :    Initial version February 2008
       6             :    Maintained by ESO since 2013.
       7             :    Renamed radiometermeasure.cc 2023
       8             : 
       9             : */
      10             : 
      11             : #include <functional>
      12             : #include <vector>
      13             : 
      14             : #include "radiometermeasure.h"
      15             : #include "radiometer_utils.h"
      16             : 
      17             : namespace LibAIR2 {
      18             : 
      19         324 :   Radiometer::Radiometer( const std::vector<double> & FGrid,
      20         324 :                           const std::vector<double> & coeffs):
      21         324 :     FGrid(FGrid),
      22         324 :     coeffs_v(1)
      23             :   {
      24         324 :     coeffs_v[0]=coeffs;
      25         324 :   }
      26             : 
      27          81 :   Radiometer::Radiometer( const std::vector<double> & FGrid,
      28          81 :                           const std::vector< std::vector<double> >  & coeffs_v):
      29          81 :     FGrid(FGrid),
      30          81 :     coeffs_v(coeffs_v)    
      31             :   {
      32          81 :   }
      33             :   
      34             : 
      35           0 :   DSBRadio::DSBRadio( double f_0,
      36           0 :                       double f_if):
      37           0 :     f_0(f_0),
      38           0 :     f_if(f_if)
      39             :   {
      40           0 :     std::vector<double> FGrid(2);
      41           0 :     FGrid[0] = f_0- f_if;
      42           0 :     FGrid[1] = f_0+ f_if;
      43           0 :     std::vector<double> coeffs(2, 0.5);
      44             :     
      45           0 :     r.reset( new Radiometer(FGrid, coeffs));
      46           0 :   }
      47             : 
      48         324 :   DSBRadio::DSBRadio( double f_0,
      49             :                       double f_if,
      50         324 :                       Radiometer * rr):
      51         324 :     r(rr),
      52         324 :     f_0(f_0),
      53         324 :     f_if(f_if)
      54             :   {
      55             : 
      56         324 :   }
      57             : 
      58         324 :   const Radiometer & DSBRadio::getRadiometer(void) const
      59             :   {
      60         324 :     return *r;
      61             :   }
      62             : 
      63             : 
      64           0 :   double DSBRadio::eval( const std::vector<double> & skyTb) const
      65             :   {
      66           0 :     return r->eval(skyTb);
      67             :   }
      68             : 
      69           0 :   DSBBWRadio::DSBBWRadio( double f_0,
      70             :                           double f_if,
      71           0 :                           double f_bw):
      72             :     DSBRadio(f_0, f_if, 
      73             :              MkRadio( f_0, f_if, f_bw) ),
      74           0 :     f_bw(f_bw)
      75             :   {
      76           0 :   }
      77             : 
      78           0 :   Radiometer * DSBBWRadio::MkRadio( double f_0,
      79             :                                     double f_if,
      80             :                                     double f_bw)
      81             :   {
      82           0 :     const size_t nsamples=30;
      83             : 
      84           0 :     std::vector<double> FGrid(nsamples *2 );
      85           0 :     std::vector<double> coeffs(nsamples *2, 1.0/(nsamples *2));
      86             : 
      87           0 :     const double delta = f_bw / (nsamples -1);
      88           0 :     const double flow  = f_if - f_bw *0.5;
      89             : 
      90           0 :     for (size_t i =0 ; i < nsamples ; ++i)
      91             :     {
      92           0 :       const double fif_c = flow + delta * i;
      93           0 :       FGrid[nsamples-i-1] =   f_0- fif_c;
      94           0 :       FGrid[nsamples+i]   = f_0+ fif_c;
      95             :       
      96             :     }
      97           0 :     return new Radiometer(FGrid, coeffs);
      98             : 
      99           0 :   }
     100             : 
     101         324 :   DSBBW_QuadRadio::DSBBW_QuadRadio( double f_0,
     102             :                                     double f_if,
     103         324 :                                     double f_bw):
     104             :     DSBRadio(f_0, f_if, 
     105         324 :              MkRadio( f_0, f_if, f_bw) )
     106             :   {
     107         324 :   }
     108             : 
     109         324 :   Radiometer * DSBBW_QuadRadio::MkRadio( double f_0,
     110             :                                          double f_if,
     111             :                                          double f_bw)
     112             :   {
     113             :     // 5 point Gauss-Legendre Rule.
     114             :     // See http://www.sitmo.com/eq/423
     115         324 :     const double x[] = {-9.06179845938663992811e-01,
     116             :                         -5.38469310105683091018e-01,
     117             :                         0.00000000000000000000e+00,    
     118             :                         5.38469310105683091018e-01,
     119             :                         9.06179845938663992811e-01};
     120             :     
     121         324 :     const double w[] = {2.36926885056189087515e-01,
     122             :                         4.78628670499366468030e-01,
     123             :                         5.68888888888888888883e-01,    
     124             :                         4.78628670499366468030e-01,
     125             :                         2.36926885056189087515e-01};
     126             : 
     127         324 :     const size_t nsamples = sizeof(x)/sizeof(double);
     128             : 
     129         324 :     std::vector<double> FGrid(nsamples*2);
     130         324 :     std::vector<double> coeffs(nsamples*2);
     131             : 
     132             :     /// Note we want the average signal over the bandwidth. Therefore
     133             :     /// integrathe the function over bandwidth then divide by
     134             :     /// bandwidth to get average value. As ressult coefficients below
     135             :     /// do not f_bw in their expressions.
     136             : 
     137             :     /// Note that there is an extra factor of * 0.5 becuase we have
     138             :     /// two bands
     139             : 
     140             :     /// Lower band
     141        1944 :     for (size_t i =0 ; i < nsamples ; ++i)
     142             :     {
     143        1620 :       const double fc = f_0 - f_if;
     144        1620 :       FGrid[i] = fc + 0.5* f_bw * x[i];
     145        1620 :       coeffs[i]= 0.5 * 0.5 * w[i];
     146             :     }
     147             : 
     148             :     /// Upper band
     149        1944 :     for (size_t i =0 ; i < nsamples ; ++i)
     150             :     {
     151        1620 :       const double fc = f_0 + f_if;
     152        1620 :       FGrid [i+nsamples] = fc + 0.5* f_bw * x[i];
     153        1620 :       coeffs[i+nsamples]= 0.5 * 0.5 * w[i];
     154             :     }
     155         648 :     return new Radiometer(FGrid, coeffs);
     156         324 :   }
     157             : 
     158           0 :   InvalidWVRChannel::InvalidWVRChannel(int chlow,
     159             :                                        int chhigh,
     160           0 :                                        int ch) :
     161           0 :     chlow(chlow),
     162           0 :     chhigh(chhigh),
     163           0 :     ch(ch)
     164             :   {
     165           0 :   }
     166             : 
     167           0 :   DSBRadio * MkALMARadiometer(int ch,
     168             :                               double cf_off,
     169             :                               double bw_off) noexcept(false)
     170             :   {
     171           0 :     const double filter_c[] = { 1.25, 3.25, 5.5, 7.25};
     172           0 :     const double filter_bw[]= { 1.5 , 2.5 , 2.0, 1.5};
     173             : 
     174           0 :     if ( ch<1 or ch > 4)
     175             :     {
     176           0 :       throw InvalidWVRChannel(1 , 4, ch);
     177             :     }
     178             : 
     179             :     return new DSBBW_QuadRadio( 183.31,
     180           0 :                                 filter_c[ch-1] +cf_off,
     181           0 :                                 filter_bw[ch-1]+bw_off);
     182             :                            
     183             : 
     184             :   }
     185             : 
     186           0 :   DSBRadio * MkALMADickeProto(int ch) noexcept(false)
     187             :   {
     188             : 
     189           0 :     const double filter_c[] = { 0.88 , 1.94 , 3.175, 5.2 };
     190           0 :     const double filter_bw[]= { 0.16 , 0.75 , 1.25 , 2.5 };
     191             : 
     192           0 :     if ( ch<1 or ch > 4)
     193             :     {
     194           0 :       throw InvalidWVRChannel(1 , 4, ch);
     195             :     }
     196             : 
     197             :     return new DSBBW_QuadRadio( 183.31,
     198           0 :                            filter_c[ch-1],
     199           0 :                            filter_bw[ch-1]);
     200             :                            
     201             : 
     202             :   }
     203             : 
     204             :   /***
     205             :       Merge the four channels into single radiomer
     206             :    */
     207           0 :   Radiometer * MkFullWVR( const std::function< DSBRadio*  (int ch) > & mkchn )
     208             :   {
     209           0 :     std::vector< std::shared_ptr<DSBRadio>  > dsbv;
     210           0 :     std::vector<const Radiometer *>  rv;
     211             : 
     212           0 :     for (size_t j = 1 ; j < 5; ++j )
     213             :     {
     214           0 :       dsbv.push_back( std::shared_ptr<DSBRadio> (mkchn(j)) );
     215           0 :       rv.push_back( & dsbv[ j-1]->getRadiometer());
     216             :     }
     217             : 
     218           0 :     return MergeRadiometers( rv).release();
     219           0 :   }
     220             : 
     221           0 :   Radiometer * MkFullALMAWVR(void)
     222             :   {
     223           0 :     return MkFullWVR(std::bind(MkALMARadiometer,std::placeholders::_1,0.0,0.0));
     224             :   }
     225             : 
     226           0 :   Radiometer * MkALMAWVR_offset(double cf,
     227             :                                 double bw)
     228             :   {
     229           0 :     return MkFullWVR(std::bind(MkALMARadiometer,
     230             :                                std::placeholders::_1,
     231             :                                cf,
     232           0 :                                bw));
     233             :   }
     234             : 
     235          81 :   ALMAWVRCharacter::ALMAWVRCharacter(void)
     236             :   {
     237          81 :     cf1=1.25;
     238          81 :     cf2=3.25;
     239          81 :     cf3=5.5;
     240          81 :     cf4=7.25;
     241             :     
     242          81 :     bw1=1.5;
     243          81 :     bw2=2.5;
     244          81 :     bw3=2.0;
     245          81 :     bw4=1.5;
     246             : 
     247          81 :   }
     248             : 
     249          81 :   Radiometer *MkALMAWVR(const ALMAWVRCharacter &c)
     250             :   {
     251          81 :     std::vector< std::shared_ptr<DSBRadio> > dsbv;
     252          81 :     dsbv.push_back(std::shared_ptr<DSBRadio>(new DSBBW_QuadRadio(183.31,
     253          81 :                                                                  c.cf1,
     254          81 :                                                                  c.bw1))
     255             :                    );
     256          81 :     dsbv.push_back(std::shared_ptr<DSBRadio>(new DSBBW_QuadRadio(183.31,
     257          81 :                                                                  c.cf2,
     258          81 :                                                                  c.bw2))
     259             :                    );
     260          81 :     dsbv.push_back(std::shared_ptr<DSBRadio>(new DSBBW_QuadRadio(183.31,
     261          81 :                                                                  c.cf3,
     262          81 :                                                                  c.bw3))
     263             :                    );
     264          81 :     dsbv.push_back(std::shared_ptr<DSBRadio>(new DSBBW_QuadRadio(183.31,
     265          81 :                                                                  c.cf4,
     266          81 :                                                                  c.bw4))
     267             :                    );
     268             : 
     269          81 :     std::vector<const Radiometer *>  rv;    
     270         405 :     for(size_t i=0; i<dsbv.size(); ++i)
     271             :     {
     272         324 :       rv.push_back(&dsbv[i]->getRadiometer());
     273             :     }
     274         162 :     return MergeRadiometers( rv).release();    
     275          81 :   }
     276             : 
     277             : 
     278           0 :   Radiometer * MkFullDickeProtoWVR(void)
     279             :   {
     280           0 :     return MkFullWVR( MkALMADickeProto);
     281             :   }
     282             : 
     283           0 :   Radiometer * MkSSBRadio(double f_c,
     284             :                           double f_bw)
     285             :   {
     286             :     // 5 point Gauss-Legendre Rule.  See http://www.sitmo.com/eq/423
     287           0 :     const double x[] = {-9.06179845938663992811e-01,
     288             :                         -5.38469310105683091018e-01,
     289             :                         0.00000000000000000000e+00,    
     290             :                         5.38469310105683091018e-01,
     291             :                         9.06179845938663992811e-01};
     292             :     
     293           0 :     const double w[] = {2.36926885056189087515e-01,
     294             :                         4.78628670499366468030e-01,
     295             :                         5.68888888888888888883e-01,    
     296             :                         4.78628670499366468030e-01,
     297             :                         2.36926885056189087515e-01};
     298             : 
     299           0 :     const size_t nsamples = sizeof(x)/sizeof(double);
     300             : 
     301           0 :     std::vector<double> FGrid(nsamples);
     302           0 :     std::vector<double> coeffs(nsamples);
     303             : 
     304           0 :     for (size_t i =0 ; i < nsamples ; ++i)
     305             :     {
     306           0 :       FGrid[i] = f_c + 0.5* f_bw * x[i];
     307           0 :       coeffs[i]= 0.5 * w[i];
     308             :     }
     309             :     
     310           0 :     return new Radiometer(FGrid, coeffs);
     311             : 
     312           0 :   }
     313             : 
     314           0 :   Radiometer * MkIRAM22(void)
     315             :   {
     316           0 :     const double filter_c[] = { 19.2, 22, 25.2};
     317           0 :     const double filter_bw[] = {1.15, 1.15, 1.15};
     318             :     
     319           0 :     std::vector< std::shared_ptr<Radiometer> > rv;
     320           0 :     std::vector< const Radiometer * > rv_obs;
     321             :     
     322           0 :     for (size_t i =0 ; i < 3; ++i)
     323             :     {
     324           0 :       rv.push_back(std::shared_ptr<Radiometer>(MkSSBRadio(filter_c[i],
     325           0 :                                                             filter_bw[i])));
     326             : 
     327           0 :       rv_obs.push_back(rv[i].get());
     328             :     }
     329             :     
     330           0 :     return MergeRadiometers(rv_obs).release();
     331             :     
     332           0 :   }
     333             : 
     334             : }
     335             : 
     336             : 
     337             : 

Generated by: LCOV version 1.16