Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/hadronic/FlukaCern/utils/src/tools_histo_flair.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 ///  \file tools_histo_flair.cc
 27 ///  \brief Tools to dump any G4H1 into Flair-compatible format.
 28 //
 29 //  Author: G.Hugo, 08 December 2022
 30 //
 31 // ***************************************************************************
 32 //
 33 //      tools_histo_flair
 34 //
 35 ///  Tools to dump any G4H1 into Flair-compatible format.
 36 ///
 37 ///  These tools are fully application-agnostic,
 38 ///  and could also be placed outside of the G4 examples,
 39 ///  as a core G4 Analysis Manager extension.
 40 //
 41 // ***************************************************************************
 42 
 43 #include "tools_histo_flair.hh"
 44 
 45 #include "G4SystemOfUnits.hh"
 46 #include "G4UnitsTable.hh"
 47 #include "G4ios.hh"
 48 
 49 #include <cstring>
 50 #include <fstream>
 51 #include <iomanip>
 52 #include <memory>
 53 #include <stdarg.h>
 54 #include <stdlib.h>
 55 
 56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 57 
 58 namespace tools
 59 {
 60 namespace histo
 61 {
 62 namespace flair
 63 {
 64 
 65 // ***************************************************************************
 66 // Returns abscissa name.
 67 // ***************************************************************************
 68 G4String getAbscissaName(const Abscissa abscissaKind)
 69 {
 70   G4String abscissaName = "";
 71   if (abscissaKind == Abscissa::KineticEnergy) {
 72     abscissaName = "kE";
 73   }
 74   else if (abscissaKind == Abscissa::Z) {
 75     abscissaName = "Z";
 76   }
 77   else if (abscissaKind == Abscissa::A) {
 78     abscissaName = "A";
 79   }
 80   return abscissaName;
 81 }
 82 
 83 // ***************************************************************************
 84 // Returns abscissa unit.
 85 // ***************************************************************************
 86 G4String getAbscissaUnit(const Abscissa abscissaKind)
 87 {
 88   G4String abscissaUnit = "";
 89   if (abscissaKind == Abscissa::KineticEnergy) {
 90     abscissaUnit = "GeV";
 91   }
 92   return abscissaUnit;
 93 }
 94 
 95 // ***************************************************************************
 96 // Returns abscissa unit value.
 97 // ***************************************************************************
 98 G4double getAbscissaUnitValue(const Abscissa abscissaKind)
 99 {
100   G4double abscissaUnitValue = 1.;
101   if (abscissaKind == Abscissa::KineticEnergy) {
102     abscissaUnitValue = G4UnitDefinition::GetValueOf(getAbscissaUnit(Abscissa::KineticEnergy));
103   }
104   return abscissaUnitValue;
105 }
106 
107 // ***************************************************************************
108 // String format like printf() for strings.
109 // This sformat function is extracted as-is from geoviewer,
110 // and was written by V. Vlachoudis in 2010.
111 // ***************************************************************************
112 G4String sformat(const char* fmt, ...)
113 {
114   std::unique_ptr<char[]> formatted;
115   G4int n = (G4int)strlen(fmt) * 2;  // Reserve two times as much as the length of the fmt_str.
116   while (true) {
117     // Wrap the plain char array into the unique_ptr.
118     formatted.reset(new char[n]);
119     strcpy(&formatted[0], fmt);
120     va_list ap;
121     va_start(ap, fmt);
122     G4int final_n = vsnprintf(&formatted[0], n, fmt, ap);
123     va_end(ap);
124     if (final_n < 0 || final_n >= n) {
125       n += std::abs(final_n - n + 1);
126     }
127     else {
128       break;
129     }
130   }
131   return G4String(formatted.get());
132 }
133 
134 // ***************************************************************************
135 // Returns MC error.
136 // ***************************************************************************
137 G4double computeError(const G4double mean, const G4double sumSquares, const G4int numEvents)
138 {
139   const G4double var = std::max(0., sumSquares / numEvents - mean * mean);
140   const G4double err =
141     ((mean != 0. && numEvents > 1) ? std::sqrt(var / (numEvents - 1)) / mean : 1.);
142 
143   return err * 100.;
144 }
145 
146 // ***************************************************************************
147 // Dump G4H1 (histo mode) to a Flair-compatible format.
148 // ***************************************************************************
149 void dumpG4H1HistoInFlairFormat(std::ofstream& output, const G4int indexInOutputFile,
150                                 const G4String& histoName, G4H1* const histo,
151                                 const Abscissa abscissaKind, const G4String& binSchemeName,
152                                 const G4int numEvents, const G4double sumSquaredEventTotals,
153                                 const G4double sumSquaredEventInRangeTotals)
154 {
155   const G4bool isProfile = false;
156   dumpG4H1InFlairFormat(output, indexInOutputFile, histoName, histo, abscissaKind, binSchemeName,
157                         numEvents, isProfile, sumSquaredEventTotals, sumSquaredEventInRangeTotals);
158 }
159 
160 // ***************************************************************************
161 // Dump G4H1 (profile mode, ie no stats) to a Flair-compatible format.
162 // ***************************************************************************
163 void dumpG4H1ProfileInFlairFormat(std::ofstream& output, const G4int indexInOutputFile,
164                                   const G4String& histoName, G4H1* const histo,
165                                   const Abscissa abscissaKind, const G4String& binSchemeName)
166 {
167   const G4bool isProfile = true;
168   const G4int numEvents = 1;
169   dumpG4H1InFlairFormat(output, indexInOutputFile, histoName, histo, abscissaKind, binSchemeName,
170                         numEvents, isProfile);
171 }
172 
173 // ***************************************************************************
174 // Dump G4H1 (profile + histo modes) to a Flair-compatible format.
175 // ***************************************************************************
176 void dumpG4H1InFlairFormat(std::ofstream& output, const G4int indexInOutputFile,
177                            const G4String& histoName, G4H1* const histo,
178                            const Abscissa abscissaKind, const G4String& binSchemeName,
179                            const G4int numEvents, const G4bool isProfile,
180                            const G4double sumSquaredEventTotals,
181                            const G4double sumSquaredEventInRangeTotals)
182 {
183   const G4int numBins = histo->axis().bins();
184   const G4double minAbscissa = histo->axis().lower_edge();
185   const G4double maxAbscissa = histo->axis().upper_edge();
186 
187   const G4String abscissaName = getAbscissaName(abscissaKind);
188   const G4String abscissaUnit = getAbscissaUnit(abscissaKind);
189   const G4double abscissaUnitValue = getAbscissaUnitValue(abscissaKind);
190 
191   // START HEADER.
192   if (indexInOutputFile != 1) {
193     output << G4endl << G4endl;
194   }
195   output << std::left << std::setw(13) << "# Detector: " << indexInOutputFile << " " << histoName
196          << G4endl;
197   output << std::left << std::setw(13) << "# Dim: " << histo->get_dimension() << G4endl;
198   output << std::left << std::setw(13) << "# Entries: " << numEvents << G4endl;
199 
200   if (!isProfile) {
201     // Total integral
202     const G4double total = static_cast<G4double>(histo->sum_all_bin_heights()) / numEvents;
203     const G4double totalError = computeError(total, sumSquaredEventTotals, numEvents);
204     output << std::left << std::setw(13)
205            << "# Total: " << sformat("%-15g [1/pr] +/- %6.2f [%] \n", total, totalError);
206 
207     // In range integral
208     const G4double inRange = static_cast<G4double>(histo->sum_bin_heights()) / numEvents;
209     const G4double inRangeError = computeError(inRange, sumSquaredEventInRangeTotals, numEvents);
210     output << std::left << std::setw(13)
211            << "# InRange: " << sformat("%-15g [1/pr] +/- %6.2f [%] \n", inRange, inRangeError);
212 
213     // Underflow
214     const G4double underflow = static_cast<G4double>(histo->bins_sum_w().at(0)) / numEvents;
215     const G4double underflowError = computeError(underflow, histo->bins_sum_w2().at(0), numEvents);
216     output << std::left << std::setw(13)
217            << "# Under: " << sformat("%-15g [1/pr] +/- %6.2f [%] \n", underflow, underflowError);
218 
219     // Overflow
220     const G4double overflow =
221       static_cast<G4double>(histo->bins_sum_w().at(numBins + 1)) / numEvents;
222     const G4double overflowError =
223       computeError(overflow, histo->bins_sum_w2().at(numBins + 1), numEvents);
224     output << std::left << std::setw(13)
225            << "# Over: " << sformat("%-15g [1/pr] +/- %6.2f [%] \n", overflow, overflowError);
226   }
227 
228   // END HEADER.
229   output << std::left << std::setw(13) << "# Log: " << binSchemeName << G4endl;
230   output << std::left << std::setw(13) << "# Histogram: " << numBins << " "
231          << minAbscissa / abscissaUnitValue << " " << maxAbscissa / abscissaUnitValue << "  ["
232          << abscissaUnit << "]" << G4endl;
233 
234   output << std::left << std::setw(13) << "# Column: "
235          << "1  " << abscissaName << "_min  "
236          << "[" << abscissaUnit << "]" << G4endl;
237   output << std::left << std::setw(13) << "# Column: "
238          << "2  " << abscissaName << "_max  "
239          << "[" << abscissaUnit << "]" << G4endl;
240   output << std::left << std::setw(13) << "# Column: "
241          << "3  dN/d(" << abscissaName << ")  "
242          << "[1" << (abscissaUnit.empty() ? "" : ("/" + abscissaUnit)) << "/pr]" << G4endl;
243   if (!isProfile) {
244     output << std::left << std::setw(13) << "# Column: "
245            << "4  error  "
246            << "[%]" << G4endl;
247   }
248 
249   // HISTO / PROFILE DATA.
250   for (G4int binIndex = 0; binIndex < numBins; ++binIndex) {
251     const G4double mean = histo->bin_height(binIndex) / numEvents;
252     const G4double err = computeError(mean, histo->bins_sum_w2().at(binIndex + 1), numEvents);
253 
254     // histo mode
255     if (!isProfile) {
256       output << sformat("%15g %15g %15g %6.2f\n",
257                         histo->axis().bin_lower_edge(binIndex) / abscissaUnitValue,
258                         histo->axis().bin_upper_edge(binIndex) / abscissaUnitValue,
259                         mean / histo->axis().bin_width(binIndex) * abscissaUnitValue, err);
260     }
261     // profile mode
262     else {
263       output << sformat("%15g %15g %15g\n",
264                         histo->axis().bin_lower_edge(binIndex) / abscissaUnitValue,
265                         histo->axis().bin_upper_edge(binIndex) / abscissaUnitValue,
266                         mean / histo->axis().bin_width(binIndex) * abscissaUnitValue);
267     }
268   }  // loop on all bins
269 }  // dumpG4H1InFlairFormat
270 
271 }  // namespace flair
272 }  // namespace histo
273 }  // namespace tools
274 
275 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
276