AmpTools
PlotGenerator.cc
Go to the documentation of this file.
1 //******************************************************************************
2 // This file is part of AmpTools, a package for performing Amplitude Analysis
3 //
4 // Copyright Trustees of Indiana University 2010, all rights reserved
5 //
6 // This software written by Matthew Shepherd, Ryan Mitchell, and
7 // Hrayr Matevosyan at Indiana University, Bloomington
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 // 1. Redistributions of source code must retain the above copyright
13 // notice and author attribution, this list of conditions and the
14 // following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright
16 // notice and author attribution, this list of conditions and the
17 // following disclaimer in the documentation and/or other materials
18 // provided with the distribution.
19 // 3. Neither the name of the University nor the names of its contributors
20 // may be used to endorse or promote products derived from this software
21 // without specific prior written permission.
22 //
23 // Creation of derivative forms of this software for commercial
24 // utilization may be subject to restriction; written permission may be
25 // obtained from the Trustees of Indiana University.
26 //
27 // INDIANA UNIVERSITY AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES,
28 // EXPRESS OR IMPLIED. By way of example, but not limitation, INDIANA
29 // UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCANTABILITY OR
30 // FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THIS SOFTWARE OR
31 // DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS,
32 // OR OTHER RIGHTS. Neither Indiana University nor the authors shall be
33 // held liable for any liability with respect to any claim by the user or
34 // any other party arising from use of the program.
35 //******************************************************************************
36 
37 #include <iostream>
38 #include <fstream>
39 #include <string>
40 #include <vector>
41 #include <complex>
42 #include <algorithm>
43 #include <cassert>
44 
49 #include "IUAmpTools/FitResults.h"
50 
52 m_fitResults( results ),
53 // in the context of this class we are not going to modify the
54 // configuration info, but the AmpToolsInterface requires a
55 // non-const pointer for flexiblity so we will cast away
56 // the constness although the ConfigurationInfo will really
57 // remain constant
58 m_ati( const_cast< ConfigurationInfo* >( results.configInfo() ),
59  AmpToolsInterface::kPlotGeneration ),
60 m_cfgInfo( results.configInfo() ),
61 m_fullAmplitudes( 0 ),
62 m_uniqueAmplitudes( 0 ),
63 m_histVect( 0 ),
64 m_histTitles( 0 )
65 {
66 
67  vector< string > amps = m_fitResults.ampList();
68 
69  for( unsigned int i = 0; i < amps.size(); ++i ){
70 
71  m_ampIndex[amps[i]] = i;
72 
73  // keep vector with orginal fit values
74  m_fitProdAmps.push_back( m_fitResults.productionParameter( amps[i] ) );
75 
76  // a parallel vector of zeros
77  m_zeroProdAmps.push_back( complex< double >( 0, 0 ) );
78 
79  // and a vector from which to distribute values to the
80  // amplitude managers (initially this vector is set to
81  // the original fit values)
82  m_prodAmps.push_back( m_fitProdAmps[i] );
83  }
84 
85  // fetch the amplitude parameters
86  m_ampParameters = m_fitResults.ampParMap();
87 
88  vector<ReactionInfo*> rctInfoVector = m_cfgInfo->reactionList();
89 
90  for( unsigned int i = 0; i < rctInfoVector.size(); i++ ){
91 
92  const ReactionInfo* rctInfo = rctInfoVector[i];
93  string reactName = rctInfo->reactionName();
94 
95  m_reactIndex[reactName] = i;
96 
97  // enable the reaction by default
98  m_reactEnabled[rctInfo->reactionName()] = true;
99 
100  // keep a pointer to the NormalizationIntegralInterface
101  m_normIntMap[reactName] = m_ati.normIntInterface( reactName );
102 
103  // keep a pointer to the AmplitudeManager
104  m_intenManagerMap[reactName] = m_ati.intensityManager( reactName );
105 
106  vector< string > ampNames;
107  vector<AmplitudeInfo*> ampInfoVector = m_cfgInfo->amplitudeList( reactName );
108  for (unsigned int j = 0; j < ampInfoVector.size(); j++){
109  ampNames.push_back(ampInfoVector[j]->fullName());
110  }
111 
112  // tell the amplitude manager to look at member data of this class for
113  // the production amplitudes
114  for( vector< string >::iterator ampName = ampNames.begin();
115  ampName != ampNames.end();
116  ++ampName ){
117 
118  m_fullAmplitudes.push_back( *ampName );
119 
120  if( m_ampIndex.find( *ampName ) == m_ampIndex.end() ){
121 
122  cout << "ERROR: cannot find production parameter for: "
123  << *ampName << "\n\tAre fit results and config file consistent?"
124  << endl;
125 
126  assert( false );
127  }
128 
129  complex< double >* prodPtr = &(m_prodAmps[m_ampIndex[*ampName]]);
130  m_intenManagerMap[reactName]->setExternalProductionFactor( *ampName, prodPtr );
131 
132  for( map< string, double >::const_iterator mapItr = m_ampParameters.begin();
133  mapItr != m_ampParameters.end();
134  ++mapItr ){
135 
136  cout << "setting parameter " << mapItr->first << " to " << mapItr->second << endl;
137 
138  m_intenManagerMap[reactName]->setParValue( *ampName, mapItr->first, mapItr->second );
139  }
140  }
141 
142  // now load up the data and MC for that reaction
143  m_ati.loadEvents( m_ati.dataReader( reactName ), i * kNumTypes + kData );
144  m_ati.loadEvents( m_ati.accMCReader( reactName ), i * kNumTypes + kAccMC );
145  m_ati.loadEvents( m_ati.genMCReader( reactName ), i * kNumTypes + kGenMC );
146 
147  // calculate the amplitudes and intensities for the accepted and generated MC
148  m_ati.processEvents( reactName, i * kNumTypes + kAccMC );
149  m_ati.processEvents( reactName, i * kNumTypes + kGenMC );
150  }
151 
152  // buildUniqueAmplitudes will also create an initalize the maps that store
153  // the enable/disable status of the amplitudes and sums
154  buildUniqueAmplitudes();
155  recordConfiguration();
156 }
157 
158 /*Delete the histograms in the cache*/
160  map < string, map< string, vector< Histogram* > > >::iterator hit1;
161  map< string, vector< Histogram* > >::iterator hit2;
162  vector< Histogram* >::iterator hit3;
163 
164  for( map < string, map< string, vector< Histogram* > > >::iterator hit1 = m_accMCHistCache.begin();hit1 != m_accMCHistCache.end();++hit1 ){
165  for( map< string, vector< Histogram* > >::iterator hit2 = (hit1->second).begin();hit2 != (hit1->second).end();++hit2 ){
166  for (vector< Histogram* >::iterator hit3 = (hit2->second).begin();hit3 != (hit2->second).end();++hit3){
167  if (*hit3) delete (*hit3);
168  }
169  }
170  }
171  for( map < string, map< string, vector< Histogram* > > >::iterator hit1 = m_genMCHistCache.begin();hit1 != m_genMCHistCache.end();++hit1 ){
172  for( map< string, vector< Histogram* > >::iterator hit2 = (hit1->second).begin();hit2 != (hit1->second).end();++hit2 ){
173  for (vector< Histogram* >::iterator hit3 = (hit2->second).begin();hit3 != (hit2->second).end();++hit3){
174  if (*hit3) delete (*hit3);
175  }
176  }
177  }
178  for( map < string, map< string, vector< Histogram* > > >::iterator hit1 = m_dataHistCache.begin();hit1 != m_dataHistCache.end();++hit1 ){
179  for( map< string, vector< Histogram* > >::iterator hit2 = (hit1->second).begin();hit2 != (hit1->second).end();++hit2 ){
180  for (vector< Histogram* >::iterator hit3 = (hit2->second).begin();hit3 != (hit2->second).end();++hit3){
181  if (*hit3) delete (*hit3);
182  }
183  }
184  }
185 
186  for( int i=0; i < m_histVect.size(); i++) {
187 
188  if( m_histVect[i] ) delete m_histVect[i];
189  }
190 }
191 
192 pair< double, double >
193 PlotGenerator::intensity( bool accCorrected ) const {
194 
195  vector< string > enabledAmps;
196 
197  // loop over amplitudes and find out what is turned on
198  for( vector< string >::const_iterator amp = m_fullAmplitudes.begin();
199  amp != m_fullAmplitudes.end();
200  ++amp ){
201 
202  vector< string > parts = stringSplit( *amp, "::" );
203 
204  // be sure the reaction, sum, and amplitude are enabled
205  if( !m_reactEnabled.find( parts[0] )->second ) continue;
206  if( !m_sumEnabled.find( parts[1] )->second ) continue;
207  if( !m_ampEnabled.find( parts[2] )->second ) continue;
208 
209  enabledAmps.push_back( *amp );
210  }
211 
212  return m_fitResults.intensity( enabledAmps, accCorrected );
213 }
214 
215 
216 Histogram* PlotGenerator::projection( unsigned int projectionIndex, string reactName,
217  unsigned int type ) {
218 
219  // return an empty histogram if final state is not enabled
220  if( !m_reactEnabled[reactName] ) return NULL;
221 
222  // use same ampConfig for data since data histograms are
223  // independent of which projections are turned on
224  string config = ( type == kData ? "" : m_currentConfiguration );
225 
226  map< string, map< string, vector< Histogram* > > > *cachePtr;
227 
228  switch( type ){
229 
230  case kData:
231 
232  cachePtr = &m_dataHistCache;
233  break;
234 
235  case kAccMC:
236 
237  cachePtr = &m_accMCHistCache;
238  break;
239 
240  case kGenMC:
241 
242  cachePtr = &m_genMCHistCache;
243  break;
244 
245  default:
246 
247  assert( false );
248  }
249  map< string, map< string, vector< Histogram* > > >::iterator ampCfg = cachePtr->find( config );
250 
251  // short circuit here so second condition doesn't get a null ptr
252  if( ( ampCfg == cachePtr->end() ) ||
253  ( ampCfg->second.find( reactName ) == ampCfg->second.end() ) ) {
254 
255  // histograms don't exist
256  // first clear the histogram vector: m_histVect
257  clearHistograms();
258 
259  // this triggers user routines that fill m_histVect
260  fillProjections( reactName, type );
261 
262  //now cache the vector of histograms
263  /*Clone m_histVect content and point the cache to the clone address*/
264  /*m_histVect is a vector<Histogram*>*/
265  m_histVect_clone.clear();
266  for( vector< Histogram* >::iterator hist = m_histVect.begin();hist != m_histVect.end();++hist ){
267  m_histVect_clone.push_back((*hist)->Clone()); //The address of the i-th cloned histogram
268  }
269  (*cachePtr)[config][reactName] = m_histVect_clone;
270 
271  // renormalize MC
272  if( type != kData ){
273 
274  vector< Histogram* >* histVect = &((*cachePtr)[config][reactName]);
275  for( vector< Histogram* >::iterator hist = histVect->begin();
276  hist != histVect->end();
277  ++hist ){
278 
279  switch( type ){
280 
281  case kAccMC: (*hist)->normalize( intensity( false ).first );
282  break;
283 
284  case kGenMC: (*hist)->normalize( intensity( true ).first );
285  break;
286 
287  default:
288  break;
289  }
290  }
291  }
292  }
293 
294  // return the correct histogram:
295  return (*cachePtr)[config][reactName][projectionIndex];
296 }
297 
298 unsigned int
299 PlotGenerator::getAmpIndex( const string& ampName) const {
300 
301  map<string, unsigned int>::const_iterator mapItr = m_ampIndex.find(ampName);
302  if (mapItr == m_ampIndex.end()){
303  cout << "PlotGenerator ERROR: Could not find amplitude " << ampName << endl;
304  assert (false);
305  }
306 
307  return mapItr->second;
308 }
309 
310 void
311 PlotGenerator::bookHistogram( int index, const string& title, Histogram* hist){
312 
313  if( index >= m_histVect.size() ){
314 
315  m_histVect.resize( index + 1 );
316  m_histTitles.resize( index + 1 );
317  }
318 
319  m_histVect[index] = hist;
320  m_histTitles[index] = title;
321 }
322 
323 void
325 
326  bookHistogram( index, hist->title(), hist );
327 }
328 
329 void
330 PlotGenerator::clearHistograms(){
331 
332  for( vector< Histogram*>::iterator hist = m_histVect.begin();
333  hist != m_histVect.end();
334  ++hist ){
335 
336  (*hist)->clear();
337  }
338 }
339 
340 void
341 PlotGenerator::fillProjections( const string& reactName, unsigned int type ){
342 
343  bool isData = ( type == kData ? true : false );
344  int dataIndex = m_reactIndex[reactName] * kNumTypes + type;
345 
346  // calculate intensities for MC:
347  if( !isData ) m_ati.processEvents( reactName, dataIndex );
348 
349  // loop over ampVecs and fill histograms
350  for( unsigned int i = 0; i < m_ati.numEvents( dataIndex ); ++i ){
351 
352  // the subsequent calls here allocate new memory for
353  // the Kinematics object
354  Kinematics* kin = m_ati.kinematics(i, dataIndex);
355 
356  m_currentEventWeight = ( isData ? 1.0 : m_ati.intensity( i, dataIndex ) );
357  // m_ati.intensity already contains a possible MC-event weight
358 
359  // the user defines this function in the derived class and it
360  // calls the fillHistogram method immediately below
361 
362  projectEvent( kin );
363 
364  // cleanup allocated memory
365  delete kin;
366  }
367 }
368 
369 void
370 PlotGenerator::fillHistogram( int histIndex, double valueX ){
371  vector < double > tmp;
372  tmp.push_back(valueX);
373  m_histVect[histIndex]->fill( tmp, m_currentEventWeight );
374 }
375 
376 void
377 PlotGenerator::fillHistogram( int histIndex, double valueX,double valueY ){
378  vector < double > tmp;
379  tmp.push_back(valueX);
380  tmp.push_back(valueY);
381  m_histVect[histIndex]->fill(tmp, m_currentEventWeight );
382 }
383 
384 void
385 PlotGenerator::fillHistogram( int histIndex, vector <double> &data, double weight){
386  m_histVect[histIndex]->fill(data, m_currentEventWeight*weight );
387 }
388 
389 
390 bool
391 PlotGenerator::haveAmp( const string& amp ) const {
392 
393  return ( m_ampIndex.find( amp ) != m_ampIndex.end() );
394 }
395 
396 void
397 PlotGenerator::disableAmp( unsigned int uniqueAmpIndex ){
398 
399  string amp = m_uniqueAmplitudes[uniqueAmpIndex];
400 
401  for( map< string, unsigned int >::iterator mapItr = m_ampIndex.begin();
402  mapItr != m_ampIndex.end();
403  ++mapItr ){
404 
405  vector< string > ampParts = stringSplit( mapItr->first, "::" );
406  if( ampParts[2] != amp ) continue;
407 
408  unsigned int i = mapItr->second;
409 
410  // cout << "Setting production amp for " << mapItr->first << " from "
411  // << m_prodAmps[i] << " to " << m_zeroProdAmps[i] << endl;
412 
413  m_prodAmps[i] = m_zeroProdAmps[i];
414  m_ampEnabled[amp] = false;
415  }
416 
417  recordConfiguration();
418 }
419 
420 void
421 PlotGenerator::enableAmp( unsigned int uniqueAmpIndex ){
422 
423  string amp = m_uniqueAmplitudes[uniqueAmpIndex];
424 
425  for( map< string, unsigned int >::iterator mapItr = m_ampIndex.begin();
426  mapItr != m_ampIndex.end();
427  ++mapItr ){
428 
429  vector< string > ampParts = stringSplit( mapItr->first, "::" );
430  if( ampParts[2] != amp ) continue;
431 
432  unsigned int i = mapItr->second;
433 
434  m_ampEnabled[amp] = true;
435 
436  // on turn back on the amplitude in the amplitude manager if the
437  // sum to which it belogins is also enabled
438 
439  if( m_sumEnabled[ampParts[1]] ){
440 
441  // cout << "Setting production amp for " << mapItr->first << " from "
442  // << m_prodAmps[i] << " to " << m_fitProdAmps[i] << endl;
443 
444  m_prodAmps[i] = m_fitProdAmps[i];
445  }
446  }
447 
448  recordConfiguration();
449 }
450 
451 void
452 PlotGenerator::disableSum( unsigned int uniqueSumIndex ){
453 
454  string sum = m_uniqueSums[uniqueSumIndex];
455 
456  for( map< string, unsigned int >::iterator mapItr = m_ampIndex.begin();
457  mapItr != m_ampIndex.end();
458  ++mapItr ){
459 
460  vector< string > ampParts = stringSplit( mapItr->first, "::" );
461  if( ampParts[1] != sum ) continue;
462 
463  unsigned int i = mapItr->second;
464 
465  m_sumEnabled[sum] = false;
466 
467  // cout << "Setting production amp for " << mapItr->first << " from "
468  // << m_prodAmps[i] << " to " << m_zeroProdAmps[i] << endl;
469 
470  m_prodAmps[i] = m_zeroProdAmps[i];
471  }
472 
473  recordConfiguration();
474 }
475 
476 void
477 PlotGenerator::enableSum( unsigned int uniqueSumIndex ){
478 
479  string sum = m_uniqueSums[uniqueSumIndex];
480 
481  for( map< string, unsigned int >::iterator mapItr = m_ampIndex.begin();
482  mapItr != m_ampIndex.end();
483  ++mapItr ){
484 
485  vector< string > ampParts = stringSplit( mapItr->first, "::" );
486  if( ampParts[1] != sum ) continue;
487 
488  unsigned int i = mapItr->second;
489 
490  m_sumEnabled[sum] = true;
491 
492  // only turn back on this part of the sum if the amplitude
493  // is also enabled
494 
495  if( m_ampEnabled[ampParts[2]] ){
496 
497  // cout << "Setting production amp for " << mapItr->first << " from "
498  // << m_prodAmps[i] << " to " << m_fitProdAmps[i] << endl;
499 
500  m_prodAmps[i] = m_fitProdAmps[i];
501  }
502  }
503 
504  recordConfiguration();
505 }
506 
507 
508 bool
509 PlotGenerator::isAmpEnabled( unsigned int uniqueIndex ) const {
510 
511  map< string, bool >::const_iterator itr =
512  m_ampEnabled.find( m_uniqueAmplitudes[uniqueIndex] );
513 
514  assert( itr != m_ampEnabled.end() );
515 
516  return itr->second;
517 }
518 
519 bool
520 PlotGenerator::isSumEnabled( unsigned int uniqueIndex ) const {
521 
522  map< string, bool >::const_iterator itr =
523  m_sumEnabled.find( m_uniqueSums[uniqueIndex] );
524 
525  assert( itr != m_sumEnabled.end() );
526 
527  return itr->second;
528 }
529 
530 void
531 PlotGenerator::disableReaction( const string& reactName ){
532 
533  m_reactEnabled[reactName] = false;
534 }
535 
536 void
537 PlotGenerator::enableReaction( const string& reactName ){
538 
539  m_reactEnabled[reactName] = true;
540 }
541 
542 bool
543 PlotGenerator::isReactionEnabled( const string& reactName ) const {
544 
545  map< string, bool >::const_iterator mapItr = m_reactEnabled.find( reactName );
546  assert( mapItr != m_reactEnabled.end() );
547  return mapItr->second;
548 }
549 
550 void
551 PlotGenerator::recordConfiguration() {
552 
553  // generate a string to identify the current amplitude configuation
554  // by concatenating all amplitudes together -- this string will
555  // be used as a key in a cache lookup
556 
557  m_currentConfiguration = "";
558 
559  for( vector< string >:: iterator ampItr = m_fullAmplitudes.begin();
560  ampItr != m_fullAmplitudes.end();
561  ++ampItr ){
562 
563  vector< string > ampParts = stringSplit( *ampItr, "::" );
564 
565  if( m_ampEnabled[ampParts[2]] && m_sumEnabled[ampParts[1]] ){
566 
567  m_currentConfiguration += *ampItr;
568  }
569  }
570 }
571 
572 void
573 PlotGenerator::buildUniqueAmplitudes(){
574 
575  m_uniqueAmplitudes.clear();
576  m_uniqueSums.clear();
577 
578  for( vector< string >::iterator amp = m_fullAmplitudes.begin();
579  amp != m_fullAmplitudes.end();
580  ++amp ){
581 
582  vector< string > tok = stringSplit( *amp, "::" );
583 
584  if( find( m_uniqueAmplitudes.begin(), m_uniqueAmplitudes.end(), tok[2] ) ==
585  m_uniqueAmplitudes.end() ){
586 
587  m_uniqueAmplitudes.push_back( tok[2] );
588 
589  // if this amp hasn't been added to the ampEnabled list,
590  // then add it and set it to true
591  if( m_ampEnabled.find( tok[2] ) == m_ampEnabled.end() ) {
592 
593  m_ampEnabled[tok[2]] = true;
594  }
595  }
596 
597  if( find( m_uniqueSums.begin(), m_uniqueSums.end(), tok[1] ) ==
598  m_uniqueSums.end() ){
599 
600  m_uniqueSums.push_back( tok[1] );
601 
602  // if this sum hasn't been added to the sumEnabled list,
603  // then add it and set it to true
604  if( m_sumEnabled.find( tok[1] ) == m_sumEnabled.end() ){
605 
606  m_sumEnabled[tok[1]] = true;
607  }
608  }
609  }
610 }
611 
612 vector< string >
614 
615  vector<string> rcts;
616  vector<ReactionInfo*> rctInfoVector = m_cfgInfo->reactionList();
617  for (unsigned int i = 0; i < rctInfoVector.size(); i++){
618  rcts.push_back(rctInfoVector[i]->reactionName());
619  }
620  return rcts;
621 }
622 
623 vector< string >
624 PlotGenerator::stringSplit(const string& str, const string& delimiters ) const
625 {
626 
627  vector< string > tokens;
628 
629  string::size_type lastPos = str.find_first_not_of(delimiters, 0);
630  string::size_type pos = str.find_first_of(delimiters, lastPos);
631 
632  while (string::npos != pos || string::npos != lastPos)
633  {
634  tokens.push_back(str.substr(lastPos, pos - lastPos));
635  lastPos = str.find_first_not_of(delimiters, pos);
636  pos = str.find_first_of(delimiters, lastPos);
637  }
638 
639  return tokens;
640 }
641 
complex< double > productionParameter(const string &ampName) const
Definition: FitResults.cc:490
bool haveAmp(const string &amp) const
void fillHistogram(int index, double value)
void disableSum(unsigned int uniqueSumIndex)
int numEvents(unsigned int iDataSet=0) const
DataReader * dataReader(const string &reactionName) const
bool isSumEnabled(unsigned int uniqueSumIndex) const
bool isReactionEnabled(const string &reactName) const
vector< string > reactions() const
void enableSum(unsigned int uniqueSumIndex)
void bookHistogram(int index, const string &title, Histogram *hist)
void loadEvents(DataReader *dataReader, unsigned int iDataSet=0)
#define NULL
Definition: URtypes.h:72
double intensity(int iEvent, unsigned int iDataSet=0) const
void disableAmp(unsigned int uniqueAmpIndex)
void disableReaction(const string &fsName)
unsigned int getAmpIndex(const string &ampName) const
void enableReaction(const string &fsName)
pair< double, double > intensity(bool accCorrected=true) const
Definition: FitResults.cc:107
Kinematics * kinematics(int iEvent, unsigned int iDataSet=0)
Histogram * projection(unsigned int projectionIndex, string fsName, unsigned int type)
pair< double, double > intensity(bool accCorrected=true) const
bool isAmpEnabled(unsigned int uniqueAmpIndex) const
IntensityManager * intensityManager(const string &reactionName) const
vector< AmplitudeInfo * > amplitudeList(const string &reactionName="", const string &sumName="", const string &ampName="") const
map< string, double > ampParMap() const
Definition: FitResults.cc:472
vector< string > ampList() const
Definition: FitResults.cc:574
PlotGenerator(const FitResults &fitResults)
vector< ReactionInfo * > reactionList(const string &reactionName="") const
DataReader * accMCReader(const string &reactionName) const
void enableAmp(unsigned int uniqueAmpIndex)
virtual ~PlotGenerator()
double processEvents(string reactionName, unsigned int iDataSet=0)
string reactionName() const
NormIntInterface * normIntInterface(const string &reactionName) const
string title() const
Definition: Histogram.h:77
DataReader * genMCReader(const string &reactionName) const