LCOV - code coverage report
Current view: top level - synthesis/TransformMachines - PBMath.h (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1 2 50.0 %
Date: 2024-10-04 18:58:15 Functions: 1 2 50.0 %

          Line data    Source code
       1             : //# PBMath.h: Envelope class for PBMath1D and PBMath2D types
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2002,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be adressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //#
      27             : //# $Id$
      28             : 
      29             : #ifndef SYNTHESIS_PBMATH_H
      30             : #define SYNTHESIS_PBMATH_H
      31             : 
      32             : #include <casacore/casa/aips.h>
      33             : #include <synthesis/TransformMachines/PBMathInterface.h>
      34             : #include <synthesis/TransformMachines/PBMath1DGauss.h>
      35             : #include <synthesis/TransformMachines/PBMath1DNumeric.h>
      36             : #include <synthesis/TransformMachines/PBMath1DAiry.h>
      37             : #include <synthesis/TransformMachines/PBMath1DPoly.h>
      38             : #include <synthesis/TransformMachines/PBMath1DIPoly.h>
      39             : #include <synthesis/TransformMachines/PBMath1DCosPoly.h>
      40             : #include <synthesis/TransformMachines/PBMath2DImage.h>
      41             : #include <synthesis/TransformMachines/BeamSquint.h>
      42             : #include <casacore/images/Images/ImageInterface.h>
      43             : #include <casacore/measures/Measures.h>
      44             : #include <casacore/casa/Utilities/CountedPtr.h>
      45             : 
      46             : namespace casacore{
      47             : 
      48             : class Table;
      49             : class ImageRegion;
      50             : class RecordInterface;
      51             : class CoordinateSystem;
      52             : }
      53             : 
      54             : namespace casa { //# NAMESPACE CASA - BEGIN
      55             : 
      56             : //#forward
      57             : // <summary> Primary beam envelope class, derived from PBMathInterface </summary>
      58             : 
      59             : // <use visibility=export>
      60             : 
      61             : // <reviewed reviewer="" date="" tests="" demos="">
      62             : 
      63             : // <prerequisite>
      64             : // <li> <linkto class="SkyJones">SkyJones</linkto> class
      65             : // <li> <linkto class="BeamSkyJones">BeamSkyJones</linkto> class
      66             : // <li> <linkto class="PBMathInterface">PBMathInterface</linkto> class
      67             : // </prerequisite>
      68             : //
      69             : // <etymology>
      70             : // PBMath types do the mathematical operations of the Primary Beamss or
      71             : // Voltage patterns.  This envelope class's name was designed for simplicity.
      72             : // </etymology>
      73             : //
      74             : // <synopsis> 
      75             : // PBMath is an envelope class for the various types of 1D and 2D primary
      76             : // beam/voltage pattern objects.  They all have a common interface defined
      77             : // by PBMathInterface.  The PBMath object has a counted pointer to the
      78             : // actual PB type; hence, the PBMath object is lightweight and can
      79             : // be passed around by value in other classes.
      80             : //
      81             : // Construct a PBMath via PBMath's enumerated CommonPB type.
      82             : // <example>
      83             : // <srcblock>
      84             : // PBMath wsrtPB(PBMath::WSRT);
      85             : // PBMath vla_LPB(PBMath::VLA_L);  // has L band squint built in
      86             : // </srcblock>
      87             : // </example>
      88             : //
      89             : // A PBMath can also be constructed by the complete argument list for
      90             : // the type of PB it holds.  Since different PB types can have the same
      91             : // argument list (PBMath1DPoly and PBMath1DIPoly, for example), the exact
      92             : // type also needs to be specified via the PBMathInterface::PBClass.
      93             : //
      94             : // The main thing you want to do with a primary beam or voltage pattern is
      95             : // to apply it to an image.  The PBMath object forwards its low level
      96             : // "apply" calls to the letter class's "apply" calls.
      97             : // <example>
      98             : // <srcblock>
      99             : //
     100             : //    casacore::PagedImage<casacore::Float> in;
     101             : //    casacore::PagedImage<casacore::Complex> out;
     102             : //    casacore::MDirection pointingDir(casacore::Quantity(135.0, "deg"), casacore::Quantity(60.0, "deg"), 
     103             : //                           casacore::MDirection::Ref(casacore::MDirection::J2000));
     104             : //    casacore::Quantity parallacticAngle(26.5, "deg");
     105             : //    PBMath wsrtPB(PBMath::WSRT_LOW);
     106             : //    wsrtPB.applyPB(in, out, pointingDir);   // multiply by primary beam
     107             : //    wsrtPB.applyPB(in, out, pointingDir, parallacticAngle, BeamSquint::GOFIGURE, 
     108             : //                   true, 0.02); // divide by primary beam
     109             : //    wsrtPB.applyVP(in, out, pointingDir);   // multiply by voltage pattern
     110             : // </srcblock>
     111             : // </example>
     112             : // 
     113             : // </synopsis> 
     114             : //
     115             : //
     116             : // <motivation>
     117             : // This Envelope class allows the user to create a PBMath object which
     118             : // can display all the polymorphic traits of PBMath1D classes or
     119             : // PBMath2D classes.
     120             : // </motivation>
     121             : //
     122             : // <todo asof="98/010/21">
     123             : // </todo>
     124             : 
     125             :  
     126             : class PBMath {
     127             : public:
     128             : 
     129             :   // This enumeration provides a simple way to instantiate the
     130             :   // common primary beam models.  They are each represented by one of
     131             :   // the more fundamental PBMath1D types
     132             :   //
     133             :   // New CommonPB Types must go to the end
     134             :   enum CommonPB {UNKNOWN, DEFAULT,
     135             :                  ATCA_L1, ATCA_L2, ATCA_L3, ATCA_S, ATCA_C, ATCA_X, 
     136             :                  GBT, 
     137             :                  GMRT,
     138             :                  HATCREEK,
     139             :                  NRAO12M,
     140             :                  NRAO140FT,
     141             :                  OVRO, 
     142             :                  VLA, VLA_INVERSE, VLA_NVSS, VLA_2NULL, 
     143             :                  VLA_4, VLA_P, VLA_L, VLA_C, VLA_X, VLA_U, VLA_K, VLA_Q, 
     144             :                  WSRT, WSRT_LOW, ALMA, ALMASD, ACA, IRAMPDB, IRAM30M, SMA, 
     145             :                  ATA, ATCA_C_RI, ATCA, ATCA_16, ATCA_K, ATCA_Q, ATCA_W,  EVLA, NGVLA, NONE
     146             :   };
     147             : 
     148             :   enum {
     149             :     NumberOfCommonPB=44  };
     150             : 
     151             :   // Default constructor, required for casacore::Block<PBMath>
     152             :   PBMath();
     153             :   
     154             :   // Make a PB of common type
     155             :   explicit PBMath(PBMath::CommonPB myPBType, casacore::Bool useSymmetricBeam=false);
     156             : 
     157             :   //Make a PB from a telescopename and frequency
     158             : 
     159             :   PBMath(casacore::String& telescopeName, casacore::Bool useSymmetricBeam=false, 
     160             :          casacore::Quantity freq=casacore::Quantity(0.0, "Hz"));
     161             : 
     162             :   //Make a PB by dish diameter
     163             :   PBMath(casacore::Double dishDiam, casacore::Bool useSymmetricBeam, casacore::Quantity freq);
     164             : 
     165             :   // Make a PB from a RecordInterface
     166             :   explicit PBMath(const casacore::RecordInterface& myrec);
     167             : 
     168             :   // Make a Gaussian Primary beam
     169             :   PBMath(PBMathInterface::PBClass theclass, casacore::Quantity halfWidth, 
     170             :          casacore::Quantity maxRad, casacore::Quantity refFreq, 
     171             :          casacore::Bool isThisVP=false,
     172             :          BeamSquint squint=BeamSquint(casacore::MDirection(casacore::Quantity(0.0, "deg"),
     173             :                                                  casacore::Quantity(0.0, "deg"),
     174             :                                                  casacore::MDirection::Ref(casacore::MDirection::AZEL)), 
     175             :                                       casacore::Quantity(1.0, "GHz")),
     176             :          casacore::Bool useSymmetricBeam=false);
     177             :   
     178             : 
     179             :   // Make a casacore::Polynomial, Inverse casacore::Polynomial, or Numeric Primary beam
     180             :   // (These three have identical calling signatures, they can only be distinguished
     181             :   // by the PBClass enumeration)
     182             :   PBMath(PBMathInterface::PBClass theclass, const casacore::Vector<casacore::Double>& coeff, 
     183             :          casacore::Quantity maxRad, casacore::Quantity refFreq, 
     184             :          casacore::Bool isThisVP=false,
     185             :          BeamSquint squint=BeamSquint(casacore::MDirection(casacore::Quantity(0.0, "deg"),
     186             :                                                  casacore::Quantity(0.0, "deg"),
     187             :                                                  casacore::MDirection::Ref(casacore::MDirection::AZEL)),
     188             :                                       casacore::Quantity(1.0, "GHz")),
     189             :          casacore::Bool useSymmetricBeam=false);
     190             : 
     191             :   
     192             : 
     193             :   // Make a Numeric Primary beam (FLOAT!)
     194             :   PBMath(PBMathInterface::PBClass theclass, const casacore::Vector<casacore::Float>& coeff, 
     195             :          casacore::Quantity maxRad, casacore::Quantity refFreq, 
     196             :          casacore::Bool isThisVP=false,
     197             :          BeamSquint squint=BeamSquint(casacore::MDirection(casacore::Quantity(0.0, "deg"),
     198             :                                                  casacore::Quantity(0.0, "deg"),
     199             :                                                  casacore::MDirection::Ref(casacore::MDirection::AZEL)),
     200             :                                       casacore::Quantity(1.0, "GHz")),
     201             :          casacore::Bool useSymmetricBeam=false);
     202             : 
     203             :   
     204             :   // Make a CosPolynomial beam type
     205             :   PBMath(PBMathInterface::PBClass theclass, const casacore::Vector<casacore::Double>& coeff, 
     206             :          const casacore::Vector<casacore::Double>& scale, 
     207             :          casacore::Quantity maxRad, casacore::Quantity refFreq,
     208             :          casacore::Bool isThisVP=false,
     209             :          BeamSquint squint=BeamSquint(casacore::MDirection(casacore::Quantity(0.0, "deg"),
     210             :                                                  casacore::Quantity(0.0, "deg"),
     211             :                                                  casacore::MDirection::Ref(casacore::MDirection::AZEL)),
     212             :                                       casacore::Quantity(1.0, "GHz")),
     213             :          casacore::Bool useSymmetricBeam=false);
     214             :   
     215             :   // Make an Airy beam type
     216             :   PBMath(PBMathInterface::PBClass theclass, casacore::Quantity dishDiam, casacore::Quantity blockageDiam,
     217             :          casacore::Quantity maxRad, casacore::Quantity refFreq,
     218             :          BeamSquint squint=BeamSquint(casacore::MDirection(casacore::Quantity(0.0, "deg"),
     219             :                                                  casacore::Quantity(0.0, "deg"),
     220             :                                                  casacore::MDirection::Ref(casacore::MDirection::AZEL)),
     221             :                                       casacore::Quantity(1.0, "GHz")),
     222             :          casacore::Bool useSymmetricBeam=false);
     223             :   
     224             :   // Make an Image-based beam
     225             :   PBMath(PBMathInterface::PBClass theclass,
     226             :          casacore::ImageInterface<casacore::Float>& reJones);
     227             :   PBMath(PBMathInterface::PBClass theclass,
     228             :          casacore::ImageInterface<casacore::Float>& reJones,
     229             :          casacore::ImageInterface<casacore::Float>& imJones);
     230             :   
     231             :   // Instantiate from a Table
     232             :   //  PBMath(const casacore::Table& theTable, casacore::Int row);
     233             :   
     234             :   
     235             :   // copy ctor: copies the reference counted pointer
     236             :   PBMath(const PBMath &other);
     237             : 
     238             :   // destructor
     239             :   virtual ~PBMath();
     240             :   
     241             :   //operator=   returns a reference to the PBMath; reference counted pointer
     242             :   PBMath& operator=(const PBMath& other);
     243             :   
     244             :   // comparison operator: just checks that the objects are same
     245             :   // (could have two different objects with identical data, these are treated
     246             :   // as !=)
     247             :   casacore::Bool operator==(const PBMath& other) const;
     248             :   
     249             :   // comparison operator: just checks that the objects are different
     250             :   // (could have two different objects with identical data, these are treated
     251             :   // as !=)
     252             :   casacore::Bool operator!=(const PBMath& other) const;
     253             :   
     254             :   // copy()      returns a copy of the PBMath
     255             :   // PBMath copy() const;
     256             :   
     257             : 
     258             :   //  Apply Jones matrix to an image (and adjoint)
     259             :   // <group>
     260             : 
     261             :   casacore::ImageInterface<casacore::Complex>& applyVP(const casacore::ImageInterface<casacore::Complex>& in,
     262             :                                    casacore::ImageInterface<casacore::Complex>& out,
     263             :                                    const casacore::MDirection& sp,
     264             :                                    const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     265             :                                    const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     266             :                                    casacore::Bool inverse = false,
     267             :                                    casacore::Bool conjugate = false,
     268             :                                    casacore::Float cutoff = 0.01,
     269             :                                    casacore::Bool forward=true);
     270             : 
     271             :   casacore::ImageInterface<casacore::Complex>& applyPB(const casacore::ImageInterface<casacore::Complex>& in,
     272             :                                    casacore::ImageInterface<casacore::Complex>& out,
     273             :                                    const casacore::MDirection& sp,
     274             :                                    const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     275             :                                    const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     276             :                                    casacore::Bool inverse = false,
     277             :                                    casacore::Float cutoff = 0.01,
     278             :                                    casacore::Bool forward = true);
     279             : 
     280             :   casacore::ImageInterface<casacore::Float>& applyPB(const casacore::ImageInterface<casacore::Float>& in,
     281             :                                    casacore::ImageInterface<casacore::Float>& out,
     282             :                                    const casacore::MDirection& sp,
     283             :                                    const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     284             :                                    const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     285             :                                    casacore::Float cutoff = 0.01);
     286             : 
     287             : 
     288             :   casacore::ImageInterface<casacore::Float>& applyPB2(const casacore::ImageInterface<casacore::Float>& in,
     289             :                                   casacore::ImageInterface<casacore::Float>& out,
     290             :                                   const casacore::MDirection& sp,
     291             :                                   const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     292             :                                   const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     293             :                                   casacore::Float cutoff=0.01);
     294             :   // </group>
     295             :   
     296             :   // Apply Jones matrix to a sky component (and adjoint)
     297             :   // <group>
     298             :   SkyComponent& applyVP(SkyComponent& in,
     299             :                         SkyComponent& out,
     300             :                         const casacore::MDirection& sp,
     301             :                         const casacore::Quantity frequency,
     302             :                         const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     303             :                         const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     304             :                         casacore::Bool inverse = false,
     305             :                         casacore::Bool conjugate = false,
     306             :                         casacore::Float cutoff = 0.01,
     307             :                         casacore::Bool forward = true);
     308             : 
     309             :   SkyComponent& applyPB(SkyComponent& in,
     310             :                         SkyComponent& out,
     311             :                         const casacore::MDirection& sp,
     312             :                         const casacore::Quantity frequency,
     313             :                         const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     314             :                         const BeamSquint::SquintType doSquint = BeamSquint::NONE,
     315             :                         casacore::Bool inverse = false,
     316             :                         casacore::Float cutoff = 0.01,
     317             :                         casacore::Bool forward = true);
     318             : 
     319             :   SkyComponent& applyPB2(SkyComponent& in,
     320             :                          SkyComponent& out,
     321             :                          const casacore::MDirection& sp,
     322             :                          const casacore::Quantity frequency,
     323             :                          const casacore::Quantity parAngle = casacore::Quantity(0.0,"deg"),
     324             :                          const BeamSquint::SquintType doSquint = BeamSquint::NONE);
     325             :   // </group>
     326             : 
     327             : 
     328             : 
     329             : 
     330             : 
     331             :   
     332             :   // Fit an azimuthally symmetric beam to the squinted or otherwise 2-D beam
     333             :   // for casacore::Stokes I?
     334             :   void setUseSymmetric(casacore::Bool useSym=true) { pb_pointer_p->setUseSymmetric(useSym); }
     335             : 
     336             :   // Get value of useSymmetric
     337             :   casacore::Bool getUseSymmetric() { return pb_pointer_p->getUseSymmetric(); }
     338             :   
     339             :   // Get the type of PB this is
     340           0 :   PBMathInterface::PBClass whichPBClass() { return pb_pointer_p->whichPBClass(); }  
     341             : 
     342             :   // Summarize the Voltage Pattern;
     343             :   void summary(casacore::Int nValues=0);
     344             : 
     345             :   // Is the state of the PBMath OK?
     346             :   casacore::Bool ok() const;
     347             : 
     348             :   // Get the BLC, TRC of the primary beam on an Image for a given pointing
     349             :   // Note: BLC and TRC are not necesarily constrained to lie within the
     350             :   // image region (for example, if the pointing center is near the edge of the
     351             :   // image).  fPad: extra fractional padding above PB support
     352             :   // (note: we do not properly treat squint yet, this will cover it for now)
     353             :   // iChan: frequency channel to take: lowest frequency channel is safe for all
     354             :   casacore::ImageRegion* extent (const casacore::ImageInterface<casacore::Complex>& im, 
     355             :                        const casacore::MDirection& pointing,
     356             :                        const casacore::Int row,
     357             :                        const casacore::Float fPad,  
     358             :                        const casacore::Int iChan,  
     359             :                        const SkyJones::SizeType);
     360             :   casacore::ImageRegion* extent (const casacore::ImageInterface<casacore::Float>& im, 
     361             :                        const casacore::MDirection& pointing,
     362             :                        const casacore::Int row,
     363             :                        const casacore::Float fPad,  
     364             :                        const casacore::Int iChan,  
     365             :                        const SkyJones::SizeType);
     366             : 
     367             :   virtual casacore::Int support (const casacore::CoordinateSystem& cs);
     368             : 
     369             :   // given the Telescope name and the frequency, guess the most approrpiate
     370             :   // CommonPB primary beam type and the band
     371             :   static void whichCommonPBtoUse (casacore::String &telescope, casacore::Quantity &freq, 
     372             :                                   casacore::String &band, PBMath::CommonPB &whichPB, 
     373             :                                   casacore::String &pbName);
     374             : 
     375             :   // converts the enumrated type into a string
     376             :   static void nameCommonPB(const PBMath::CommonPB iPB, casacore::String & str);
     377             :   
     378             :   // converts the PB casacore::String into an enumrated type
     379             :   static void enumerateCommonPB(const casacore::String & str, PBMath::CommonPB &ipb);
     380             : 
     381             : 
     382             :   // return a PBMathInteface for a commonPB ; caller needs to delete pointer
     383             :   static PBMathInterface* pbMathInterfaceForCommonPB(const PBMath::CommonPB ipb, bool useSymmetricBeam);
     384             : 
     385             :   // return a PBMathInteface from a Vpmanager record ; caller needs to delete pointer
     386             :   static PBMathInterface* pbMathInterfaceFromRecord(const casacore::RecordInterface& rec);
     387             :   // gives the name of the PB Class that has been used
     388          14 :   void namePBClass(casacore::String & name) {  pb_pointer_p->namePBClass(name); }  
     389             : 
     390             :   
     391             :   // Gradient stuff: this needs more thought, as it is not
     392             :   // really connected with the stuff in VPSkyJones and all.
     393             :   // This will return the partial derivatives of chi^2 w.r.t
     394             :   // the beam model parameters, represented here as a vector.
     395             :   // Not implemented yet.  
     396             :   // void parameterGradient(casacore::Vector<casacore::Float> grad);
     397             :   
     398             :   // Flush the construction parameters to disk
     399             :   // This is a public method because this class doesn't know what Table
     400             :   // it is to be stored in
     401             : 
     402             :   //virtual casacore::Bool flushToTable(casacore::Table& beamSubTable, casacore::Int iRow);
     403             : 
     404             :   
     405             : protected:
     406             : 
     407             :   // polymorphic lower level helping apply methods
     408             :   // <group>
     409             :   casacore::ImageInterface<casacore::Complex>& apply(const casacore::ImageInterface<casacore::Complex>& in,
     410             :                                  casacore::ImageInterface<casacore::Complex>& out,
     411             :                                  const casacore::MDirection& sp,
     412             :                                  const casacore::Quantity parAngle,           
     413             :                                  const BeamSquint::SquintType doSquint,
     414             :                                  casacore::Bool inverse,
     415             :                                  casacore::Bool conjugate,
     416             :                                  casacore::Int ipower,  // ie, 1=VP, 2=PB
     417             :                                  casacore::Float cutoff=0.01,
     418             :                                  casacore::Bool forward=true); 
     419             : 
     420             :   SkyComponent& apply(SkyComponent& in,
     421             :                       SkyComponent& out,
     422             :                       const casacore::MDirection& sp,
     423             :                       const casacore::Quantity frequency,             
     424             :                       const casacore::Quantity parAngle,              
     425             :                       const BeamSquint::SquintType doSquint,
     426             :                       casacore::Bool inverse,
     427             :                       casacore::Bool conjugate,
     428             :                       casacore::Int ipower,  // ie, 1=VP, 2=PB, 4=PB^2
     429             :                       casacore::Float cutoff=0.01,
     430             :                       casacore::Bool forward=true); 
     431             :   // </group>  
     432             : 
     433             : 
     434             : private:    
     435             :   
     436             :   casacore::CountedPtr<PBMathInterface> pb_pointer_p;
     437             :   
     438             : 
     439             :   // These should probably move to casacore::RecordInterface when we are happy with their performance
     440             :   // <group>
     441             : 
     442             :   static casacore::Bool getQuantity(const casacore::RecordInterface& rec, const casacore::String& item, 
     443             :                    casacore::Quantity& returnedQuantity) ;
     444             :   static casacore::Bool getMDirection(const casacore::RecordInterface& rec, const casacore::String& item, 
     445             :                      casacore::MDirection& returnedMDirection);
     446             :   //casacore::Function to initialize the state of the tool
     447             :   void initByTelescope(PBMath::CommonPB myPBType, casacore::Bool useSymmetricBeam=false, 
     448             :                        casacore::Double frequency=0.0);
     449             : 
     450             :   //casacore::Function to initialize the by dish diameter 
     451             :   void initByDiameter(casacore::Double diam, casacore::Bool useSymmetricBeam, casacore::Double freq); 
     452             : 
     453             :   // </group>
     454             : 
     455             : };
     456             : 
     457             :   
     458             : 
     459             : } //# NAMESPACE CASA - END
     460             : 
     461             : #endif

Generated by: LCOV version 1.16