Skip to content

Commit

Permalink
Merge pull request #160 from mach3-software/feature_SaveYamlCofnig
Browse files Browse the repository at this point in the history
Save Covariance in MCMC File
  • Loading branch information
KSkwarczynski authored Oct 10, 2024
2 parents 8893e7b + efdce81 commit 60dfdff
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 151 deletions.
9 changes: 2 additions & 7 deletions .github/workflows/CDImage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,12 @@ jobs:
- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Set MACH3_VERSION
run: echo "MACH3_VERSION=${{ github.head_ref }}" >> "$GITHUB_ENV"
env:
GITHUB_HEAD_REF: ${{ github.head_ref }}

- name: Build Docker image
run: |
if [ "${{ github.ref_type }}" == 'tag' ]; then
docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.os }}${{ github.ref_name }} --build-arg MACH3_VERSION="${MACH3_VERSION}"
docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.os }}${{ github.ref_name }} --build-arg MACH3_VERSION=${{ github.ref_name }}
else
docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.tag_latest }} --build-arg MACH3_VERSION="develop"
docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.tag_latest }} --build-arg MACH3_VERSION=develop
fi
- name: Push Docker image
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/CIBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,5 @@ jobs:
- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Set environment variable for MACH3_VERSION
run: echo "MACH3_VERSION=${{ github.head_ref }}" >> "$GITHUB_ENV"

- name: Build the Docker image
run: docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.tag }} --build-arg MACH3_VERSION=${{ env.MACH3_VERSION }} --build-arg CMAKE_OPTIONS="${{ matrix.cmakeoptions }}"
run: docker build . --file ${{ matrix.file }} --tag ghcr.io/${{ github.repository_owner }}/mach3:${{ matrix.tag }} --build-arg MACH3_VERSION=${{ github.head_ref }} --build-arg CMAKE_OPTIONS="${{ matrix.cmakeoptions }}"
5 changes: 2 additions & 3 deletions .github/workflows/CIValidations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,15 @@ jobs:
steps:
- uses: actions/checkout@v4


- name: Get MaCh3 Validations
run: |
cd /opt/
git clone https://github.com/mach3-software/MaCh3Tutorial.git MaCh3Validations
cd MaCh3Validations
mkdir build
cd build
cmake ../ -DMaCh3_Branch="${{ env.GITHUB_HEAD_REF }}"
env:
GITHUB_HEAD_REF: ${{ github.head_ref }}
cmake ../ -DMaCh3_Branch=${{ github.head_ref }}
- name: Build MaCh3 Validations
run: |
Expand Down
11 changes: 10 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ bool AsimovFit = GetFromManager<bool>(config[AsimovFit], false);
```

## double vs float?
Some fits require lot's of RAM. Easiest and fastest solution to reduce RAM is use floats instead of doubles. MaCh3 has custom type like \_float\_ defined [here](https://github.com/mach3-software/MaCh3/blob/761cdc168663a6cfe659e4e3bab0d939bf715273/samplePDF/Structs.h#L9). \_float\_ is usually double unless \_LOW_MEMORY_STRUCTS\_ is defined at compilation level. Then \_float\_ will be actual float. By using \_float\_ one can flexibly change from one type to another. When developing it is advised to used these data types unless some data types are necessary due to desired precision code safety etc.
Some fits require a lot of RAM. The easiest and fastest solution to reduce RAM
is to use `float` instead of `double`.

MaCh3 has a custom type defined as `_float_`, which is usually a `double`
unless the `_LOW_MEMORY_STRUCTS_` directive is defined at the compilation
level. When defined, `_float_` will be an actual `float`.

By using `_float_`, one can flexibly change between these types. During
development, it is advised to use these data types unless specific data
types are necessary due to desired precision, code safety, etc.

## Error handling
MaCh3 uses custom error handling implemented [here](https://github.com/mach3-software/MaCh3/blob/develop/manager/MaCh3Exception.h)
Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# MaCh3 <img src="Doc/mach3logo.png" alt="MaCh3" align="center" width="100"/>
The Markov Chain 3 flavour is a framework born in 2013 as a Bayesian MCMC fitter for [T2K](https://t2k-experiment.org/pl/) oscillation analysis. It has now been used for multiple T2K Oscillation analyses both at the Near and Far detectors throughout the years and is also used by the [DUNE](https://www.dunescience.org/) and [HK](https://www-sk.icrr.u-tokyo.ac.jp/en/hk/) oscillation analysis groups as well as for joint fits between T2K and NOvA and T2K and SK's atmospheric data.

The framework has also evolved to allow non MCMC modules to interrogate the likelihoods implemented.
The Markov Chain 3 flavour is a framework born in 2013 as a Bayesian MCMC
fitter for [T2K](https://t2k-experiment.org/pl/) oscillation analysis. It has
now been used for multiple T2K Oscillation analyses at both the Near and Far
detectors throughout the years. The framework is also utilized by the
[DUNE](https://www.dunescience.org/) and [HK](https://www-sk.icrr.u-tokyo.ac.jp/en/hk/)
oscillation analysis groups. Additionally, it supports joint fits between T2K
and NOvA, as well as T2K and SK's atmospheric data.

The framework has also evolved to allow non-MCMC modules to interrogate the
likelihoods implemented.

[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://github.com/mach3-software/MaCh3/blob/develop/LICENSE.txt)
[![Release](https://img.shields.io/github/release/mach3-software/MaCh3.svg)](https://github.com/mach3-software/MaCh3/releases/latest)
Expand Down Expand Up @@ -70,7 +78,7 @@ Additionally, you can build just the Python module by doing:

```bash
pip install -t <install location> .
```
```
The -t option specifies an install location which can be useful if you are on a computing cluster and don't have write access to the default install location. If you specify a non-standard location you will need to add it to your `PYTHONPATH` as above so that python can find the module.

## Multithreading
Expand Down
50 changes: 0 additions & 50 deletions covariance/covarianceBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,57 +32,10 @@ covarianceBase::covarianceBase(const std::vector<std::string>& YAMLFile, const c
if (pca) ConstructPCA();
}

// ********************************************
covarianceBase::covarianceBase(const char *name, const char *file, int seed) : inputFile(std::string(file)), pca(false) {
// ********************************************

#ifdef MULTITHREAD
if(seed != 0)
{
MACH3LOG_WARN("You have set seed to {}", seed);
MACH3LOG_WARN("And you are running with MULTITHREAD");
MACH3LOG_WARN("TRandom for each thread will have same seed");
MACH3LOG_WARN("This is fine if this was your intention");
}
#endif

init(name, file);
FirstPCAdpar = -999;
LastPCAdpar = -999;
}

// ********************************************
covarianceBase::covarianceBase(const char *name, const char *file, int seed, double threshold, int firstpcapar, int lastpcapar) : inputFile(std::string(file)), pca(true), eigen_threshold(threshold), FirstPCAdpar(firstpcapar), LastPCAdpar(lastpcapar) {
// ********************************************

if (threshold < 0 || threshold >= 1) {
MACH3LOG_INFO("NOTE: {} {}", name, file);
MACH3LOG_INFO("Principal component analysis but given the threshold for the principal components to be less than 0, or greater than (or equal to) 1. This will not work");
MACH3LOG_INFO("Please specify a number between 0 and 1");
MACH3LOG_INFO("You specified: ");
MACH3LOG_INFO("Am instead calling the usual non-PCA constructor...");
pca = false;
}
#ifdef MULTITHREAD
if(seed != 0)
{
MACH3LOG_WARN("You have set seed to {}", seed);
MACH3LOG_WARN("And you are running with MULTITHREAD");
MACH3LOG_WARN("TRandom for each thread will have same seed");
MACH3LOG_WARN("This is fine if this was your intention");
}
#endif
MACH3LOG_INFO("Constructing instance of covarianceBase");
init(name, file);
// Call the innocent helper function
if (pca) ConstructPCA();
}

// ********************************************
//Destructor
covarianceBase::~covarianceBase(){
// ********************************************

_fPreFitValue.clear();
_fError.clear();
_fCurrVal.clear();
Expand Down Expand Up @@ -846,7 +799,6 @@ void covarianceBase::printNominalCurrProp() {
// false = don't evaluate likelihood (so run without a prior)
double covarianceBase::CalcLikelihood() {
// ********************************************

double logL = 0.0;
#ifdef MULTITHREAD
#pragma omp parallel for reduction(+:logL)
Expand All @@ -869,7 +821,6 @@ double covarianceBase::CalcLikelihood() {
// ********************************************
int covarianceBase::CheckBounds() {
// ********************************************

int NOutside = 0;
#ifdef MULTITHREAD
#pragma omp parallel for reduction(+:NOutside)
Expand Down Expand Up @@ -1353,7 +1304,6 @@ void covarianceBase::makeClosestPosDef(TMatrixDSym *cov) {
// ********************************************
std::vector<double> covarianceBase::getNominalArray() {
// ********************************************

std::vector<double> nominal(_fNumPar);
for (int i = 0; i < _fNumPar; ++i)
{
Expand Down
16 changes: 3 additions & 13 deletions covariance/covarianceBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,7 @@ class covarianceBase {
/// @param name Matrix name
/// @param file Path to matrix root file
covarianceBase(const char *name, const char *file);
/// @brief "Usual" constructors from root file with seed
/// @param name Matrix name
/// @param file Path to matrix root file
/// @param seed Seed for TRandom3
covarianceBase(const char *name, const char *file, int seed);
/// @brief Constructor For Eigen Value decomp
/// @param name Matrix name
/// @param file Path to matrix root file
/// @param seed Seed for TRandom3
/// @param threshold PCA threshold from 0 to 1. Default is -1 and means no PCA
/// @param FirstPCAdpar First PCA parameter that will be decomposed.
/// @param LastPCAdpar First PCA parameter that will be decomposed.
covarianceBase(const char *name, const char *file, int seed, double threshold, int FirstPCAdpar, int LastPCAdpar);

/// @brief Destructor
virtual ~covarianceBase();

Expand Down Expand Up @@ -355,6 +343,8 @@ class covarianceBase {
/// @brief KS: Custom function to perform multiplication of matrix and single element which is thread safe
inline double MatrixVectorMultiSingle(double** _restrict_ matrix, const double* _restrict_ vector, const int Length, const int i);

/// @brief Getter to return a copy of the YAML node
YAML::Node GetConfig() const { return _fYAMLDoc; }
protected:
/// @brief Initialisation of the class using matrix from root file
void init(const char *name, const char *file);
Expand Down
20 changes: 20 additions & 0 deletions manager/YamlHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ inline YAML::Node TMacroToYAML(const TMacro& macro) {
return yaml_node;
}

// **********************
/// @brief Convert a YAML node to a ROOT TMacro object.
/// @param yaml_node The YAML node to convert to a TMacro.
/// @param name Name of TMacro that will be saved
/// @return TMacro The TMacro object constructed from the YAML node.
inline TMacro YAMLtoTMacro(const YAML::Node& yaml_node, const std::string& name) {
// **********************
// Convert the YAML node to a string representation
std::string macro_string = YAMLtoSTRING(yaml_node);

std::cout<<macro_string<<std::endl;
// Create a TMacro object with the collected lines
TMacro macro(name.c_str(), name.c_str());
macro.AddLine(macro_string.c_str());

macro.Print();

return macro;
}

// **********************
/// @brief Overrides the configuration settings based on provided arguments.
///
Expand Down
52 changes: 14 additions & 38 deletions mcmc/FitterBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,14 @@ void FitterBase::addSystObj(covarianceBase * const cov) {
CorrMatrix->Write((cov->getName() + std::string("_Corr")).c_str());
delete CorrMatrix;

// If we have yaml config file for covariance let's save it
YAML::Node Config = cov->GetConfig();
if(!Config.IsNull())
{
TMacro ConfigSave = YAMLtoTMacro(Config, (std::string("Config_") + cov->getName()));
ConfigSave.Write();
}

outputFile->cd();

return;
Expand Down Expand Up @@ -324,44 +332,12 @@ void FitterBase::addOscHandler(covarianceOsc * const oscf) {
outputFile->cd();
}

return;
}

// *************************
// When using separate oscillations for neutrino and anti-neutrino
void FitterBase::addOscHandler(covarianceOsc *oscf, covarianceOsc *oscf2) {
// *************************

osc = oscf;
osc2 = oscf2;

if (save_nominal) {
CovFolder->cd();
std::vector<double> vec = oscf->getNominalArray();
size_t n = vec.size();
double *n_vec = new double[n];
for (size_t i = 0; i < n; ++i) {
n_vec[i] = vec[i];
}
TVectorT<double> t_vec(n, n_vec);
TString nameof = TString(oscf->getName());
nameof = nameof.Append("_nom");
t_vec.Write(nameof);

std::vector<double> vec2 = oscf2->getNominalArray();
size_t n2 = vec2.size();
double *n_vec2 = new double[n];
for (size_t i = 0; i < n; ++i) {
n_vec2[i] = vec2[i];
}
TVectorT<double> t_vec2(n2, n_vec2);
TString nameof2 = TString(oscf2->getName());
nameof2 = nameof2.Append("_2_nom");
t_vec2.Write(nameof2);
delete[] n_vec;
delete[] n_vec2;

outputFile->cd();
// If we have yaml config file for covariance let's save it
YAML::Node Config = oscf->GetConfig();
if(!Config.IsNull())
{
TMacro ConfigSave = YAMLtoTMacro(Config, (std::string("Config_") + oscf->getName()));
ConfigSave.Write();
}

return;
Expand Down
7 changes: 0 additions & 7 deletions mcmc/FitterBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ class FitterBase {
/// @param oscf A pointer to a covarianceOsc object for forward oscillations.
void addOscHandler(covarianceOsc* oscf);

/// @brief Adds two oscillation handlers for covariance objects.
/// @param osca A pointer to a covarianceOsc object for the first oscillation.
/// @param oscb A pointer to a covarianceOsc object for the second oscillation.
void addOscHandler(covarianceOsc* osca, covarianceOsc* oscb);

/// @brief The specific fitting algorithm implemented in this function depends on the derived class. It could be Markov Chain Monte Carlo (MCMC), MinuitFit, or another algorithm.
virtual void runMCMC() = 0;

Expand Down Expand Up @@ -125,8 +120,6 @@ class FitterBase {

/// handles oscillation parameters
covarianceOsc *osc;
/// handles oscillation parameters
covarianceOsc *osc2;

/// tells global time how long fit took
TStopwatch* clock;
Expand Down
Loading

0 comments on commit 60dfdff

Please sign in to comment.