LCOV - code coverage report
Current view: top level - include/ao/sim - ccdDetector.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 22.2 % 54 12
Test Date: 2026-08-30 22:23:37 Functions: 15.0 % 20 3

            Line data    Source code
       1              : /** \file ccdDetector.hpp
       2              :  * \author Jared R. Males (jaredmales@gmail.com)
       3              :  * \brief Provides a class to simulate a CCD.
       4              :  * \ingroup mxAO_files
       5              :  *
       6              :  */
       7              : 
       8              : #ifndef ccdDetector_hpp
       9              : #define ccdDetector_hpp
      10              : 
      11              : // #include <Eigen/Dense>
      12              : 
      13              : #include "../../improc/imageTransforms.hpp"
      14              : #include "../../math/randomT.hpp"
      15              : 
      16              : #include "wavefront.hpp"
      17              : 
      18              : #include <fcntl.h>
      19              : #include <iostream>
      20              : 
      21              : #ifndef BREAD_CRUMB
      22              : #define MXLIB_CCD_DETECTOR_LOCAL_BREAD_CRUMB
      23              : #ifdef DEBUG
      24              : #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
      25              : #else
      26              : #define BREAD_CRUMB
      27              : #endif
      28              : #endif
      29              : 
      30              : namespace mx
      31              : {
      32              : namespace AO
      33              : {
      34              : namespace sim
      35              : {
      36              : 
      37              : /// A simulated CCD detector
      38              : /** A simulated CCD detector, including an optional EMCCD noise model.
      39              :  *
      40              :  * \ingroup mxAOSim
      41              :  */
      42              : template <typename _realT>
      43              : class ccdDetector
      44              : {
      45              : 
      46              :   public:
      47              :     typedef _realT realT;
      48              : 
      49              :     typedef wavefront<realT> wavefrontT;
      50              : 
      51              :     //typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
      52              : 
      53              :     typedef mx::math::randomT<realT, std::mt19937_64, std::normal_distribution<realT>> norm_distT;
      54              : 
      55              :     typedef mx::math::randomT<int, std::mt19937_64, std::poisson_distribution<int>> poisson_distT;
      56              : 
      57              :     typedef mx::math::randomT<realT, std::mt19937_64, std::gamma_distribution<realT>> gamma_distT;
      58              : 
      59              :     ccdDetector();
      60              : 
      61              :   protected:
      62              :     norm_distT m_normVar;       ///< Gets normal-distributed variates
      63              :     poisson_distT m_poissonVar; ///< Gets Poisson distributed variates
      64              :     gamma_distT m_gammaVar;     ///< Gets gamma distributed variates
      65              : 
      66              :     realT m_qe{ 1 }; ///< The quantum efficiency.
      67              : 
      68              :     realT m_darkCurrent{ 0 }; ///< The dark current, per pixel per second
      69              :     realT m_ron{ 0 };         ///< The readout noise, electrons per pixel per read.
      70              : 
      71              :     realT m_cic{ 0 };  ///< EMCCD clock induced charge, electrons per pixel per read.
      72              :     realT m_gain{ 1 }; ///< Electron multiplication gain.  If >1, then EMCCD is modeled.
      73              : 
      74              :     realT m_expTime{ 1 }; ///< The exposure time, in seconds.
      75              : 
      76              :     int m_rows{ 0 }; ///< The detector size, in rows.
      77              :     int m_cols{ 0 }; ///< The detector size, in columns.
      78              : 
      79              :     bool m_noNoise{ false }; ///< If true no noise is added to the exposed image.
      80              : 
      81              :     // This is probably vestigial, commented out on 2018-07-23
      82              :     // Delete after testing with an aoSim compile.
      83              :     // long get_seed();
      84              : 
      85              :   public:
      86              :     /// Get the current value of qe.
      87              :     /**
      88              :      * \returns the current value of m_qe
      89              :      */
      90              :     realT qe();
      91              : 
      92              :     void qe( const realT &q );
      93              : 
      94              :     realT darkCurrent();
      95              : 
      96              :     void darkCurrent( const realT &dc );
      97              : 
      98              :     realT ron();
      99              : 
     100              :     void ron( const realT &r );
     101              : 
     102              :     realT cic();
     103              : 
     104              :     void cic( const realT &c );
     105              : 
     106              :     realT gain();
     107              : 
     108              :     void gain( const realT &g );
     109              : 
     110              :     realT expTime();
     111              : 
     112              :     void expTime( const realT &dt );
     113              : 
     114              :     int rows();
     115              : 
     116              :     void rows( const int &r );
     117              : 
     118              :     int cols();
     119              : 
     120              :     void cols( const int &c );
     121              : 
     122              :     void setSize( const int &r, const int &c );
     123              : 
     124              :     bool noNoise();
     125              : 
     126              :     void noNoise( bool nn );
     127              : 
     128              :     /// Rebin and add noise to the input image, placing the result in the output image.
     129              :     /** The output image must be the same size or smaller than the input image.
     130              :      * The output image is resized only if necessary.
     131              :      * The input image is multiplied by expTime, so its flux should be in photons/sec.
     132              :      * Noise is modeled as follows:
     133              :      * -# The number of input photons for pixel (i,j) is \f$ n_{ie} = (in(i,j) + darkCurrent)*expTime + cic \f$
     134              :      * -# The Poisson distribution with mean and variance \f$ n_{ie} \f$ is sampled.
     135              :      * -# If gain > 1, the gamma distribution is sampled
     136              :      * -# Read noise is applied
     137              :      * -# Result is rounded to nearest whole integer.
     138              :      */
     139              :     template<typename imageTout, typename imageTin>
     140              :     void exposeImage( imageTout &out, ///< [out] The output image, after all above steps applied.
     141              :                       imageTin &in   ///< [in] the input image, in photons/sec flux units.
     142              :     );
     143              : };
     144              : 
     145              : template <typename realT>
     146            1 : ccdDetector<realT>::ccdDetector()
     147              : {
     148            1 :     m_normVar.seed();
     149            1 :     m_poissonVar.seed();
     150            1 :     m_gammaVar.seed();
     151            1 : }
     152              : 
     153              : /*template<typename realT>
     154              : long ccdDetector<realT>::get_seed()
     155              : {
     156              :    long int seedval;
     157              : 
     158              :    int fd;
     159              : 
     160              :    fd = open("/dev/urandom", O_RDONLY);
     161              : 
     162              :    int rv =read(fd, &seedval, sizeof(long int));
     163              : 
     164              :     close(fd);
     165              : 
     166              : 
     167              :    if(rv < 0)
     168              :    {
     169              :       std::cerr << "read from /dev/urandom returned error\n";
     170              : 
     171              :       return 0;
     172              :    }
     173              : 
     174              :    return seedval;
     175              : }
     176              : */
     177              : 
     178              : template <typename realT>
     179            0 : realT ccdDetector<realT>::qe()
     180              : {
     181            0 :     return m_qe;
     182              : }
     183              : 
     184              : template <typename realT>
     185            0 : void ccdDetector<realT>::qe( const realT &q )
     186              : {
     187            0 :     m_qe = q;
     188            0 : }
     189              : 
     190              : template <typename realT>
     191            0 : realT ccdDetector<realT>::darkCurrent()
     192              : {
     193            0 :     return m_darkCurrent;
     194              : }
     195              : 
     196              : template <typename realT>
     197            0 : void ccdDetector<realT>::darkCurrent( const realT &dc )
     198              : {
     199            0 :     m_darkCurrent = dc;
     200            0 : }
     201              : 
     202              : template <typename realT>
     203            0 : realT ccdDetector<realT>::ron()
     204              : {
     205            0 :     return m_ron;
     206              : }
     207              : 
     208              : template <typename realT>
     209            0 : void ccdDetector<realT>::ron( const realT &r )
     210              : {
     211            0 :     m_ron = r;
     212            0 : }
     213              : 
     214              : template <typename realT>
     215            0 : realT ccdDetector<realT>::cic()
     216              : {
     217            0 :     return m_cic;
     218              : }
     219              : 
     220              : template <typename realT>
     221            0 : void ccdDetector<realT>::cic( const realT &c )
     222              : {
     223            0 :     m_cic = c;
     224            0 : }
     225              : 
     226              : template <typename realT>
     227            0 : realT ccdDetector<realT>::gain()
     228              : {
     229            0 :     return m_gain;
     230              : }
     231              : 
     232              : template <typename realT>
     233            0 : void ccdDetector<realT>::gain( const realT &g )
     234              : {
     235            0 :     m_gain = g;
     236            0 : }
     237              : 
     238              : template <typename realT>
     239            0 : realT ccdDetector<realT>::expTime()
     240              : {
     241            0 :     return m_expTime;
     242              : }
     243              : 
     244              : template <typename realT>
     245            1 : void ccdDetector<realT>::expTime( const realT &dt )
     246              : {
     247            1 :     m_expTime = dt;
     248            1 : }
     249              : 
     250              : template <typename realT>
     251            0 : int ccdDetector<realT>::rows()
     252              : {
     253            0 :     return m_rows;
     254              : }
     255              : 
     256              : template <typename realT>
     257            0 : void ccdDetector<realT>::rows( const int &r )
     258              : {
     259            0 :     m_rows = r;
     260            0 : }
     261              : 
     262              : template <typename realT>
     263            0 : int ccdDetector<realT>::cols()
     264              : {
     265            0 :     return m_cols;
     266              : }
     267              : 
     268              : template <typename realT>
     269            0 : void ccdDetector<realT>::cols( const int &c )
     270              : {
     271            0 :     m_cols = c;
     272            0 : }
     273              : 
     274              : template <typename realT>
     275            3 : void ccdDetector<realT>::setSize( const int &r, const int &c )
     276              : {
     277            3 :     m_rows = r;
     278            3 :     m_cols = c;
     279            3 : }
     280              : 
     281              : template <typename realT>
     282            0 : bool ccdDetector<realT>::noNoise()
     283              : {
     284            0 :     return m_noNoise;
     285              : }
     286              : 
     287              : template <typename realT>
     288            0 : void ccdDetector<realT>::noNoise( bool nn )
     289              : {
     290            0 :     m_noNoise = nn;
     291            0 : }
     292              : 
     293              : template <typename realT>
     294              : template<typename imageTout, typename imageTin>
     295              : void ccdDetector<realT>::exposeImage( imageTout &out, imageTin &in )
     296              : {
     297              : 
     298              :     using poisson_param_t = typename std::poisson_distribution<int>::param_type;
     299              :     using gamma_param_t = typename std::gamma_distribution<realT>::param_type;
     300              : 
     301              :     BREAD_CRUMB
     302              : 
     303              :     out.resize( m_rows, m_cols );
     304              : 
     305              :     BREAD_CRUMB
     306              : 
     307              :     improc::imageDownSample( out, in );
     308              : 
     309              :     BREAD_CRUMB
     310              : 
     311              :     if( m_noNoise )
     312              :         return;
     313              : 
     314              :     for( int j = 0; j < m_cols; ++j )
     315              :     {
     316              :         for( int i = 0; i < m_rows; ++i )
     317              :         {
     318              :             realT charge = ( out( i, j ) * m_qe + m_darkCurrent ) * m_expTime + m_cic;
     319              : 
     320              :             if( charge > 1000 )
     321              :             {
     322              :                 out( i, j ) = charge + m_normVar * sqrt( charge );
     323              :             }
     324              :             else
     325              :             {
     326              :                 m_poissonVar.distribution.param( poisson_param_t{ charge } );
     327              :                 out( i, j ) = m_poissonVar;
     328              :             }
     329              : 
     330              :             if( m_gain > 1 )
     331              :             {
     332              :                 m_gammaVar.distribution.param( gamma_param_t{ out( i, j ), m_gain } );
     333              : 
     334              :                 out( i, j ) = m_gammaVar;
     335              :             }
     336              : 
     337              :             if( m_ron > 0 )
     338              :             {
     339              :                 out( i, j ) += m_normVar * m_ron;
     340              :             }
     341              : 
     342              :             if( m_gain > 1 )
     343              :             {
     344              :                 out( i, j ) /= m_gain;
     345              :             }
     346              : 
     347              :             // out(i,j) = round(out(i,j));
     348              :         }
     349              :     }
     350              : }
     351              : 
     352              : } // namespace sim
     353              : } // namespace AO
     354              : } // namespace mx
     355              : 
     356              : #ifdef MXLIB_CCD_DETECTOR_LOCAL_BREAD_CRUMB
     357              : #undef BREAD_CRUMB
     358              : #undef MXLIB_CCD_DETECTOR_LOCAL_BREAD_CRUMB
     359              : #endif
     360              : 
     361              : #endif // ccdDetector_hpp
        

Generated by: LCOV version 2.0-1