This is an example of how to fit the dark current.
The distribution of pixels values in a CCD comes from the convolution of the pixel charge with the pixel readout noise. The pixel charge is the sum of a Poisson-distributed leakage current accumulated during the exposure and a ionized signal charge (from a ionizing particle that interacts with the silicon target). The readout noise is paramtrized from the pixel value distribution of blanks and overscans, and found to be well-described by the convolution of a Poisson with average $\lambda$ and a Gaussian of standard deviation $\sigma$.
If the input image contains tracks, the best is to estimate the dark current only using the first two single electron peaks where contribution from any ionizing particle is almost negligigle. In this case the pixel value distribution (in units of ADU) for the n-first single electron peaks is derived as
\begin{equation} \mathcal{N} \cdot \sum_{n=0}^{n-th} \mathcal{P}(n- \frac{\mu_{0}}{k} ; \lambda) \circledast \mathcal{G}(n-\frac{\mu_{0}}{k},\sigma) \qquad\qquad\qquad\qquad [1] \end{equation}where
This is done by FitDarkCurrentProcess
provided by pysimdamicm.processes.skipper_analysis
which contains a large number of processes related to skipper images.
This process use ROOT.TH1F.Fit to fit the pixel charge distribution to equation 1.
FitDarkCurrentProcess
¶image
config param¶Same idea as in the previous process (PedestalSubtractedProcess
).
The image to be used to fit the dark current can calibrated image (i.e. image_mean_compressed_pedestal_subtracted_e
pixel charge in units of $e^{-}/$pix, but not introduced yet) or the one from the pedestal subtracted process (i.e. image_mean_compressed_pedestal_subtracted
, in units of ADU/pix). The later is the one by default.
method
config param¶Only one method is availablre right now
in_overscan
config param¶Set to use the overscan cols region instead of the active retion (which is the one by default!)
n_peask
config param¶Number of single electron peak to fit (from 0, up to n_peaks
-1 )
n_sigma_fit
config param¶To fit the image in units of ADU and without knowing the calibration constant this parameter is quite important. The fitting process is recursive, and the spectral window size change from trail to trail. This number n_sigma_fit
is used to define the spectral window and using only those pixel charge within the espectral window:
where
n
is given by n_sigma_fit
and calibration
n_peaks
do_calibration
config param¶Set this parameter to also fit the calibration constant (or gain). The fit algorithm is assuming the image is in units of ADU and the calibration constant will be also fitted.
What you can also do also, is use the already calibrated image, and still fit the gain. In this case, the fitted calibration constant should be around 1. This is used to bettter estimate the already know calibration constant which perhaps changed for whatever reason.
calibration
config param¶If do_calibration
is set, just the starting point of the calibration constant.
lambda_poisson
, mu_gauss
config params¶The starting point for the fitting algorithm. If nothing is passed, a first estimation is done internally
binning_size
config param¶The binning size for the histogram used to fit the dark current. If negative, the binning size will be integer of $2 \cdot \sqrt{ N_{pixels} }$
In this howto there are two sections:
In both cases, we will do the same (fit the dark current), but using two different approaches. The first option allows yo to get to know and go deeper into the different sub-modules of pysimdamicm
, while the second is the use of pysimdamicm
as a black box through the panaSKImg
script.
%matplotlib inline
# loading damicm module
import pysimdamicm as ccd
# loading other packages
import ROOT
# variable pointing where my#### data is
path_to_raw_data = "/data/workdir/compton/data/calidaq_backup/DataTaking/Am241/skip_2000_img/"
# pattern file name
img_pattern_file_name = "Image_Am241_Source_55_{}.fits"
# absolute path to the file name
file_name = "{}/{}".format(path_to_raw_data,img_pattern_file_name)
print("\nMy images follows the patter file name:\n {}\n".format(file_name.format("*")))
# path where our JSON file is
cfg_file = "{}/json/panaSKImg_configuration.json".format(ccd.__path__[0])
# False to interpret the JSON file as a configuration for data instead of simulations (default one)
cfg = ccd.utils.config.Config(cfg_file, simulations=False)
print(ccd.utils.config.json.dumps(cfg.configuration['input'], indent=4, sort_keys=True))
Remember that this step only read all necessary parameters from the header (convention
) as well as the image. However, it does not create the different regions for the overscan, prescan and sensor. For that, use the function member of the RawData (see 3.1).
ccd.io.rawdata.__verbose__ = False
rdata = ccd.io.rawdata.BuilderRawData(file_name.format('skip_1'), cfg.configuration['input'])
Internally what this function does is the creation of a boolean array for each region. This boolean array with the same size than the full image, should be used against the object rdata.image_mean_compressed
to select only regions we are insterested in by using numpy.ma.array
. The object rdata.image_mean_compressed
is the averaged skip image (see next steps).
rdata.prepare_data()
The attribute image
of rdata
contains our data image. It is an array of 3 dimensions if the input file corresponds to an skipper image, and a 2D is is the already averaged image.
The dimensions are for:
rdata.image.shape
This image has 60 rows, 275 columns and each pixels has been measured 2000 times.
comp = ccd.processes.skipper_analysis.CompressSkipperProcess()
comp.id_skip_start = 10
comp.execute_process(rdata)
print("Total pixel charge: ", rdata.image_mean_compressed.sum())
ped = ccd.processes.skipper_analysis.PedestalSubtractionProcess()
%matplotlib inline
# full image
ped.in_overscan = True
ped.axis = "row"
ped.n_sigma_to_mask = 10
ped.use_mad = True
# set method
ped.method = 'gauss_fit'
ped.execute_process(rdata)
dcfit = ccd.processes.skipper_analysis.FitDarkCurrentProcess()
The user can change the following configuration parameters:
dcfit.info()
This process has a lot of parameters and for that a lot of combinations. $\color{orange}{\text{Be careful when using them, altough some options are allowd, this does not mean that they all make sense!}}$
dcfit = ccd.processes.skipper_analysis.FitDarkCurrentProcess()
dcfit.__verbose__ = False
dcfit.do_calibration = True
dcfit.binning_size = 0.15
dcfit.calibration = 1.0
dcfit.n_peaks = 2
dcfit.n_sigma_fit = 10
dcfit.mu_gauss = 0.0
dcfit.sigma_gauss = 0.03
dcfit.fit_options = "QSE"
dcfit.execute_process(rdata)
c = ROOT.TCanvas()
c.Draw()
dcfit.hist.Draw()
c.SetLogy()
c.Update()
c.Draw()
%matplotlib inline
# loading damicm module
import pysimdamicm as ccd
import ROOT
cfg = ccd.utils.config.Config("{}/json/panaSKImg_configuration.json".format(ccd.__path__[0]), simulations=False)
ccd.io.rawdata.__verbose__ = False
image_file_name = "/data/workdir/compton/data/calidaq_backup/DataTaking/Am241/skip_2000_img/"+\
"Image_Am241_Source_55_skip_1.fits"
rdata = ccd.io.rawdata.BuilderRawData(image_file_name, cfg.configuration['input'])
rdata.prepare_data()
## compress image with the default funcitons: mean, and std; and skip 10 first measurements
comp = ccd.processes.skipper_analysis.CompressSkipperProcess()
comp.id_skip_start = 10
comp.execute_process(rdata)
## substract pedestal using overscan and row by row (default)
ped = ccd.processes.skipper_analysis.PedestalSubtractionProcess()
ped.__verbose__ = True
ped.use_mad = True
ped.method = 'gauss_fit'
ped.execute_process(rdata)
## fit dark current to the first two peaks
dcfit = ccd.processes.skipper_analysis.FitDarkCurrentProcess()
dcfit.__verbose__ = False
dcfit.do_calibration = True
dcfit.binning_size = 0.15
dcfit.calibration = 1.0
dcfit.n_peaks = 2
dcfit.n_sigma_fit = 10
dcfit.mu_gauss = 0.0
dcfit.sigma_gauss = 0.03
dcfit.fit_options = "QSE"
dcfit.execute_process(rdata)
## due to notebook issues the DC plot must be explicitely plot (to be the plot integretad into the document)
c = ROOT.TCanvas()
c.Draw()
dcfit.hist.Draw()
c.SetLogy()
c.Update()
c.Draw()
The main script for analysis is panaSKImg
also provided by pysimdamicm
. It is a python3 script to apply a chain of processes over a real data CCD image. Find more information here.
To $\color{green}{\text{fit the dark current}}$ we can also use panaSKImg
. We will only need
Here is an example of how to run the same as in Sect. A (How to from a Python Interpreter), but with panaSKImg
:
panaSKImg --json <config_file.json> "image_file" --display --verbose -o .
display
and verbose
will display all plots created along the process.
Two possible ways:
It is possible to use both the json file and command lines. $\color{green}{\text{The command lines have preference over those of the json file.}}$
This has to be done in the configuration file. Here you can find information about the full JSON file.
"FitDarkCurrentProcess":
{
"image":"pedestal_subtracted",
"method":"root",
"do_calibration":false,
"n_peaks":2,
"n_sigma_fit":2,
"mu_gauss":0.0,
"sigma_gauss":0.2,
"lambda_poisson":0.05,
"fit_options":"QSL",
"save_as":true
},
All these parameters have been explained along this howto.
Almost all parameters has a command line to be pass as an argument of panaSKImg
. Run
panaSKImg --help
for help on the command lines. Here the output of the help related with FitDarkCurrentProcess
*** For Process FitDarkCurrentProcess ************************** :
--dc-axis DC_AXIS Axis to fit the dark current.
--n-elec N_ELEC Number of single eletron peaks to use to fit the dark
current
--n-sigma-fit N_SIGMA_FIT
Number of sigmas to define the spectral window to
estimate the initial values of all paramters to be fit
--mu-gauss MU_GAUSS Initial value for the position of the single electron
peak at 0 electrons
--sigma-gauss SIGMA_GAUSS
Initial value for the electronic noise (e-/pix)
--lambda-poisson LAMBDA_POISSON
Initial value for the dark current (e-/pix)
--fit-options FIT_OPTIONS
Options for the fitting see ROOT::TGraph::Fit
--do-calibration Set if the calibration constant from user should be
used (in this case, use calibration option to pass its
value)
sequence
is mandatory¶Remember that the parameter sequence
of the process
section of the JSON file must be informed. You can do that using the command line -s as follows
panaSKImg --json <config_file.json> "image_file" --display --verbose -o . -s CompressSkipperProcess,PedestalSubtractionProcess,FitDarkCurrentProcess
To list all possible process you can just run
panaSKImg --list-process help
%sx panaSKImg --list-process help