19. Calibrations    Appendix

This appendix explains the different calibrations that need to be performed for the Timepix to bring it into its operating window, sec. 19.1. Then in sec. 19.2 we present additional calibrations for all chips.

19.1. Timepix calibrations

Before a Timepix based detector can be used for data taking, different calibrations have to be performed. We will discuss those calibrations, which are performed before any data taking here.

First, the THS optimization and threshold equalization (sec. 19.1.1). These two are calibrations that are used to set different DACs on the Timepix to good working points. The very important ToT calibration was already introduced in the main body, section 8.1.1. Its purpose is to interpret the ToT values in amount of charge of recorded electrons. In principle there are many other calibrations one could perform, as the Timepix has 13 different DACs. Most are used with default values that are seen in tab. 8. S-Curve scans are introduced in sec. 19.1.3, which can be used to map THL threshold DAC values to charges and determine the activation threshold. Similarly, the Pólya distribution can also act as a means to determine the activation threshold, see sec. 19.1.4.

Important references for the Timepix in general and for the calibration procedures explained below are (Llopart et al. 2007; Llopart Cudie 2007; Llopart and Poikela 2006; Lupberger 2016).

19.1.1. THS optimization and threshold equalization

For an optimal operation of a Timepix based detector, each pixel should ideally have the same threshold. While all pixels are theoretically identical, imperfections in the production process will always lead to slight differences, either locally (transistor threshold voltage or current mismatches (Llopart et al. 2007; Pelgrom, Duinmaijer, and Welbers 1989) ) or global effects like small supply voltage instabilities. Therefore, each pixel has 4 independently selectable current sources to minimize the spread of threshold values (Llopart and Poikela 2006; Llopart et al. 2007). Together all 4 sources act as an effective 4-bit DAC to slightly adjust the threshold. The absolute current for the 4 sources is dependent on the global THS DAC, allowing currents in the range of \(\SIrange{0}{40}{nA}\).

To achieve a good calibration for a homogeneous threshold, first the THS DAC has to be set correctly. This is referred to as the THS optimization. Once the correct value is found, the 4-bit DAC on each pixel can be adjusted to minimize the spread of threshold values of all pixels together.

If the THS DAC is set too high, the 4-bit DAC on each pixel will be too coarse for a fine adjustment (as the 'current steps' will be too large). If it is too low, not enough range will be available to adjust each pixel to an equal noise / sensitivity level (not enough current available via the 4 current sources). The goal of the THS optimization is therefore to find just the right value, as to provide a range of values such that all values can be shifted to the same threshold of the threshold DAC THL.

The algorithm scans a range of THL values through a subset of \(\num{4096}\) pixels using different 4-bit DAC values. First 0 for all pixels and then the maximum value of 15. At each THL and 4-bit value the number of hits due to pure noise is recorded for each pixel. The weighted mean of the THL values, using the number of hits as weight, is the value of interest for each pixel and each 4-bit DAC value: the effective THL noise value for that pixel. For each of the two cases (4-bit value 0 and 15) we can then compute a histogram of the number of pixels at each THL value. The resulting histogram will be a normal distribution around a specific THL value. The stopping criterion, which defines the final THS value, is such that these two distributions overlap at the 3 RMS level. This is performed by comparing the means of the 0 and 15 value distribution at a starting THS value and again at half of that THS value. Using linear regression of the two differences, the optimal THS value is computed.

With a suitable THS value set, the actual threshold equalization can start. The algorithm used is fundamentally very similar to the logic of the THS optimization. Each pixel of the chip is scanned for a range of THL values and the weighted THL noise mean is computed both at a 4-bit DAC value of 0 and at 15. The normalized deviation of each pixel's THL value to the mean THL value of all pixels is computed. Using a linear regression the optimal required shift (in units of the 4-bit DAC) yields the final 4-bit DAC value for each pixel.

An example of the 0 and 15 value distributions as well as the distribution using the final 4-bit DAC values for each pixel is shown in fig. 1(a). 1 Each of the distributions represent different 4-bit DAC settings of all pixels of the chip. Orange ("min") represents all pixels using a 4-bit DAC value of 0, purple ("max") of 15. In green is the same distribution for the case where every pixel uses its optimal 4-bit DAC value. The threshold equalization thus yields a very strong reduction in the THL spread of all pixels. Fig. 1(b) shows how all pixels are spread in the values of the 4-bit DAC. The narrow equalized line of fig. 1(a) is achieved by a normal distribution around \(\num{8}\) of the 4-bit DAC values, with only very few at the edges of the DAC (\(\num{0}\) and \(\num{15}\)). Finally, fig. 2 shows a heatmap of an entire chip with its 4-bit DAC values after equalization.

Similar plots for all other chips during both run periods can be found in the extended thesis.

Figure 1(a): THL distributions
Figure 1(b): 4-bit distributions
Figure 1: 1(a)Distributions of different 4-bit DAC settings of all pixels of the chip. Orange ("min"): all pixels using a 4-bit DAC value of 0, purple ("max"): 15. Green: every pixel uses the optimal 4-bit DAC value after equalization. The result is a significant in =THL= value spread of all pixels.1(b)Distribution of all 4-bit DAC values for the pixels after the threshold equalization. A normal distribution around a middle value is expected to largest likelihood of achieving a flat threshold around the whole chip. Very few pixels are either in value \num{0} or \num{15}, implying few pixels likely outside their range to adjust to the required threshold. In this example represented is the center chip of the Septemboard with its calibration from July 2018.
heatmap_threshold_equalization_Run3_chip_3.svg
Figure 2: Figure 115: Heatmap of the distribution of the 4-bit DAC values of all pixels as they are spread over the full Timepix. In this example represented is the center chip of the Septemboard with its calibration from July 2018.
19.1.1.1. Generate the plot for the THS optimization result    extended
import std / strformat
import ggplotnim

proc csbs(): Theme =
  result = sideBySide()
  result.titleFont = some(font(7.0))

proc main(fname, runPeriod: string, chip: int) =
  var df = readCsv(fname, sep = '\t', colNames = @["x", "y", "min", "max", "bit", "opt"])
  let breaks = linspace(-0.5, 15.5, 17).toSeq1D
  echo breaks
  ggplot(df, aes("bit")) +
    geom_histogram(breaks = breaks, hdKind = hdOutline) +
    scale_x_continuous() +
    xlim(-0.5, 16.5) +
    xlab("4-bit DAC") +
    margin(left = 3.5) + 
    themeLatex(fWidth = 0.5, width = 600, height = 420, baseTheme = csbs) + 
    ggtitle(&"All equalization bits after optimization, {runPeriod}, chip {chip}") + 
    ggsave(&"/home/basti/phd/Figs/detector/calibration/optimized_equalization_bits_{runPeriod}_chip_{chip}.pdf",
           useTeX = true, standalone = true)
  df = df.gather(["min", "max", "opt"], "type", "THL")
  ggplot(df.filter(f{`THL` > 330.0 and `THL` < 460.0}), aes("THL", fill = "type")) +
    geom_histogram(binWidth = 1.0, position = "identity", hdKind = hdOutline, alpha = 0.7) +
    ggtitle(&"All equalization bits at 0, 15 and optimized, {runPeriod}, chip {chip}") +
    #xlim(330, 460) +
    margin(left = 3.5) +     
    themeLatex(fWidth = 0.5, width = 600, height = 420, baseTheme = csbs) +     
    ggsave(&"/home/basti/phd/Figs/detector/calibration/ths_optimization_distributions_{runPeriod}_chip_{chip}.pdf",
           useTeX = true, standalone = true)
when isMainModule:
  import cligen
  dispatch main

Laptop:

for chip in {0..6}; do
    ./code/ths_optimization -f ~/septemH_calibration/SeptemH_FullCalib_2018_2/chip$chip/thresholdMeans$chip.txt --runPeriod Run3 --chip $chip &;
done

Desktop / Laptop:

for run in 2 3; do
    for chip in {0..6}; do
        ./code/ths_optimization -f ~/CastData/ExternCode/TimepixAnalysis/resources/ChipCalibrations/Run$run/chip$chip/thresholdMeans$chip.txt --runPeriod Run$run --chip $chip &;
    done
done

resources/ths_optimization.html

import ggplotnim
import std / [sequtils, strutils, strformat]

proc main(fname, runPeriod: string, chip: int) =
  let aranged = toSeq(0 .. 255).mapIt($it)
  var df = readCsv(fname, sep = '\t', colNames = aranged)
  df["y"] = toSeq(0 .. 255)
  df = df.gather(aranged, "x", "4-bit DAC")
    .mutate(f{"x" ~ `x`.parseInt})
  echo df
  
  ggplot(df, aes("x", "y", fill = "4-bit DAC")) +
    geom_raster() + 
    #scale_x_continuous() +
    #xlim(-0.5, 16.5) +
    coord_fixed(1.0) +
    xlab("x [pixel]") + ylab("y [pixel]") + 
    xlim(0, 255) + ylim(0, 255) +
    themeLatex(fWidth = 0.9, width = 600, baseTheme = singlePlot) + 
    ggtitle(&"Equalization bits after optimization, {runPeriod}, chip: {chip}") + 
    ggsave(&"/home/basti/phd/Figs/detector/calibration/heatmap_threshold_equalization_{runPeriod}_chip_{chip}.pdf",
           useTeX = true, standalone = true)

when isMainModule:
  import cligen
  dispatch main
./code/threshold_equalization_heatmap -f ~/septemH_calibration/SeptemH_FullCalib_2018_2/chip3/threshold3.txt
for run in 2 3; do
    for chip in {0..6}; do
        ./code/threshold_equalization_heatmap -f ~/CastData/ExternCode/TimepixAnalysis/resources/ChipCalibrations/Run$run/chip$chip/threshold$chip.txt --runPeriod Run$run --chip $chip &;
    done
done

All plots are found under sec. 19.2.

19.1.1.2. Relevant code for calculation of mean values from TOS    extended

Filling of sum in THscan. array_pos is effectively the THL value currently being scanned. pix_tempdata is the response matrix of each pixel (contains hit counter for each pixel). Also fills hit_counter, which is simply the counts.

    fpga->DataFPGAPC(pix_tempdata2,chp); //!!!only one chip!!!
    for(short y=step;y<256;y+=(256/pix_per_row)){
        for(short x=0;x<256;x++){
            if(pix_tempdata2[y][x]>=20 and pix_tempdata2[y][x]!=11810){
                //if (pix_tempdata2[y][x]>=200) {std::cout << "hits for thl " << thl <<" :" << pix_tempdata2[y][x] << std::endl;}
                p3DArray[y][x][array_pos] = pix_tempdata2[y][x];
                //if(LFSR_LookUpTable[(*VecData)[chp][y][x]]>=20 and LFSR_LookUpTable[(*VecData)[chp][y][x]]!=11810){
                //p3DArray[y][x][array_pos] = LFSR_LookUpTable[(*VecData)[chp][y][x]];
                sum[y][x]+=p3DArray[y][x][array_pos]*(array_pos);
                hit_counter[y][x]+=p3DArray[y][x][array_pos];
            }
            else{
                p3DArray[y][x][array_pos] = 0;
                sum[y][x]+=0;
                hit_counter[y][x]+=0;
            }
        }
    }

And in the THSopt the code to compute the mean:

        for(y=0;y<256;y++){
            for(x=0;x<256;x++){
                if (hit_counter0[y][x]!=0){
                    mean0[y][x] = sum0[y][x]/hit_counter0[y][x];
                    mean0entries += 1;
                    summean0 += mean0[y][x];
                }
                if (hit_counter15[y][x]!=0){
                    mean15[y][x] = sum15[y][x]/hit_counter15[y][x];
                    mean15entries += 1;
                    summean15 += mean15[y][x];
                }
            }
        }

Length of shutter used is

    // calling CountingTime with second argument == 1
    // corresponds to n = 1, power of 256
    fpga->CountingTime(10, 1);

(could compute the length, but not important right now)

Given that the THscan is run for each THL value (and thus summing up all contributions of all THL values for sum0), the algorithm effectively computes:

mean = Σ_i #hits_i * THL_i / Σ_i #hits_i

which is simply the weighted mean of the THL value, weighted by the number of hits. Essentially we compute the THL value with the most dominant noise? In a sense it makes sense as changing the 4-bit DAC will move around the position of that noise effectively. The

The point of interest then here is the fact that the number of hits depends on the THL value strongly. We only see the number of injected test pulses, if we're above the noise. Ideally we don't want to see any noise due to too low THL range. Therefore let's check what is used in TOS.

We will verify this by computing the same value for an S-curve calibration file:

import ggplotnim

const path = "/home/basti/septemH_calibration/SCurve/chip_3/voltage_100.txt"
let df = readCsv(path, sep = '\t', header = "#", colNames = @["THL", "counts"])
  .filter(f{`THL` > 424})
echo df
let thls = df["THL", float]
let counts = df["counts", float]
var sum = 0.0
var hits = 0.0
for (thl, count) in zip(thls, counts):
  sum += count * thl
  hits += count
echo "Mean value = ", sum / hits

which results in a mean value of 463.8. Given the range of data that's, surprise, what we would expect from a weighted mean with the hit counter used.

Of course, in the THS optimization the input is purely noise and not a fixed set of test pulses.

19.1.2. Final THL (threshold) DAC value selection

Once the detector is THS optimized and threshold equalized, the final threshold value of the THL DAC can be determined for the data taking. While measurements like an S-Curve scan (see sec. 19.1.3) can be used to understand where the noise level of the chip is in terms of THL values, it is typically not a reliable measure as the real noise depends strongly on the shutter length. If an experiment – like a low rate experiment as CAST – requires long shutter lengths, the best way to determine the lowest possible noise-free THL value is to perform a simple scan through all THL values using the shutter length in use for the experiment.

For a correctly equalized chip a sharp drop off of noisy pixels should be visible at a certain threshold. In principle the THL value at which no more pixels are noisy is the ideal THL value.

TOS first performs a quick scan in a THL range given by the user, using short shutter lengths. The determined drop values that still see some noise to a noise-free range is used as a basis for a long shutter length scan using a shutter length given by the user. For safe noise free operation one should choose a THL value 2 or 3 above the first noise-free THL value at the target shutter length. Especially for long shutter lengths it is important to perform this calibration without any high voltage applied to the detector as otherwise cosmic background starts to affect the data.

19.1.3. S-Curve scan

The S-Curve scan is one of 2 different ways to determine the optimal THL value.

The purpose of the S-curve scan is to understand the relationship between injected charges in electron and the THL DAC values by providing a \({\text{\# } e^-}/\mathtt{THL}\text{ step}\) number (or without a ToT calibration \(\mathtt{ToT}/\mathtt{THL}\)).

It works by injecting charges onto each pixel and checking the pixel response of each pixel at different THL values. Below a certain THL value all pixels will respond to the injected charge. At some point certain pixels will be insensitive to the induced charge and a 90° rotated "S" will form. By fitting an error function to this S an ideal THL value can be deduced.

By calculating THL value at which half of all test pulses are recorded, we can compute the number of electrons corresponding to that THL DAC value, as we know the amplitude of the test pulse and thus number of injected electrons.

Fig. 3 shows an S-Curve scan of chip 0 of the Septemboard using the calibration from July 2018. The center peak in the middle is the noise peak of the detector at the shutter length used for the S-Curve scan. The symmetrical shape is due to specific implementation details of how the pixels function, the upper side is the one of interest. The center point (half way between both plateaus) corresponds to the effective threshold of the detector at that injected charge. The falling edge of each curve can be fit by the cumulative distribution function of a normal distribution, eq. \eqref{eq:daq:s_curve_fit_function}.

\begin{equation} \label{eq:daq:s_curve_fit_function} f(μ, σ, N) = \frac{N}{2} · \text{erfc}((x - μ) / (σ · \sqrt{2})) \end{equation}

where the parameter \(N\) is simply a scaling factor and \(μ\) represents the x value of the half-amplitude point. \(σ\) is the spread of the drop and \(\text{erfc}\) is the complementary error function \(\text{erfc}(x) = 1 - \text{erf}(x)\). The error function is of course just the integral over a normal distribution up to the evaluation point \(x\):

\[ \text{erf}(x) = \frac{2}{\sqrt{π}} ∫_0^{x} e^{-t²} \dd t. \]

Given that the number of injected electrons is known for each test pulse amplitude (see sec. 8.1.1), we can compute the relationship of the number of electrons per THL value step. This is called the THL calibration and an example corresponding to fig. 3 is shown in fig. 4, where the THL values used correspond to the \(μ\) parameters of eq. \eqref{eq:daq:s_curve_fit_function}. The resulting fit is useful, as it allows to easily convert a given THL DAC value into an effective number of electrons, which then corresponds to the effective threshold in electrons required to activate a pixel on average. When looking at the distribution of charges in a dataset, that cutoff in electrons is of interest (see sec. 19.1.4).

Table tab. 29 shows the fit parameters for the fits of fig. 3. See the extended thesis for all fit parameters and plots.

s_curves_0_Run3_lX_425.0_lY_3050.0.svg
Figure 3: Figure 116: S-Curve scan of chip 0 of the Septemboard using the calibration from July 2018. The scan works by injecting \num{1000} test pulses at different amplitudes onto the pixels. Each line represents one such measurement and each point is the mean number of counted hits for all pixels with injected test pulses. The center peak in the middle is the noise peak of the detector. The symmetrical shape is due to specific implementation details of how the pixels function. The upper side is the one of interest. The falling edge of each curve can be fit by the complement of the cumulative distribution function of a normal distribution. The center point (half way between both plateaus) corresponds to the effective threshold of the detector at that injected charge. The fit parameters are found in tab. 29.
thl_calibration_chip_0_Run3_lX_425.0_lY_3050.0.svg
Figure 4: Figure 117: The THL calibration can be used to gauge the 'threshold gain' the THL DAC has on the number of electrons required to cross the threshold. The THL DAC in the Timepix normally adjusts the threshold by about \num{25} electrons per DAC value cite:timepix_manual, which is reproduced well here (parameter \(1/m\)). The root of the linear fit (written as \(f⁻¹(y=0)\) in the annotation) corresponds to the position of the noise peak in fig. 3.
Table 29: Fit parameters of all S-Curves for Run-3 of chip 0 as shown in fig. 3.
V [U] N ΔN μ Δμ σ Δσ
20 1001 0.37 421.3 0.004754 4.221 0.006294
25 1004 0.3732 430.8 0.004994 4.545 0.006582
30 1000 0.3867 440.1 0.004989 4.429 0.006561
35 1005 0.3935 449.3 0.005154 4.627 0.006748
40 1002 0.3842 459.4 0.005048 4.53 0.006635
50 1002 0.3928 478.2 0.005145 4.603 0.006741
60 1001 0.3806 497.6 0.00505 4.553 0.006643
100 1004 0.3936 569.8 0.005365 4.895 0.007004
19.1.3.1. Fit function for S-Curve    extended

The implementation of the S-Curve fit is found in ./../CastData/ExternCode/TimepixAnalysis/Analysis/ingrid/calibration/fit_functions.nim,

func sCurveFunc*(p: seq[float], x: float): float =
  ## we fit the complement of a cumulative distribution function
  ## of the normal distribution
  # parameter p[2] == sigma
  # parameter p[1] == x0
  # parameter p[0] == scale factor
  result = normalCdfC(x, p[2], p[1]) * p[0]

which is typically called from ./../CastData/ExternCode/TimepixAnalysis/Analysis/ingrid/calibration/calib_fitting.nim, and for these plots used in file:///home/basti/CastData/ExternCode/TimepixAnalysis/Plotting/plotCalibration/plotCalibration.nim.

19.1.3.2. Generate plots and compute electrons per THL DAC value [0/2]    extended

We generate both the S-Curve and THL calibration plots using plotCalibration. Let's simply generate all Run2 and Run3 plots for S-Curves and THL values.

for run in Run2 Run3; do
    for chip in {0..6}; do
        plotCalibration --scurve --chip $chip --runPeriod $run --useTeX --legendX 425.0 --legendY 3050 --outpath ~/phd/Figs/detector/calibration --quiet &;
    done
done

and for the THL calibration:

for run in Run2 Run3; do
    for chip in {0..6}; do 
        plotCalibration --scurve --chip $chip --runPeriod $run --useTeX --legendX 422.0 --legendY 3550 --outpath ~/phd/Figs/detector/calibration --quiet &;
    done
done

the only difference being the legend placement (as the coordinates are applied to both plots).

The following is essentially the main code required to plot the SCurves, determine the middle point and fit THL calib (not the SCurve fit though):

import std / [strutils, strscans, os, strformat] 
import ggplotnim
import unchained

proc charge(voltage: mV): UnitLess =
  ## Returns the number of electrons given a voltage pulse of amplitude `voltage`
  ## at the 8.fF capacitor of the Timepix1
  result = 8.fF * voltage / e

#const path = "/home/basti/septemH_calibration/SCurve/chip_3/voltage_*.txt"
#const path = "/home/basti/septemH_calibration/CalibJul2018/SCurves/chip_1/voltage_*.txt"
const path = "/home/basti/septemH_calibration/SeptemH_FullCalib_InGridDatabase/chip3/SCurve/voltage_*.txt"
#const path = "/home/basti/septemH_calibration/SeptemH_FullCalib_2018_2/chip0/SCurve/voltage_*.txt"
var charges = newSeq[float]()
var thls = newSeq[int]()
for file in walkFiles(path):
  let (success, _, voltage) = scanTuple(file.extractFilename, "$*_$i.txt$.")
  if voltage == 0: continue # skip 0
  charges.add charge(voltage.mV)
  ## we'll do the simplest approach to get the correct THL value:
  ## - strip everything before noise peak (to have single THL value)
  ## - compute
  var df = readCsv(file, sep = '\t', header = "#", colNames = @["THL", "counts"])
  let thlAtMax = df.filter(f{int: `counts` == `counts`.max})["THL", int][0] # must be single element
  const TestPulses = 1000
  df = df.filter(f{`THL` > thlAtMax})
    .mutate(f{int: "DiffHalf" ~ abs(`counts` - TestPulses div 2)})
    .filter(f{int: `DiffHalf` == min(col("DiffHalf"))}) # f{int: `DiffHalf` < 200})
  thls.add df["THL", int][0] # must be single element

import polynumeric
let fit = polyFit(thls.toTensor.asType(float),
                  charges.toTensor,
                  polyOrder = 1)
echo fit
proc linear(x, m, b: float): float = m * x + b

let thlFit = linspace(thls.min, thls.max, 10)
let chargesFit = linspace(charges.min, charges.max, 10)
var dfFit = toDf({ "thls" : thlFit,
                   "charges" : thlFit.map_inline(linear(x, fit[1], fit[0])) })
echo dfFit
let df = toDf(thls, charges)

ggplot(df, aes("thls", "charges")) + 
  geom_point() +
  geom_line(data = dfFit, aes = aes("thls", "charges"), color = parseHex("FF00FF")) +
  xlab("THL DAC") + ylab("Injected charge [e⁻]") + 
  ggtitle(&"Fit parameters: m = {fit[1]:.2f} e⁻/THL, b = {fit[0]:.2f} e⁻") +
  ggsave("/home/basti/phd/Figs/charge_per_thl.pdf")

All plots are found under sec. 19.2.

19.1.3.3. Compute minimally detectable charge    extended

Ref:

The following quotes explain how to compute the effective threshold:

page 5/10:

The electronic noise and effective threshold can be measured using the s-curve method [8] when the pixel is set in counting mode.

page 5/10:

The effective threshold is at 50% of this s-curve. The charge difference between the 97.75% and 2.25% of the s- curve is four times the RMS noise of the front end assuming a gaussian distributed noise.

The measured electronic noise is 99:4 ± 3:8 e⁻ rms for hole collection and 104:8 ± 6 e⁻ rms for electron collection. The measured DAC step gain is 24:7 ± 0:7 e⁻ =step for hole collection and 25:4 ± 1:2 e⁻ =step for electron collection.

page 7/10:

The threshold variation before equalization is ~240 e⁻ rms and after equalization the achieved noise free threshold variation is ~35 e⁻ rms for both polarities.

page 7/10:

The minimum detectable charge can be calculated by quadratically adding the measured electronic noise and the threshold variation because both measurements are uncorrelated.

Before equalization the minimum detectable charge for the full matrix is ~1600 e⁻ and after equalization is ~650 e⁻ for both polarities.

This means:

  • [ ] compute the 97.75 ⇔ 2.25% range of the S-curve. Yields 4 times RMS noise. Width in THL of that can be converted to #e⁻ using THL calibration. -> electronic noise \(N_e\)
  • [ ] compute width of optimized threshold variation based on histogram. Fit gaussian (?) to optimized threshold variation. σ of that gaussian is width in THL. Convert THL to electrons. -> threshold variation \(N_t\)
  • [ ] CHECK IF THIS IS CORRECT: If I'm not mistaken, the noise peak we see in the S-curve scan is essentially the same as the optimized distribution from the threshold equalization.

Then with those two parameters we compute the effective detectable charge as:

\[ N_d = √(N_e² + N_t²) \]

which for the numbers listed above yields

\[ N_d = √(105² + 35²) = 110 \]

which is not close to the expected 650 e⁻!

Checking in the PhD thesis of Llopert, page 115, equation 4.5 is:

\[ \text{MinDetect}Q = 6·\sqrt{ ENC² + σ_{\text{dist}}²} \] which then works out nicely (110·6 = 660 is close enough)!

So in theory we can compute this for all our chips and all calibrations.

  • [ ] CALCULATE FOR ALL CHIPS AND PUT INTO APPENDIX

19.1.4. Pólya distribution for threshold detection

In a gaseous detector the gas amplification (see sec. 6.3.6) allows to easily exceed the minimum detectable charge of \(\mathcal{O}(\SIrange{500}{1000}{e^-})\). The typically used THL threshold will be quite a bit higher than the 'theoretical limit' however for multiple reasons. One can either compute the effective threshold in use based on the THL calibration as explained in sec. 19.1.3, or use an experimental approach by utilizing the Pólya distribution as introduced in sec. 6.3.6 and 8.1.2. By taking data over a certain period of time and computing a histogram of the charge values recorded by each pixel, a Pólya distribution naturally arises.

The Pólya distribution can be used to determine the actual activation threshold by simply checking what the lowest charge is that sees significant statistics.

An example of such a Pólya distribution with a very obvious cutoff at low charges is seen in fig. 5. We see chip 0 using the same calibration from July 2018 as in the figures in the previous section 19.1.3. The data is a \(\SI{90}{min}\) interval of background data at CAST. The pink line represents the fit of the Pólya distribution to the data. The dashed part of the line was not used for the fit and is only an extension using the final fit parameters. The cutoff at the lower end due to the chip's threshold is clearly visible. The fit determines a gas gain of about \(\num{2700}\), compared to the mean of the data yielding about \(\num{2430}\).

Based on the data a threshold value of – very roughly – \(\num{1000}\) can be estimated. Using the THL calibration of the chip as shown in fig. 4 yields a value of

\[ Q(\text{THL} = 419) = 26.8 · 419 - 10300 = 929.2 \]

where we used the fit parameters as printed on the plot (\(1/m\) and \(f⁻¹(y=0)\)) and the THL DAC value of \(\num{419}\) as used during the data taking for this chip. Indeed, the real threshold is in the same range, but clearly a bit higher than the theoretical limit for this chip. This matches our expectation.

gas_gain_run_306_chip_0_2_90_min_1545296149.svg
Figure 5: Figure 118: An example of a Pólya distribution of chip 0 using the calibration of July 2018 based on \SI{90}{min} of background data. The lower cutoff is easily visible. The pink line represents the fit of the Pólya distribution to the data. In the dashed region the line was extended using the final fit parameters.
19.1.4.1. Generate Polya plot for chip 0, run period 3 [0/1]    extended

The current placeholder polya distribution (although it's the right chip and calibration) is:

basti at void in /mnt/1TB/CAST/2018_2/out/DataRuns2018_Raw_2020-04-28_16-13-28 λ
  cp gas_gain_run_306_chip_0_5_30_min_1545294386.pdf \
     ~/phd/Figs/gas_gain_run_306_chip_0_placeholder_example.pdf
  • [X] REPLACE BY BETTER PLOT. USING 90MIN AMONG OTHER THINGS

We simply use the existing reconstructed data and create the gas gain plots again:

WRITE_PLOT_CSV=true reconstruction -i ~/CastData/data/DataRuns2018_Reco.h5 \
               --only_gas_gain \
               --run 306 \
               --plotOutPath ~/phd/Figs/gasGain/ \
               --useTeX=true \
               --overwrite

19.2. Septemboard calibration

In the extended thesis this section contains all THS optimization, S-Curves and ToT calibrations for both run periods and all chips of the Septemboard. As this leads to a lot of pages of figures, here we only show a histogram of all optimized THL distributions for each run period in sec. 19.2.5.

19.2.1. Generate all ToT calibration plots    extended

See sec. 8.1.1.1 for the section producing the single plot used in the thesis.

# To generate fig:septem:tot_calibration_example
for run in 2 3; do
    for chip in {0..6}; do
        plotCalibration --tot --chip $chip --runPeriod Run$run --useTeX --file ~/CastData/ExternCode/TimepixAnalysis/resources/ChipCalibrations/Run$run/chip$chip/TOTCalib$chip.txt --outpath ~/phd/Figs/detector/calibration --quiet &;
    done
done

19.2.2. All ToT calibrations    extended

All plots without caption, too much repetition and the run period & chip number are in the title. Looking at these plots one of the things I've long thought is that the fit function is way too overspecified, given that usually one parameter (most of the time \(t\)) is just zero. The errors go crazy in Run-2 for chip 0, because the fit produces crazily large errors. Not quite sure why, but I guess it's just another reason of the function having too many parameters. :)

  • tot_calib_Run2_chip_0.svg
  • tot_calib_Run2_chip_1.svg
  • tot_calib_Run2_chip_2.svg
  • tot_calib_Run2_chip_3.svg
  • tot_calib_Run2_chip_4.svg
  • tot_calib_Run2_chip_5.svg
  • tot_calib_Run2_chip_6.svg
  • tot_calib_Run3_chip_0.svg
  • tot_calib_Run3_chip_1.svg
  • tot_calib_Run3_chip_2.svg
  • tot_calib_Run3_chip_3.svg
  • tot_calib_Run3_chip_4.svg
  • tot_calib_Run3_chip_5.svg
  • tot_calib_Run3_chip_6.svg
19.2.2.1. Investigate fit alone of Run-2, chip 0
plotCalibration --tot --chip 0 --runPeriod Run2 --useTeX --file ~/CastData/ExternCode/TimepixAnalysis/resources/ChipCalibrations/Run2/chip0/TOTCalib0.txt \
                --outpath /tmp/

See the crazy errors on parameters 1, 2 and 3?

19.2.3. All plots of THS optimization and equalization    extended

Again, all plots without caption or anything. That's why they have titles, you know.

  • heatmap_threshold_equalization_Run2_chip_0.svg
  • heatmap_threshold_equalization_Run2_chip_1.svg
  • heatmap_threshold_equalization_Run2_chip_2.svg
  • heatmap_threshold_equalization_Run2_chip_3.svg
  • heatmap_threshold_equalization_Run2_chip_4.svg
  • heatmap_threshold_equalization_Run2_chip_5.svg
  • heatmap_threshold_equalization_Run2_chip_6.svg
  • heatmap_threshold_equalization_Run3_chip_0.svg
  • heatmap_threshold_equalization_Run3_chip_1.svg
  • heatmap_threshold_equalization_Run3_chip_2.svg
  • heatmap_threshold_equalization_Run3_chip_3.svg
  • heatmap_threshold_equalization_Run3_chip_4.svg
  • heatmap_threshold_equalization_Run3_chip_5.svg
  • heatmap_threshold_equalization_Run3_chip_6.svg

19.2.4. All S-Curve plots    extended

Excuse the mismatched order of the tables… I don't really expect anyone to be particularly interested in this, hence I didn't want to spend time sorting them by hand.

All figures:

  • s_curves_0_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_0_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_1_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_1_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_2_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_2_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_3_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_3_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_4_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_4_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_5_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_5_Run3_lX_425.0_lY_3050.0.svg
  • s_curves_6_Run2_lX_425.0_lY_3050.0.svg
  • s_curves_6_Run3_lX_425.0_lY_3050.0.svg

All tables:

chip voltage runPeriod N ΔN μ Δμ σ Δσ
4 20 Run3 999.7 0.4 437.3 0.004919 4.256 0.006459
4 25 Run3 1003 0.376 446.7 0.005023 4.561 0.006614
4 30 Run3 999.5 0.3509 455.5 0.004807 4.4 0.006384
4 35 Run3 999.4 0.424 465.1 0.005229 4.494 0.0068
4 40 Run3 997.6 0.372 474.8 0.004981 4.492 0.006571
4 50 Run3 997.6 0.4397 492.6 0.005304 4.476 0.006868
4 60 Run3 1004 0.3632 511.5 0.005063 4.706 0.006681
4 100 Run3 998.8 0.3903 582.7 0.005315 4.818 0.00695
chip voltage runPeriod N ΔN μ Δμ σ Δσ
3 20 Run2 1020 1.225 422.9 0.00906 4.107 0.009371
3 25 Run2 1011 0.5655 428.1 0.005788 4.353 0.007229
3 30 Run2 1003 0.3785 433.1 0.004842 4.303 0.006391
3 35 Run2 1001 0.3727 438.4 0.004825 4.305 0.006377
3 40 Run2 1001 0.3724 444.3 0.004802 4.272 0.00635
3 50 Run2 1001 0.3643 454.1 0.004931 4.496 0.006519
3 60 Run2 999.5 0.3824 464.3 0.005009 4.477 0.006591
3 100 Run2 1005 0.4337 502.6 0.005988 5.397 0.007674
chip voltage runPeriod N ΔN μ Δμ σ Δσ
4 20 Run2 1040 1.203 427.4 0.009416 4.453 0.009669
4 25 Run2 1006 0.6367 433.2 0.006145 4.298 0.007513
4 30 Run2 1005 0.3829 438.1 0.004901 4.371 0.006456
4 35 Run2 1001 0.3561 443.3 0.004829 4.407 0.006405
4 40 Run2 1001 0.4318 449.2 0.005384 4.642 0.006972
4 50 Run2 999.3 0.362 459.1 0.004891 4.445 0.006473
4 60 Run2 1010 0.4457 469.4 0.005662 4.944 0.00727
4 100 Run2 1006 0.4092 507.6 0.005949 5.552 0.00768
chip voltage runPeriod N ΔN μ Δμ σ Δσ
1 20 Run3 1007 0.5532 384.6 0.00592 4.532 0.007397
1 25 Run3 1023 0.6033 393.6 0.007034 5.418 0.008488
1 30 Run3 1000 0.467 403.7 0.005764 4.853 0.007362
1 35 Run3 983.4 0.3714 413.1 0.004776 4.133 0.006327
1 40 Run3 1013 0.3916 422 0.005359 4.966 0.006994
1 50 Run3 1022 0.6807 440.9 0.007737 5.551 0.009052
1 60 Run3 982.4 0.3855 461.3 0.005151 4.526 0.006767
1 100 Run3 999.6 0.3774 534.6 0.005401 5.032 0.007076
chip voltage runPeriod N ΔN μ Δμ σ Δσ
5 20 Run3 980.6 0.3185 351.3 0.004076 3.441 0.005511
5 25 Run3 1012 0.4223 359.8 0.005834 5.346 0.007509
5 30 Run3 1003 0.3553 369.1 0.00509 4.786 0.006727
5 35 Run3 999.5 0.5331 378.9 0.006367 5.063 0.007928
5 40 Run3 991.5 0.4121 388.8 0.005378 4.701 0.006998
5 50 Run3 993.7 0.3681 406.8 0.004946 4.445 0.006536
5 60 Run3 1009 0.3795 425.5 0.005705 5.503 0.007451
5 100 Run3 1006 0.4792 498.9 0.006008 5.086 0.007616
chip voltage runPeriod N ΔN μ Δμ σ Δσ
0 20 Run3 1001 0.37 421.3 0.004754 4.221 0.006294
0 25 Run3 1004 0.3732 430.8 0.004994 4.545 0.006582
0 30 Run3 1000 0.3867 440.1 0.004989 4.429 0.006561
0 35 Run3 1005 0.3935 449.3 0.005154 4.627 0.006748
0 40 Run3 1002 0.3842 459.4 0.005048 4.53 0.006635
0 50 Run3 1002 0.3928 478.2 0.005145 4.603 0.006741
0 60 Run3 1001 0.3806 497.6 0.00505 4.553 0.006643
0 100 Run3 1004 0.3936 569.8 0.005365 4.895 0.007004
chip voltage runPeriod N ΔN μ Δμ σ Δσ
2 20 Run2 998.4 0.8093 351.8 0.007102 4.242 0.008231
2 25 Run2 1028 0.7173 356.9 0.006721 4.518 0.00796
2 30 Run2 1006 0.396 362.3 0.005205 4.683 0.006806
2 35 Run2 1003 0.3835 368.1 0.005318 4.898 0.006962
2 40 Run2 1013 0.4821 373.9 0.006488 5.664 0.008148
2 50 Run2 985.4 0.405 386.9 0.005722 5.14 0.007423
2 60 Run2 1015 0.4928 397.8 0.006599 5.721 0.008248
2 100 Run2 1002 0.4138 436 0.005847 5.353 0.007547
chip voltage runPeriod N ΔN μ Δμ σ Δσ
6 20 Run2 1008 1.057 400.5 0.00954 4.876 0.01006
6 25 Run2 981.7 0.433 407.7 0.005316 4.43 0.006901
6 30 Run2 990.9 0.3359 413.2 0.004408 3.878 0.005909
6 35 Run2 996.6 0.3557 417.6 0.004588 4.055 0.006108
6 40 Run2 995.3 0.3669 423.4 0.004743 4.192 0.006287
6 50 Run2 995.7 0.384 433.3 0.005026 4.464 0.006612
6 60 Run2 990.4 0.3798 444.6 0.005093 4.542 0.006701
6 100 Run2 998.2 0.4102 483.5 0.00559 5.026 0.007249
chip voltage runPeriod N ΔN μ Δμ σ Δσ
2 20 Run3 1000 0.3853 366.4 0.005084 4.56 0.006677
2 25 Run3 1001 0.3791 375.9 0.005146 4.689 0.006762
2 30 Run3 1003 0.4448 384.9 0.005457 4.657 0.007037
2 35 Run3 1001 0.3878 394.5 0.005168 4.66 0.006776
2 40 Run3 1001 0.4325 405 0.005309 4.55 0.006881
2 50 Run3 1002 0.3695 423.3 0.005096 4.69 0.006713
2 60 Run3 1001 0.3829 443.1 0.005312 4.886 0.006957
2 100 Run3 1003 0.3783 516.5 0.005342 4.972 0.007
chip voltage runPeriod N ΔN μ Δμ σ Δσ
3 20 Run3 998.8 0.3833 436 0.004918 4.348 0.006479
3 25 Run3 1002 0.377 445.6 0.005006 4.521 0.006593
3 30 Run3 1001 0.3666 454.1 0.00497 4.537 0.006564
3 35 Run3 1005 0.3822 463.6 0.005077 4.604 0.00667
3 40 Run3 1001 0.3767 473.6 0.004984 4.488 0.006567
3 50 Run3 1002 0.3772 491.7 0.005049 4.579 0.006646
3 60 Run3 999.8 0.3738 511.6 0.00493 4.427 0.006506
3 100 Run3 954.5 0.3897 583.8 0.005565 4.828 0.007279
chip voltage runPeriod N ΔN μ Δμ σ Δσ
0 20 Run2 989.8 0.8928 408.9 0.007268 3.991 0.008277
0 25 Run2 1006 0.4597 414.2 0.004923 3.974 0.006386
0 30 Run2 1004 0.3651 419.2 0.004602 4.067 0.006111
0 35 Run2 999.3 0.3604 424.4 0.004597 4.058 0.006113
0 40 Run2 1003 0.3845 429.2 0.004994 4.465 0.006569
0 50 Run2 1002 0.3689 439 0.00499 4.554 0.006585
0 60 Run2 1004 0.4107 449.1 0.00541 4.834 0.007032
0 100 Run2 1013 0.4559 486.9 0.006465 5.853 0.008183
chip voltage runPeriod N ΔN μ Δμ σ Δσ
5 20 Run2 1017 0.9365 336 0.007614 4.191 0.008502
5 25 Run2 1047 0.7914 341.5 0.00795 5.237 0.009016
5 30 Run2 988 0.4721 347.8 0.005962 4.962 0.007589
5 35 Run2 993.4 0.3367 352.5 0.004536 4.066 0.006067
5 40 Run2 1002 0.3981 357.8 0.005052 4.453 0.00662
5 50 Run2 999 0.3784 368.3 0.005305 4.891 0.006957
5 60 Run2 982.6 0.4703 381.5 0.006751 5.831 0.0085
5 100 Run2 1009 0.407 420.7 0.005546 5.066 0.007196
chip voltage runPeriod N ΔN μ Δμ σ Δσ
6 20 Run3 993.9 0.375 413.2 0.004854 4.282 0.006414
6 25 Run3 1002 0.3873 422.3 0.005074 4.549 0.006662
6 30 Run3 997.5 0.3923 431.5 0.005272 4.74 0.006896
6 35 Run3 1000 0.4067 441.1 0.005354 4.764 0.006972
6 40 Run3 1001 0.379 450.8 0.005124 4.662 0.006734
6 50 Run3 1005 0.4097 469.4 0.005494 4.956 0.007131
6 60 Run3 1000 0.3918 489.3 0.005174 4.637 0.006778
6 100 Run3 1009 0.4163 562.9 0.005794 5.32 0.007475
chip voltage runPeriod N ΔN μ Δμ σ Δσ
1 20 Run2 1069 1.481 368.1 0.01156 4.832 0.01095
1 25 Run2 1067 0.7955 374.7 0.009635 6.7 0.01062
1 30 Run2 975.2 0.3802 382.1 0.005377 4.803 0.007053
1 35 Run2 990.6 0.4188 387.6 0.005426 4.709 0.007046
1 40 Run2 1023 0.6093 393.5 0.007115 5.453 0.008561
1 50 Run2 989.8 0.4391 405.3 0.006054 5.321 0.007752
1 60 Run2 987.7 0.3325 415.5 0.004108 3.466 0.005535
1 100 Run2 1018 0.4941 452.2 0.006787 5.945 0.008457

19.2.5. THL calibration

Figure 6 shows the optimized THL distributions of all chips after threshold equalization for run 2 (left) and 3 (right).

septemboard_all_thl_optimized.svg
Figure 6: Figure 119: Distributions of the THL values of all Septemboard (board H) chips at the noise peak with the calibration for for run 2 on the left and run 3 on the right.
19.2.5.1. Generate facet plot of THL optimization    extended

The plot is generated as part of sec. 8.1.3.1.

19.2.6. All THL calibration plots    extended

Note: The text should be placed in relative coordinates based on the data range, but that's currently not done. Sorry about tcho "hat.

  • thl_calibration_chip_0_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_0_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_1_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_1_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_2_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_2_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_3_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_3_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_4_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_4_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_5_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_5_Run3_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_6_Run2_lX_425.0_lY_3050.0.svg
  • thl_calibration_chip_6_Run3_lX_425.0_lY_3050.0.svg

19.3. Calibration measurements of the veto scintillator paddle    extended

The following is a set of notes taken when calibrating the scintillator paddle in the laboratory of the RD51 group at CERN. It is reproduced here for transparency and completeness.

19.3.1. Scintillator paddle calibrations [0/2]

This document contains the data for the calibration of the MM veto scintillator. It is a 'report' created while data taking and thus may contain conflicting information. Not to be understood as a simple reference protocol.

The scintillator has a Canberra 2007 base, which accepts positive HV. The PMT is a Bicron Corp. 31.49x15.74M2BC408/2-X, where the first two numbers are the scintillators dimensions in inch.

For calibration we're using $\SI{1400}{\volt}$, while Juanan mentioned in his mail to use $\SI{1200}{\volt}$ during data taking.

For calibration we're using an Ortec 9302 amplifier after the PMT with a gain of 20. This is fed into an LRS 621CL discriminator. The PMT and base are used at a HV of \(+\SI{1200}{\volt}\).

Scintillator is of size \(\SI{42}{\cm}\) times \(\SI{82}{\cm}\). Which is an area of

let x = 0.42
let y = 0.82
echo x * y 
  • [ ] TODO: CROSS CHECK THESE NUMBERS HERE

At a cosmic muon rate of \(\sim\SI{100}{\hertz \per \meter \squared \steradian}\), the expected signal rate of munons is thus \(\sim \SI{33}{\hertz}\).

let area = 0.34
let total_muons = 60000.0
echo area * total_muons
  • [ ] UPDATE: Muon rate about \(\SI{1}{cm^{-2}.min^{-1}} \approx \SI{166.67}{m^{-2}.s^{-1}}\)
19.3.1.1. Calibration

Threshold values are scaled by a factor of 10. Coincidence using Theodoros 2 scintillator paddles in RD51 lab.

  • upper scinti: \(\SI{-2070}{\volt}\)
  • lower scinti: \(\SI{-2050}{\volt}\)

Measurement time for each value: \(\SI{10}{\minute}\)

Note: The reason the coincidences are much lower than the single scintillator counts is of course due to the much smaller coincidence area of the small scintillators used for the measurement.

Threshold / mV Counts Szinti Counts Coincidence
-301.9 24062 760
-399 13332 496
-498 6584 300
-603 3363 167
-699 1900 104
-802 1087 83
-901 651 54
-1005 523 50
-1104 361 32
-1203 231 32
-1305 189 38
-1400 151 23
-1502 96 14
-1602 78 15
-1703 72 10
-1802 58 11
     

Second set of measurements around interesting point of \(\SI{1000}{\milli\volt}\)

Threshold / mV Counts Szinti Counts Coincidence
-1200 259 35
-1100 350 34
-1000 456 48
-900 774 42

A third measurement using an amplifier after the PMT, since the output signal of the PMT is so small (see mail of JuanAn). Now the HV was lowered to \(\SI{1200}{\volt}\) again, since it is not necessary.

Threshold / mV Counts Szinti Counts Coincidence
-598 31221 634
-700 30132 674
-804 28893 635
-903 28076 644
-1005 27012 684
-1103 25259 566
-1200 22483 495
-1303 19314 437
-1403 16392 356
-1505 13677 312
-1600 11866 267
-1701 10008 243
     
-900 28263 892
-1000 26789 991
import ggplotnim, sequtils
proc parse(s: openArray[string]): seq[float] = s.filterIt(it.len > 0).mapIt(it.parseFloat)
let df = toDf({ "Thr" : tbl["Threshold / mV"].parse,
                "Szinti" : tbl["Counts Szinti"].parse,
                "Coinc" : tbl["Counts Coincidence"].parse })
ggplot(df, aes("Thr", "Szinti")) +
  geom_point() + geom_line() +
  ggsave("/t/test.pdf")

Export this table using org-table-export to ./data/veto_szinti_counts.txt. Then remove unnecessary last line and add # to beginning of first line.

  • [ ] REWRITE TO USE AN INLINE GGPLOTNIM PLOTTING AND SHOW DATA

Then use ./PyS_mm_veto_szinti_calib.py to plot the data.

A threshold of \(\SI{-110}{\milli\volt}\) was selected, after analysis.

Footnotes:

1

The plot is generated from the thresholdMeans.txt file created as part of the equalization procedure in TOS.

Click on any heading marked 'extended' to open it