AmpTools
ParameterManager.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 <cassert>
41 #include <string>
42 
50 
52  IntensityManager* intenManager ) :
53 MIObserver(),
54 m_minuitManager( minuitManager ),
55 m_intenManagers( 0 )
56 {
57  m_minuitManager->attach( this );
58  m_intenManagers.push_back(intenManager);
59 // cout << "Parameter manager initialized." << endl;
60 }
61 
62 ParameterManager::
63 ParameterManager( MinuitMinimizationManager* minuitManager,
64  const vector<IntensityManager*>& intenManagers ) :
65 MIObserver(),
66 m_minuitManager( minuitManager ),
67 m_intenManagers( intenManagers )
68 {
69  m_minuitManager->attach( this );
70 // cout << "Parameter manager initialized." << endl;
71 }
72 
73 // protected constructors: these are used in MPI implementations where
74 // the ParameterManager is created on a worker node that does not have
75 // a MinuitMinimizationManager. The reference must be initialized, so
76 // it is initialized to NULL but never used. The class using these
77 // constructors must override any method that uses the
78 // MinuitMinimizationManager in order to avoid dereferencing a null
79 // pointer.
80 
82  m_minuitManager( NULL ),
83  m_intenManagers( 0 )
84 {
85  m_intenManagers.push_back(ampManager);
86 // cout << "Parameter manager initialized." << endl;
87 }
88 
89 ParameterManager::
90 ParameterManager( const vector<IntensityManager*>& intenManagers ) :
91  m_minuitManager( NULL ),
92  m_intenManagers( intenManagers )
93 {
94 // cout << "Parameter manager initialized." << endl;
95 }
96 
98 {
99  for( vector< ComplexParameter* >::iterator parItr = m_prodPtrCache.begin();
100  parItr != m_prodPtrCache.end();
101  ++parItr ){
102 
103  delete *parItr;
104  }
105 
106  for( vector< MinuitParameter* >::iterator parItr = m_ampPtrCache.begin();
107  parItr != m_ampPtrCache.end();
108  ++parItr ){
109 
110  delete *parItr;
111  }
112 
113  for( vector< GaussianBound* >::iterator boundItr = m_boundPtrCache.begin();
114  boundItr != m_boundPtrCache.end();
115  ++boundItr ){
116 
117  delete *boundItr;
118  }
119 }
120 
121 void
123 
124  vector< AmplitudeInfo* > amps = cfgInfo->amplitudeList();
125 
126  m_constraintMap = cfgInfo->constraintMap();
127 
128  // separate creation of amplitude parameters from production parameters
129  // in order to make the error matrix more easily separable
130  // practically, this just means two loops below
131 
132  for( vector< AmplitudeInfo* >::iterator ampItr = amps.begin();
133  ampItr != amps.end();
134  ++ampItr ){
135 
136  addProductionParameter( (**ampItr).fullName(), (**ampItr).real(), (**ampItr).fixed() );
137  }
138 
139  for( vector< AmplitudeInfo* >::iterator ampItr = amps.begin();
140  ampItr != amps.end();
141  ++ampItr ){
142 
143  vector< ParameterInfo* > pars = (**ampItr).parameters();
144 
145  for( vector< ParameterInfo* >::const_iterator parItr = pars.begin();
146  parItr != pars.end();
147  ++parItr ){
148 
149  addAmplitudeParameter( (**ampItr).fullName(), *parItr );
150  }
151  }
152 }
153 
154 
155 void
156 ParameterManager::addAmplitudeParameter( const string& termName, const ParameterInfo* parInfo ){
157 
158  const string& parName = parInfo->parName();
159 
160  // see if this is a parameter that we already know about
161 
162  map< string, MinuitParameter* >::iterator mapItr = m_ampParams.find( parName );
163  MinuitParameter* parPtr;
164 
165  if( mapItr == m_ampParams.end() ){
166 
167 // cout << "Creating new amplitude parameter: " << parInfo->parName() << endl;
168 
169  parPtr = new MinuitParameter( parName, m_minuitManager->parameterManager(),
170  parInfo->value());
171 
172  // attach to allow the parameter to call back this class when it is updated
173  parPtr->attach( this );
174 
175  if( parInfo->fixed() ){
176 
177  parPtr->fix();
178  }
179 
180  if( parInfo->bounded() ){
181 
182  parPtr->bound( parInfo->lowerBound(), parInfo->upperBound() );
183  }
184 
185  if( parInfo->gaussianBounded() ){
186 
187  GaussianBound* boundPtr =
188  new GaussianBound( m_minuitManager, parPtr, parInfo->centralValue(),
189  parInfo->gaussianError() );
190 
191  m_boundPtrCache.push_back( boundPtr );
192  }
193 
194  // keep track of new objects that are being allocated
195  m_ampPtrCache.push_back( parPtr );
196  m_ampParams[parName] = parPtr;
197  }
198  else{
199 
200  parPtr = mapItr->second;
201  }
202 
203  // find the Amplitude Manager that has the relevant amplitude
204  bool foundOne = false;
205  vector< IntensityManager* >::iterator intenManPtr = m_intenManagers.begin();
206  for( ; intenManPtr != m_intenManagers.end(); ++intenManPtr ){
207 
208  if( !(*intenManPtr)->hasTerm( termName ) ) continue;
209 
210  foundOne = true;
211 
212  if( parInfo->fixed() ){
213 
214  // if it is fixed just go ahead and set the parameter by value
215  // this prevents Amplitude class from thinking that is has
216  // a free parameter
217 
218  (**intenManPtr).setParValue( termName, parName, parInfo->value() );
219  }
220  else{
221 
222  (**intenManPtr).setParPtr( termName, parName, parPtr->constValuePtr() );
223  }
224  }
225 
226  if( !foundOne ){
227 
228  cout << "WARNING: could not find amplitude named " << termName
229  << " while trying to set parameter " << parName << endl;
230  }
231 }
232 
233 void
234 ParameterManager::addProductionParameter( const string& termName, bool real, bool fixed )
235 {
236 
237  // find the Amplitude Manager that has this amplitude
238 
239  vector< IntensityManager* >::iterator intenManPtr = m_intenManagers.begin();
240  for( ; intenManPtr != m_intenManagers.end(); ++intenManPtr ){
241  if( (*intenManPtr)->hasTerm( termName ) ) break;
242  }
243  if( intenManPtr == m_intenManagers.end() ){
244  cout << "ParameterManager ERROR: Could not find production amplitude for "
245  << termName << endl;
246  assert( false );
247  }
248 
249  // get the parameter's initial value from the amplitude manager
250  // (The productionAmp method will return the scaled production amplitude
251  // we need to divide out the scale to get the production parameter initial
252  // value that was specified in the configuration file.)
253  complex< double > initialValue = (**intenManPtr).productionFactor( termName ) /
254  (double)(**intenManPtr).getScale( termName );
255 
256  // find the ComplexParameter for this amplitude or an amplitude constrained to
257  // be the same as this amplitude
258 
259  ComplexParameter* par = findParameter(termName);
260 
261  // create ComplexParameter from scratch if it doesn't already exist
262 
263  if (!par){
264 // cout << "ParameterManager: Creating new complex production amplitude parameter for "
265 // << termName << endl;
266  par = new ComplexParameter( termName, *m_minuitManager, initialValue, real );
267  m_prodPtrCache.push_back( par );
268  }
269 
270  if( fixed ) par->fix();
271 
272  // update the amplitude manager
273 
274  (**intenManPtr).setExternalProductionFactor( termName,
275  par->constValuePtr() );
276 
277  // record this parameter
278 
279  m_prodParams[termName] = par;
280 
281 }
282 
283 complex< double >*
284 ParameterManager::getProdParPtr( const string& termName ){
285 
286  map< string, ComplexParameter* >::iterator mapItr
287  = m_prodParams.find( termName );
288 
289  // make sure we found one
290  assert( mapItr != m_prodParams.end() );
291 
292  return mapItr->second->valuePtr();
293 }
294 
295 double*
296 ParameterManager::getAmpParPtr( const string& parName ){
297 
298  map< string, MinuitParameter* >::iterator mapItr = m_ampParams.find( parName );
299 
300  // make sure we found one
301  assert( mapItr != m_ampParams.end() );
302 
303  return mapItr->second->valuePtr();
304 }
305 
306 bool
307 ParameterManager::hasConstraints( const string& termName ) const{
308  map<string, vector<string> >::const_iterator
309  mapItr = m_constraintMap.find(termName);
310  return (mapItr != m_constraintMap.end()) ? true : false;
311 }
312 
313 bool
314 ParameterManager::hasParameter( const string& termName ) const{
315  map<string, ComplexParameter* >::const_iterator
316  mapItr = m_prodParams.find(termName);
317  return (mapItr != m_prodParams.end()) ? true : false;
318 }
319 
321 ParameterManager::findParameter( const string& termName) const{
322 
323  // return the parameter associated with this amplitude if it is already defined
324 
325  map<string, ComplexParameter*>::const_iterator pItr = m_prodParams.find(termName);
326  if (pItr != m_prodParams.end()) return pItr->second;
327 
328  // otherwise look for a parameter associated with an amplitude that is
329  // constrained to be the same as this amplitude
330 
331  map<string, vector<string> >::const_iterator cItr = m_constraintMap.find(termName);
332  if (cItr == m_constraintMap.end()) return NULL;
333 
334  vector<string> constraints = cItr->second;
335  for (unsigned int i = 0; i < constraints.size(); i++){
336  pItr = m_prodParams.find(constraints[i]);
337  if (pItr != m_prodParams.end()) return pItr->second;
338  }
339 
340  return NULL;
341 }
342 
343 void
345 
346  // this method is called whenever any parameter changes
347  // if it is an amplitude parameter, we want to notify the
348  // amplitude of the change
349 
350  // first loop over the map containing the parameter pointers and
351  // try to find the one that matches parPtr
352 
353  for( map< string, MinuitParameter* >::const_iterator mapItr = m_ampParams.begin();
354  mapItr != m_ampParams.end();
355  ++mapItr ){
356 
357  if( mapItr->second == parPtr ){
358 
359  // we found the relevant param -- now notify all amplitude managers that
360  // the parameter has changed
361 
362  update( mapItr->first );
363  }
364  }
365 
366  updateParCovariance();
367 }
368 
369 void
370 ParameterManager::update( const string& parName ){
371 
372  // useful to have this method available to update by name
373 
374  for( vector< IntensityManager* >::const_iterator intenMan = m_intenManagers.begin();
375  intenMan != m_intenManagers.end();
376  ++intenMan ){
377 
378  (**intenMan).updatePar( parName );
379  }
380 }
381 
382 void
383 ParameterManager::updateParCovariance(){
384 
385  // build a vector that provides the MINUIT parameter index i for
386  // the real parts of the production parameters, if there is an imaginary
387  // part it will have an index of i + 1
388 
389  vector< int > prodParMinuitIndex( 0 );
390  int numMinuitPars = 0;
391  for( vector< ComplexParameter* >::const_iterator par = m_prodPtrCache.begin();
392  par != m_prodPtrCache.end();
393  ++par ){
394 
395  if( (**par).isFixed() ){
396 
397  // if the production parameter is fixed, then it won't
398  // have a MINUIT index and were going to set this to kFixedIndex
399  // later in building minuitParIndex, but we need an entry in this
400  // vector for that ComplexParameter
401 
402  prodParMinuitIndex.push_back( kFixedIndex );
403  }
404  else{
405 
406  prodParMinuitIndex.push_back( numMinuitPars );
407  numMinuitPars += ( (**par).isPurelyReal() ? 1 : 2 );
408  }
409  }
410 
411  vector< int > minuitParIndex( 0 );
412 
413  // build the list of parameters by looping over all amplitude managers and looping
414  // over all amplitudes
415 
416  m_parList.clear();
417  m_parValues.clear();
418  m_parIndex.clear();
419 
420  int index = 0;
421  for( vector< IntensityManager* >::const_iterator intenMan = m_intenManagers.begin();
422  intenMan != m_intenManagers.end();
423  ++intenMan ){
424 
425  const vector< string >& termNames = (**intenMan).getTermNames();
426  for( vector< string >::const_iterator name = termNames.begin();
427  name != termNames.end();
428  ++name ){
429 
430  // this will return the complex parameter associated with
431  // this amplitude or the complex parameter to which this
432  // amplitude is constrained
433  const ComplexParameter* prodPar = findParameter( *name );
434 
435  // now determine the index of this parameter in the cache
436  vector< ComplexParameter* >::const_iterator parItr =
437  find( m_prodPtrCache.begin(), m_prodPtrCache.end(), prodPar );
438  assert( parItr != m_prodPtrCache.end() );
439  int cacheIndex = parItr - m_prodPtrCache.begin();
440 
441  // if the parameter is fixed, the real part won't
442  // have a MINUIT index, save kFixedIndex (negative) and watch
443  // out for this when building the error matrix
444  // (this is a redundant check since the check has already been
445  // done above in building prodParMinuitIndex, but it helps
446  // to make the code a little clearer)
447  minuitParIndex.push_back( prodPar->isFixed() ?
448  kFixedIndex : prodParMinuitIndex[cacheIndex] );
449 
450  // record the other values
451  m_parList.push_back( (*name) + "_re" );
452  m_parValues.push_back( real( prodPar->value() ) );
453  m_parIndex[m_parList.back()] = index++;
454 
455  // if the parameter is purely real or fixed, the imaginary part won't
456  // have a MINUIT index, save kFixedIndex (negative) and watch
457  // out for this when building the error matrix
458  minuitParIndex.push_back( prodPar->isPurelyReal() || prodPar->isFixed() ?
459  kFixedIndex : prodParMinuitIndex[cacheIndex] + 1 );
460 
461  // record the imaginary parameter info
462  m_parList.push_back( (*name) + "_im" );
463  m_parValues.push_back( imag( prodPar->value() ) );
464  m_parIndex[m_parList.back()] = index++;
465  }
466  }
467 
468  // finish this list by looping over all the amplitude parameters
469 
470  for( vector< MinuitParameter* >::const_iterator ampPar = m_ampPtrCache.begin();
471  ampPar != m_ampPtrCache.end();
472  ++ampPar ){
473 
474  // if the parameter is not floating, it won't have a row in the covariance matrix
475 
476  if( (**ampPar).floating() ){
477 
478  // the MINUIT parameter indices number
479  // sequentially after the production parameters
480 
481  minuitParIndex.push_back( numMinuitPars );
482  ++numMinuitPars;
483  }
484  else{
485 
486  minuitParIndex.push_back( kFixedIndex );
487  }
488 
489  m_parList.push_back( (**ampPar).name() );
490  m_parValues.push_back( (**ampPar).value() );
491  m_parIndex[m_parList.back()] = index++;
492  }
493 
494  // now we have a flat list of all the (real valued) parameters
495  // we need to fill out the covariance matrix
496 
497  int nPar = m_parList.size();
498 
499  const vector< vector< double > >& minCovMtx =
500  m_minuitManager->parameterManager().covarianceMatrix();
501 
502  m_covMatrix.clear();
503  for( int i = 0; i < nPar; ++i ){
504 
505  // create a new covariance matrix row
506  m_covMatrix.push_back( vector< double >( nPar ) );
507 
508  for( int j = 0; j < nPar; ++j ){
509 
510  int iIndex = minuitParIndex[i];
511  int jIndex = minuitParIndex[j];
512 
513  // if either i or j are a fixed parameter we set the
514  // index
515 
516  if( iIndex == kFixedIndex || jIndex == kFixedIndex ){
517 
518  m_covMatrix[i][j] = 0;
519  continue;
520  }
521 
522  // this shouldn't happen -- if it does, something has
523  // gone wrong with the parameter numbering or the
524  // construction of the covariance matrix and we should
525  // crash
526 
527  assert( iIndex < minCovMtx.size() );
528  assert( jIndex < minCovMtx.size() );
529 
530  m_covMatrix[i][j] = minCovMtx[iIndex][jIndex];
531  }
532  }
533 }
bool fixed() const
double * getAmpParPtr(const string &parName)
double gaussianError() const
bool gaussianBounded() const
void setupFromConfigurationInfo(ConfigurationInfo *cfgInfo)
bool hasConstraints(const string &ampName) const
bool bounded() const
map< string, vector< string > > constraintMap() const
double upperBound() const
double value() const
ParameterManager(MinuitMinimizationManager *minuitManager, IntensityManager *intenManager)
virtual void addAmplitudeParameter(const string &ampName, const ParameterInfo *parInfo)
void bound(double lowerBound, double upperBound)
const double * constValuePtr() const
Definition: Parameter.h:55
void update(const MISubject *parPtr)
#define NULL
Definition: URtypes.h:72
virtual void addProductionParameter(const string &ampName, bool real=false, bool fixed=false)
void attach(MIObserver *)
Definition: MISubject.cc:48
double lowerBound() const
string parName() const
bool isFixed() const
complex< double > * getProdParPtr(const string &ampName)
vector< AmplitudeInfo * > amplitudeList(const string &reactionName="", const string &sumName="", const string &ampName="") const
vector< vector< double > > covarianceMatrix()
MinuitParameterManager & parameterManager()
double centralValue() const
bool isPurelyReal() const
bool hasParameter(const string &ampName) const
const complex< double > * constValuePtr() const
complex< double > value() const