LCOV - code coverage report
Current view: top level - air_casawvr/src/apps - almaabs.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 137 280 48.9 %
Date: 2024-12-11 20:54:31 Functions: 10 19 52.6 %

          Line data    Source code
       1             : /**
       2             :    Bojan Nikolic <b.nikolic@mrao.cam.ac.uk>, <bojan@bnikolic.co.uk>
       3             :    Initial version November 2009
       4             :    Maintained by ESO since 2013.
       5             : 
       6             :    Renamed almaabs.cc 2023
       7             : 
       8             : */
       9             : 
      10             : #include "almaabs.h"
      11             : 
      12             : #include <iostream>
      13             : #include <stdio.h>            /*** for sprintf(...) ***/
      14             : #include <cassert>
      15             : 
      16             : #include "almaabs_i.h"
      17             : #include "almaopts.h"
      18             : #include "arraydata.h"
      19             : #include "dtdlcoeffs.h"
      20             : #include "segmentation.h"
      21             : #include "../radiometermeasure.h"
      22             : #include "../dtdltools.h"
      23             : 
      24             : #include "../model_make.h"
      25             : #include "bnmin1/src/nestedsampler.h"
      26             : #include "bnmin1/src/nestedinitial.h"
      27             : 
      28             : 
      29             : #ifdef ELLIPSESAMPLE
      30             : #include "bnmin1/src/prior_sampler.h"
      31             : #include "bnmin1/src/mcmonitor.h"
      32             : #endif
      33             : 
      34             : namespace LibAIR2 {
      35             : 
      36          81 :   ALMAAbsRet::ALMAAbsRet(const std::vector<double> &TObs,
      37             :                          double el,
      38             :                          const ALMAWVRCharacter &WVRChar,
      39          81 :                          unsigned rseed):
      40          81 :     i(new iALMAAbsRet(TObs,
      41             :                       el,
      42             :                       WVRChar,
      43          81 :                       rseed)),
      44          81 :     valid(true)
      45             :   {
      46          81 :     if( ! i->sample()){
      47           4 :       valid = false;
      48             :     }
      49          81 :   }
      50             : 
      51          81 :   ALMAAbsRet::~ALMAAbsRet()
      52             :   {
      53          81 :   }
      54             : 
      55          81 :   bool ALMAAbsRet::g_Res(ALMAResBase &res)
      56             :   {
      57          81 :     if(valid){ 
      58          77 :       i->g_Pars(res);
      59          77 :       i->g_Coeffs(res);
      60          77 :       return true;
      61             :     }
      62             :     else{
      63           4 :       return false;
      64             :     }
      65             :   }
      66             : 
      67           0 :   std::ostream & operator<<(std::ostream &os, 
      68             :                             const  ALMAAbsInput &i)
      69             :   {
      70             :     char tstr[120];                                                                                       
      71           0 :     sprintf(tstr, "[%5.2f, %5.2f, %5.2f, %5.2f]", i.TObs[0], i.TObs[1], i.TObs[2], i.TObs[3]); 
      72             : 
      73           0 :     os<<i.time<<"\t"
      74           0 :       <<i.antno<<"\t"
      75             :       <<tstr 
      76           0 :       <<"\t"
      77           0 :       <<i.el
      78           0 :       <<"\t"
      79           0 :       <<i.state;
      80           0 :     return os;
      81             :   }
      82             : 
      83           0 :   std::ostream & operator<<(std::ostream &os, 
      84             :                             const  ALMAAbsInpL &i)
      85             :   {
      86           0 :     os<<"     Input WVR data information:   "<<std::endl
      87           0 :       <<"-----------------------------------"<<std::endl;    
      88             :     os<<"Timestamp"<<"\t"
      89             :       <<"Ant. #"<<"\t"
      90             :       <<"["<<"Chn 0"<<", "
      91             :            <<"Chn 1"<<", "
      92             :            <<"Chn 2"<<", "
      93             :            <<"Chn 3"<<"]"
      94             :       <<"\t"
      95             :       <<"Elevation"
      96             :       <<"\t"
      97           0 :       <<"STATE_ID"<<std::endl;
      98           0 :     for(const ALMAAbsInput &x: i)
      99             :     {
     100           0 :       os<<x<<std::endl;
     101             :     }
     102           0 :     return os;
     103             :   }
     104             : 
     105             :   /** \brief Check that the supplied temperatures are reasonable
     106             :    */
     107          81 :   static void checkTObs(const std::vector<double>  &TObs)
     108             :   {
     109          81 :     int above = 0;
     110          81 :     int below = 0;
     111         405 :     for(size_t i=0; i<TObs.size(); ++i)
     112             :     {
     113         324 :       if (TObs[i]<2.7){
     114           0 :         below++;
     115             :       }
     116         324 :       else if (TObs[i]>350.){
     117           0 :         above++;
     118             :       }
     119             :     }
     120          81 :     if (above>0 || below>0){
     121             :       char tstr[120];                                                                                       
     122           0 :       sprintf(tstr, "Values out of range: Out of %d TObs values, %d were below 2.7 K and %d were above 350 K.", 
     123           0 :               (int)TObs.size(), below, above); 
     124           0 :       throw std::runtime_error(tstr);
     125             :     }
     126          81 :   }
     127             :   
     128           0 :   static void getMidPointData(const InterpArrayData &d,
     129             :                               int refant,
     130             :                               std::vector<double>  &TObs,
     131             :                               double &el,
     132             :                               double &time,
     133             :                               size_t &state)
     134             :   {
     135           0 :     TObs.resize(4);
     136           0 :     const size_t midpoint=static_cast<size_t>(d.g_time().size() *0.5);
     137           0 :     for(size_t k=0; k<4; ++k)
     138             :     {
     139           0 :       TObs[k]=d.g_wvrdata()(midpoint, refant, k);
     140             :     }
     141           0 :     checkTObs(TObs);    
     142           0 :     el=d.g_el()[midpoint];
     143           0 :     time=d.g_time()[midpoint];
     144           0 :     state=d.g_state()[midpoint];
     145           0 :   }
     146             : 
     147             :   // Convert to units of K/meter
     148           0 :   static void convertKm(std::vector<double> &dTdL)
     149             :   {
     150           0 :     for(size_t i=0; i<4; ++i)
     151             :     {
     152           0 :       dTdL[i]*=1e3;
     153             :     }
     154           0 :   }
     155           0 :   ALMAAbsInpL SimpleSingleI(const InterpArrayData &d,
     156             :                             int refant)
     157             :   {
     158           0 :     ALMAAbsInpL res;
     159             :     ALMAAbsInput a;
     160             : 
     161           0 :     std::vector<double>  TObs(4);
     162             :     double el, time;
     163             :     size_t state;
     164           0 :     getMidPointData(d, refant, 
     165             :                     TObs, 
     166             :                     el, time,
     167             :                     state);    
     168             : 
     169           0 :     a.antno=refant;
     170           0 :     for(size_t i=0; i<4; ++i)
     171           0 :       a.TObs[i]=TObs[i];
     172           0 :     a.el=el;
     173           0 :     a.time=time;
     174           0 :     a.state=state;
     175           0 :     res.push_back(a);
     176           0 :     return res;
     177           0 :   }
     178             : 
     179           6 :   ALMAAbsInpL MultipleUniformI(const InterpArrayData &d,
     180             :                                size_t n,
     181             :                                const std::set<size_t> &states,
     182             :                                int refant)
     183             :   {
     184           6 :     ALMAAbsInpL res;
     185           6 :     const size_t nrows=d.g_time().size();
     186           6 :     const size_t ndelta=nrows / (n+1);
     187             : 
     188          16 :     for(size_t i=0; i<n; ++i)
     189             :     {
     190             :       ALMAAbsInput a;
     191          10 :       size_t row=ndelta*(i+1);
     192          10 :       while (row<(nrows-1) and states.count(d.g_state()[row])==0)
     193             :       {
     194           0 :         ++row;
     195             :       }
     196             : 
     197          10 :       if (states.count(d.g_state()[row]) == 0)
     198             :       {
     199           0 :         throw std::runtime_error("Could not find a row with a sky state");
     200             :       }      
     201          10 :       a.antno=refant;
     202          50 :       for(size_t k=0; k<4; ++k)
     203          40 :         a.TObs[k]=d.g_wvrdata()(row, refant, k);
     204          10 :       a.el=d.g_el()[row];
     205          10 :       a.time=d.g_time()[row];
     206          10 :       a.state=d.g_state()[row];
     207             : 
     208          10 :       res.push_back(a);
     209             :     }
     210           6 :     return res;
     211           0 :   }
     212             : 
     213          19 :   ALMAAbsInpL FieldMidPointI(const InterpArrayData &d,
     214             :                              const std::vector<std::pair<double, double> >  &fb,
     215             :                              const std::set<size_t> &states,
     216             :                              int refant)
     217             :   {
     218          19 :     ALMAAbsInpL res;
     219             : 
     220          19 :     const size_t nrows=d.g_time().size();
     221          19 :     size_t row=0;
     222          92 :     for(size_t i=0; i<fb.size(); ++i)
     223             :     {
     224             :       ALMAAbsInput a;
     225          73 :       const double ftime=fb[i].first;
     226          73 :       const double ltime=fb[i].second;
     227          73 :       const double mtime=(ftime+ltime)/2;
     228             :       
     229         715 :       while (row<(nrows-1) and d.g_time()[row] < mtime)
     230             :       {
     231         642 :         ++row;
     232             :       }
     233             : 
     234             :       // Now find the next row with a good state
     235          73 :       while (row<(nrows-1) and states.count(d.g_state()[row])==0)
     236             :       {
     237           0 :         ++row;
     238             :       }
     239          73 :       if (states.count(d.g_state()[row]) == 0)
     240             :       {
     241           0 :         throw std::runtime_error("Could not find a row with a sky state");
     242             :       }
     243          73 :       a.antno=refant;
     244         365 :       for(size_t k=0; k<4; ++k)
     245             :       {
     246         292 :         a.TObs[k]=d.g_wvrdata()(row, refant, k);
     247             :       }
     248          73 :       a.el=d.g_el()[row];
     249          73 :       a.time=d.g_time()[row];
     250          73 :       a.state=d.g_state()[row];
     251          73 :       a.source=d.g_source()[row];
     252          73 :       res.push_back(a);
     253             :     }
     254          19 :     return res;
     255           0 :   }
     256             : 
     257             :   dTdLCoeffsBase * 
     258           0 :   SimpleSingle(const InterpArrayData &d, int refant)
     259             :   {
     260           0 :     std::vector<double>  TObs(4);
     261             :     double el, time;
     262             :     size_t state;
     263           0 :     getMidPointData(d, refant, TObs, el, time, state);
     264             : 
     265           0 :     ALMAWVRCharacter wvrchar;
     266             :     ALMAAbsRet ar(TObs, 
     267             :                   M_PI/2.0,  
     268           0 :                   wvrchar);
     269           0 :     ALMAResBase res;
     270           0 :     ar.g_Res(res);
     271             : 
     272             :     // Convert to units of K/meter
     273           0 :     std::vector<double> dTdL(4);
     274           0 :     std::vector<double> dTdL_err(4);
     275           0 :     for(size_t i=0; i<4; ++i)
     276             :     {
     277           0 :       dTdL[i]=res.dTdL[i];
     278           0 :       dTdL_err[i]=res.dTdL_err[i];
     279             :     }
     280             : 
     281           0 :     convertKm(dTdL);
     282           0 :     convertKm(dTdL_err);
     283             : 
     284             :     return new dTdLCoeffsSingle(dTdL,
     285             :                                 dTdL_err
     286           0 :                                 );
     287             :     
     288           0 :   }
     289             : 
     290             :   // There is too much repetition here, need to merge with other
     291             :   // functions here
     292             :   dTdLCoeffsBase * 
     293           0 :   SimpleSingleCont(const InterpArrayData &d, int refant)
     294             :   {
     295             : 
     296           0 :     std::vector<double>  TObs(4);
     297             :     double el, time;
     298             :     size_t state;
     299           0 :     getMidPointData(d, refant, TObs, el, time, state);
     300             : 
     301           0 :     LibAIR2::ALMARetOpts opts;
     302           0 :     LibAIR2::ALMAContRes res;
     303           0 :     ALMAWVRCharacter wvrchar;
     304             : 
     305           0 :     ALMAAbsContRetrieve(TObs,
     306             :                         el,
     307             :                         wvrchar,
     308             :                         res,
     309             :                         opts);
     310             : 
     311             :     // Convert to units of K/meter
     312           0 :     std::vector<double> dTdL(4);
     313           0 :     std::vector<double> dTdL_err(4);
     314           0 :     for(size_t i=0; i<4; ++i)
     315             :     {
     316           0 :       dTdL[i]=res.dTdL[i];
     317           0 :       dTdL_err[i]=res.dTdL_err[i];
     318             :     }
     319             : 
     320           0 :     convertKm(dTdL);
     321           0 :     convertKm(dTdL_err);
     322             : 
     323             :     return new dTdLCoeffsSingle(dTdL,
     324           0 :                                 dTdL_err);
     325             :     
     326           0 :   }
     327             : 
     328          25 :   ALMAResBaseList doALMAAbsRet(ALMAAbsInpL &il,
     329             :                                std::vector<std::pair<double, double> > &fb,
     330             :                                AntSet& problemAnts,
     331             :                                unsigned rseed)
     332             :   {
     333             : 
     334          25 :     problemAnts.clear();
     335             : 
     336          25 :     AntSet resZeroAnts;
     337          25 :     AntSet resNonZeroAnts;
     338             : 
     339          25 :     ALMAResBaseList res;
     340             : 
     341          25 :     ALMAAbsInpL newil;
     342          25 :     std::vector<std::pair<double, double> > newfb;
     343          25 :     bool fbFilled = (fb.size()>0);
     344             : 
     345          25 :     if (rseed==0){ // if rseed is set to zero, use a default value
     346          25 :       rseed=43;
     347             :     }
     348             :     
     349          25 :     size_t count=0;
     350             : 
     351         106 :     for(const ALMAAbsInput &x: il)
     352             :     {
     353          81 :       bool problematic = false;
     354          81 :       std::vector<double>  TObs(4);
     355         405 :       for(size_t i=0; i<4; ++i){
     356         324 :         TObs[i]=x.TObs[i];
     357             :       }
     358             :       try {
     359          81 :         checkTObs(TObs);
     360             :       }
     361           0 :       catch(const std::runtime_error rE){
     362           0 :         std::cout << std::endl << "WARNING: problem with Tobs of antenna " << x.antno
     363           0 :                   << std::endl << "         LibAIR2::checkTObs: " << rE.what() << std::endl;
     364           0 :         std::cerr << std::endl << "WARNING: problem with Tobs of antenna " << x.antno
     365           0 :                   << std::endl << "         LibAIR2::checkTObs: " << rE.what() << std::endl;
     366           0 :         problematic = true;
     367           0 :       }
     368          81 :       ALMAWVRCharacter wvrchar;
     369             :      
     370          81 :       std::cout << "Using random seed " << rseed << std::endl;
     371             : 
     372             :       ALMAAbsRet ar(TObs, 
     373          81 :                     x.el,  
     374             :                     wvrchar,
     375          81 :                     rseed);
     376             :       
     377          81 :       ALMAResBase *ares=new ALMAResBase;      
     378          81 :       if(!ar.g_Res(*ares)){
     379           4 :         std::cout << "WARNING: Bayesian evidence was zero for antenna " << x.antno << std::endl
     380           4 :                   << "         TObs was " << TObs[0] << " " << TObs[1] << " " << TObs[2] << " " <<TObs[3] 
     381           4 :                   << " K, elevation " << x.el/M_PI*180. << " deg" << std::endl;
     382           4 :         std::cerr << "WARNING: Bayesian evidence was zero for antenna " << x.antno << std::endl
     383           4 :                   << "         TObs was " << TObs[0] << " " << TObs[1] << " " << TObs[2] << " " <<TObs[3] 
     384           4 :                   << " K, elevation " << x.el/M_PI*180. << " deg" << std::endl;
     385             :       }
     386             :       else{
     387          77 :         res.ptr_list.push_back(ares);
     388          77 :         newil.push_back(x);
     389          77 :         if(fbFilled){
     390          67 :           newfb.push_back(fb[count++]);
     391             :         }
     392             :       }
     393             :         
     394          81 :       if(problematic){
     395           0 :         problemAnts.insert(x.antno);
     396             :       }
     397             : 
     398          81 :       if(res.ptr_list.size()==0){
     399           2 :         resZeroAnts.insert(x.antno);
     400             :       }
     401             :       else{
     402          79 :         resNonZeroAnts.insert(x.antno);
     403             :       } 
     404             : 
     405          81 :     }
     406             : 
     407          27 :     for(AntSet::const_iterator it=resZeroAnts.begin(); it!=resZeroAnts.end(); it++){
     408           2 :       if(resNonZeroAnts.count(*it)==0){ // in none of the retrievals was there a non-zero evidence
     409           0 :         problemAnts.insert(*it);
     410             :       }
     411             :     }
     412             : 
     413          25 :     il = newil;
     414          25 :     fb = newfb;
     415             : 
     416          50 :     return res;
     417          25 :   }
     418             : 
     419          77 :   static void ALMAAbsRetP(ALMAResBase *i,
     420             :                           std::array<double, 4> &dTdL,
     421             :                           std::array<double, 4> &dTdL_err)
     422             :   {
     423         385 :     for(size_t k=0; k<4; ++k)
     424             :     {
     425         308 :       dTdL[k]= i->dTdL[k]*1e3;
     426         308 :       dTdL_err[k]= i->dTdL_err[k]*1e3;
     427             :     }
     428          77 :   }
     429             : 
     430             :   dTdLCoeffsBase *
     431           6 :   ALMAAbsProcessor(const ALMAAbsInpL &inp,
     432             :                    ALMAResBaseList &r)
     433             :   {
     434           6 :     assert(inp.size() == r.ptr_list.size());
     435             : 
     436           6 :     std::unique_ptr<dTdLCoeffsBase> res;
     437           6 :     if (inp.size()>0){
     438           6 :       dTdLCoeffsSingleInterpolated *rr=new dTdLCoeffsSingleInterpolated();
     439           6 :       res=std::unique_ptr<dTdLCoeffsBase>(rr);
     440             : 
     441           6 :       for(ALMAAbsInpL::const_iterator i=inp.begin(); 
     442          16 :           i!=inp.end(); 
     443          10 :           ++i)
     444             :       {
     445          10 :         ALMAResBase *rp = *(r.ptr_list.begin());
     446             : 
     447             :         std::array<double, 4> dTdL;
     448             :         std::array<double, 4> dTdL_err;
     449          10 :         ALMAAbsRetP(rp, dTdL, dTdL_err);
     450             : 
     451          10 :         rr->insert(i->time,
     452             :                    dTdL,
     453             :                    dTdL_err);
     454             : 
     455          10 :         r.ptr_list.pop_front(); // remove this almaresbase pointer from the list
     456          10 :         delete rp; // and free it
     457             :       }
     458             :       
     459             :     }
     460          12 :     return res.release();
     461           6 :   }
     462             : 
     463             : 
     464             :   dTdLCoeffsSingleInterpolated *
     465          19 :   SimpleMultiple(const std::vector<std::pair<double, double> > &fb,
     466             :                  ALMAResBaseList &r)
     467             :   {
     468             : 
     469          19 :     assert(fb.size()==r.ptr_list.size());
     470             :     
     471          19 :     std::unique_ptr<dTdLCoeffsSingleInterpolated> res(new dTdLCoeffsSingleInterpolated());
     472             : 
     473          19 :     std::list<ALMAResBase*>::iterator ir=r.ptr_list.begin();
     474          86 :     for(size_t i=0; i<fb.size(); ++i)
     475             :     {
     476             :     
     477             :       // Convert to units of K/meter
     478             :       std::array<double, 4> dTdL;
     479             :       std::array<double, 4> dTdL_err;
     480          67 :       ALMAAbsRetP(*ir, dTdL, dTdL_err);
     481          67 :       res->insert(fb[i].first,
     482             :                   dTdL,
     483             :                   dTdL_err);
     484          67 :       res->insert(fb[i].second,
     485             :                   dTdL,
     486             :                   dTdL_err);
     487          67 :       ++ir;
     488             :     }
     489             :     
     490          38 :     return res.release();
     491             :     
     492          19 :   }
     493             : 
     494           0 :   void ALMAAbsContRetrieve(const std::vector<double> &TObs,
     495             :                            double el,
     496             :                            const ALMAWVRCharacter &WVRChar,
     497             :                            ALMAContRes &res,
     498             :                            const ALMARetOpts &opts)
     499             :   {
     500           0 :     CouplingModel *cm= new CouplingModel(mkCloudy(WVRChar,
     501             :                                                   PartTable,
     502           0 :                                                   AirCont));
     503           0 :     PPDipModel m(cm);
     504           0 :     AbsNormMeasure *ll=new AbsNormMeasure(m);
     505           0 :     Minim::IndependentFlatPriors pll(ll);
     506             :     
     507           0 :     cm->setSpill(0.98, 275);
     508           0 :     m.setZA(0.5 * M_PI -el);
     509           0 :     ll->obs=TObs;
     510           0 :     ll->thermNoise=std::vector<double>(TObs.size(),
     511           0 :                                        1.0);
     512             :     
     513           0 :     if (opts.OSFPriors)
     514             :     {
     515           0 :       pll.AddPrior("n", 0, 15);
     516           0 :       pll.AddPrior("T", 250, 295);
     517           0 :       pll.AddPrior("P", 550, 750);
     518           0 :       pll.AddPrior("tau183", 0, 0.2);
     519             :     }
     520             :     else
     521             :     {
     522           0 :       pll.AddPrior("n", 0, 10);
     523           0 :       pll.AddPrior("T", 250, 295);
     524           0 :       pll.AddPrior("P", 300, 550);
     525           0 :       pll.AddPrior("tau183", 0, 0.2);
     526             :     }
     527             : 
     528             : 
     529           0 :     std::list<Minim::MCPoint> ss;
     530           0 :     startSetDirect(pll,
     531             :                    200,
     532             :                    ss);
     533             : 
     534             :     // Create the nested sampler
     535           0 :     std::unique_ptr<Minim::NestedS> ns;
     536           0 :     ns.reset(new Minim::NestedS(pll));
     537           0 :     (*ns)["coupling"]->dofit=false;
     538             : 
     539             : #ifdef ELLIPSESAMPLE    
     540             :     Minim::EllipsoidCPSampler *cps=new Minim::EllipsoidCPSampler(pll,
     541             :                                                                  *ns);    
     542             :     cps->reshape_maxp=50;
     543             : 
     544             :     ns->reset(ss,
     545             :               cps);
     546             :     cps->reshape();
     547             : #else
     548           0 :     ns->reset(ss);
     549             : #endif
     550             : 
     551             : #if 0
     552             :     Minim::SOutMCMon *pp=new Minim::SOutMCMon();
     553             :     ns->mon=pp;
     554             :     cps->mon=pp;
     555             : #endif 
     556             :     //ns->InitalS(new Minim::InitialRandom(200));
     557             : 
     558           0 :     double evidence=ns->sample(3000);
     559             :     /// The posterior 
     560           0 :     std::list<Minim::WPPoint> post;
     561           0 :     post=ns->g_post();
     562             : 
     563           0 :     if (post.size() < 10000 )
     564             :     {
     565           0 :       std::cout<<"Terminated after "<<post.size()
     566           0 :                <<std::endl;
     567             :     }
     568             : 
     569           0 :     res.ev=evidence;
     570             : 
     571           0 :     std::vector<double> m1(4), m2(4);
     572           0 :     moment1(post,
     573             :             evidence,
     574             :             m1);
     575             : 
     576           0 :     moment2(post,
     577             :             m1,
     578             :             evidence,
     579             :             m2);
     580             : 
     581           0 :     res.c=m1[0];
     582           0 :     res.c_err=std::pow(m2[0], 0.5);
     583             : 
     584           0 :     res.tau183=m1[3];
     585           0 :     res.tau183_err=std::pow(m2[3], 0.5);
     586             : 
     587           0 :     dTdLMom1(post,
     588           0 :              *ns,
     589             :              m,
     590             :              evidence,
     591             :              1e-10,
     592           0 :              res.dTdL);
     593             : 
     594           0 :     dTdLMom2(post,
     595           0 :              *ns,
     596             :              m,
     597           0 :              res.dTdL,
     598             :              evidence,
     599             :              1e-10,
     600           0 :              res.dTdL_err);
     601             : 
     602           0 :   }
     603             : 
     604             : }
     605             : 
     606             : 

Generated by: LCOV version 1.16