ATLAS Offline Software
Loading...
Searching...
No Matches
CaloLCCoeffHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// //-----------------------------------------------------------------------
6// File and Version Information:
7// $Id: CaloHadDMCoeffHelper.cxx,v 1.2 2009-03-06 14:43:23 pospelov Exp $
8//
9// Description: see CaloHadDMCoeffHelper.h
10//
11// Environment:
12// Software developed for the ATLAS Detector at CERN LHC
13//
14// Author List:
15// Gennady Pospelov
16//
17//-----------------------------------------------------------------------
19#include <iostream>
20#include <sstream>
21#include <cstring>
22#include <iomanip>
23#include <cmath>
24#include <format>
25
28
29
31= default;
32
33
35= default;
36
37
38// get HadDMArea from area name
39const CaloLocalHadCoeff::LocalHadArea * CaloLCCoeffHelper::getAreaFromName(const CaloLocalHadCoeff * coeff, const std::string& sname, int &indx)
40{
41 for(int i_area=0; i_area<coeff->getSizeAreaSet(); i_area++) {
42 if(sname == coeff->getArea(i_area)->getTitle()) {
43 indx = i_area;
44 return coeff->getArea(i_area);
45 }
46 }
47 std::cout << "CaloLCCoeffHelper::getAreaFromName() -> Error! No such area '" << sname << "'" << std::endl;
48 return nullptr;
49}
50
51
52
53/* ****************************************************************************
54To read set of local hadronic coefficients from text file
55**************************************************************************** */
56std::optional<CaloLocalHadCoeff> CaloLCCoeffHelper::InitDataFromFile(const char *filename)
57{
58 std::optional<CaloLocalHadCoeff> data=std::make_optional<CaloLocalHadCoeff>();
59
60 char cLine[1024];
61
62 // Find the full path to filename
63 std::cout << "CaloLCCoeffHelper::InitDataFromFile - Reading file '" << filename << "'." << std::endl;
64
65 std::ifstream fin(filename);
66 if ( !fin ) {
67 std::cout << "CaloLCCoeffHelper::InitDataFromFile - Can't open file '" << filename << "'." << std::endl;
68 return std::nullopt;
69 }
70
71 std::string sLine;
72 std::istringstream ist;
73 while(fin.getline(cLine,sizeof(cLine)-1)) {
74 if( strlen(cLine)==0 || cLine[0] == '#' || cLine[0] == '\n') continue;
75
76 // parsing area line
77 sLine = cLine;
78 ist.clear(); ist.str(sLine);
79 std::string sdummy, area_title;
80 int area_indx(0), area_type(0), area_npars(0);
81 if( !(ist >> sdummy >> area_indx >> area_title >> area_type >> area_npars) ||
82 area_npars < 0 || area_npars > 1000 ) {
83 std::cout << "CaloLCCoeffHelper::initDataFromFile() -> Error! Could not parse line '" << cLine << "' at p1." << std::endl;
84 return std::nullopt;
85 }
86
87 CaloLocalHadCoeff::LocalHadArea theArea(area_title.c_str(), area_type, area_npars);
88
89 // loop over defined dimensions
90 while(fin.getline(cLine,sizeof(cLine)-1)){
91 if( cLine[0] == '#') continue;
92 sLine = cLine;
93 if(sLine.find("break") != std::string::npos) {
94 break;
95 }
96 auto dim = parse_dim(sLine);
97 if( !dim ) {
98 std::cout << "CaloLCCoeffHelper::initDataFromFile() ->Error! Could not parse line '" << sLine << "' at p2a." << std::endl;
99 return std::nullopt;
100 }
101 theArea.addDimension(*dim);
102 }
103 data->addArea(theArea);
104
105 // now reading parameters
106 for(int i_len=0; i_len<theArea.getLength(); i_len++){
107 if(!fin.getline(cLine,sizeof(cLine)-1)) {
108 std::cout << "panic " << std::endl;
109 return std::nullopt;
110 }
111 sLine = cLine;
112 ist.clear(); ist.str(sLine);
113 int idummy;
114 if( !(ist >> idummy) ) {
115 std::cout << "CaloLCCoeffHelper::initDataFromFile() -> Warning! Area " << theArea.getTitle() << " doesn't have parameters." << std::endl;
116 break;
117 }
118 if(idummy != theArea.getOffset()+i_len){
119 std::cout << "CaloLCCoeffHelper::initDataFromFile() ->Error! Could not parse line '" << cLine << "' at p3." << std::endl;
120 return std::nullopt;
121 }
122 for(int j=0; j<theArea.getNdim(); j++) {
123 if(!(ist >> idummy)) {
124 std::cout << "CaloLCCoeffHelper::initDataFromFile() -> panic!" << std::endl;
125 return std::nullopt;
126 }
127 }
129 pars.resize(theArea.getNpars(),0.0);
130 for(int j=0; j<theArea.getNpars(); j++) {
131 if( !(ist >> pars[j]) ) {
132 std::cout << "CaloLCCoeffHelper::initDataFromFile() ->Error! Could not parse line '" << cLine << "' at p4." << std::endl;
133 std::cout << " dmArea.m_title" << theArea.getTitle() << std::endl;
134 return std::nullopt;
135 }
136 }
137 data->setCoeff(theArea.getOffset()+i_len, pars);
138 }
139 }
140 fin.close();
141
142 return data;
143}
144
145
146
147/* ****************************************************************************
148
149**************************************************************************** */
151{
152 std::ofstream fout;
153 fout.open(fname);
154 PrintData(data, fout);
155 fout.close();
156}
157
158
159
160/* ****************************************************************************
161
162**************************************************************************** */
164{
165 const char *comments =
166 {
167 "# Coefficients for local hadronic calibration .\n\n"
168 };
169 fout << comments << std::endl;
170 char line[1024];
171
172 // loop over areas
173 for(int i_area=0; i_area < data->getSizeAreaSet(); i_area++){
174 const CaloLocalHadCoeff::LocalHadArea *area = data->getArea(i_area);
175 fout << "area " << i_area << " " << area->getTitle() << " " << area->getType() << " " << area->getNpars() << std::endl;
176 for(int i_dim=0; i_dim<area->getNdim(); i_dim++){
177 const CaloLocalHadCoeff::LocalHadDimension *dim = area->getDimension(i_dim);
178 snprintf(line,sizeof(line),
179 "%-6s %2d %6.3f %12.3f ",dim->getTitle().c_str(), dim->getNbins(), dim->getXmin(), dim->getXmax() );
180 std::string sline(line);
181 sline += "flat";
182 fout << sline;
183// if( !dim.m_xbins.size() ) {
184// sline += "flat";
185// fout << sline;
186// }else {
187// sline += "hand";
188// fout << sline;
189// for(unsigned int i=0; i<dim.m_xbins.size(); i++){
190// fout << " " << dim.m_xbins[i];
191// }
192// }
193 fout << std::endl;
194 }
195 fout << "break" << std::endl; // i.e. no more dimensions
196
197 // now printing the data
198 for(int i_data=0; i_data<area->getLength(); i_data++) {
199 int indx = area->getOffset() + i_data;
200 const CaloLocalHadCoeff::LocalHadCoeff *pars = data->getCoeff(indx);
201 if( !pars ) {
202 std::cout << "CaloLCCoeffHelper::PrintData() -> Error! Wrong bin number" << std::endl;
203 return;
204 }
205 fout << std::format("{:>5} ", indx);
206 std::vector<int > v_dim_indexes;
207 data->bin2indexes(indx, v_dim_indexes);
208 for(unsigned int i_dim=0; i_dim<v_dim_indexes.size(); i_dim++){
209 fout << std::format("{:>4} ", v_dim_indexes[i_dim]);
210 }
211 fout << " ";
212 for(unsigned int i_par=0; i_par<(*pars).size(); i_par++) {
213 fout << std::format("{:>12.6f} ", (*pars)[i_par]);
214 }
215 fout << std::endl;
216 }
217
218 // end of DM area
219 fout << std::endl;
220 }
221 // printing title strin
222}
223
224
225
226/* **************************************************************************
227 Interpolate data, area in phase space point x, over dimensions dim (all if 0)
228 for speed reason, no check on dim content !!!!!!!!
229*************************************************************************** */
230bool CaloLCCoeffHelper::Interpolate(const CaloLocalHadCoeff *data, const unsigned int n_area,
231 std::vector<float> &x, CaloLocalHadCoeff::LocalHadCoeff &pars,
232 const std::vector<int> &dim, double xfit)
233{
234 // Sanity check
235 if( n_area >= (unsigned int)data->getSizeAreaSet()) return false;
236 // We are not extrapolator
237 if(!data->isFilled(data->getBin(n_area,x))) {
238 return false;
239 }
240
241 const CaloLocalHadCoeff::LocalHadArea *area = data->getArea(n_area);
242 unsigned int ndim;
243 if(dim.empty()) {
244 std::cout << "CaloLCCoeffHelper::Interpolate() -> Error! Empty vector of dimensions to interpolate trough." << std::endl;
245 return false;
246 } else if ( (int)dim.size() > area->getNdim()){
247 std::cout << "CaloLCCoeffHelper::Interpolate() -> Error! Vector of dimensions to interpolate exceed defined in area." << std::endl;
248 return false;
249 } else ndim=dim.size();
250 unsigned int ncorners = (1<<ndim);
251
252 std::vector<double > vXadj(ndim);
253 std::vector<unsigned int > vgbins(ncorners);
254 std::vector<double > vWeights(ncorners);
255 std::vector<int> ebindx;
256 std::vector<int> bx;
257 unsigned int nip;
258
259 switch (area->getType()) {
261 nip = data->getCoeff(area->getOffset()+1)->size();
262 if(area->getType() == CaloLocalHadDefs::AREA_DMFIT) {
263 nip = 1;
264 } else {
265 nip = data->getCoeff(area->getOffset()+1)->size();
266 }
267 pars.resize(nip);
268 for(unsigned int ip=0; ip<nip; ++ip) {
269 bool isa = data->getInterpArrays(n_area,dim,x,vXadj,vgbins);
270 if(! isa) {
271 std::cout<<"No arrays for x: ";
272 for(unsigned int l=0; l<x.size(); ++l) std::cout<<x[l]<<" ";
273 std::cout<<std::endl;
274 return false;
275 }
276 for(unsigned int i_len=0; i_len<ncorners; ++i_len){
277 // Check for empty bin here TODO !!!!!
278 if(data->isFilled(vgbins[i_len])) {
280 data->getCoeff(vgbins[i_len]);
281 if(area->getType() == CaloLocalHadDefs::AREA_DMFIT) {
282 // std::cout << "xxx " << xfit << " " << (*pars)[0] << " " << (*pars)[1] << " " << (*pars)[2] << std::endl;
283 vWeights[i_len] = (*lpars)[0] + (*lpars)[1]*pow(xfit,(*lpars)[2]);
284 } else {
285 vWeights[i_len] = (*lpars)[ip];
286 }
287 // std::cout<<vWeights[i_len]<<" ";
288 } else {
289 // std::cout<<x[0]<<" "<<x[1]<<" : "<<vXadj[0]<<" "<<vXadj[1]<<" | ";
290 // if empty, put inside average over all neighbours in our list
291 vWeights[i_len] = 0.;
292 unsigned int icount = 0;
293 data->bin2indexes(vgbins[i_len],ebindx);
294 // for(unsigned int blen=0; blen<ebindx.size(); ++blen) { std::cout<<ebindx[blen]<<" "; }
295 //std::cout<<" | ";
296 for(unsigned int blen=0; blen<ncorners; ++blen){
297 if(blen == i_len) continue;
298 if(!data->isFilled(vgbins[blen])){
299 data->bin2indexes(vgbins[i_len],bx);
300 //for(unsigned int l=0; l<bx.size(); ++l) { std::cout<<bx[l]<<" "; }
301 //std::cout<<" nf| ";
302 continue;
303 }
304 if(data->isNeighbour(vgbins[blen], ebindx)) {
306 data->getCoeff(vgbins[blen]);
307 if(area->getType() == CaloLocalHadDefs::AREA_DMFIT) {
308 vWeights[i_len] = (*lpars)[0] + (*lpars)[1]*pow(xfit,(*lpars)[2]);
309 } else {
310 vWeights[i_len] += (*lpars)[ip];
311 }
312 ++icount;
313 }
314 }
315 if(icount) {
316 //std::cout<<"i";
317 vWeights[i_len] /= icount;
318 }
319 //std::cout<<vWeights[i_len]<<"a ";
320 //std::cout<<std::endl;
321 }
322 }
323 pars[ip] = CaloWeightInterpolator::getWeight(vWeights,vXadj);
324 }
325 return true;
326 }
327 default: {
328 std::cout<<"Not implemented yet for this Area type !!!"<<std::endl;
329 return false;
330 }
331 }
332 // Should not get here, but syntax needs this
333 return false;
334}
335
336
337
338/* **************************************************************************
339parsing dimension string of type 'ener 8 3.1 6.3'
340*************************************************************************** */
341std::optional<CaloLocalHadCoeff::LocalHadDimension> CaloLCCoeffHelper::parse_dim(const std::string &sLine)
342{
343 std::optional<CaloLocalHadCoeff::LocalHadDimension> dim{std::nullopt};
344 std::istringstream ist(sLine.c_str());
345
346 std::string dim_title;
347 std::string stype;
348 int dim_nbins(0), dim_type(0);
349 float dim_xmax(0), dim_xmin(0);
350
351 if( !(ist >> dim_title >> dim_nbins >> dim_xmin >> dim_xmax >> stype) ){
352 std::cout << "CaloHadDMCoeffHelper::parse_dim() -> Error! Could not parse line '" << sLine << "' at p1." << std::endl;
353 return std::nullopt;
354 }
355
356 // Check nbins for reasonableness --- prevents a coverity warning.
357 if (dim_nbins < 1)
358 dim_nbins = 1;
359 else if (dim_nbins > 10000)
360 dim_nbins = 10000;
361
362 if(stype.find("flat") != std::string::npos) {
363 // equidistant binning
364 dim.emplace(dim_title.c_str(), dim_type, dim_nbins, dim_xmin, dim_xmax);
365 }else if(stype.find("hand") != std::string::npos) {
366 // user defined binning
367 std::vector<float> x_bins;
368 float e;
369 for(int i=0; i<dim_nbins+1; i++) {
370 if( !(ist >> e) ) {
371 std::cout << "CaloHadDMCoeffHelper::parse_dim() -> Error! Could not parse line '" << sLine << "' at p2." << std::endl;
372 return std::nullopt;
373 }else{
374 x_bins.push_back(e);
375 }
376 }
377 dim.emplace(dim_title.c_str(), dim_type, x_bins);
378 }else{
379 std::cout << "CaloHadDMCoeffHelper::parse_dim() -> Error! Could not parse line '" << sLine << "' at p3." << std::endl;
380 return std::nullopt;
381 }
382 return dim;
383}
384
double area(double R)
#define x
virtual ~CaloLCCoeffHelper()
static bool Interpolate(const CaloLocalHadCoeff *m_data, const unsigned int n_area, std::vector< float > &x, CaloLocalHadCoeff::LocalHadCoeff &pars, const std::vector< int > &dim, double xfit=0.)
static void PrintData(CaloLocalHadCoeff *m_data, std::ostream &fout)
static std::optional< CaloLocalHadCoeff > InitDataFromFile(const char *fname)
static std::optional< CaloLocalHadCoeff::LocalHadDimension > parse_dim(const std::string &sLine)
static const CaloLocalHadCoeff::LocalHadArea * getAreaFromName(const CaloLocalHadCoeff *m_coeff, const std::string &sname, int &m_indx)
Definition of correction area.
int getLength() const
return area length
const std::string & getTitle() const
return name
int getNdim() const
get number of dimensions
int getNpars() const
return number of parameters
int getOffset() const
return area offset
void addDimension(LocalHadDimension &dim)
to add new dimension
Class defines binning for user dimension.
Hold binned correction data for local hadronic calibration procedure.
const LocalHadArea * getArea(int n_area) const
return area
std::vector< float > LocalHadCoeff
Correction parameters for one general bin.
int getSizeAreaSet() const
return number of areas defined for this data set
static TFile * fout
Definition listroot.cxx:40
static double getWeight(std::vector< double > &w, std::vector< double > &x)