From a806756642728e7dfcdb730fd649805e04657e72 Mon Sep 17 00:00:00 2001 From: Sofia Calgaro Date: Fri, 6 Dec 2024 07:06:48 -0800 Subject: [PATCH] Deploy documentation --- config/index.html | 2 +- index.html | 16 +++++++++++++++- inputs/index.html | 2 +- installation/index.html | 2 +- internal_api/index.html | 2 ++ search_index.js | 2 +- toys/index.html | 2 +- tutorial/index.html | 2 +- 8 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 internal_api/index.html diff --git a/config/index.html b/config/index.html index a13f1ac..10cfb42 100644 --- a/config/index.html +++ b/config/index.html @@ -33,4 +33,4 @@ }

In particular, you can set "correlated": true if you want to use one variable to correlate the nuisance parameters (eg to speed up the computation times), and "fixed": false if you want to include a prior for nuisance parameters (otherwise these parameters they will be fixed to their partition value and not constrained).

If a variable is correlated (either energy_scale or efficiency), the code will search for a field in the fit_groups block of the partitions JSON file to use a correlated variable per each fit group. In particular, the field has to be specified as:

Note

If the key doesn't exist, this defaults to "all"

Parameters are then added to the model called αr_\$name (for resolution), αe_\$name for efficiency and αb_\$name for bias.

Warning

The $\alpha$ parameter names default to _all, if you want one different per experiment this must be explicitly specified in the fit groups entry

Background shape and correlation

There are several options to control the background in more detail. These can be added to the "bkg" section of the config: In particular:

"correlated":{"mode":"lognormal","range":[0,0.1]}

The three options for the mode are 'lognormal', 'normal' or 'none'. While the range gives the range of the uniform prior on the \sigma_B parameter.

for example:

"shape":{
             "name":"exponential",
             "pars":{"slope":[-10,10]}
-        },

The "pars" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are "uniform", "linear" and "exponential". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.

This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.

Note

If these keys are not provided the model defaults to a uniform uncorrelated background.

Signal shape

The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the "Partitions and events" documentation.

+ },

The "pars" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are "uniform", "linear" and "exponential". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.

This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.

Note

If these keys are not provided the model defaults to a uniform uncorrelated background.

Signal shape

The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the "Partitions and events" documentation.

diff --git a/index.html b/index.html index 85c9f1d..803a0bf 100644 --- a/index.html +++ b/index.html @@ -1,2 +1,16 @@ -Home · ZeroNuFit.jl

ZeroNuFit.jl Documentation

Welcome to the documentation for ZeroNuFit.jl.

Introduction

ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay ($0\nu\beta\beta$) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other $0\nu\beta\beta$ experiment or to any other physical processes that can be modelled in a similar way.

The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).

Likelihood Function

The implemented unbinned Likelihood function reads as: $\mathcal{L} = \prod_{\rm k=1}^{N_{\rm p}} \left[\frac{\mu_{\rm k}^{N_{\rm k}} e^{-\mu_{\rm k}}}{N_{\rm k}!} \times \prod_{\rm i=1}^{N_{\rm k}} \frac{1}{\mu_{\rm k}}\left(\frac{\mu_{\rm b,\,k}}{\Delta E} + \mu_{\rm s,\,k} \times \frac{dP(E_{\rm i} | Q_{\beta\beta} +\Delta_{\rm k}, \omega_{\rm k})}{dE}\right) \right]$.

Here, the first product runs over the number of partitions k ($N_{\rm p}$ partitions in total) and the second over the events i in a given partition ($N_{\rm k}$ events in total). In particular, $E_{\rm i}$ are the energies of the events falling in the analysis window for a partition k with energy bias $\Delta_{\rm k}$ and energy width $\omega_{\rm k}$.

The background and signal contributions are defined as $\mu_{\rm b,\,k} = \mathcal{B}_{\rm k} \cdot \Delta E \cdot \mathcal{E}_{\rm k}$ and $\mu_{\rm s,\,k} = \frac{\text{ln}\,2\mathcal{N}_{\rm A}}{m_{\rm 76}} \cdot (\varepsilon_{\rm k} + \alpha \cdot \sigma_{\varepsilon_{\rm k}}) \cdot \mathcal{E}_{\rm k} \cdot \mathcal{S}$. The total contribution can thus be defined as $\mu_{\rm b,\,k} = \mu_{\rm b,\,k} + \mu_{\rm s,\,k}$.

The prior distributions were taken as Gaussian distributions centred around the true value $\pi(\Delta_{\rm k},\, \omega_{\rm k},\, \alpha) = \frac{1}{\sqrt{2\pi}\sigma_{\Delta_{\rm k}}} \,e^{-\frac{\left(\Delta_{\rm k} - \widehat{\Delta}_{\rm k} \right)^2}{2 \sigma_{\Delta_{\rm k}} ^2}} \times \frac{1}{\sqrt{2\pi}\sigma_{\omega_{\rm k}}} \,e^{-\frac{\left(\omega_{\rm k} - \widehat{\omega}_{\rm k} \right)^2}{2 \sigma_{\omega_{\rm k}} ^2}} \times e^{-\alpha^2/2}$.

The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND), $\frac{dP(E | x, \sigma)}{dE} = \frac{1}{\sqrt{2\pi\sigma^2}} \times e^{-\frac{\left(E - x \right)^2}{2 \sigma ^2}}$.

Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR), $\frac{dP(E | x, \gamma)}{dE} = \frac{1-f}{\sqrt{2\pi(\gamma \sigma)^2}} \times e^{-\frac{\left(E - x \right)^2}{2 (\gamma \sigma) ^2}}+\frac{f}{2\gamma\tau}\times e^{ \frac{(\gamma \sigma)^2}{2(\gamma\tau)^2} + \frac{E-x}{\gamma\tau} } \times erfc \left(\frac{\sigma}{\sqrt{2}\tau}+ \frac{E-x}{\sqrt{2}\gamma\sigma} \right)$.

In particular, for a given partition k, $\mathcal{B}_{\rm k}$ is the background index, $\mathcal{E}_{\rm k}$ is the exposure, $\Delta E$ is the fit window, $\varepsilon_{\rm k}$ is the efficiency with uncertainty $\sigma_{\varepsilon_{\rm k}}$ and $\mathcal{S}=\Gamma_{\rm 1/2}=1/T_{\rm 1/2}$ is the signal.

Table of contents

+Home · ZeroNuFit.jl

ZeroNuFit.jl Documentation

Welcome to the documentation for ZeroNuFit.jl.

Introduction

ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay ($0\nu\beta\beta$) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other $0\nu\beta\beta$ experiment or to any other physical processes that can be modelled in a similar way.

The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).

Likelihood Function

The implemented unbinned Likelihood function reads as:

\[\begin{aligned} +\mathcal{L} = \prod_{\rm k=1}^{N_{\rm p}} \left[\frac{\mu_{\rm k}^{N_{\rm k}} e^{-\mu_{\rm k}}}{N_{\rm k}!} \times \prod_{\rm i=1}^{N_{\rm k}} \frac{1}{\mu_{\rm k}}\left(\frac{\mu_{\rm b,\,k}}{\Delta E} + \mu_{\rm s,\,k} \times \frac{dP(E_{\rm i} | Q_{\beta\beta} +\Delta_{\rm k}, \omega_{\rm k})}{dE}\right) \right] +\end{aligned}\]

Here, the first product runs over the number of partitions k ($N_{\rm p}$ partitions in total) and the second over the events i in a given partition ($N_{\rm k}$ events in total). In particular, $E_{\rm i}$ are the energies of the events falling in the analysis window for a partition k with energy bias $\Delta_{\rm k}$ and energy width $\omega_{\rm k}$.

The background and signal contributions are defined as

\[\begin{aligned} +\mu_{\rm b,\,k} = \mathcal{B}_{\rm k} \cdot \Delta E \cdot \mathcal{E}_{\rm k} +\end{aligned}\]

and

\[\begin{aligned} +\mu_{\rm s,\,k} = \frac{\text{ln}\,2\mathcal{N}_{\rm A}}{m_{\rm 76}} \cdot (\varepsilon_{\rm k} + \alpha \cdot \sigma_{\varepsilon_{\rm k}}) \cdot \mathcal{E}_{\rm k} \cdot \mathcal{S} +\end{aligned}\]

The total contribution can thus be defined as

\[\begin{aligned} +\mu_{\rm b,\,k} = \mu_{\rm b,\,k} + \mu_{\rm s,\,k} +\end{aligned}\]

The prior distributions were taken as Gaussian distributions centred around the true value

\[\begin{aligned} +\pi(\Delta_{\rm k},\, \omega_{\rm k},\, \alpha) = \frac{1}{\sqrt{2\pi}\sigma_{\Delta_{\rm k}}} \,e^{-\frac{\left(\Delta_{\rm k} - \widehat{\Delta}_{\rm k} \right)^2}{2 \sigma_{\Delta_{\rm k}} ^2}} \times \frac{1}{\sqrt{2\pi}\sigma_{\omega_{\rm k}}} \,e^{-\frac{\left(\omega_{\rm k} - \widehat{\omega}_{\rm k} \right)^2}{2 \sigma_{\omega_{\rm k}} ^2}} \times e^{-\alpha^2/2} +\end{aligned}\]

The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND),

\[\begin{aligned} +\frac{dP(E | x, \sigma)}{dE} = \frac{1}{\sqrt{2\pi\sigma^2}} \times e^{-\frac{\left(E - x \right)^2}{2 \sigma ^2}} +\end{aligned}\]

Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR),

\[\begin{aligned} +\frac{dP(E | x, \gamma)}{dE} = \frac{1-f}{\sqrt{2\pi(\gamma \sigma)^2}} \times e^{-\frac{\left(E - x \right)^2}{2 (\gamma \sigma) ^2}}+\frac{f}{2\gamma\tau}\times e^{ \frac{(\gamma \sigma)^2}{2(\gamma\tau)^2} + \frac{E-x}{\gamma\tau} } \times erfc \left(\frac{\sigma}{\sqrt{2}\tau}+ \frac{E-x}{\sqrt{2}\gamma\sigma} \right) +\end{aligned}\]

In particular, for a given partition k, $\mathcal{B}_{\rm k}$ is the background index, $\mathcal{E}_{\rm k}$ is the exposure, $\Delta E$ is the fit window, $\varepsilon_{\rm k}$ is the efficiency with uncertainty $\sigma_{\varepsilon_{\rm k}}$ and $\mathcal{S}=\Gamma_{\rm 1/2}=1/T_{\rm 1/2}$ is the signal.

Table of contents

diff --git a/inputs/index.html b/inputs/index.html index b7b66ea..530dbb2 100644 --- a/inputs/index.html +++ b/inputs/index.html @@ -35,4 +35,4 @@ "energy": 2069.420, "timestamp": 1755109448, "detector": "DET_0" - },

The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.

It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.

Warning

If multiple files are provided fit_group must still be unique.

+ },

The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.

It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.

Warning

If multiple files are provided fit_group must still be unique.

diff --git a/installation/index.html b/installation/index.html index 7d4e9d7..f132ad5 100644 --- a/installation/index.html +++ b/installation/index.html @@ -1,4 +1,4 @@ First steps · ZeroNuFit.jl

First steps

How to run the code

Run the following command by specifying the path to the configuration file used for settings:

$ julia main.jl -c config/config.json

Julia Project enviroments

To run the code in a virtual enviroment you can use the following. Start by entering the Julia command view by typing julia on your terminal. Once inside, enter the packagge manager (via ]), activate the environment in the current directory, and resolve (and install, if necessary) dependencies:

pkg> ] 
 pkg> activate .
-pkg> instantiate

Now you can run the script inside this enviroment with:

$ julia main.jl --project=. -c config/config.json
Note

The tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.

+pkg> instantiate

Now you can run the script inside this enviroment with:

$ julia main.jl --project=. -c config/config.json
Note

The tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.

diff --git a/internal_api/index.html b/internal_api/index.html new file mode 100644 index 0000000..b60e46b --- /dev/null +++ b/internal_api/index.html @@ -0,0 +1,2 @@ + +VegaGraphs.jl · ZeroNuFit.jl
diff --git a/search_index.js b/search_index.js index 147b1d6..50d8f00 100644 --- a/search_index.js +++ b/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"installation/#First-steps","page":"First steps","title":"First steps","text":"","category":"section"},{"location":"installation/#How-to-run-the-code","page":"First steps","title":"How to run the code","text":"","category":"section"},{"location":"installation/","page":"First steps","title":"First steps","text":"Run the following command by specifying the path to the configuration file used for settings:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"$ julia main.jl -c config/config.json","category":"page"},{"location":"installation/#Julia-Project-enviroments","page":"First steps","title":"Julia Project enviroments","text":"","category":"section"},{"location":"installation/","page":"First steps","title":"First steps","text":"To run the code in a virtual enviroment you can use the following. Start by entering the Julia command view by typing julia on your terminal. Once inside, enter the packagge manager (via ]), activate the environment in the current directory, and resolve (and install, if necessary) dependencies:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"pkg> ] \npkg> activate .\npkg> instantiate","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"Now you can run the script inside this enviroment with:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"$ julia main.jl --project=. -c config/config.json","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"note: Note\nThe tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The fit takes in inputs two files in JSON format (for a full customization of the fit), which paths have to be specified in the config.json file.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Pages = [\"inputs.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/#Partitions-file","page":"-","title":"Partitions file","text":"","category":"section"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The partitions file gives information on the independent spectra to be used in the fit/likelihood, this is set by the \"partitions\" key in the config file. This provides all the information neccessary to define the fit model.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The file consists of a file of independent spectra to include in the fit (for example channels or partitions). A partition is defined uniquely by a range of time-stamps, a detector name and an experiment name. ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"note: Note\nIn principle the 'detector' does not need to be a single detector (e.g. C000RG1) but can be a label for any groups of detectors (e.g. COAX_dets). This allows to make fits where all detectors are fit together.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The partitions are grouped into fit_groups: these are sets of partitions which are treated with the same background/signal fit model and range. In the partitions file, the user must provide the information on the fit groups and partitions (organized by fit group). ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"This JSON file has a nested structure with two subdictionaries, the first with key \"fit_groups\", describing the groupings in the fit, and the second \"partitions\" giving a list of partitions for each fit group. An example is shown below.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"{\n\"fit_groups\":{\n \"group_one\":{\n \"range\":[[1930,2099],[2109,2114],[2124,2190]],\n \"model\":\"uniform\",\n \"bkg_name\":\"low_bkg\"\n \"signal_name\":\"gaussian_plus_lowEtail\"\n }\n\n},\n\"partitions\": {\n \"group_one\":[\n\n { \n \"experiment\": \"LEGEND\",\n \"detector\": \"DET_0\",\n \"start_ts\": 1704950367,\n \"end_ts\": 1708271505,\n \"eff_tot\": 0.6,\n \"eff_tot_sigma\": 0.1,\n \"width\": 3,\n \"width_sigma\": 1,\n \"exposure\": 1,\n \"bias\": 0.2,\n \"bias_sigma\": 0.1\n }, ...\n ],\n \"group_two\":...\n },\n\n\n}\n ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"They key bkg_name is used to set the name of the background parameter for this group. Note that several groups can be fitted with the same background parameter, this enables quick modification of the fit.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The key \"model\":\"uniform\" is used to set the background model to uniform as default. For different background model shapes, additional information are necessary and these can be specified in the config.json (see the \"Configuration file\" documentation).","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nThe background shape is set to global for all partitions, differently from the signal shape (see below) that can be specified differently for each fit group.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Notice it is possible to specify the signal shape for each fit group. The available options at the moment are \"signal_name\":\"gaussian_plus_lowEtail\" or \"signal_name\":\"gaussian\" (default). If the key is omitted, the default Gaussian signal shape will be adopted. Notice that if you want to use the \"signal_name\":\"gaussian_plus_lowEtail\" option (eg for MAJORANA DEMONSTRATOR data), you need to provide additional input signal shape parameters (frac, sigma, tau). ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"note: Note\nMAJORANA DEMONSTRATOR (MJD) input data are taken from \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\". Here, you can find the input data under the supplemental materials: supp_analysis_parameters.txt and supp_event_list.txt.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nNotice that the width parameter assumes different meanings depending on the chosen signal shape:if \"signal_name\":\"gaussian_plus_lowEtail\", width is the fractional uncertainty on the FWHM of the peak at 2039 keV (it rescales the energy resolution of the peak)\nif \"signal_name\":\"gaussian\", width is the energy resolution expressed in standard deviations (NOT in FWHM)","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/#Events-file","page":"-","title":"Events file","text":"","category":"section"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"In addition, it is neccessary to provide an 'event' file describing the events observed in the data, the path to this file is specified by the 'events' key in the config. Again this is a JSON file consisting of a list of observed events of the form.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":" { \"experiment\":\"LEGEND\",\n \"energy\": 2069.420,\n \"timestamp\": 1755109448,\n \"detector\": \"DET_0\"\n },","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nIf multiple files are provided fit_group must still be unique.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The fit takes in inputs two files in JSON format (for a full customization of the fit), which paths have to be specified in the config.json file.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Table of contents:","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Pages = [\"inputs.md\"]\nDepth = 3","category":"page"},{"location":"inputs/#Partitions-file","page":"Partitions and events","title":"Partitions file","text":"","category":"section"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The partitions file gives information on the independent spectra to be used in the fit/likelihood, this is set by the \"partitions\" key in the config file. This provides all the information neccessary to define the fit model.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The file consists of a file of independent spectra to include in the fit (for example channels or partitions). A partition is defined uniquely by a range of time-stamps, a detector name and an experiment name. ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"note: Note\nIn principle the 'detector' does not need to be a single detector (e.g. C000RG1) but can be a label for any groups of detectors (e.g. COAX_dets). This allows to make fits where all detectors are fit together.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The partitions are grouped into fit_groups: these are sets of partitions which are treated with the same background/signal fit model and range. In the partitions file, the user must provide the information on the fit groups and partitions (organized by fit group). ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"This JSON file has a nested structure with two subdictionaries, the first with key \"fit_groups\", describing the groupings in the fit, and the second \"partitions\" giving a list of partitions for each fit group. An example is shown below.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"{\n\"fit_groups\":{\n \"group_one\":{\n \"range\":[[1930,2099],[2109,2114],[2124,2190]],\n \"model\":\"uniform\",\n \"bkg_name\":\"low_bkg\"\n \"signal_name\":\"gaussian_plus_lowEtail\"\n }\n\n},\n\"partitions\": {\n \"group_one\":[\n\n { \n \"experiment\": \"LEGEND\",\n \"detector\": \"DET_0\",\n \"start_ts\": 1704950367,\n \"end_ts\": 1708271505,\n \"eff_tot\": 0.6,\n \"eff_tot_sigma\": 0.1,\n \"width\": 3,\n \"width_sigma\": 1,\n \"exposure\": 1,\n \"bias\": 0.2,\n \"bias_sigma\": 0.1\n }, ...\n ],\n \"group_two\":...\n },\n\n\n}\n ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"They key bkg_name is used to set the name of the background parameter for this group. Note that several groups can be fitted with the same background parameter, this enables quick modification of the fit.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The key \"model\":\"uniform\" is used to set the background model to uniform as default. For different background model shapes, additional information are necessary and these can be specified in the config.json (see the \"Configuration file\" documentation).","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nThe background shape is set to global for all partitions, differently from the signal shape (see below) that can be specified differently for each fit group.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Notice it is possible to specify the signal shape for each fit group. The available options at the moment are \"signal_name\":\"gaussian_plus_lowEtail\" or \"signal_name\":\"gaussian\" (default). If the key is omitted, the default Gaussian signal shape will be adopted. Notice that if you want to use the \"signal_name\":\"gaussian_plus_lowEtail\" option (eg for MAJORANA DEMONSTRATOR data), you need to provide additional input signal shape parameters (frac, sigma, tau). ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"note: Note\nMAJORANA DEMONSTRATOR (MJD) input data are taken from \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\". Here, you can find the input data under the supplemental materials: supp_analysis_parameters.txt and supp_event_list.txt.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nNotice that the width parameter assumes different meanings depending on the chosen signal shape:if \"signal_name\":\"gaussian_plus_lowEtail\", width is the fractional uncertainty on the FWHM of the peak at 2039 keV (it rescales the energy resolution of the peak)\nif \"signal_name\":\"gaussian\", width is the energy resolution expressed in standard deviations (NOT in FWHM)","category":"page"},{"location":"inputs/#Events-file","page":"Partitions and events","title":"Events file","text":"","category":"section"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"In addition, it is neccessary to provide an 'event' file describing the events observed in the data, the path to this file is specified by the 'events' key in the config. Again this is a JSON file consisting of a list of observed events of the form.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":" { \"experiment\":\"LEGEND\",\n \"energy\": 2069.420,\n \"timestamp\": 1755109448,\n \"detector\": \"DET_0\"\n },","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nIf multiple files are provided fit_group must still be unique.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Table of contents:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Pages = [\"config.md\"]\nDepth = 3","category":"page"},{"location":"config/#Building-the-configuration-file","page":"Configuration file","title":"Building the configuration file","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Before running the code, set the input config.json file with following entries:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"{\n \"debug\":false,\n \"partitions\":[\"config/partitions_gerda_new.json\",\"config/partitions_l200.json\",\"config/partitions_mjd_new.json\"],\n \"events\": [\"config/events_gerda.json\",\"config/events_l200.json\",\"config/events_mjd_new_part.json\"],\n \"output_path\": \"output/fit_mjd_l200_gerda_v2/\",\n \"overwrite\":true,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\n \"fit_and_data\": false,\n \"bandfit_and_data\": false,\n \"scheme\":\"red\",\n \"alpha\":0.3\n },\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\":1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\":0.1,\n \"prior\": \"uniform\"\n },\n\n ...\n}","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"where","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"debug\": true if you want to display debug output on terminal;\n\"partitions\": list of partitions JSON inputs; it takes one entry per experiment;\n\"events\": list of events JSON inputs; it takes one entry per experiment;\n\"output_path\": path where to store outputs (logs, plots, mcmc results);\n\"overwrite\": true if you want to overwrite a previous fit with same output_path; if set to false but no fits were previously performed (ie there are no outputs to overwrite), the code will save the output of this fit;\n\"bat_fit\": settings for the BAT fit;\n\"plot\": settings for plotting; \"fit_and_data\": true plots fit line over data (and CI bands if \"bandfit_and_data\": true); \"scheme\":\"red\" and \"alpha\":0.3 are used for customizing output appearances;\n\"bkg_only\": true if we fit assuming no signal (S=0), false otherwise;\n\"signal\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, sqrt, ...);\n\"bkg\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, ...) there are several optional keys with details given below, if these are not provided the fit defaults to a flat background without correlations.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Moreover, the config requires the following block for nuisance parameters, ie energy scale (=energy bias and resolution) and efficiency:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":" {\n ...\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": true,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"In particular, you can set \"correlated\": true if you want to use one variable to correlate the nuisance parameters (eg to speed up the computation times), and \"fixed\": false if you want to include a prior for nuisance parameters (otherwise these parameters they will be fixed to their partition value and not constrained).","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"If a variable is correlated (either energy_scale or efficiency), the code will search for a field in the fit_groups block of the partitions JSON file to use a correlated variable per each fit group. In particular, the field has to be specified as:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"efficiency_group_name\": \"...\"\n\"energy_scale_group_name\": \"...\"","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"note: Note\nIf the key doesn't exist, this defaults to \"all\"","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Parameters are then added to the model called αr_\\$name (for resolution), αe_\\$name for efficiency and αb_\\$name for bias.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"warning: Warning\nThe alpha parameter names default to _all, if you want one different per experiment this must be explicitly specified in the fit groups entry","category":"page"},{"location":"config/#Background-shape-and-correlation","page":"Configuration file","title":"Background shape and correlation","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"There are several options to control the background in more detail. These can be added to the \"bkg\" section of the config: In particular:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"correlated\" adds a hierarchical (correlated) background to the model, this key should have a dictionary giving details on the prior shape and ranges for example:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"correlated\":{\"mode\":\"lognormal\",\"range\":[0,0.1]}","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The three options for the mode are 'lognormal', 'normal' or 'none'. While the range gives the range of the uniform prior on the \\sigma_B parameter.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"shape\" changes the shape of the background from uniform. The user should provide a dictionary giving details on the shape:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"for example:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n },","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The \"pars\" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are \"uniform\", \"linear\" and \"exponential\". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"note: Note\nIf these keys are not provided the model defaults to a uniform uncorrelated background.","category":"page"},{"location":"config/#Signal-shape","page":"Configuration file","title":"Signal shape","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the \"Partitions and events\" documentation.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#ZeroNuFit.jl-Documentation","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Welcome to the documentation for ZeroNuFit.jl.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Introduction","page":"ZeroNuFit.jl Documentation","title":"Introduction","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay (0nubetabeta) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other 0nubetabeta experiment or to any other physical processes that can be modelled in a similar way.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Likelihood-Function","page":"ZeroNuFit.jl Documentation","title":"Likelihood Function","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The implemented unbinned Likelihood function reads as: mathcalL = prod_rm k=1^N_rm p leftfracmu_rm k^N_rm k e^-mu_rm kN_rm k times prod_rm i=1^N_rm k frac1mu_rm kleft(fracmu_rm bkDelta E + mu_rm sk times fracdP(E_rm i Q_betabeta +Delta_rm k omega_rm k)dEright) right.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Here, the first product runs over the number of partitions k (N_rm p partitions in total) and the second over the events i in a given partition (N_rm k events in total). In particular, E_rm i are the energies of the events falling in the analysis window for a partition k with energy bias Delta_rm k and energy width omega_rm k.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The background and signal contributions are defined as mu_rm bk = mathcalB_rm k cdot Delta E cdot mathcalE_rm k and mu_rm sk = fractextln2mathcalN_rm Am_rm 76 cdot (varepsilon_rm k + alpha cdot sigma_varepsilon_rm k) cdot mathcalE_rm k cdot mathcalS. The total contribution can thus be defined as mu_rm bk = mu_rm bk + mu_rm sk.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The prior distributions were taken as Gaussian distributions centred around the true value pi(Delta_rm k omega_rm k alpha) = frac1sqrt2pisigma_Delta_rm k e^-fracleft(Delta_rm k - widehatDelta_rm k right)^22 sigma_Delta_rm k ^2 times frac1sqrt2pisigma_omega_rm k e^-fracleft(omega_rm k - widehatomega_rm k right)^22 sigma_omega_rm k ^2 times e^-alpha^22.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND), fracdP(E x sigma)dE = frac1sqrt2pisigma^2 times e^-fracleft(E - x right)^22 sigma ^2.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR), fracdP(E x gamma)dE = frac1-fsqrt2pi(gamma sigma)^2 times e^-fracleft(E - x right)^22 (gamma sigma) ^2+fracf2gammatautimes e^ frac(gamma sigma)^22(gammatau)^2 + fracE-xgammatau times erfc left(fracsigmasqrt2tau+ fracE-xsqrt2gammasigma right).","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"In particular, for a given partition k, mathcalB_rm k is the background index, mathcalE_rm k is the exposure, Delta E is the fit window, varepsilon_rm k is the efficiency with uncertainty sigma_varepsilon_rm k and mathcalS=Gamma_rm 12=1T_rm 12 is the signal.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Table-of-contents","page":"ZeroNuFit.jl Documentation","title":"Table of contents","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Pages = [\n \"installation.md\",\n \"config.md\",\n \"inputs.md\",\n \"toys.md\"\n]\nDepth = 1","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/#First-steps","page":"First steps","title":"First steps","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/#How-to-run-the-code","page":"First steps","title":"How to run the code","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"Run the following command by specifying the path to the configuration file used for settings:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"$ julia main.jl -c config/config.json","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/#Julia-Project-enviroments","page":"First steps","title":"Julia Project enviroments","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"To run the code in a virtual enviroment you can use the following. Start by entering the Julia command view by typing julia on your terminal. Once inside, enter the packagge manager (via ]), activate the environment in the current directory, and resolve (and install, if necessary) dependencies:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"pkg> ] \npkg> activate .\npkg> instantiate","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"Now you can run the script inside this enviroment with:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"$ julia main.jl --project=. -c config/config.json","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"note: Note\nThe tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Table of contents:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Pages = [\"toys.md\"]\nDepth = 3","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Another module is present for generating toys and running sensitivity studies. This can be run as","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"$ julia sensitivity.jl -c config_fake_data.json -i N","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"where N is an integer number corresponding to the toy index. The command can be run in an external bash script for looping over this index.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"The input config file (config_fake_data.json) has the following entries:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"{\n \"path_to_fit\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"best_fit\": false,\n \"seed\": null\n}\n","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"where","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"\"path_to_fit\" is the path to the already performed fit over real data;\n\"best_fit\": true if we want to fix the paramaters to the best fit;\n\"seed\": null if we want a random seed when generating fake data, otherwise you can fix it to an Int value.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Any information about the signal being included or not in the fit of real data, was saved and retrieved from the output JSON file with results.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Below, we show an example of bash file used for running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n\n# run parallel jobs\n$srun $parallel \"julia sensitivity.jl -c config_fake_data.json -i {1}\" ::: {1..10000} &\n\nwait","category":"page"},{"location":"toys/#Using-already-existing-toys","page":"Generating toys","title":"Using already existing toys","text":"","category":"section"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Another way to run the code is present if, for instance, an user wants to use toy data generated according to one model but fit them with another model. In this case, the path to the folder containing the already existing JSON files with toy data has to be provided together with the toy index:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"julia sensitivity.jl -c config_fake_data.json -i N --path_to_toys path_to_your_toys","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Below, an updated version of a bash file that can be used for retrieving multiple existing toy data and running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\n# set the directory path to toys\npath_to_toys=\"output/fit_9_l200_1BI_new_data_coax_bkg_noS/sensitivity/fake_data\" #\"path/to/your/toys\"\nall_files=(\"$path_to_toys\"/*.json)\nfull_paths=()\nfor file in \"${all_files[@]}\"; do\n if [[ -f \"$file\" ]]; then \n full_paths+=(\"$file\")\n fi\ndone\nif [ ${#full_paths[@]} -eq 0 ]; then\n echo \"The list of existing toy data is empty! Exit here.\"\n exit 1\nelse\n echo \"You are going to run a fit over ${#full_paths[@]} number of already existing toys stored under $path_to_toys\"\nfi\n\n# array to hold toy_idx\ntoy_indices=()\n\n# Loop over available fake JSON toys\nfor path in \"${full_paths[@]}\"; do\n base_name=\"${path%.json}\"\n number_str=\"${base_name##*fake_data}\" \n toy_idx=$((number_str)) \n\n toy_indices+=(\"$toy_idx\") \ndone\necho \"List of toy indices: ${toy_indices[*]}\"\n\n# parallel execution - convert array to a space-separated list\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n$srun $parallel \"julia sensitivity.jl -c config/toy_9_l200_1BI_new_data_same_bkg_noS.json -i {1}\" ::: \"${toy_indices[@]}\"\n\nwait","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Pages = [\"config.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Building-the-configuration-file","page":"-","title":"Building the configuration file","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Before running the code, set the input config.json file with following entries:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"{\n \"debug\":false,\n \"partitions\":[\"config/partitions_gerda_new.json\",\"config/partitions_l200.json\",\"config/partitions_mjd_new.json\"],\n \"events\": [\"config/events_gerda.json\",\"config/events_l200.json\",\"config/events_mjd_new_part.json\"],\n \"output_path\": \"output/fit_mjd_l200_gerda_v2/\",\n \"overwrite\":true,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\n \"fit_and_data\": false,\n \"bandfit_and_data\": false,\n \"scheme\":\"red\",\n \"alpha\":0.3\n },\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\":1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\":0.1,\n \"prior\": \"uniform\"\n },\n\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"where","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"debug\": true if you want to display debug output on terminal;\n\"partitions\": list of partitions JSON inputs; it takes one entry per experiment;\n\"events\": list of events JSON inputs; it takes one entry per experiment;\n\"output_path\": path where to store outputs (logs, plots, mcmc results);\n\"overwrite\": true if you want to overwrite a previous fit with same output_path; if set to false but no fits were previously performed (ie there are no outputs to overwrite), the code will save the output of this fit;\n\"bat_fit\": settings for the BAT fit;\n\"plot\": settings for plotting; \"fit_and_data\": true plots fit line over data (and CI bands if \"bandfit_and_data\": true); \"scheme\":\"red\" and \"alpha\":0.3 are used for customizing output appearances;\n\"bkg_only\": true if we fit assuming no signal (S=0), false otherwise;\n\"signal\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, sqrt, ...);\n\"bkg\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, ...) there are several optional keys with details given below, if these are not provided the fit defaults to a flat background without correlations.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Moreover, the config requires the following block for nuisance parameters, ie energy scale (=energy bias and resolution) and efficiency:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":" {\n ...\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": true,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"In particular, you can set \"correlated\": true if you want to use one variable to correlate the nuisance parameters (eg to speed up the computation times), and \"fixed\": false if you want to include a prior for nuisance parameters (otherwise these parameters they will be fixed to their partition value and not constrained).","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"If a variable is correlated (either energy_scale or efficiency), the code will search for a field in the fit_groups block of the partitions JSON file to use a correlated variable per each fit group. In particular, the field has to be specified as:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"efficiency_group_name\": \"...\"\n\"energy_scale_group_name\": \"...\"","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"note: Note\nIf the key doesn't exist, this defaults to \"all\"","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Parameters are then added to the model called αr_\\$name (for resolution), αe_\\$name for efficiency and αb_\\$name for bias.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"warning: Warning\nThe alpha parameter names default to _all, if you want one different per experiment this must be explicitly specified in the fit groups entry","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Background-shape-and-correlation","page":"-","title":"Background shape and correlation","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"There are several options to control the background in more detail. These can be added to the \"bkg\" section of the config: In particular:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"correlated\" adds a hierarchical (correlated) background to the model, this key should have a dictionary giving details on the prior shape and ranges for example:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"correlated\":{\"mode\":\"lognormal\",\"range\":[0,0.1]}","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The three options for the mode are 'lognormal', 'normal' or 'none'. While the range gives the range of the uniform prior on the \\sigma_B parameter.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"shape\" changes the shape of the background from uniform. The user should provide a dictionary giving details on the shape:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"for example:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n },","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The \"pars\" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are \"uniform\", \"linear\" and \"exponential\". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"note: Note\nIf these keys are not provided the model defaults to a uniform uncorrelated background.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Signal-shape","page":"-","title":"Signal shape","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the \"Partitions and events\" documentation.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Pages = [\"toys.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Another module is present for generating toys and running sensitivity studies. This can be run as","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"$ julia sensitivity.jl -c config_fake_data.json -i N","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"where N is an integer number corresponding to the toy index. The command can be run in an external bash script for looping over this index.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"The input config file (config_fake_data.json) has the following entries:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"{\n \"path_to_fit\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"best_fit\": false,\n \"seed\": null\n}\n","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"where","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"\"path_to_fit\" is the path to the already performed fit over real data;\n\"best_fit\": true if we want to fix the paramaters to the best fit;\n\"seed\": null if we want a random seed when generating fake data, otherwise you can fix it to an Int value.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Any information about the signal being included or not in the fit of real data, was saved and retrieved from the output JSON file with results.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Below, we show an example of bash file used for running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n\n# run parallel jobs\n$srun $parallel \"julia sensitivity.jl -c config_fake_data.json -i {1}\" ::: {1..10000} &\n\nwait","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/#Using-already-existing-toys","page":"-","title":"Using already existing toys","text":"","category":"section"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Another way to run the code is present if, for instance, an user wants to use toy data generated according to one model but fit them with another model. In this case, the path to the folder containing the already existing JSON files with toy data has to be provided together with the toy index:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"julia sensitivity.jl -c config_fake_data.json -i N --path_to_toys path_to_your_toys","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Below, an updated version of a bash file that can be used for retrieving multiple existing toy data and running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\n# set the directory path to toys\npath_to_toys=\"output/fit_9_l200_1BI_new_data_coax_bkg_noS/sensitivity/fake_data\" #\"path/to/your/toys\"\nall_files=(\"$path_to_toys\"/*.json)\nfull_paths=()\nfor file in \"${all_files[@]}\"; do\n if [[ -f \"$file\" ]]; then \n full_paths+=(\"$file\")\n fi\ndone\nif [ ${#full_paths[@]} -eq 0 ]; then\n echo \"The list of existing toy data is empty! Exit here.\"\n exit 1\nelse\n echo \"You are going to run a fit over ${#full_paths[@]} number of already existing toys stored under $path_to_toys\"\nfi\n\n# array to hold toy_idx\ntoy_indices=()\n\n# Loop over available fake JSON toys\nfor path in \"${full_paths[@]}\"; do\n base_name=\"${path%.json}\"\n number_str=\"${base_name##*fake_data}\" \n toy_idx=$((number_str)) \n\n toy_indices+=(\"$toy_idx\") \ndone\necho \"List of toy indices: ${toy_indices[*]}\"\n\n# parallel execution - convert array to a space-separated list\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n$srun $parallel \"julia sensitivity.jl -c config/toy_9_l200_1BI_new_data_same_bkg_noS.json -i {1}\" ::: \"${toy_indices[@]}\"\n\nwait","category":"page"},{"location":"#ZeroNuFit.jl-Documentation","page":"Home","title":"ZeroNuFit.jl Documentation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Welcome to the documentation for ZeroNuFit.jl.","category":"page"},{"location":"#Introduction","page":"Home","title":"Introduction","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay (0nubetabeta) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other 0nubetabeta experiment or to any other physical processes that can be modelled in a similar way.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).","category":"page"},{"location":"#Likelihood-Function","page":"Home","title":"Likelihood Function","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The implemented unbinned Likelihood function reads as: mathcalL = prod_rm k=1^N_rm p leftfracmu_rm k^N_rm k e^-mu_rm kN_rm k times prod_rm i=1^N_rm k frac1mu_rm kleft(fracmu_rm bkDelta E + mu_rm sk times fracdP(E_rm i Q_betabeta +Delta_rm k omega_rm k)dEright) right.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Here, the first product runs over the number of partitions k (N_rm p partitions in total) and the second over the events i in a given partition (N_rm k events in total). In particular, E_rm i are the energies of the events falling in the analysis window for a partition k with energy bias Delta_rm k and energy width omega_rm k.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The background and signal contributions are defined as mu_rm bk = mathcalB_rm k cdot Delta E cdot mathcalE_rm k and mu_rm sk = fractextln2mathcalN_rm Am_rm 76 cdot (varepsilon_rm k + alpha cdot sigma_varepsilon_rm k) cdot mathcalE_rm k cdot mathcalS. The total contribution can thus be defined as mu_rm bk = mu_rm bk + mu_rm sk.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The prior distributions were taken as Gaussian distributions centred around the true value pi(Delta_rm k omega_rm k alpha) = frac1sqrt2pisigma_Delta_rm k e^-fracleft(Delta_rm k - widehatDelta_rm k right)^22 sigma_Delta_rm k ^2 times frac1sqrt2pisigma_omega_rm k e^-fracleft(omega_rm k - widehatomega_rm k right)^22 sigma_omega_rm k ^2 times e^-alpha^22.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND), fracdP(E x sigma)dE = frac1sqrt2pisigma^2 times e^-fracleft(E - x right)^22 sigma ^2.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR), fracdP(E x gamma)dE = frac1-fsqrt2pi(gamma sigma)^2 times e^-fracleft(E - x right)^22 (gamma sigma) ^2+fracf2gammatautimes e^ frac(gamma sigma)^22(gammatau)^2 + fracE-xgammatau times erfc left(fracsigmasqrt2tau+ fracE-xsqrt2gammasigma right).","category":"page"},{"location":"","page":"Home","title":"Home","text":"In particular, for a given partition k, mathcalB_rm k is the background index, mathcalE_rm k is the exposure, Delta E is the fit window, varepsilon_rm k is the efficiency with uncertainty sigma_varepsilon_rm k and mathcalS=Gamma_rm 12=1T_rm 12 is the signal.","category":"page"},{"location":"#Table-of-contents","page":"Home","title":"Table of contents","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Pages = [\n \"installation.md\",\n \"config.md\",\n \"inputs.md\",\n \"toys.md\"\n]\nDepth = 1","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The aim of this tutorial consists in building proper config JSON files in order to run a neutrinoless double-beta decay analysis over GERDA and MAJORANA DEMONSTRATO (MJD) published data. Additional info on the meaning of input parameters can be found under the \"Configuration file\" section, and for input files under the \"Partitions and events\" section.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Table of contents:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Pages = [\"tutorial.md\"]\nDepth = 3","category":"page"},{"location":"tutorial/#GERDA-Phase-I:-SB-fit","page":"Tutorial","title":"GERDA Phase I: S+B fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's start by fitting data acquired by the GERDA experiment during its Phase I and let's fit them with a signal+background model.","category":"page"},{"location":"tutorial/#Input-files","page":"Tutorial","title":"Input files","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"First of all, we have to populate partitions and events JSON input files. These dictionaries can be built manually by each user, but some reference files are already present for GERDA/LEGEND/MJD experiments at a private location (ask Toby Dixon for access to the repository). Some of these files were also copied in the inputs/ folder for already published material. The following files can be used for this tutorial:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"GERDA Phase I Events -> \"inputs/events_gerda_pI.json\"\nGERDA Phase I Partitions -> \"inputs/partitions_gerda_pI.json\"","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Notice that in \"inputs/partitions_gerda_pI.json\" we already specify in which range we want to fit data (here it is set common to all fit groups, i.e. [1930,2099] U [2109,2114] U [2124,2190] keV) and how we want to group different detectors. In particular, 4 fit groups are specified, with names ph1_golden, ph1_silver, phI_bege and phI_extra. For each group, we will have a separate background index (BI): mathcalB_phI-golden, mathcalB_phI-silver, mathcalB_phI-bege, mathcalB_phI-extra. In case you want one BI only for all phase I events, mathcalB_phI-all, then you have to modify the partitions input file to account for that.","category":"page"},{"location":"tutorial/#Fit-configuration","page":"Tutorial","title":"Fit configuration","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's fit GERDA Phase I events with a simple signal+background=S+B model (\"bkg_only\": false) where the signal is modelled with a Gaussian function (default option).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The signal prior is taken as uniform (\"signal\": {\"prior\": \"uniform\", ...}) in 010^-24 yr^-1. Notice that for the signal the values are expressed in terms of 10^-27yr^-1 (that is why \"signal\": {\"upper_bound\": 1000, ...}). The BI prior is taken as uniform (\"bkg\": {\"prior\": \"uniform\", ...}) in 001 counts/keV/kg/yr. Signal and background are always defined as positive, i.e. the lower bound is set to 0 by default.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"We assume the 4 BIs are not correlated (\"bkg\": {\"correlated\": {\"mode\": \"none\", \"range\": \"none\"}}). If they are, change the entry into \"bkg\": {\"correlated\": {\"mode\": x, \"range\": [...,...]}} where x={\"lognormal\", \"normal\"}. These are the only hierarchical models present at the moment. More documentation on this topic can be found in \"A. Gelman, J.B. Carlin, H.S. Stern, D.B. Dunson, A. Vehtari and D.B. Rubin, “Bayesian Data Analysis (3rd ed.)”, Chapman & Hall (2013)\".","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As regards the nuisance parameters, we can leave free the energy biases and energy widths by not fixing them to their best value (\"nuisance\": {\"energy_scale\": {\"fixed\": false, ...}, ...}), but constraining them via a Gaussian prior. An additional option for treating all energy biases or widths together via one common parameter, i.e. alpha_Delta or alpha_omega, can be enabled/disabled. For the moment, we leave this out and we treat nuisance parameters individually (\"nuisance\": {\"energy_scale\": {\"correlated\": false, ...}, ...}).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As regards the efficiencies, we don't fix the values to their best value (\"nuisance\": {\"efficiency\": {\"fixed\": false, ...}, ...}), but we correlated them via a global parameter alpha_varepsilon (\"nuisance\": {\"efficiency\": {\"correlated\": true, ...}, ...}).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"All these fit settings can therefore be grouped in the following config JSON file with name config_gerda_phI.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n \"debug\":false,\n \"events\": [\"inputs/events_gerda_pI.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\"],\n \"output_path\": \"output/fit_gerda_phI/\",\n \"overwrite\": true,\n \"light_output\": false,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\"fit_and_data\": false, \"bandfit_and_data\": false, \"scheme\":\"green\", \"alpha\": 0.3},\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\": 1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\": 0.1, \"prior\": \"uniform\", \"correlated\": {\"mode\": \"none\", \"range\": \"none\"}},\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": false,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phI.json","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-SB-fit","page":"Tutorial","title":"GERDA Phase I and II: S+B fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's add data acquired by the GERDA experiment during its Phase II and let's fit them with a S+B model, leaving previous settings invariate.","category":"page"},{"location":"tutorial/#Input-files-2","page":"Tutorial","title":"Input files","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"In the partitions file, we group detectors from Phase II in one fit group only (i.e. all_phase_II) such that they all share one BI, i.e. mathcalB_phII-all.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"GERDA Phase II events -> \"inputs/events_gerda_pII.json\"\nGERDA Phase II partitions -> \"inputs/partitions_gerda_pII.json\"","category":"page"},{"location":"tutorial/#Fit-configuration-2","page":"Tutorial","title":"Fit configuration","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Combined fits of different phases of one experiment (or, from a more general point of view, combined fits of different experiments) can be achieved by introducing new events and partitions files to the config JSON file. Let's create the following config JSON file with name config_gerda_phIandphII.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII/\",\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"All the rest can be left unchanged and you can now run the GERDA Phase I+II combined fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII.json","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-SB-fit,-non-flat-background","page":"Tutorial","title":"GERDA Phase I and II: S+B fit, non flat background","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The background is assumed flat by default, but how can we include a potential different shape? A linear or exponential background shape were implemented as well, and one of these shapes can be specified under the \"bkg\" key. Let's create the following config JSON file with name config_gerda_phIandphII_linearB.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_linearB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"linear\",\n \"pars\":{\"slope\":[-1,3]}\n }\n },\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"or config_gerda_phIandphII_expoB.json:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_expoB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n }\n },\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_linearB.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"if you want to shape the background with a linear function, or ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_expoB.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"if you want to shape the background with an exponential function.","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-B-only-fit","page":"Tutorial","title":"GERDA Phase I and II: B only fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Sometimes it is required to fit under the mathcalS=0 (no signal) assumption. This might be helpful when performing sensitivity studies in the context of 0nubetabeta decay analyses. This can be achieved by setting \"bkg_only\": true in our config JSON file that we now call config_gerda_phIandphII_NoSignal.json:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"bkg_only\": true,\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_NoSignal.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Additional details on the type of available sensitivity studies (e.g. how to generate fake spectra and fit them) can be found in the \"Generating toys\" section.","category":"page"},{"location":"tutorial/#GERDA-MJD:-different-S-shapes","page":"Tutorial","title":"GERDA + MJD: different S shapes","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As explained in \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\", MJD used a modified Gaussian signal peak shape. The code can take care of this difference once you specify the type of signal shape one wants to use in the partitions file. Use \"signal_name\": \"gaussian_plus_lowEtail\" for MJD, and \"signal_name\": \"gaussian\" (or don't enter any key - this is the default option) for GERDA partitions. Below we report an example of how the MJD partitions JSON file should look like for changing the Gaussian signal function into a modified one. Notice that for MJD we can also specify a different fit range (that now includes an additional window in 2209.1-2350.0 keV) compared to the one used by GERDA.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":" {\n \"fit_groups\": {\n \"mjd-DS0\": {\n \"range\": [[1950.0, 2098.511], [2108.511, 2113.513], [2123.513, 2199.1], [2209.1, 2350.0]],\n \"model\": \"uniform\",\n \"bkg_name\": \"B_mjd-DS0\",\n \"signal_name\": \"gaussian_plus_lowEtail\"\n }\n },\n \"partitions\": {\n \"mjd-DS0\": [...]\n }\n }","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The aim of this tutorial consists in building proper config JSON files in order to run a neutrinoless double-beta decay analysis over GERDA and MAJORANA DEMONSTRATO (MJD) published data. Additional info on the meaning of input parameters can be found under the \"Configuration file\" section, and for input files under the \"Partitions and events\" section.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Pages = [\"tutorial.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I:-SB-fit","page":"-","title":"GERDA Phase I: S+B fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's start by fitting data acquired by the GERDA experiment during its Phase I and let's fit them with a signal+background model.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Input-files","page":"-","title":"Input files","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"First of all, we have to populate partitions and events JSON input files. These dictionaries can be built manually by each user, but some reference files are already present for GERDA/LEGEND/MJD experiments at a private location (ask Toby Dixon for access to the repository). Some of these files were also copied in the inputs/ folder for already published material. The following files can be used for this tutorial:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"GERDA Phase I Events -> \"inputs/events_gerda_pI.json\"\nGERDA Phase I Partitions -> \"inputs/partitions_gerda_pI.json\"","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Notice that in \"inputs/partitions_gerda_pI.json\" we already specify in which range we want to fit data (here it is set common to all fit groups, i.e. [1930,2099] U [2109,2114] U [2124,2190] keV) and how we want to group different detectors. In particular, 4 fit groups are specified, with names ph1_golden, ph1_silver, phI_bege and phI_extra. For each group, we will have a separate background index (BI): mathcalB_phI-golden, mathcalB_phI-silver, mathcalB_phI-bege, mathcalB_phI-extra. In case you want one BI only for all phase I events, mathcalB_phI-all, then you have to modify the partitions input file to account for that.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Fit-configuration","page":"-","title":"Fit configuration","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's fit GERDA Phase I events with a simple signal+background=S+B model (\"bkg_only\": false) where the signal is modelled with a Gaussian function (default option).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The signal prior is taken as uniform (\"signal\": {\"prior\": \"uniform\", ...}) in 010^-24 yr^-1. Notice that for the signal the values are expressed in terms of 10^-27yr^-1 (that is why \"signal\": {\"upper_bound\": 1000, ...}). The BI prior is taken as uniform (\"bkg\": {\"prior\": \"uniform\", ...}) in 001 counts/keV/kg/yr. Signal and background are always defined as positive, i.e. the lower bound is set to 0 by default.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"We assume the 4 BIs are not correlated (\"bkg\": {\"correlated\": {\"mode\": \"none\", \"range\": \"none\"}}). If they are, change the entry into \"bkg\": {\"correlated\": {\"mode\": x, \"range\": [...,...]}} where x={\"lognormal\", \"normal\"}. These are the only hierarchical models present at the moment. More documentation on this topic can be found in \"A. Gelman, J.B. Carlin, H.S. Stern, D.B. Dunson, A. Vehtari and D.B. Rubin, “Bayesian Data Analysis (3rd ed.)”, Chapman & Hall (2013)\".","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As regards the nuisance parameters, we can leave free the energy biases and energy widths by not fixing them to their best value (\"nuisance\": {\"energy_scale\": {\"fixed\": false, ...}, ...}), but constraining them via a Gaussian prior. An additional option for treating all energy biases or widths together via one common parameter, i.e. alpha_Delta or alpha_omega, can be enabled/disabled. For the moment, we leave this out and we treat nuisance parameters individually (\"nuisance\": {\"energy_scale\": {\"correlated\": false, ...}, ...}).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As regards the efficiencies, we don't fix the values to their best value (\"nuisance\": {\"efficiency\": {\"fixed\": false, ...}, ...}), but we correlated them via a global parameter alpha_varepsilon (\"nuisance\": {\"efficiency\": {\"correlated\": true, ...}, ...}).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"All these fit settings can therefore be grouped in the following config JSON file with name config_gerda_phI.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n \"debug\":false,\n \"events\": [\"inputs/events_gerda_pI.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\"],\n \"output_path\": \"output/fit_gerda_phI/\",\n \"overwrite\": true,\n \"light_output\": false,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\"fit_and_data\": false, \"bandfit_and_data\": false, \"scheme\":\"green\", \"alpha\": 0.3},\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\": 1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\": 0.1, \"prior\": \"uniform\", \"correlated\": {\"mode\": \"none\", \"range\": \"none\"}},\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": false,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phI.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-SB-fit","page":"-","title":"GERDA Phase I and II: S+B fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's add data acquired by the GERDA experiment during its Phase II and let's fit them with a S+B model, leaving previous settings invariate.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Input-files-2","page":"-","title":"Input files","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"In the partitions file, we group detectors from Phase II in one fit group only (i.e. all_phase_II) such that they all share one BI, i.e. mathcalB_phII-all.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"GERDA Phase II events -> \"inputs/events_gerda_pII.json\"\nGERDA Phase II partitions -> \"inputs/partitions_gerda_pII.json\"","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Fit-configuration-2","page":"-","title":"Fit configuration","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Combined fits of different phases of one experiment (or, from a more general point of view, combined fits of different experiments) can be achieved by introducing new events and partitions files to the config JSON file. Let's create the following config JSON file with name config_gerda_phIandphII.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII/\",\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"All the rest can be left unchanged and you can now run the GERDA Phase I+II combined fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-SB-fit,-non-flat-background","page":"-","title":"GERDA Phase I and II: S+B fit, non flat background","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The background is assumed flat by default, but how can we include a potential different shape? A linear or exponential background shape were implemented as well, and one of these shapes can be specified under the \"bkg\" key. Let's create the following config JSON file with name config_gerda_phIandphII_linearB.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_linearB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"linear\",\n \"pars\":{\"slope\":[-1,3]}\n }\n },\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"or config_gerda_phIandphII_expoB.json:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_expoB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n }\n },\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_linearB.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"if you want to shape the background with a linear function, or ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_expoB.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"if you want to shape the background with an exponential function.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-B-only-fit","page":"-","title":"GERDA Phase I and II: B only fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Sometimes it is required to fit under the mathcalS=0 (no signal) assumption. This might be helpful when performing sensitivity studies in the context of 0nubetabeta decay analyses. This can be achieved by setting \"bkg_only\": true in our config JSON file that we now call config_gerda_phIandphII_NoSignal.json:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"bkg_only\": true,\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_NoSignal.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Additional details on the type of available sensitivity studies (e.g. how to generate fake spectra and fit them) can be found in the \"Generating toys\" section.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-MJD:-different-S-shapes","page":"-","title":"GERDA + MJD: different S shapes","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As explained in \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\", MJD used a modified Gaussian signal peak shape. The code can take care of this difference once you specify the type of signal shape one wants to use in the partitions file. Use \"signal_name\": \"gaussian_plus_lowEtail\" for MJD, and \"signal_name\": \"gaussian\" (or don't enter any key - this is the default option) for GERDA partitions. Below we report an example of how the MJD partitions JSON file should look like for changing the Gaussian signal function into a modified one. Notice that for MJD we can also specify a different fit range (that now includes an additional window in 2209.1-2350.0 keV) compared to the one used by GERDA.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":" {\n \"fit_groups\": {\n \"mjd-DS0\": {\n \"range\": [[1950.0, 2098.511], [2108.511, 2113.513], [2123.513, 2199.1], [2209.1, 2350.0]],\n \"model\": \"uniform\",\n \"bkg_name\": \"B_mjd-DS0\",\n \"signal_name\": \"gaussian_plus_lowEtail\"\n }\n },\n \"partitions\": {\n \"mjd-DS0\": [...]\n }\n }","category":"page"}] +[{"location":"installation/#First-steps","page":"First steps","title":"First steps","text":"","category":"section"},{"location":"installation/#How-to-run-the-code","page":"First steps","title":"How to run the code","text":"","category":"section"},{"location":"installation/","page":"First steps","title":"First steps","text":"Run the following command by specifying the path to the configuration file used for settings:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"$ julia main.jl -c config/config.json","category":"page"},{"location":"installation/#Julia-Project-enviroments","page":"First steps","title":"Julia Project enviroments","text":"","category":"section"},{"location":"installation/","page":"First steps","title":"First steps","text":"To run the code in a virtual enviroment you can use the following. Start by entering the Julia command view by typing julia on your terminal. Once inside, enter the packagge manager (via ]), activate the environment in the current directory, and resolve (and install, if necessary) dependencies:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"pkg> ] \npkg> activate .\npkg> instantiate","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"Now you can run the script inside this enviroment with:","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"$ julia main.jl --project=. -c config/config.json","category":"page"},{"location":"installation/","page":"First steps","title":"First steps","text":"note: Note\nThe tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The fit takes in inputs two files in JSON format (for a full customization of the fit), which paths have to be specified in the config.json file.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Pages = [\"inputs.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/#Partitions-file","page":"-","title":"Partitions file","text":"","category":"section"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The partitions file gives information on the independent spectra to be used in the fit/likelihood, this is set by the \"partitions\" key in the config file. This provides all the information neccessary to define the fit model.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The file consists of a file of independent spectra to include in the fit (for example channels or partitions). A partition is defined uniquely by a range of time-stamps, a detector name and an experiment name. ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"note: Note\nIn principle the 'detector' does not need to be a single detector (e.g. C000RG1) but can be a label for any groups of detectors (e.g. COAX_dets). This allows to make fits where all detectors are fit together.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The partitions are grouped into fit_groups: these are sets of partitions which are treated with the same background/signal fit model and range. In the partitions file, the user must provide the information on the fit groups and partitions (organized by fit group). ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"This JSON file has a nested structure with two subdictionaries, the first with key \"fit_groups\", describing the groupings in the fit, and the second \"partitions\" giving a list of partitions for each fit group. An example is shown below.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"{\n\"fit_groups\":{\n \"group_one\":{\n \"range\":[[1930,2099],[2109,2114],[2124,2190]],\n \"model\":\"uniform\",\n \"bkg_name\":\"low_bkg\"\n \"signal_name\":\"gaussian_plus_lowEtail\"\n }\n\n},\n\"partitions\": {\n \"group_one\":[\n\n { \n \"experiment\": \"LEGEND\",\n \"detector\": \"DET_0\",\n \"start_ts\": 1704950367,\n \"end_ts\": 1708271505,\n \"eff_tot\": 0.6,\n \"eff_tot_sigma\": 0.1,\n \"width\": 3,\n \"width_sigma\": 1,\n \"exposure\": 1,\n \"bias\": 0.2,\n \"bias_sigma\": 0.1\n }, ...\n ],\n \"group_two\":...\n },\n\n\n}\n ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"They key bkg_name is used to set the name of the background parameter for this group. Note that several groups can be fitted with the same background parameter, this enables quick modification of the fit.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The key \"model\":\"uniform\" is used to set the background model to uniform as default. For different background model shapes, additional information are necessary and these can be specified in the config.json (see the \"Configuration file\" documentation).","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nThe background shape is set to global for all partitions, differently from the signal shape (see below) that can be specified differently for each fit group.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"Notice it is possible to specify the signal shape for each fit group. The available options at the moment are \"signal_name\":\"gaussian_plus_lowEtail\" or \"signal_name\":\"gaussian\" (default). If the key is omitted, the default Gaussian signal shape will be adopted. Notice that if you want to use the \"signal_name\":\"gaussian_plus_lowEtail\" option (eg for MAJORANA DEMONSTRATOR data), you need to provide additional input signal shape parameters (frac, sigma, tau). ","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"note: Note\nMAJORANA DEMONSTRATOR (MJD) input data are taken from \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\". Here, you can find the input data under the supplemental materials: supp_analysis_parameters.txt and supp_event_list.txt.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nNotice that the width parameter assumes different meanings depending on the chosen signal shape:if \"signal_name\":\"gaussian_plus_lowEtail\", width is the fractional uncertainty on the FWHM of the peak at 2039 keV (it rescales the energy resolution of the peak)\nif \"signal_name\":\"gaussian\", width is the energy resolution expressed in standard deviations (NOT in FWHM)","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/#Events-file","page":"-","title":"Events file","text":"","category":"section"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"In addition, it is neccessary to provide an 'event' file describing the events observed in the data, the path to this file is specified by the 'events' key in the config. Again this is a JSON file consisting of a list of observed events of the form.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":" { \"experiment\":\"LEGEND\",\n \"energy\": 2069.420,\n \"timestamp\": 1755109448,\n \"detector\": \"DET_0\"\n },","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.","category":"page"},{"location":".ipynb_checkpoints/inputs-checkpoint/","page":"-","title":"-","text":"warning: Warning\nIf multiple files are provided fit_group must still be unique.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The fit takes in inputs two files in JSON format (for a full customization of the fit), which paths have to be specified in the config.json file.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Table of contents:","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Pages = [\"inputs.md\"]\nDepth = 3","category":"page"},{"location":"inputs/#Partitions-file","page":"Partitions and events","title":"Partitions file","text":"","category":"section"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The partitions file gives information on the independent spectra to be used in the fit/likelihood, this is set by the \"partitions\" key in the config file. This provides all the information neccessary to define the fit model.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The file consists of a file of independent spectra to include in the fit (for example channels or partitions). A partition is defined uniquely by a range of time-stamps, a detector name and an experiment name. ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"note: Note\nIn principle the 'detector' does not need to be a single detector (e.g. C000RG1) but can be a label for any groups of detectors (e.g. COAX_dets). This allows to make fits where all detectors are fit together.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The partitions are grouped into fit_groups: these are sets of partitions which are treated with the same background/signal fit model and range. In the partitions file, the user must provide the information on the fit groups and partitions (organized by fit group). ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"This JSON file has a nested structure with two subdictionaries, the first with key \"fit_groups\", describing the groupings in the fit, and the second \"partitions\" giving a list of partitions for each fit group. An example is shown below.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"{\n\"fit_groups\":{\n \"group_one\":{\n \"range\":[[1930,2099],[2109,2114],[2124,2190]],\n \"model\":\"uniform\",\n \"bkg_name\":\"low_bkg\"\n \"signal_name\":\"gaussian_plus_lowEtail\"\n }\n\n},\n\"partitions\": {\n \"group_one\":[\n\n { \n \"experiment\": \"LEGEND\",\n \"detector\": \"DET_0\",\n \"start_ts\": 1704950367,\n \"end_ts\": 1708271505,\n \"eff_tot\": 0.6,\n \"eff_tot_sigma\": 0.1,\n \"width\": 3,\n \"width_sigma\": 1,\n \"exposure\": 1,\n \"bias\": 0.2,\n \"bias_sigma\": 0.1\n }, ...\n ],\n \"group_two\":...\n },\n\n\n}\n ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"They key bkg_name is used to set the name of the background parameter for this group. Note that several groups can be fitted with the same background parameter, this enables quick modification of the fit.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The key \"model\":\"uniform\" is used to set the background model to uniform as default. For different background model shapes, additional information are necessary and these can be specified in the config.json (see the \"Configuration file\" documentation).","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nThe background shape is set to global for all partitions, differently from the signal shape (see below) that can be specified differently for each fit group.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"Notice it is possible to specify the signal shape for each fit group. The available options at the moment are \"signal_name\":\"gaussian_plus_lowEtail\" or \"signal_name\":\"gaussian\" (default). If the key is omitted, the default Gaussian signal shape will be adopted. Notice that if you want to use the \"signal_name\":\"gaussian_plus_lowEtail\" option (eg for MAJORANA DEMONSTRATOR data), you need to provide additional input signal shape parameters (frac, sigma, tau). ","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"note: Note\nMAJORANA DEMONSTRATOR (MJD) input data are taken from \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\". Here, you can find the input data under the supplemental materials: supp_analysis_parameters.txt and supp_event_list.txt.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nNotice that the width parameter assumes different meanings depending on the chosen signal shape:if \"signal_name\":\"gaussian_plus_lowEtail\", width is the fractional uncertainty on the FWHM of the peak at 2039 keV (it rescales the energy resolution of the peak)\nif \"signal_name\":\"gaussian\", width is the energy resolution expressed in standard deviations (NOT in FWHM)","category":"page"},{"location":"inputs/#Events-file","page":"Partitions and events","title":"Events file","text":"","category":"section"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"In addition, it is neccessary to provide an 'event' file describing the events observed in the data, the path to this file is specified by the 'events' key in the config. Again this is a JSON file consisting of a list of observed events of the form.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":" { \"experiment\":\"LEGEND\",\n \"energy\": 2069.420,\n \"timestamp\": 1755109448,\n \"detector\": \"DET_0\"\n },","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"The timestamp and detector are used to extract which partition this event corresponds to. To convert to this format from the standard GERDA and LEGEND files, there are tools available in https://github.com/tdixon97/legend-0vbb-config.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"It is possible to supply a list of partition and event files in this case the list of fit groups and events are concatenated.","category":"page"},{"location":"inputs/","page":"Partitions and events","title":"Partitions and events","text":"warning: Warning\nIf multiple files are provided fit_group must still be unique.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Table of contents:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Pages = [\"config.md\"]\nDepth = 3","category":"page"},{"location":"config/#Building-the-configuration-file","page":"Configuration file","title":"Building the configuration file","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Before running the code, set the input config.json file with following entries:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"{\n \"debug\":false,\n \"partitions\":[\"config/partitions_gerda_new.json\",\"config/partitions_l200.json\",\"config/partitions_mjd_new.json\"],\n \"events\": [\"config/events_gerda.json\",\"config/events_l200.json\",\"config/events_mjd_new_part.json\"],\n \"output_path\": \"output/fit_mjd_l200_gerda_v2/\",\n \"overwrite\":true,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\n \"fit_and_data\": false,\n \"bandfit_and_data\": false,\n \"scheme\":\"red\",\n \"alpha\":0.3\n },\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\":1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\":0.1,\n \"prior\": \"uniform\"\n },\n\n ...\n}","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"where","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"debug\": true if you want to display debug output on terminal;\n\"partitions\": list of partitions JSON inputs; it takes one entry per experiment;\n\"events\": list of events JSON inputs; it takes one entry per experiment;\n\"output_path\": path where to store outputs (logs, plots, mcmc results);\n\"overwrite\": true if you want to overwrite a previous fit with same output_path; if set to false but no fits were previously performed (ie there are no outputs to overwrite), the code will save the output of this fit;\n\"bat_fit\": settings for the BAT fit;\n\"plot\": settings for plotting; \"fit_and_data\": true plots fit line over data (and CI bands if \"bandfit_and_data\": true); \"scheme\":\"red\" and \"alpha\":0.3 are used for customizing output appearances;\n\"bkg_only\": true if we fit assuming no signal (S=0), false otherwise;\n\"signal\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, sqrt, ...);\n\"bkg\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, ...) there are several optional keys with details given below, if these are not provided the fit defaults to a flat background without correlations.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Moreover, the config requires the following block for nuisance parameters, ie energy scale (=energy bias and resolution) and efficiency:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":" {\n ...\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": true,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"In particular, you can set \"correlated\": true if you want to use one variable to correlate the nuisance parameters (eg to speed up the computation times), and \"fixed\": false if you want to include a prior for nuisance parameters (otherwise these parameters they will be fixed to their partition value and not constrained).","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"If a variable is correlated (either energy_scale or efficiency), the code will search for a field in the fit_groups block of the partitions JSON file to use a correlated variable per each fit group. In particular, the field has to be specified as:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"efficiency_group_name\": \"...\"\n\"energy_scale_group_name\": \"...\"","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"note: Note\nIf the key doesn't exist, this defaults to \"all\"","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"Parameters are then added to the model called αr_\\$name (for resolution), αe_\\$name for efficiency and αb_\\$name for bias.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"warning: Warning\nThe alpha parameter names default to _all, if you want one different per experiment this must be explicitly specified in the fit groups entry","category":"page"},{"location":"config/#Background-shape-and-correlation","page":"Configuration file","title":"Background shape and correlation","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"There are several options to control the background in more detail. These can be added to the \"bkg\" section of the config: In particular:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"correlated\" adds a hierarchical (correlated) background to the model, this key should have a dictionary giving details on the prior shape and ranges for example:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"correlated\":{\"mode\":\"lognormal\",\"range\":[0,0.1]}","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The three options for the mode are 'lognormal', 'normal' or 'none'. While the range gives the range of the uniform prior on the \\sigma_B parameter.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"shape\" changes the shape of the background from uniform. The user should provide a dictionary giving details on the shape:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"for example:","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"\"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n },","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The \"pars\" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are \"uniform\", \"linear\" and \"exponential\". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"note: Note\nIf these keys are not provided the model defaults to a uniform uncorrelated background.","category":"page"},{"location":"config/#Signal-shape","page":"Configuration file","title":"Signal shape","text":"","category":"section"},{"location":"config/","page":"Configuration file","title":"Configuration file","text":"The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the \"Partitions and events\" documentation.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#ZeroNuFit.jl-Documentation","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Welcome to the documentation for ZeroNuFit.jl.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Introduction","page":"ZeroNuFit.jl Documentation","title":"Introduction","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay (0nubetabeta) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other 0nubetabeta experiment or to any other physical processes that can be modelled in a similar way.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Likelihood-Function","page":"ZeroNuFit.jl Documentation","title":"Likelihood Function","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The implemented unbinned Likelihood function reads as: ","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nmathcalL = prod_rm k=1^N_rm p leftfracmu_rm k^N_rm k e^-mu_rm kN_rm k times prod_rm i=1^N_rm k frac1mu_rm kleft(fracmu_rm bkDelta E + mu_rm sk times fracdP(E_rm i Q_betabeta +Delta_rm k omega_rm k)dEright) right\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Here, the first product runs over the number of partitions k (N_rm p partitions in total) and the second over the events i in a given partition (N_rm k events in total). In particular, E_rm i are the energies of the events falling in the analysis window for a partition k with energy bias Delta_rm k and energy width omega_rm k.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The background and signal contributions are defined as ","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nmu_rm bk = mathcalB_rm k cdot Delta E cdot mathcalE_rm k\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"and","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nmu_rm sk = fractextln2mathcalN_rm Am_rm 76 cdot (varepsilon_rm k + alpha cdot sigma_varepsilon_rm k) cdot mathcalE_rm k cdot mathcalS\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The total contribution can thus be defined as","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nmu_rm bk = mu_rm bk + mu_rm sk\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The prior distributions were taken as Gaussian distributions centred around the true value ","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\npi(Delta_rm k omega_rm k alpha) = frac1sqrt2pisigma_Delta_rm k e^-fracleft(Delta_rm k - widehatDelta_rm k right)^22 sigma_Delta_rm k ^2 times frac1sqrt2pisigma_omega_rm k e^-fracleft(omega_rm k - widehatomega_rm k right)^22 sigma_omega_rm k ^2 times e^-alpha^22\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND), ","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nfracdP(E x sigma)dE = frac1sqrt2pisigma^2 times e^-fracleft(E - x right)^22 sigma ^2\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR), ","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"beginaligned\nfracdP(E x gamma)dE = frac1-fsqrt2pi(gamma sigma)^2 times e^-fracleft(E - x right)^22 (gamma sigma) ^2+fracf2gammatautimes e^ frac(gamma sigma)^22(gammatau)^2 + fracE-xgammatau times erfc left(fracsigmasqrt2tau+ fracE-xsqrt2gammasigma right)\nendaligned","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"In particular, for a given partition k, mathcalB_rm k is the background index, mathcalE_rm k is the exposure, Delta E is the fit window, varepsilon_rm k is the efficiency with uncertainty sigma_varepsilon_rm k and mathcalS=Gamma_rm 12=1T_rm 12 is the signal.","category":"page"},{"location":".ipynb_checkpoints/index-checkpoint/#Table-of-contents","page":"ZeroNuFit.jl Documentation","title":"Table of contents","text":"","category":"section"},{"location":".ipynb_checkpoints/index-checkpoint/","page":"ZeroNuFit.jl Documentation","title":"ZeroNuFit.jl Documentation","text":"Pages = [\n \"installation.md\",\n \"config.md\",\n \"inputs.md\",\n \"toys.md\"\n]\nDepth = 1","category":"page"},{"location":".ipynb_checkpoints/internal_api-checkpoint/#VegaGraphs.jl","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"","category":"section"},{"location":".ipynb_checkpoints/internal_api-checkpoint/","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"The best summation package.","category":"page"},{"location":".ipynb_checkpoints/internal_api-checkpoint/#Package-Features","page":"VegaGraphs.jl","title":"Package Features","text":"","category":"section"},{"location":".ipynb_checkpoints/internal_api-checkpoint/","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"Sum the squares of two numbers","category":"page"},{"location":".ipynb_checkpoints/internal_api-checkpoint/#Function-Documentation","page":"VegaGraphs.jl","title":"Function Documentation","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/#First-steps","page":"First steps","title":"First steps","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/#How-to-run-the-code","page":"First steps","title":"How to run the code","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"Run the following command by specifying the path to the configuration file used for settings:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"$ julia main.jl -c config/config.json","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/#Julia-Project-enviroments","page":"First steps","title":"Julia Project enviroments","text":"","category":"section"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"To run the code in a virtual enviroment you can use the following. Start by entering the Julia command view by typing julia on your terminal. Once inside, enter the packagge manager (via ]), activate the environment in the current directory, and resolve (and install, if necessary) dependencies:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"pkg> ] \npkg> activate .\npkg> instantiate","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"Now you can run the script inside this enviroment with:","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"$ julia main.jl --project=. -c config/config.json","category":"page"},{"location":".ipynb_checkpoints/installation-checkpoint/","page":"First steps","title":"First steps","text":"note: Note\nThe tool was developed for the LEGEND experiment. People from the LEGEND Collaborations can alternatively run the code within a LEGEND container with julia installed, see this tutorial for more details.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Table of contents:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Pages = [\"toys.md\"]\nDepth = 3","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Another module is present for generating toys and running sensitivity studies. This can be run as","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"$ julia sensitivity.jl -c config_fake_data.json -i N","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"where N is an integer number corresponding to the toy index. The command can be run in an external bash script for looping over this index.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"The input config file (config_fake_data.json) has the following entries:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"{\n \"path_to_fit\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"best_fit\": false,\n \"seed\": null\n}\n","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"where","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"\"path_to_fit\" is the path to the already performed fit over real data;\n\"best_fit\": true if we want to fix the paramaters to the best fit;\n\"seed\": null if we want a random seed when generating fake data, otherwise you can fix it to an Int value.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Any information about the signal being included or not in the fit of real data, was saved and retrieved from the output JSON file with results.","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Below, we show an example of bash file used for running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n\n# run parallel jobs\n$srun $parallel \"julia sensitivity.jl -c config_fake_data.json -i {1}\" ::: {1..10000} &\n\nwait","category":"page"},{"location":"toys/#Using-already-existing-toys","page":"Generating toys","title":"Using already existing toys","text":"","category":"section"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Another way to run the code is present if, for instance, an user wants to use toy data generated according to one model but fit them with another model. In this case, the path to the folder containing the already existing JSON files with toy data has to be provided together with the toy index:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"julia sensitivity.jl -c config_fake_data.json -i N --path_to_toys path_to_your_toys","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"Below, an updated version of a bash file that can be used for retrieving multiple existing toy data and running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":"toys/","page":"Generating toys","title":"Generating toys","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\n# set the directory path to toys\npath_to_toys=\"output/fit_9_l200_1BI_new_data_coax_bkg_noS/sensitivity/fake_data\" #\"path/to/your/toys\"\nall_files=(\"$path_to_toys\"/*.json)\nfull_paths=()\nfor file in \"${all_files[@]}\"; do\n if [[ -f \"$file\" ]]; then \n full_paths+=(\"$file\")\n fi\ndone\nif [ ${#full_paths[@]} -eq 0 ]; then\n echo \"The list of existing toy data is empty! Exit here.\"\n exit 1\nelse\n echo \"You are going to run a fit over ${#full_paths[@]} number of already existing toys stored under $path_to_toys\"\nfi\n\n# array to hold toy_idx\ntoy_indices=()\n\n# Loop over available fake JSON toys\nfor path in \"${full_paths[@]}\"; do\n base_name=\"${path%.json}\"\n number_str=\"${base_name##*fake_data}\" \n toy_idx=$((number_str)) \n\n toy_indices+=(\"$toy_idx\") \ndone\necho \"List of toy indices: ${toy_indices[*]}\"\n\n# parallel execution - convert array to a space-separated list\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n$srun $parallel \"julia sensitivity.jl -c config/toy_9_l200_1BI_new_data_same_bkg_noS.json -i {1}\" ::: \"${toy_indices[@]}\"\n\nwait","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Pages = [\"config.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Building-the-configuration-file","page":"-","title":"Building the configuration file","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Before running the code, set the input config.json file with following entries:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"{\n \"debug\":false,\n \"partitions\":[\"config/partitions_gerda_new.json\",\"config/partitions_l200.json\",\"config/partitions_mjd_new.json\"],\n \"events\": [\"config/events_gerda.json\",\"config/events_l200.json\",\"config/events_mjd_new_part.json\"],\n \"output_path\": \"output/fit_mjd_l200_gerda_v2/\",\n \"overwrite\":true,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\n \"fit_and_data\": false,\n \"bandfit_and_data\": false,\n \"scheme\":\"red\",\n \"alpha\":0.3\n },\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\":1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\":0.1,\n \"prior\": \"uniform\"\n },\n\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"where","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"debug\": true if you want to display debug output on terminal;\n\"partitions\": list of partitions JSON inputs; it takes one entry per experiment;\n\"events\": list of events JSON inputs; it takes one entry per experiment;\n\"output_path\": path where to store outputs (logs, plots, mcmc results);\n\"overwrite\": true if you want to overwrite a previous fit with same output_path; if set to false but no fits were previously performed (ie there are no outputs to overwrite), the code will save the output of this fit;\n\"bat_fit\": settings for the BAT fit;\n\"plot\": settings for plotting; \"fit_and_data\": true plots fit line over data (and CI bands if \"bandfit_and_data\": true); \"scheme\":\"red\" and \"alpha\":0.3 are used for customizing output appearances;\n\"bkg_only\": true if we fit assuming no signal (S=0), false otherwise;\n\"signal\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, sqrt, ...);\n\"bkg\": select \"upper_bound\" for the prior and the \"prior\" shape (uniform, ...) there are several optional keys with details given below, if these are not provided the fit defaults to a flat background without correlations.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Moreover, the config requires the following block for nuisance parameters, ie energy scale (=energy bias and resolution) and efficiency:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":" {\n ...\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": true,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"In particular, you can set \"correlated\": true if you want to use one variable to correlate the nuisance parameters (eg to speed up the computation times), and \"fixed\": false if you want to include a prior for nuisance parameters (otherwise these parameters they will be fixed to their partition value and not constrained).","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"If a variable is correlated (either energy_scale or efficiency), the code will search for a field in the fit_groups block of the partitions JSON file to use a correlated variable per each fit group. In particular, the field has to be specified as:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"efficiency_group_name\": \"...\"\n\"energy_scale_group_name\": \"...\"","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"note: Note\nIf the key doesn't exist, this defaults to \"all\"","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"Parameters are then added to the model called αr_\\$name (for resolution), αe_\\$name for efficiency and αb_\\$name for bias.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"warning: Warning\nThe alpha parameter names default to _all, if you want one different per experiment this must be explicitly specified in the fit groups entry","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Background-shape-and-correlation","page":"-","title":"Background shape and correlation","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"There are several options to control the background in more detail. These can be added to the \"bkg\" section of the config: In particular:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"correlated\" adds a hierarchical (correlated) background to the model, this key should have a dictionary giving details on the prior shape and ranges for example:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"correlated\":{\"mode\":\"lognormal\",\"range\":[0,0.1]}","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The three options for the mode are 'lognormal', 'normal' or 'none'. While the range gives the range of the uniform prior on the \\sigma_B parameter.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"shape\" changes the shape of the background from uniform. The user should provide a dictionary giving details on the shape:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"for example:","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"\"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n },","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The \"pars\" subdictionary describes the range of the priors on the parameters of the model, currently implemented shapes are \"uniform\", \"linear\" and \"exponential\". These names correspond to functions in fitting.jl and logical conditions in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"This will add parameters ${bkg_name}_slope or similar to the model (and then call them). This names therefore must correspond to the names in the functions in fitting.jl. To add a new shape simply define a new method in fitting.jl and a new logical condition in get_bkg_pdf in likelihood.jl.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"note: Note\nIf these keys are not provided the model defaults to a uniform uncorrelated background.","category":"page"},{"location":".ipynb_checkpoints/config-checkpoint/#Signal-shape","page":"-","title":"Signal shape","text":"","category":"section"},{"location":".ipynb_checkpoints/config-checkpoint/","page":"-","title":"-","text":"The signal shape can be specified in the partition JSON file in order to have a different signal shape for different partitions. An example is given by the combined fit of GERDA/LEGEND and MAJORANA DEMONSTRATOR (MJD) partitions where for the first one we want to model the signal with a simple gaussian function while we want to model data from MJD accounting for an additional tail at the low-energy side of the gaussian. See the \"Partitions and events\" documentation.","category":"page"},{"location":"internal_api/#VegaGraphs.jl","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"","category":"section"},{"location":"internal_api/","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"The best summation package.","category":"page"},{"location":"internal_api/#Package-Features","page":"VegaGraphs.jl","title":"Package Features","text":"","category":"section"},{"location":"internal_api/","page":"VegaGraphs.jl","title":"VegaGraphs.jl","text":"Sum the squares of two numbers","category":"page"},{"location":"internal_api/#Function-Documentation","page":"VegaGraphs.jl","title":"Function Documentation","text":"","category":"section"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Pages = [\"toys.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Another module is present for generating toys and running sensitivity studies. This can be run as","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"$ julia sensitivity.jl -c config_fake_data.json -i N","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"where N is an integer number corresponding to the toy index. The command can be run in an external bash script for looping over this index.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"The input config file (config_fake_data.json) has the following entries:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"{\n \"path_to_fit\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"best_fit\": false,\n \"seed\": null\n}\n","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"where","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"\"path_to_fit\" is the path to the already performed fit over real data;\n\"best_fit\": true if we want to fix the paramaters to the best fit;\n\"seed\": null if we want a random seed when generating fake data, otherwise you can fix it to an Int value.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Any information about the signal being included or not in the fit of real data, was saved and retrieved from the output JSON file with results.","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Below, we show an example of bash file used for running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n\n# run parallel jobs\n$srun $parallel \"julia sensitivity.jl -c config_fake_data.json -i {1}\" ::: {1..10000} &\n\nwait","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/#Using-already-existing-toys","page":"-","title":"Using already existing toys","text":"","category":"section"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Another way to run the code is present if, for instance, an user wants to use toy data generated according to one model but fit them with another model. In this case, the path to the folder containing the already existing JSON files with toy data has to be provided together with the toy index:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"julia sensitivity.jl -c config_fake_data.json -i N --path_to_toys path_to_your_toys","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"Below, an updated version of a bash file that can be used for retrieving multiple existing toy data and running sensitivity studies as multiple jobs on NERSC:","category":"page"},{"location":".ipynb_checkpoints/toys-checkpoint/","page":"-","title":"-","text":"#!/bin/bash \n#SBATCH -q regular \n#SBATCH --constraint=cpu \n#SBATCH -t 48:00:00\n#SBATCH -J sens_test \n\n#SBATCH --mail-user=\n#SBATCH --mail-type=ALL \n#SBATCH --output output_path/parallel.log \n#SBATCH --error output_path/parallel.err \n\n#SBATCH --image=legendexp/legend-base:latest \n\n# set the directory path to toys\npath_to_toys=\"output/fit_9_l200_1BI_new_data_coax_bkg_noS/sensitivity/fake_data\" #\"path/to/your/toys\"\nall_files=(\"$path_to_toys\"/*.json)\nfull_paths=()\nfor file in \"${all_files[@]}\"; do\n if [[ -f \"$file\" ]]; then \n full_paths+=(\"$file\")\n fi\ndone\nif [ ${#full_paths[@]} -eq 0 ]; then\n echo \"The list of existing toy data is empty! Exit here.\"\n exit 1\nelse\n echo \"You are going to run a fit over ${#full_paths[@]} number of already existing toys stored under $path_to_toys\"\nfi\n\n# array to hold toy_idx\ntoy_indices=()\n\n# Loop over available fake JSON toys\nfor path in \"${full_paths[@]}\"; do\n base_name=\"${path%.json}\"\n number_str=\"${base_name##*fake_data}\" \n toy_idx=$((number_str)) \n\n toy_indices+=(\"$toy_idx\") \ndone\necho \"List of toy indices: ${toy_indices[*]}\"\n\n# parallel execution - convert array to a space-separated list\nmodule load parallel\nmodule load julia\nsrun=\"srun -N 1\"\nparallel=\"parallel --delay 1 -j 128\"\n$srun $parallel \"julia sensitivity.jl -c config/toy_9_l200_1BI_new_data_same_bkg_noS.json -i {1}\" ::: \"${toy_indices[@]}\"\n\nwait","category":"page"},{"location":"#ZeroNuFit.jl-Documentation","page":"Home","title":"ZeroNuFit.jl Documentation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Welcome to the documentation for ZeroNuFit.jl.","category":"page"},{"location":"#Introduction","page":"Home","title":"Introduction","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"ZeroNuFit.jl is a Julia package for running an unbinned fit of a Gaussian signal over a background for the neutrinoless double-beta decay (0nubetabeta) analysis. The tool was developed for the LEGEND experiment but it can be easily extended to data collected by any other 0nubetabeta experiment or to any other physical processes that can be modelled in a similar way.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The package uses the BAT.jl tool box for Bayesian inference (see O. Schulz, F. Beaujean, A. Caldwell, C. Grunwald, V. Hafych, K. Kröninger et al., “Bat.jl: A julia-based tool for bayesian inference”, SN Computer Science 2 (2021) 210).","category":"page"},{"location":"#Likelihood-Function","page":"Home","title":"Likelihood Function","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The implemented unbinned Likelihood function reads as: ","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nmathcalL = prod_rm k=1^N_rm p leftfracmu_rm k^N_rm k e^-mu_rm kN_rm k times prod_rm i=1^N_rm k frac1mu_rm kleft(fracmu_rm bkDelta E + mu_rm sk times fracdP(E_rm i Q_betabeta +Delta_rm k omega_rm k)dEright) right\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"Here, the first product runs over the number of partitions k (N_rm p partitions in total) and the second over the events i in a given partition (N_rm k events in total). In particular, E_rm i are the energies of the events falling in the analysis window for a partition k with energy bias Delta_rm k and energy width omega_rm k.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The background and signal contributions are defined as ","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nmu_rm bk = mathcalB_rm k cdot Delta E cdot mathcalE_rm k\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"and","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nmu_rm sk = fractextln2mathcalN_rm Am_rm 76 cdot (varepsilon_rm k + alpha cdot sigma_varepsilon_rm k) cdot mathcalE_rm k cdot mathcalS\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"The total contribution can thus be defined as","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nmu_rm bk = mu_rm bk + mu_rm sk\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"The prior distributions were taken as Gaussian distributions centred around the true value ","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\npi(Delta_rm k omega_rm k alpha) = frac1sqrt2pisigma_Delta_rm k e^-fracleft(Delta_rm k - widehatDelta_rm k right)^22 sigma_Delta_rm k ^2 times frac1sqrt2pisigma_omega_rm k e^-fracleft(omega_rm k - widehatomega_rm k right)^22 sigma_omega_rm k ^2 times e^-alpha^22\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"The signal energy distribution for each partition is taken as a Gaussian (e.g. for GERDA/LEGEND), ","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nfracdP(E x sigma)dE = frac1sqrt2pisigma^2 times e^-fracleft(E - x right)^22 sigma ^2\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"Alternatively, the signal energy distribution can also be shaped as a Gaussian with a tail at low energies (e.g. for MAJORANA DEMONSTRATOR), ","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nfracdP(E x gamma)dE = frac1-fsqrt2pi(gamma sigma)^2 times e^-fracleft(E - x right)^22 (gamma sigma) ^2+fracf2gammatautimes e^ frac(gamma sigma)^22(gammatau)^2 + fracE-xgammatau times erfc left(fracsigmasqrt2tau+ fracE-xsqrt2gammasigma right)\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"In particular, for a given partition k, mathcalB_rm k is the background index, mathcalE_rm k is the exposure, Delta E is the fit window, varepsilon_rm k is the efficiency with uncertainty sigma_varepsilon_rm k and mathcalS=Gamma_rm 12=1T_rm 12 is the signal.","category":"page"},{"location":"#Table-of-contents","page":"Home","title":"Table of contents","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Pages = [\n \"installation.md\",\n \"config.md\",\n \"inputs.md\",\n \"toys.md\"\n]\nDepth = 1","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The aim of this tutorial consists in building proper config JSON files in order to run a neutrinoless double-beta decay analysis over GERDA and MAJORANA DEMONSTRATO (MJD) published data. Additional info on the meaning of input parameters can be found under the \"Configuration file\" section, and for input files under the \"Partitions and events\" section.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Table of contents:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Pages = [\"tutorial.md\"]\nDepth = 3","category":"page"},{"location":"tutorial/#GERDA-Phase-I:-SB-fit","page":"Tutorial","title":"GERDA Phase I: S+B fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's start by fitting data acquired by the GERDA experiment during its Phase I and let's fit them with a signal+background model.","category":"page"},{"location":"tutorial/#Input-files","page":"Tutorial","title":"Input files","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"First of all, we have to populate partitions and events JSON input files. These dictionaries can be built manually by each user, but some reference files are already present for GERDA/LEGEND/MJD experiments at a private location (ask Toby Dixon for access to the repository). Some of these files were also copied in the inputs/ folder for already published material. The following files can be used for this tutorial:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"GERDA Phase I Events -> \"inputs/events_gerda_pI.json\"\nGERDA Phase I Partitions -> \"inputs/partitions_gerda_pI.json\"","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Notice that in \"inputs/partitions_gerda_pI.json\" we already specify in which range we want to fit data (here it is set common to all fit groups, i.e. [1930,2099] U [2109,2114] U [2124,2190] keV) and how we want to group different detectors. In particular, 4 fit groups are specified, with names ph1_golden, ph1_silver, phI_bege and phI_extra. For each group, we will have a separate background index (BI): mathcalB_phI-golden, mathcalB_phI-silver, mathcalB_phI-bege, mathcalB_phI-extra. In case you want one BI only for all phase I events, mathcalB_phI-all, then you have to modify the partitions input file to account for that.","category":"page"},{"location":"tutorial/#Fit-configuration","page":"Tutorial","title":"Fit configuration","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's fit GERDA Phase I events with a simple signal+background=S+B model (\"bkg_only\": false) where the signal is modelled with a Gaussian function (default option).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The signal prior is taken as uniform (\"signal\": {\"prior\": \"uniform\", ...}) in 010^-24 yr^-1. Notice that for the signal the values are expressed in terms of 10^-27yr^-1 (that is why \"signal\": {\"upper_bound\": 1000, ...}). The BI prior is taken as uniform (\"bkg\": {\"prior\": \"uniform\", ...}) in 001 counts/keV/kg/yr. Signal and background are always defined as positive, i.e. the lower bound is set to 0 by default.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"We assume the 4 BIs are not correlated (\"bkg\": {\"correlated\": {\"mode\": \"none\", \"range\": \"none\"}}). If they are, change the entry into \"bkg\": {\"correlated\": {\"mode\": x, \"range\": [...,...]}} where x={\"lognormal\", \"normal\"}. These are the only hierarchical models present at the moment. More documentation on this topic can be found in \"A. Gelman, J.B. Carlin, H.S. Stern, D.B. Dunson, A. Vehtari and D.B. Rubin, “Bayesian Data Analysis (3rd ed.)”, Chapman & Hall (2013)\".","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As regards the nuisance parameters, we can leave free the energy biases and energy widths by not fixing them to their best value (\"nuisance\": {\"energy_scale\": {\"fixed\": false, ...}, ...}), but constraining them via a Gaussian prior. An additional option for treating all energy biases or widths together via one common parameter, i.e. alpha_Delta or alpha_omega, can be enabled/disabled. For the moment, we leave this out and we treat nuisance parameters individually (\"nuisance\": {\"energy_scale\": {\"correlated\": false, ...}, ...}).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As regards the efficiencies, we don't fix the values to their best value (\"nuisance\": {\"efficiency\": {\"fixed\": false, ...}, ...}), but we correlated them via a global parameter alpha_varepsilon (\"nuisance\": {\"efficiency\": {\"correlated\": true, ...}, ...}).","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"All these fit settings can therefore be grouped in the following config JSON file with name config_gerda_phI.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n \"debug\":false,\n \"events\": [\"inputs/events_gerda_pI.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\"],\n \"output_path\": \"output/fit_gerda_phI/\",\n \"overwrite\": true,\n \"light_output\": false,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\"fit_and_data\": false, \"bandfit_and_data\": false, \"scheme\":\"green\", \"alpha\": 0.3},\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\": 1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\": 0.1, \"prior\": \"uniform\", \"correlated\": {\"mode\": \"none\", \"range\": \"none\"}},\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": false,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phI.json","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-SB-fit","page":"Tutorial","title":"GERDA Phase I and II: S+B fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Let's add data acquired by the GERDA experiment during its Phase II and let's fit them with a S+B model, leaving previous settings invariate.","category":"page"},{"location":"tutorial/#Input-files-2","page":"Tutorial","title":"Input files","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"In the partitions file, we group detectors from Phase II in one fit group only (i.e. all_phase_II) such that they all share one BI, i.e. mathcalB_phII-all.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"GERDA Phase II events -> \"inputs/events_gerda_pII.json\"\nGERDA Phase II partitions -> \"inputs/partitions_gerda_pII.json\"","category":"page"},{"location":"tutorial/#Fit-configuration-2","page":"Tutorial","title":"Fit configuration","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Combined fits of different phases of one experiment (or, from a more general point of view, combined fits of different experiments) can be achieved by introducing new events and partitions files to the config JSON file. Let's create the following config JSON file with name config_gerda_phIandphII.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII/\",\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"All the rest can be left unchanged and you can now run the GERDA Phase I+II combined fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII.json","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-SB-fit,-non-flat-background","page":"Tutorial","title":"GERDA Phase I and II: S+B fit, non flat background","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"The background is assumed flat by default, but how can we include a potential different shape? A linear or exponential background shape were implemented as well, and one of these shapes can be specified under the \"bkg\" key. Let's create the following config JSON file with name config_gerda_phIandphII_linearB.json: ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_linearB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"linear\",\n \"pars\":{\"slope\":[-1,3]}\n }\n },\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"or config_gerda_phIandphII_expoB.json:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_expoB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n }\n },\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_linearB.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"if you want to shape the background with a linear function, or ","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_expoB.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"if you want to shape the background with an exponential function.","category":"page"},{"location":"tutorial/#GERDA-Phase-I-and-II:-B-only-fit","page":"Tutorial","title":"GERDA Phase I and II: B only fit","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Sometimes it is required to fit under the mathcalS=0 (no signal) assumption. This might be helpful when performing sensitivity studies in the context of 0nubetabeta decay analyses. This can be achieved by setting \"bkg_only\": true in our config JSON file that we now call config_gerda_phIandphII_NoSignal.json:","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"bkg_only\": true,\n ...\n}","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"You can now run this fit by running","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"$ julia main.jl -c config_gerda_phIandphII_NoSignal.json","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"Additional details on the type of available sensitivity studies (e.g. how to generate fake spectra and fit them) can be found in the \"Generating toys\" section.","category":"page"},{"location":"tutorial/#GERDA-MJD:-different-S-shapes","page":"Tutorial","title":"GERDA + MJD: different S shapes","text":"","category":"section"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":"As explained in \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\", MJD used a modified Gaussian signal peak shape. The code can take care of this difference once you specify the type of signal shape one wants to use in the partitions file. Use \"signal_name\": \"gaussian_plus_lowEtail\" for MJD, and \"signal_name\": \"gaussian\" (or don't enter any key - this is the default option) for GERDA partitions. Below we report an example of how the MJD partitions JSON file should look like for changing the Gaussian signal function into a modified one. Notice that for MJD we can also specify a different fit range (that now includes an additional window in 2209.1-2350.0 keV) compared to the one used by GERDA.","category":"page"},{"location":"tutorial/","page":"Tutorial","title":"Tutorial","text":" {\n \"fit_groups\": {\n \"mjd-DS0\": {\n \"range\": [[1950.0, 2098.511], [2108.511, 2113.513], [2123.513, 2199.1], [2209.1, 2350.0]],\n \"model\": \"uniform\",\n \"bkg_name\": \"B_mjd-DS0\",\n \"signal_name\": \"gaussian_plus_lowEtail\"\n }\n },\n \"partitions\": {\n \"mjd-DS0\": [...]\n }\n }","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The aim of this tutorial consists in building proper config JSON files in order to run a neutrinoless double-beta decay analysis over GERDA and MAJORANA DEMONSTRATO (MJD) published data. Additional info on the meaning of input parameters can be found under the \"Configuration file\" section, and for input files under the \"Partitions and events\" section.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Table of contents:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Pages = [\"tutorial.md\"]\nDepth = 3","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I:-SB-fit","page":"-","title":"GERDA Phase I: S+B fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's start by fitting data acquired by the GERDA experiment during its Phase I and let's fit them with a signal+background model.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Input-files","page":"-","title":"Input files","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"First of all, we have to populate partitions and events JSON input files. These dictionaries can be built manually by each user, but some reference files are already present for GERDA/LEGEND/MJD experiments at a private location (ask Toby Dixon for access to the repository). Some of these files were also copied in the inputs/ folder for already published material. The following files can be used for this tutorial:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"GERDA Phase I Events -> \"inputs/events_gerda_pI.json\"\nGERDA Phase I Partitions -> \"inputs/partitions_gerda_pI.json\"","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Notice that in \"inputs/partitions_gerda_pI.json\" we already specify in which range we want to fit data (here it is set common to all fit groups, i.e. [1930,2099] U [2109,2114] U [2124,2190] keV) and how we want to group different detectors. In particular, 4 fit groups are specified, with names ph1_golden, ph1_silver, phI_bege and phI_extra. For each group, we will have a separate background index (BI): mathcalB_phI-golden, mathcalB_phI-silver, mathcalB_phI-bege, mathcalB_phI-extra. In case you want one BI only for all phase I events, mathcalB_phI-all, then you have to modify the partitions input file to account for that.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Fit-configuration","page":"-","title":"Fit configuration","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's fit GERDA Phase I events with a simple signal+background=S+B model (\"bkg_only\": false) where the signal is modelled with a Gaussian function (default option).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The signal prior is taken as uniform (\"signal\": {\"prior\": \"uniform\", ...}) in 010^-24 yr^-1. Notice that for the signal the values are expressed in terms of 10^-27yr^-1 (that is why \"signal\": {\"upper_bound\": 1000, ...}). The BI prior is taken as uniform (\"bkg\": {\"prior\": \"uniform\", ...}) in 001 counts/keV/kg/yr. Signal and background are always defined as positive, i.e. the lower bound is set to 0 by default.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"We assume the 4 BIs are not correlated (\"bkg\": {\"correlated\": {\"mode\": \"none\", \"range\": \"none\"}}). If they are, change the entry into \"bkg\": {\"correlated\": {\"mode\": x, \"range\": [...,...]}} where x={\"lognormal\", \"normal\"}. These are the only hierarchical models present at the moment. More documentation on this topic can be found in \"A. Gelman, J.B. Carlin, H.S. Stern, D.B. Dunson, A. Vehtari and D.B. Rubin, “Bayesian Data Analysis (3rd ed.)”, Chapman & Hall (2013)\".","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As regards the nuisance parameters, we can leave free the energy biases and energy widths by not fixing them to their best value (\"nuisance\": {\"energy_scale\": {\"fixed\": false, ...}, ...}), but constraining them via a Gaussian prior. An additional option for treating all energy biases or widths together via one common parameter, i.e. alpha_Delta or alpha_omega, can be enabled/disabled. For the moment, we leave this out and we treat nuisance parameters individually (\"nuisance\": {\"energy_scale\": {\"correlated\": false, ...}, ...}).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As regards the efficiencies, we don't fix the values to their best value (\"nuisance\": {\"efficiency\": {\"fixed\": false, ...}, ...}), but we correlated them via a global parameter alpha_varepsilon (\"nuisance\": {\"efficiency\": {\"correlated\": true, ...}, ...}).","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"All these fit settings can therefore be grouped in the following config JSON file with name config_gerda_phI.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n \"debug\":false,\n \"events\": [\"inputs/events_gerda_pI.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\"],\n \"output_path\": \"output/fit_gerda_phI/\",\n \"overwrite\": true,\n \"light_output\": false,\n \"bat_fit\": {\"nsteps\": 1e6, \"nchains\": 6},\n \"plot\": {\"fit_and_data\": false, \"bandfit_and_data\": false, \"scheme\":\"green\", \"alpha\": 0.3},\n \"bkg_only\": false,\n \"signal\": {\"upper_bound\": 1000, \"prior\": \"uniform\"},\n \"bkg\": {\"upper_bound\": 0.1, \"prior\": \"uniform\", \"correlated\": {\"mode\": \"none\", \"range\": \"none\"}},\n \"nuisance\": { \n \"energy_scale\" : {\n \"correlated\": false,\n \"fixed\": false\n },\n \"efficiency\" : {\n \"correlated\": true,\n \"fixed\": false\n }\n }\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phI.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-SB-fit","page":"-","title":"GERDA Phase I and II: S+B fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Let's add data acquired by the GERDA experiment during its Phase II and let's fit them with a S+B model, leaving previous settings invariate.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Input-files-2","page":"-","title":"Input files","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"In the partitions file, we group detectors from Phase II in one fit group only (i.e. all_phase_II) such that they all share one BI, i.e. mathcalB_phII-all.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"GERDA Phase II events -> \"inputs/events_gerda_pII.json\"\nGERDA Phase II partitions -> \"inputs/partitions_gerda_pII.json\"","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#Fit-configuration-2","page":"-","title":"Fit configuration","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Combined fits of different phases of one experiment (or, from a more general point of view, combined fits of different experiments) can be achieved by introducing new events and partitions files to the config JSON file. Let's create the following config JSON file with name config_gerda_phIandphII.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII/\",\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"All the rest can be left unchanged and you can now run the GERDA Phase I+II combined fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-SB-fit,-non-flat-background","page":"-","title":"GERDA Phase I and II: S+B fit, non flat background","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"The background is assumed flat by default, but how can we include a potential different shape? A linear or exponential background shape were implemented as well, and one of these shapes can be specified under the \"bkg\" key. Let's create the following config JSON file with name config_gerda_phIandphII_linearB.json: ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_linearB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"linear\",\n \"pars\":{\"slope\":[-1,3]}\n }\n },\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"or config_gerda_phIandphII_expoB.json:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_expoB/\",\n \"bkg\": {\n \"upper_bound\": 0.1, \n \"prior\": \"uniform\",\n \"correlated\": {\"mode\": \"none\", \"range\": \"none\"},\n \"shape\":{\n \"name\":\"exponential\",\n \"pars\":{\"slope\":[-10,10]}\n }\n },\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_linearB.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"if you want to shape the background with a linear function, or ","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_expoB.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"if you want to shape the background with an exponential function.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-Phase-I-and-II:-B-only-fit","page":"-","title":"GERDA Phase I and II: B only fit","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Sometimes it is required to fit under the mathcalS=0 (no signal) assumption. This might be helpful when performing sensitivity studies in the context of 0nubetabeta decay analyses. This can be achieved by setting \"bkg_only\": true in our config JSON file that we now call config_gerda_phIandphII_NoSignal.json:","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"{\n ...,\n \"events\": [\"inputs/events_gerda_pI.json\", \"inputs/events_gerda_pII.json\"],\n \"partitions\":[\"inputs/partitions_gerda_pI.json\", \"inputs/partitions_gerda_pII.json\"],\n \"output_path\": \"output/fit_gerda_phIandphII_NoSignal/\",\n \"bkg_only\": true,\n ...\n}","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"You can now run this fit by running","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"$ julia main.jl -c config_gerda_phIandphII_NoSignal.json","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"Additional details on the type of available sensitivity studies (e.g. how to generate fake spectra and fit them) can be found in the \"Generating toys\" section.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/#GERDA-MJD:-different-S-shapes","page":"-","title":"GERDA + MJD: different S shapes","text":"","category":"section"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":"As explained in \"I. J. Arnquist et al., Final Result of the Majorana Demonstrator’s Search for Neutrinoless Double- β Decay in Ge 76, PRL 130, 062501 (2023)\", MJD used a modified Gaussian signal peak shape. The code can take care of this difference once you specify the type of signal shape one wants to use in the partitions file. Use \"signal_name\": \"gaussian_plus_lowEtail\" for MJD, and \"signal_name\": \"gaussian\" (or don't enter any key - this is the default option) for GERDA partitions. Below we report an example of how the MJD partitions JSON file should look like for changing the Gaussian signal function into a modified one. Notice that for MJD we can also specify a different fit range (that now includes an additional window in 2209.1-2350.0 keV) compared to the one used by GERDA.","category":"page"},{"location":".ipynb_checkpoints/tutorial-checkpoint/","page":"-","title":"-","text":" {\n \"fit_groups\": {\n \"mjd-DS0\": {\n \"range\": [[1950.0, 2098.511], [2108.511, 2113.513], [2123.513, 2199.1], [2209.1, 2350.0]],\n \"model\": \"uniform\",\n \"bkg_name\": \"B_mjd-DS0\",\n \"signal_name\": \"gaussian_plus_lowEtail\"\n }\n },\n \"partitions\": {\n \"mjd-DS0\": [...]\n }\n }","category":"page"}] } diff --git a/toys/index.html b/toys/index.html index 65f5e11..15dd9f6 100644 --- a/toys/index.html +++ b/toys/index.html @@ -74,4 +74,4 @@ parallel="parallel --delay 1 -j 128" $srun $parallel "julia sensitivity.jl -c config/toy_9_l200_1BI_new_data_same_bkg_noS.json -i {1}" ::: "${toy_indices[@]}" -wait +wait diff --git a/tutorial/index.html b/tutorial/index.html index 856a191..1745786 100644 --- a/tutorial/index.html +++ b/tutorial/index.html @@ -76,4 +76,4 @@ "partitions": { "mjd-DS0": [...] } - } + }