PDFxTMDLib 2.0.0
Loading...
Searching...
No Matches
PDFSet.h
Go to the documentation of this file.
1
5#pragma once
6#include "PDFxTMDLib/Common/Uncertainty.h"
10#include <PDFxTMDLib/Common/Exception.h>
11#include <PDFxTMDLib/Common/Logger.h>
12#include <PDFxTMDLib/Common/MathUtils.h>
13#include <PDFxTMDLib/Common/PDFErrInfo.h>
14#include <PDFxTMDLib/Common/YamlMetaInfo/YamlErrorInfo.h>
15#include <PDFxTMDLib/Common/YamlMetaInfo/YamlStandardPDFInfo.h>
16#include <PDFxTMDLib/Factory.h>
17#include <PDFxTMDLib/Implementation/Coupling/Null/NullQCDCoupling.h>
20#include <PDFxTMDLib/Uncertainty/HessianStrategy.h>
21#include <PDFxTMDLib/Uncertainty/NullUncertaintyStrategy.h>
22#include <PDFxTMDLib/Uncertainty/ReplicasPercentileStrategy.h>
23#include <PDFxTMDLib/Uncertainty/ReplicasStdDevStrategy.h>
24#include <PDFxTMDLib/Uncertainty/SymmHessianStrategy.h>
25#include <memory>
26#include <mutex>
27#include <string>
28#include <type_traits>
29#include <vector>
30
31namespace PDFxTMD
32{
35template <typename T> struct PDFType;
36
38template <> struct PDFType<TMDPDFTag>
39{
40 using type = ITMD;
41};
42
44template <> struct PDFType<CollinearPDFTag>
45{
46 using type = ICPDF;
47};
48
61template <typename Tag> class PDFSet
62{
63 public:
65 using PDF_t = typename PDFType<Tag>::type;
66
73 explicit PDFSet(std::string pdfSetName, bool alternativeReplicaUncertainty = false)
74 : m_pdfSetName(std::move(pdfSetName)),
75 m_alternativeReplicaUncertainty(alternativeReplicaUncertainty),
76 m_uncertaintyStrategy_(NullUncertaintyStrategy()),
77 m_qcdCoupling(CouplingFactory().mkCoupling(m_pdfSetName))
78 {
79 Initialize();
81 }
82
85 : m_uncertaintyStrategy_(NullUncertaintyStrategy()), m_qcdCoupling(NullQCDCoupling()){};
86
92 double alphasQ(double q) const
93 {
94 return alphasQ2(q * q);
95 }
96
102 double alphasQ2(double q2) const
103 {
104 return m_qcdCoupling.AlphaQCDMu2(q2);
105 }
106
112 PDF_t *operator[](int member)
113 {
114 std::lock_guard<std::mutex> lock(m_pdfSetMtx);
115 if (m_PDFSet_.find(member) == m_PDFSet_.end())
116 {
117 CreatePDFSet(member);
118 }
119 return m_PDFSet_[member].get();
120 }
121
127 PDF_t *operator[](int member) const
128 {
129 if (m_PDFSet_.find(member) == m_PDFSet_.end())
130 return nullptr;
131 return m_PDFSet_.at(member).get();
132 }
133
143 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, TMDPDFTag>>>
144 void Uncertainty(PartonFlavor flavor, double x, double kt2, double mu2, double cl,
145 PDFUncertainty &resUncertainty)
146 {
147 const auto pdfs = CalculatePDFValues(flavor, x, kt2, mu2);
148 PDFUncertaintyInternalEvaluation(pdfs, cl, resUncertainty);
149 }
150
159 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, CollinearPDFTag>>>
160 void Uncertainty(PartonFlavor flavor, double x, double mu2, double cl,
161 PDFUncertainty &resUncertainty)
162 {
163 const auto pdfs = CalculatePDFValues(flavor, x, mu2);
164 PDFUncertaintyInternalEvaluation(pdfs, cl, resUncertainty);
165 }
166
176 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, TMDPDFTag>>>
177 PDFUncertainty Uncertainty(PartonFlavor flavor, double x, double kt2, double mu2,
178 double cl = NO_REQUESTED_CONFIDENCE_LEVEL)
179 {
180 PDFUncertainty resUncertainty;
181 const auto pdfs = CalculatePDFValues(flavor, x, kt2, mu2);
182 PDFUncertaintyInternalEvaluation(pdfs, cl, resUncertainty);
183 return resUncertainty;
184 }
185
195 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, CollinearPDFTag>>>
196 PDFUncertainty Uncertainty(PartonFlavor flavor, double x, double mu2,
197 double cl = NO_REQUESTED_CONFIDENCE_LEVEL)
198 {
199 PDFUncertainty resUncertainty;
200 const auto pdfs = CalculatePDFValues(flavor, x, mu2);
201 PDFUncertaintyInternalEvaluation(pdfs, cl, resUncertainty);
202 return resUncertainty;
203 }
204
211 void Uncertainty(const std::vector<double> &values, double cl, PDFUncertainty &resUncertainty)
212 {
213 if (values.size() != m_pdfSetErrorInfo.size)
214 throw InvalidInputError("Error in PDFxTMD::PDFSet::Uncertainty. Input vector must "
215 "contain values for all PDF members.");
216 PDFUncertaintyInternalEvaluation(values, cl, resUncertainty);
217 }
218
225 PDFUncertainty Uncertainty(const std::vector<double> &values,
226 double cl = NO_REQUESTED_CONFIDENCE_LEVEL)
227 {
228 if (values.size() != m_pdfSetErrorInfo.size)
229 throw InvalidInputError("Error in PDFxTMD::PDFSet::Uncertainty. Input vector must "
230 "contain values for all PDF members.");
231 PDFUncertainty resUncertainty;
232 PDFUncertaintyInternalEvaluation(values, cl, resUncertainty);
233 return resUncertainty;
234 }
235
246 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, CollinearPDFTag>>>
247 double Correlation(PartonFlavor flavorA, double xA, double mu2A, PartonFlavor flavorB,
248 double xB, double mu2B)
249 {
250 const auto pdfsA = CalculatePDFValues(flavorA, xA, mu2A);
251 const auto pdfsB = CalculatePDFValues(flavorB, xB, mu2B);
252 return m_uncertaintyStrategy_.Correlation(pdfsA, pdfsB, m_pdfErrInfo.nmemCore());
253 }
254
267 template <typename T = Tag, typename = std::enable_if_t<std::is_same_v<T, TMDPDFTag>>>
268 double Correlation(PartonFlavor flavorA, double xA, double kt2A, double mu2A,
269 PartonFlavor flavorB, double xB, double kt2B, double mu2B)
270 {
271 const auto pdfsA = CalculatePDFValues(flavorA, xA, kt2A, mu2A);
272 const auto pdfsB = CalculatePDFValues(flavorB, xB, kt2B, mu2B);
273 return m_uncertaintyStrategy_.Correlation(pdfsA, pdfsB, m_pdfErrInfo.nmemCore());
274 }
275
282 double Correlation(const std::vector<double> &valuesA, const std::vector<double> &valuesB) const
283 {
284 if (valuesA.size() != m_pdfSetErrorInfo.size || valuesB.size() != m_pdfSetErrorInfo.size)
285 throw InvalidInputError("Error in PDFxTMD::PDFSet::Correlation. Input vectors must "
286 "contain values for all PDF members.");
287 return m_uncertaintyStrategy_.Correlation(valuesA, valuesB, m_pdfErrInfo.nmemCore());
288 }
289
294 void CreatePDFSet(unsigned int setMember)
295 {
296 {
297 if constexpr (std::is_same_v<Tag, TMDPDFTag>)
298 {
299 m_PDFSet_.insert_or_assign(
300 setMember, std::make_unique<PDF_t>(
301 PDFxTMD::GenericTMDFactory().mkTMD(m_pdfSetName, setMember)));
302 }
303 else if constexpr (std::is_same_v<Tag, CollinearPDFTag>)
304 {
305 m_PDFSet_.insert_or_assign(
306 setMember, std::make_unique<PDF_t>(
307 PDFxTMD::GenericCPDFFactory().mkCPDF(m_pdfSetName, setMember)));
308 }
309 else
310 {
311 static_assert(!std::is_same_v<Tag, Tag>, "Unsupported Tag");
312 }
313 }
314 }
315
320 {
321 for (int i = 0; i < m_pdfSetStdInfo.NumMembers; ++i)
322 {
323 if (m_PDFSet_.find(i) == m_PDFSet_.end())
324 {
325 CreatePDFSet(i);
326 }
327 }
328 }
329
334 void InitailizePDFSetName(std::string pdfSetName)
335 {
336 m_pdfSetName = std::move(pdfSetName);
337 Initialize();
338 }
339
344 size_t size() const
345 {
346 return m_pdfSetStdInfo.NumMembers;
347 }
348
353 YamlStandardTMDInfo getStdPDFInfo() const
354 {
355 return m_pdfSetStdInfo;
356 }
357
362 YamlErrorInfo getPDFErrorInfo() const
363 {
364 return m_pdfSetErrorInfo;
365 }
366
371 ConfigWrapper info()
372 {
373 return m_pdfSetInfo;
374 }
375
376 // Rule of Five: disable copying, allow moving.
377 PDFSet(const PDFSet &) = delete;
378 PDFSet &operator=(const PDFSet &) = delete;
379 PDFSet(PDFSet &&) = default;
380 PDFSet &operator=(PDFSet &&) = default;
381
382 private:
389 inline void PDFUncertaintyInternalEvaluation(const std::vector<double> &pdfs, double cl,
390 PDFUncertainty &resUncertainty)
391 {
392 const double reqCL = ValidateAndGetCL(cl);
393
394 m_uncertaintyStrategy_.Uncertainty(pdfs, m_pdfErrInfo.nmemCore(), reqCL, resUncertainty);
395 resUncertainty.central = pdfs[0];
396
397 ApplyConfidenceLevelScaling(resUncertainty, reqCL);
398 StoreCoreVariationErros(resUncertainty);
399 CalculateParameterVariationErrors(resUncertainty, pdfs);
400 }
401
403 void Initialize()
404 {
405 ValidatePDFSetName();
406 LoadYamlInfo();
407 InitializeUncertaintyStrategy();
408 }
409
411 void InitializeQCDCoupling()
412 {
413 m_qcdCoupling = CouplingFactory().mkCoupling(m_pdfSetName);
414 }
415
417 void ValidatePDFSetName()
418 {
419 if (m_pdfSetName.empty())
420 {
421 throw InvalidInputError(
422 "PDFxTMD::PDFSet::ValidatePDFSetName: PDF set name cannot be empty.");
423 }
424 }
425
427 void LoadYamlInfo()
428 {
429 auto infoPathPair = StandardInfoFilePath(m_pdfSetName);
430 if (infoPathPair.second != ErrorType::None)
431 throw FileLoadException(
432 "PDFxTMD::PDFSet::LoadYamlInfo: Unable to find info file of PDF set " +
433 m_pdfSetName);
434
435 m_isValid = true;
436 auto yamlInfoErrPair = YamlErrorInfoReader(*infoPathPair.first);
437 if (yamlInfoErrPair.second != ErrorType::None || !yamlInfoErrPair.first.has_value())
438 {
439 m_isValid = false;
440 }
441 else
442 {
443 m_pdfSetErrorInfo = *yamlInfoErrPair.first;
444 }
445
446 auto yamlStdInfoErrPair = YamlStandardPDFInfoReader(*infoPathPair.first);
447 if (yamlStdInfoErrPair.second != ErrorType::None || !yamlStdInfoErrPair.first.has_value())
448 {
449 m_isValid = false;
450 }
451 else
452 {
453 m_pdfSetStdInfo = *yamlStdInfoErrPair.first;
454 }
455
456 if (!m_isValid)
457 {
458 throw InvalidInputError("PDFSet: Invalid PDF set '" + m_pdfSetName +
459 "'. Please check the YAML file.");
460 }
461 if (!m_pdfSetInfo.loadFromFile(*infoPathPair.first, ConfigWrapper::Format::YAML))
462 {
463 throw FileLoadException("path: " + *infoPathPair.first + "not found.");
464 }
465 }
466
468 void InitializeUncertaintyStrategy()
469 {
470 m_pdfErrInfo = PDFErrInfo::CalculateErrorInfo(m_pdfSetErrorInfo);
471 if (m_pdfErrInfo.nmemCore() <= 0)
472 {
473 m_uncertaintyStrategy_ = IUncertainty(NullUncertaintyStrategy());
474 PDFxTMDLOG << "Error in PDFxTMD::PDFSet::InitializeUncertaintyStrategy. PDF "
475 "set must contain more than just the central value.";
476 return;
477 }
478
479 const auto &coreType = m_pdfErrInfo.coreType();
480 if (coreType == "replicas")
481 {
482 if (m_alternativeReplicaUncertainty)
483 {
484 m_uncertaintyStrategy_ = IUncertainty(ReplicasPercentileStrategy());
485 }
486 else
487 {
488 m_uncertaintyStrategy_ = IUncertainty(ReplicasStdDevStrategy());
489 }
490 }
491 else if (coreType == "hessian")
492 {
493 m_uncertaintyStrategy_ = IUncertainty(HessianStrategy());
494 }
495 else if (coreType == "symmhessian" || coreType == "symm-hessian")
496 {
497 m_uncertaintyStrategy_ = IUncertainty(SymmHessianStrategy());
498 }
499 else if (coreType == "unknown")
500 {
501 m_uncertaintyStrategy_ = IUncertainty(NullUncertaintyStrategy());
502 }
503 else
504 {
505 throw NotSupportError(
506 "PDFxTMD::PDFSet::InitializeUncertaintyStrategy: Unsupported error type '" +
507 coreType + "' for PDF set " + m_pdfSetName + ".");
508 }
509
510 m_setCL =
511 (coreType != "replicas") ? m_pdfSetErrorInfo.ErrorConfLevel / 100.0 : CL1SIGMA / 100.0;
512 }
513
515 template <typename... Args>
516 std::vector<double> CalculatePDFValues(PartonFlavor flavor, Args... args) const
517 {
518 std::vector<double> pdfs;
519 pdfs.reserve(m_pdfSetStdInfo.NumMembers);
520 for (size_t i = 0; i < size(); i++)
521 {
522 if constexpr (sizeof...(args) == 3)
523 { // TMD case
524 pdfs.emplace_back(operator[](i)->tmd(flavor, args...));
525 }
526 else
527 { // Collinear case
528 pdfs.emplace_back(operator[](i)->pdf(flavor, args...));
529 }
530 }
531 return pdfs;
532 }
533
535 double ValidateAndGetCL(double cl) const
536 {
537 const double reqCL = (cl >= 0) ? cl / 100.0 : m_setCL;
538 if (!in_range(reqCL, 0, 1) || !in_range(m_setCL, 0, 1))
539 {
540 throw InvalidInputError(
541 "Error in PDFxTMD::PDFSet::ValidateAndGetCL. Requested or PDF set "
542 "confidence level outside [0,1] range.");
543 }
544 return reqCL;
545 }
546
548 void ApplyConfidenceLevelScaling(PDFUncertainty &rtn, double reqCL) const
549 {
550 if (m_setCL != reqCL && !m_alternativeReplicaUncertainty)
551 {
552 double qsetCL = chisquared_quantile(m_setCL, 1);
553 double qreqCL = chisquared_quantile(reqCL, 1);
554 const double scale = std::sqrt(qreqCL / qsetCL);
555
556 rtn.scale = scale;
557 rtn.errplus *= scale;
558 rtn.errminus *= scale;
559 rtn.errsymm *= scale;
560 }
561 }
562
564 void StoreCoreVariationErros(PDFUncertainty &resUncertainty)
565 {
566 // Store core variation uncertainties
567 resUncertainty.errplus_pdf = resUncertainty.errplus;
568 resUncertainty.errminus_pdf = resUncertainty.errminus;
569 resUncertainty.errsymm_pdf = resUncertainty.errsymm;
570 resUncertainty.errparts.push_back(
571 {resUncertainty.errplus_pdf,
572 resUncertainty.errminus_pdf});
573 }
574
576 void CalculateParameterVariationErrors(PDFUncertainty &rtn,
577 const std::vector<double> &values) const
578 {
579 double errsq_par_plus = 0.0;
580 double errsq_par_minus = 0.0;
581 size_t index = m_pdfErrInfo.nmemCore();
582
583 for (size_t iq = 1; iq < m_pdfErrInfo.qparts.size(); ++iq)
584 {
585 const auto &eparts = m_pdfErrInfo.qparts[iq];
586 double vmin = rtn.central;
587 double vmax = rtn.central;
588
589 for (const auto &epart : eparts)
590 {
591 const bool symm = StartsWith(epart.first, "$");
592 for (size_t ie = 0; ie < epart.second; ++ie)
593 {
594 index++;
595 if (!symm)
596 {
597 vmin = std::min(values[index], vmin);
598 vmax = std::max(values[index], vmax);
599 }
600 else
601 {
602 const double delta = values[index] - rtn.central;
603 vmin = std::min({values[index], rtn.central - delta, vmin});
604 vmax = std::max({values[index], rtn.central - delta, vmax});
605 }
606 }
607 }
608
609 const double eplus = vmax - rtn.central;
610 const double eminus = rtn.central - vmin;
611 rtn.errparts.push_back({eplus, eminus});
612 errsq_par_plus += SQR(eplus);
613 errsq_par_minus += SQR(eminus);
614 }
615 }
616 std::string m_pdfSetName;
617 ConfigWrapper m_pdfSetInfo;
618 YamlErrorInfo m_pdfSetErrorInfo;
619 YamlStandardTMDInfo m_pdfSetStdInfo;
620 PDFErrInfo m_pdfErrInfo;
621 std::map<unsigned, std::unique_ptr<PDF_t>> m_PDFSet_;
622 std::vector<unsigned int>
623 m_createdPDFSetsMember;
624 IUncertainty m_uncertaintyStrategy_;
625 IQCDCoupling m_qcdCoupling;
626 double m_setCL;
627 bool m_alternativeReplicaUncertainty;
628 bool m_isValid = false;
629 std::mutex m_pdfSetMtx;
630};
631
632} // namespace PDFxTMD
Factory class for creating QCD coupling objects.
Definition Factory.h:18
Factory class for creating collinear PDF objects.
Definition Factory.h:85
ICPDF mkCPDF(const std::string &pdfSetName, int setMember)
Creates a new ICPDF object.
Factory class for creating TMD (Transverse Momentum Dependent) PDF objects.
Definition Factory.h:52
Interface for Collinear Parton Distribution Functions (CPDFs).
Definition ICPDF.h:21
double AlphaQCDMu2(double mu2) const
Return the strong coupling at the factorization scale squared.
Definition IQCDCoupling.h:36
Interface for Transverse Momentum Dependent (TMD) parton distribution functions.
Definition ITMD.h:23
void Uncertainty(const std::vector< double > &values, const int numCoreErrMember, const double cl, PDFUncertainty &uncertainty) const
Calculate uncertainty from values evaluated for all set members.
Definition IUncertainty.h:43
double Correlation(const std::vector< double > &valuesA, const std::vector< double > &valuesB, const int numCoreErrMember) const
Calculate the correlation between two member-value series.
Definition IUncertainty.h:50
Manages a set of Parton Distribution Functions (PDFs), providing tools for uncertainty and correlatio...
Definition PDFSet.h:62
PDFUncertainty Uncertainty(PartonFlavor flavor, double x, double mu2, double cl=NO_REQUESTED_CONFIDENCE_LEVEL)
Calculate the collinear PDF uncertainty and return the result.
Definition PDFSet.h:196
size_t size() const
Get the total number of members in this PDF set.
Definition PDFSet.h:344
PDFSet(const PDFSet &)=delete
YamlStandardTMDInfo getStdPDFInfo() const
Get the standard metadata for the PDF set.
Definition PDFSet.h:353
PDFSet()
Default constructor.
Definition PDFSet.h:84
typename PDFType< Tag >::type PDF_t
The specific PDF interface type (ITMD or ICPDF) determined by the Tag.
Definition PDFSet.h:65
double alphasQ2(double q2) const
Get the strong coupling constant alpha_s at a given squared scale Q^2.
Definition PDFSet.h:102
void InitailizePDFSetName(std::string pdfSetName)
Re-initializes the PDFSet with a new PDF set name.
Definition PDFSet.h:334
void Uncertainty(PartonFlavor flavor, double x, double mu2, double cl, PDFUncertainty &resUncertainty)
Calculate the collinear PDF uncertainty.
Definition PDFSet.h:160
YamlErrorInfo getPDFErrorInfo() const
Get the error metadata for the PDF set.
Definition PDFSet.h:362
PDF_t * operator[](int member) const
Access a specific PDF member from the set (const version).
Definition PDFSet.h:127
double Correlation(PartonFlavor flavorA, double xA, double kt2A, double mu2A, PartonFlavor flavorB, double xB, double kt2B, double mu2B)
Calculate the correlation for TMDs.
Definition PDFSet.h:268
ConfigWrapper info()
Get the full configuration metadata object for the set.
Definition PDFSet.h:371
double alphasQ(double q) const
Get the strong coupling constant alpha_s at a given scale Q.
Definition PDFSet.h:92
PDFSet & operator=(const PDFSet &)=delete
void Uncertainty(const std::vector< double > &values, double cl, PDFUncertainty &resUncertainty)
Calculate uncertainty from a pre-computed vector of PDF values.
Definition PDFSet.h:211
PDFUncertainty Uncertainty(const std::vector< double > &values, double cl=NO_REQUESTED_CONFIDENCE_LEVEL)
Calculate uncertainty from a pre-computed vector of PDF values and return the result.
Definition PDFSet.h:225
PDF_t * operator[](int member)
Access a specific PDF member from the set.
Definition PDFSet.h:112
void CreateAllPDFSets()
Pre-loads all PDF members in the set.
Definition PDFSet.h:319
double Correlation(PartonFlavor flavorA, double xA, double mu2A, PartonFlavor flavorB, double xB, double mu2B)
Calculate the correlation for collinear PDFs.
Definition PDFSet.h:247
PDFSet(std::string pdfSetName, bool alternativeReplicaUncertainty=false)
Constructs a PDFSet for a given PDF name.
Definition PDFSet.h:73
void CreatePDFSet(unsigned int setMember)
Explicitly creates a single PDF member.
Definition PDFSet.h:294
PDFUncertainty Uncertainty(PartonFlavor flavor, double x, double kt2, double mu2, double cl=NO_REQUESTED_CONFIDENCE_LEVEL)
Calculate the TMD uncertainty and return the result.
Definition PDFSet.h:177
PDFSet & operator=(PDFSet &&)=default
void Uncertainty(PartonFlavor flavor, double x, double kt2, double mu2, double cl, PDFUncertainty &resUncertainty)
Calculate the TMD uncertainty.
Definition PDFSet.h:144
double Correlation(const std::vector< double > &valuesA, const std::vector< double > &valuesB) const
Calculate correlation from two pre-computed vectors of PDF values.
Definition PDFSet.h:282
PDFSet(PDFSet &&)=default
Definition Factory.h:9
Definition GenericPDF.h:34
A type trait to map a tag to a specific PDF interface type.
Definition PDFSet.h:35
Definition GenericPDF.h:31