Application to fit parameters to stopping muon data.
706{
709
712
713 experiment_type setup;
716 double E_GeV;
717 double angle_Deg;
718 size_t threads;
719 option_type option;
720 bool normalise;
723
724 try {
725
727
730
732
734 <<
"possible options absorptionLength: " <<
get_keys(absorptionLength) << endl
737 "douplet of histograms corresponding to scattered and direct light, "
738 << "each of which defined by <file name>:<histogram name>");
739 zap[
'E'] =
make_field(E_GeV,
"muon energy [GeV]") = 10.0;
740 zap[
'G'] =
make_field(angle_Deg,
"grid angle for PMT directions [deg]") = 25.0;
742 zap[
'N'] =
make_field(threads,
"number threads") = 0;
743 zap[
'O'] =
make_field(option,
"fit options: \"parameter <start value> <step size>\"" << endl
744 << "possible parameters: "
745 << absorption_factor_t << ", "
746 << absorption_offset_t << ", "
747 << scattering_factor_t << ", "
748 << qe_factor_t << ", "
749 << mixed_factor_a_t << ", "
750 << mixed_factor_b_t << ", "
751 << mixed_offset_a_t << ", "
752 << mixed_offset_b_t);
753 zap[
'n'] =
make_field(normalise,
"normalise gradient");
756
757 zap(argc, argv);
758 }
759 catch(const exception& error) {
760 FATAL(error.what() << endl);
761 }
762
763
764 const TH2* ha =
dynamic_cast<const TH2*
>(
getObject(setup.Ha));
765 const TH2* hb =
dynamic_cast<const TH2*
>(
getObject(setup.Hb));
766
767 if (ha == NULL) {
FATAL(
"Missing histogram: " << setup.Ha << endl); }
768 if (hb == NULL) {
FATAL(
"Missing histogram: " << setup.Hb << endl); }
769
770 const JWifi wifi(E_GeV, ha, hb, angle_Deg, threads);
771
772
773
774 JGradient fit(FIT::number_of_iterations, FIT::number_of_extra_steps, FIT::epsilon, 3);
775
776 fit.normalise = normalise;
777
778 auto fp = [&option, &fit](
const string&
key,
double& value,
const range_type& range) {
779 if (option.count(key)) {
780 fit.push_back(
JModifier_t(key,
new JEditor(value = option[key].first, range), option[key].second));
781 }
782 };
783
784 fp(absorption_factor_t, JAbsorptionLength::get_factor(),
range_type(0.1, 1.0e1));
785 fp(absorption_offset_t, JAbsorptionLength::get_offset(),
range_type(1.0, 1.0e6));
786 fp(scattering_factor_t, JScatteringLength::get_factor(),
range_type(0.1, 1.0e1));
787 fp(qe_factor_t, JQE ::get_factor(),
range_type(0.1, 1.0e1));
788 fp(mixed_factor_a_t, JMixed ::get_factor_a(),
range_type(0.1, 1.0e1));
789 fp(mixed_factor_b_t, JMixed ::get_factor_b(),
range_type(0.1, 1.0e1));
790 fp(mixed_offset_a_t, JMixed ::get_offset_a(),
range_type(1.0, 1.0e6));
791 fp(mixed_offset_b_t, JMixed ::get_offset_b(),
range_type(1.0, 1.0e6));
792
793 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
794
795 const double chi2 = fit(wifi);
796
797 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
798
799 cout <<
"chi2/NDF " <<
FIXED(9,5) << chi2 <<
"/" << setw(4) << (wifi.getN() - fit.size()) << endl;
800
801 cout << "Elapsed time: " << setw(6) << (t1 - t0) / chrono::seconds(1) << " [s]" << endl;
802
803 for (const auto& i : fit) {
804 cout << left << setw(36) << i.name << ' ' << right << FIXED(13,3) << dynamic_cast<const JEditor*>(i.get())->getValue() << endl;
805 }
806
807 auto get_offset = [](
const double x1,
const double x2) {
const double y = 1.0/x1 + 1.0/x2;
return 1.0/
y; };
808 auto get_factor = [](const double x1, const double x2) { return x1 * x2; };
809
810 cout <<
"Additional absorption length: " <<
FIXED(13,5) << get_offset(JAbsorptionLength::get_offset(), JMixed::getOffsetAbsorptionLength()) <<
" [m]" << endl;
811 cout <<
"Scaling of absorption length: " <<
FIXED(13,5) << get_factor(JAbsorptionLength::get_factor(), JMixed::getFactorAbsorptionLength()) << endl;
812 cout <<
"Scaling of scattering length: " <<
FIXED(13,5) << JScatteringLength::get_factor() << endl;
813 cout <<
"Scaling of QE: " <<
FIXED(13,5) << get_factor(JQE ::get_factor(), JMixed::getFactorQE()) << endl;
814
815 if (!xs.empty()) {
816 fit(cout, wifi, xs);
817 }
818}
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
Utility class to parse parameter values.
Utility class to parse command line options.
TObject * getObject(const JRootObjectID &id)
Get first TObject with given identifier.
array_type< JKey_t > get_keys(const std::map< JKey_t, JValue_t, JComparator_t, JAllocator_t > &data)
Method to create array of keys of map.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary data structure for floating point format specification.
Auxiliary data structure for editable parameter.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Auxiliary data structure to customize absorption length.
Auxiliary data structure to customize scattering length.