AmpTools
NormIntInterface.cc
Go to the documentation of this file.
1 
2 //******************************************************************************
3 // This file is part of AmpTools, a package for performing Amplitude Analysis
4 //
5 // Copyright Trustees of Indiana University 2010, all rights reserved
6 //
7 // This software written by Matthew Shepherd, Ryan Mitchell, and
8 // Hrayr Matevosyan at Indiana University, Bloomington
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 // 1. Redistributions of source code must retain the above copyright
14 // notice and author attribution, this list of conditions and the
15 // following disclaimer.
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice and author attribution, this list of conditions and the
18 // following disclaimer in the documentation and/or other materials
19 // provided with the distribution.
20 // 3. Neither the name of the University nor the names of its contributors
21 // may be used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // Creation of derivative forms of this software for commercial
25 // utilization may be subject to restriction; written permission may be
26 // obtained from the Trustees of Indiana University.
27 //
28 // INDIANA UNIVERSITY AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES,
29 // EXPRESS OR IMPLIED. By way of example, but not limitation, INDIANA
30 // UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCANTABILITY OR
31 // FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THIS SOFTWARE OR
32 // DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS,
33 // OR OTHER RIGHTS. Neither Indiana University nor the authors shall be
34 // held liable for any liability with respect to any claim by the user or
35 // any other party arising from use of the program.
36 //******************************************************************************
37 
38 #include <iostream>
39 #include <fstream>
40 #include <vector>
41 #include <string>
42 #include <complex>
43 #include <cassert>
44 #include <cstring>
45 #include <iomanip>
46 
49 #include "IUAmpTools/Kinematics.h"
50 #include "IUAmpTools/DataReader.h"
51 
53 m_pIntenManager( NULL ),
54 m_accMCReader( NULL ),
55 m_genMCReader( NULL ),
56 m_emptyNormIntCache( true ),
57 m_emptyAmpIntCache( true )
58 {}
59 
60 NormIntInterface::NormIntInterface( const string& normIntFile ) :
61 m_pIntenManager( NULL ),
62 m_accMCReader( NULL ),
63 m_genMCReader( NULL ),
64 m_emptyNormIntCache( true ),
65 m_emptyAmpIntCache( true )
66 {
67 
68  cout << "Reading cached normalization integral calculation from: "
69  << normIntFile << endl;
70 
71  ifstream inFile( normIntFile.c_str() );
72 
73  if( !inFile ){
74  cout << "NormIntInterface WARNING: Could not find file "
75  << normIntFile << endl;
76  assert( false );
77  }
78 
79  inFile >> (*this);
80 }
81 
82 
84  DataReader* accMCData,
86 m_pIntenManager( &intenManager ),
87 m_accMCReader( accMCData ),
88 m_genMCReader( genMCData ),
89 m_emptyNormIntCache( true ),
90 m_emptyAmpIntCache( true ),
91 m_termNames( intenManager.getTermNames() )
92 {
93  assert( ( m_accMCReader != NULL ) && ( m_genMCReader != NULL ) );
94 
95  m_termNames = intenManager.getTermNames();
96 
97  m_nGenEvents = m_genMCReader->numEvents();
98  m_nAccEvents = m_accMCReader->numEvents();
99 
100  initializeCache();
101 }
102 
103 
104 istream&
106 {
107  input >> m_nGenEvents >> m_nAccEvents;
108 
109  int numTerms;
110  input >> numTerms;
111 
112  m_termNames.clear();
113  m_termIndex.clear();
114 
115  for( int i = 0; i < numTerms; ++i ){
116 
117  string name;
118  input >> name;
119  m_termNames.push_back( name );
120  m_termIndex[name] = i;
121  }
122 
123  initializeCache();
124 
125  for( int i = 0; i < numTerms; ++i ){
126  for( int j = 0; j < numTerms; ++j ){
127 
128  complex< double > integral;
129  input >> integral;
130 
131  m_ampIntCache[2*i*numTerms+2*j] = real( integral );
132  m_ampIntCache[2*i*numTerms+2*j+1] = imag( integral );
133  }
134  }
135 
136  for( int i = 0; i < numTerms; ++i ){
137  for( int j = 0; j < numTerms; ++j ){
138 
139  complex< double > integral;
140  input >> integral;
141 
142  m_normIntCache[2*i*numTerms+2*j] = real( integral );
143  m_normIntCache[2*i*numTerms+2*j+1] = imag( integral );
144  }
145  }
146 
147  m_emptyNormIntCache = false;
148  m_emptyAmpIntCache = false;
149 
150  return input;
151 }
152 
153 void
155 {
156 
157  double nAccEvts = nii.numAccEvents();
158  double nGenEvts = nii.numGenEvents();
159 
160  double totalAccEvts = nAccEvts + m_nAccEvents;
161  double totalGenEvts = nGenEvts + m_nGenEvents;
162 
163  string ampName, conjAmpName;
164 
165  int n = m_termNames.size();
166 
167  for( int i = 0; i < n; ++i ){
168  for( int j = 0; j < n; ++j ){
169 
170  m_ampIntCache[2*i*n+j] *= m_nAccEvents;
171  m_ampIntCache[2*i*n+j+1] *= m_nAccEvents;
172 
173  complex< double > ai = nii.ampInt( m_termNames[i], m_termNames[j] );
174 
175  m_ampIntCache[2*i*n+j] += nAccEvts * real( ai );
176  m_ampIntCache[2*i*n+j+1] += nAccEvts * imag( ai );
177 
178  m_ampIntCache[2*i*n+j] /= totalAccEvts;
179  m_ampIntCache[2*i*n+j+1] /= totalAccEvts;
180 
181 
182  m_ampIntCache[2*i*n+j] *= m_nGenEvents;
183  m_ampIntCache[2*i*n+j+1] *= m_nGenEvents;
184 
185  complex< double > ni = nii.normInt( m_termNames[i], m_termNames[j] );
186 
187  m_ampIntCache[2*i*n+j] += nGenEvts * real( ni );
188  m_ampIntCache[2*i*n+j+1] += nGenEvts * imag( ni );
189 
190  m_ampIntCache[2*i*n+j] /= totalGenEvts;
191  m_ampIntCache[2*i*n+j+1] /= totalGenEvts;
192 
193  }
194  }
195 
196 
197  m_nAccEvents = totalAccEvts;
198  m_nGenEvents = totalGenEvts;
199 
200  m_emptyNormIntCache = false;
201  m_emptyAmpIntCache = false;
202 }
203 
204 bool
206 {
207 
208  return( ( m_accMCReader != NULL ) &&
209  ( m_genMCReader != NULL ) &&
210  ( m_pIntenManager != NULL ) );
211 }
212 
213 bool
214 NormIntInterface::hasNormInt( string amp, string conjAmp ) const
215 {
216 
217  return( ( m_termIndex.find( amp ) != m_termIndex.end() ) &&
218  ( m_termIndex.find( conjAmp ) != m_termIndex.end() ) );
219 }
220 
221 
222 complex< double >
223 NormIntInterface::normInt( string amp, string conjAmp, bool forceUseCache ) const
224 {
225 
226  if( !hasNormInt( amp, conjAmp ) ){
227 
228  cout << "ERROR: normalization integral does not exist for "
229  << amp << ", " << conjAmp << "*" << endl;
230  assert( false );
231  }
232 
233  // pass in true flag to delay computation of amplitude integrals as
234  // long as possible
235 
236  if( m_emptyNormIntCache ) forceCacheUpdate( true );
237 
238  if( !hasAccessToMC() && ( m_pIntenManager != NULL ) &&
239  m_pIntenManager->hasTermWithFreeParam() ){
240 
241  cout << "ERROR: the AmplitudeManager has amplitudes that contain free\n"
242  << " parameters, but no MC has been provided to recalculate\n"
243  << " the normalization integrals. Check that config file\n"
244  << " lists appropriate data and MC sources." << endl;
245 
246  assert( false );
247  }
248 
249  if( !forceUseCache && hasAccessToMC() &&
250  ( m_pIntenManager != NULL ) && m_pIntenManager->hasTermWithFreeParam() ){
251 
252  m_pIntenManager->calcIntegrals( m_mcVecs, m_nGenEvents );
254  }
255 
256  int n = m_termNames.size();
257  int i = m_termIndex.find( amp )->second;
258  int j = m_termIndex.find( conjAmp )->second;
259 
260  return complex< double >( m_normIntCache[2*i*n+2*j],
261  m_normIntCache[2*i*n+2*j+1] );
262 }
263 
264 
265 bool
266 NormIntInterface::hasAmpInt( string amp, string conjAmp ) const
267 {
268 
269  // it is not possible to have one and not the other anymore
270 
271  return hasNormInt( amp, conjAmp );
272 }
273 
274 
275 complex< double >
276 NormIntInterface::ampInt( string amp, string conjAmp, bool forceUseCache ) const
277 {
278 
279  if( m_emptyAmpIntCache ) forceCacheUpdate();
280 
281  if( !forceUseCache && ( m_pIntenManager != NULL ) &&
282  m_pIntenManager->hasTermWithFreeParam() ){
283 
284  cout << "WARNING: request of for numerical integral of amplitude\n"
285  << " that has floating parameters using *generated* MC.\n"
286  << " (This is not typically used in a fit -- check for bugs!)\n"
287  << " Providing original cached value which may be incorrect if\n"
288  << " the parameter has changed since initialization."
289  << endl;
290 
291  // problem: this *is* used in a fit if the renormalizeAmps is turned on
292  // and there is a floating parameter in one of the amplitudes
293  // add code here to load up generated MC and hang onto it
294  // print a notice that we're hogging memory in this configuration
295  // for now renormalize is disabled in AmplitudeManager to avoid
296  // confusing the user
297  }
298 
299 
300  if( !hasAmpInt( amp, conjAmp ) ){
301 
302  cout << "ERROR: amplitude integral does not exist for "
303  << amp << ", " << conjAmp << "*" << endl;
304  assert( false );
305  }
306 
307  int n = m_termNames.size();
308  int i = m_termIndex.find( amp )->second;
309  int j = m_termIndex.find( conjAmp )->second;
310 
311  return complex< double >( m_ampIntCache[2*i*n+2*j],
312  m_ampIntCache[2*i*n+2*j+1] );
313 }
314 
315 void
316 NormIntInterface::forceCacheUpdate( bool normIntOnly ) const
317 {
318 
319  // if the accepted MC is not available, then the data have likely
320  // not been loaded into AmpVecs and we can't reclaculate the integrals
321  // below
322  assert( m_accMCReader != NULL );
323 
324  if( !m_emptyNormIntCache && normIntOnly ){
325 
326  // we can assume that m_mcVecs contains the accepted MC since the
327  // generated MC is never left in m_mcVecs
328 
329  m_pIntenManager->calcIntegrals( m_mcVecs, m_nGenEvents );
331 
332  m_emptyNormIntCache = false;
333 
334  // stop here if we just want the norm ints -- this will likely be the normal
335  // mode of operation for NI recalculations during a fit
336  return;
337  }
338 
339  if( !normIntOnly ){
340 
341  // now we need to have the generated MC in addition to the accepted
342  // MC in order to be able to continue
343  assert( m_genMCReader != NULL );
344 
345  // flush this if anything is loaded
346  m_mcVecs.deallocAmpVecs();
347 
348  cout << "Loading generated Monte Carlo..." << endl;
349  m_mcVecs.loadData( m_genMCReader );
350  m_mcVecs.allocateTerms( *m_pIntenManager );
351  cout << "\tDone.\n" << flush;
352 
353  cout << "Calculating integrals..." << endl;
354  m_pIntenManager->calcIntegrals( m_mcVecs, m_nGenEvents );
356  cout << "\tDone." << endl;
357 
358  m_emptyAmpIntCache = false;
359  }
360 
361  if( ( m_accMCReader == m_genMCReader ) && !m_emptyAmpIntCache )
362  {
363  // optimization for perfect acceptance
364  cout << "Perfect acceptance -- using integrals from generated MC" << endl;
365 
366  setNormIntMatrix( m_ampIntCache );
367  }
368  else
369  {
370  // load the accepted MC -- always leave accepted MC in memory
371  m_mcVecs.deallocAmpVecs();
372 
373  cout << "Loading acccepted Monte Carlo..." << endl;
374  m_mcVecs.loadData( m_accMCReader );
375  m_mcVecs.allocateTerms( *m_pIntenManager );
376  cout << "\tDone." << endl;
377 
378  // since we have flushed the amplitudes from AmpVecs we need
379  // to recalcualte them or else subsequent calls to calcIntegrals
380  // with firstPass set to false will fail
381  cout << "Calculating integrals..." << endl;
382  m_pIntenManager->calcIntegrals( m_mcVecs, m_nGenEvents );
384 
385  cout << "\tDone." << endl;
386  }
387 
388  m_emptyNormIntCache = false;
389 
390  // this method always leaves class in state with m_mcVecs holding accepted MC
391 }
392 
393 void
394 NormIntInterface::exportNormIntCache( const string& fileName, bool renormalize) const
395 {
396  ofstream out( fileName.c_str() );
397  out.precision( 15 );
398  exportNormIntCache( out, renormalize );
399 }
400 
401 void
402 NormIntInterface::exportNormIntCache( ostream& out, bool renormalize) const
403 {
404  if( m_emptyNormIntCache || m_emptyAmpIntCache ) forceCacheUpdate();
405 
406  out << m_nGenEvents << "\t" << m_nAccEvents << endl;
407 
408  out << m_termNames.size() << endl;
409 
410  for( vector< string >::const_iterator name = m_termNames.begin();
411  name != m_termNames.end();
412  ++name ){
413 
414  out << *name << endl;
415  }
416 
417  int n = m_termNames.size();
418 
419  // write out generated matrix first
420  for( int i = 0; i < n ; ++i ){
421  for( int j = 0; j < n; ++j ) {
422 
423  complex< double > value( m_ampIntCache[2*i*n+2*j],
424  m_ampIntCache[2*i*n+2*j+1] );
425 
426  if( renormalize ){
427 
428  // diagonal elements are real so we don't need to deal
429  // with the imaginary part in the renormalization
430 
431  value /= sqrt( m_ampIntCache[2*i*n+2*i] *
432  m_ampIntCache[2*j*n+2*j] );
433 
434  }
435 
436  out << value << "\t";
437  }
438 
439  out << endl;
440  }
441 
442  // then accepted matrix
443  for( int i = 0; i < n ; ++i ){
444  for( int j = 0; j < n; ++j ) {
445 
446  complex< double > value( m_normIntCache[2*i*n+2*j],
447  m_normIntCache[2*i*n+2*j+1] );
448 
449  if( renormalize ){
450 
451  // diagonal elements are real so we don't need to deal
452  // with the imaginary part in the renormalization
453  // renormalize by generated so one has efficiency on
454  // the diagonal for the accepted matrix
455 
456  value /= sqrt( m_ampIntCache[2*i*n+2*i] *
457  m_ampIntCache[2*j*n+2*j] );
458 
459  }
460 
461  out << value << "\t";
462  }
463 
464  out << endl;
465  }
466 }
467 
468 void
469 NormIntInterface::initializeCache() {
470 
471  int n = m_termNames.size();
472 
473  for( int i = 0; i < n; ++i )
474  m_termIndex[m_termNames[i]] = i;
475 
476  // 2 for real and imaginary
477  // allocate for the whole matrix even though it is square under
478  // complex conjugation so that memory lookups are easier
479  m_cacheSize = 2*n*n;
480 
481  m_normIntCache = new GDouble[m_cacheSize];
482  m_ampIntCache = new GDouble[m_cacheSize];
483 
484  memset( m_normIntCache, 0, m_cacheSize * sizeof( GDouble ) );
485  memset( m_ampIntCache, 0, m_cacheSize * sizeof( GDouble ) );
486 }
487 
488 void
490 
491  memcpy( m_ampIntCache, input, m_cacheSize * sizeof( GDouble ) );
492  m_emptyAmpIntCache = false;
493 }
494 
495 void
496 NormIntInterface::setNormIntMatrix( const double* input ) const {
497 
498  memcpy( m_normIntCache, input, m_cacheSize * sizeof( GDouble ) );
499  m_emptyNormIntCache = false;
500 }
int numAccEvents() const
void exportNormIntCache(const string &fileName, bool renormalize=false) const
void allocateTerms(const IntensityManager &intenMan, bool bAllocIntensity=false)
Definition: AmpVecs.cc:235
virtual complex< double > normInt(string amp, string conjAmp, bool forceUseCache=false) const
const IntensityManager * intenManager() const
bool hasNormInt(string amp, string conjAmp) const
void operator+=(const NormIntInterface &nii)
virtual complex< double > ampInt(string amp, string conjAmp, bool forceUseCache=false) const
double GDouble
virtual void forceCacheUpdate(bool normIntOnly=false) const
void deallocAmpVecs()
Definition: AmpVecs.cc:73
bool hasAmpInt(string amp, string conjAmp) const
virtual bool hasTermWithFreeParam() const =0
const vector< string > & getTermNames() const
#define NULL
Definition: URtypes.h:72
double sqrt(double)
bool hasAccessToMC() const
virtual unsigned int numEvents() const =0
void loadData(DataReader *pDataReader, bool bForceNegativeWeight=false)
Definition: AmpVecs.cc:193
void setAmpIntMatrix(const double *input) const
istream & loadNormIntCache(istream &in)
virtual void calcIntegrals(AmpVecs &ampVecs, int iNGenEvents) const =0
int numGenEvents() const
GDouble * m_pdIntegralMatrix
Definition: AmpVecs.h:132
void setNormIntMatrix(const double *input) const