Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

FunctionController.cxx

Go to the documentation of this file.
00001 
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #else
00015 #ifdef _MSC_VER
00016 #include "msdevstudio/MSconfig.h"
00017 #endif
00018 #endif
00019 
00020 #include "FunctionController.h"
00021 #include "Gammaq.h"
00022 #include "DisplayController.h"
00023 
00024 #include "datasrcs/DataSourceController.h"
00025 #include "datareps/FunctionRep.h"
00026 #include "datasrcs/NTuple.h"
00027 #include "datasrcs/TupleCut.h"
00028 
00029 #include "functions/FunctionBase.h"
00030 #include "functions/FunctionFactory.h"
00031 
00032 #include "minimizers/Fitter.h"
00033 #include "minimizers/FitterFactory.h"
00034 #include "minimizers/NTupleFCN.h"
00035 #include "minimizers/NumLinAlg.h"
00036 
00037 #include "plotters/PlotterBase.h"
00038 #include "plotters/CompositePlotter.h"
00039 #include "projectors/BinningProjector.h"
00040 #include "projectors/FunctionProjector.h"
00041 #include "projectors/NTupleProjector.h"
00042 
00043 #include <algorithm>
00044 #include <functional>
00045 #include <iterator>
00046 
00047 #ifdef SSTREAM_DEFECT
00048 #include <strstream>
00049 using std::ostrstream;
00050 #else
00051 #include <sstream>
00052 using std::ostringstream;
00053 #endif
00054 
00055 #include <cfloat>
00056 
00057 using namespace hippodraw;
00058 using namespace hippodraw::Numeric;
00059 
00060 #ifdef ITERATOR_MEMBER_DEFECT
00061 using namespace std;
00062 #else
00063 using std::distance;
00064 using std::find;
00065 using std::find_if;
00066 using std::list;
00067 using std::mem_fun;
00068 using std::string;
00069 using std::vector;
00070 using std::sqrt;
00071 using std::cos;
00072 using std::sin;
00073 using std::atan;
00074 using std::min;
00075 using std::max;
00076 using std::abs;
00077 #endif
00078 
00079 FunctionController * FunctionController::s_instance = 0;
00080 
00081 FunctionController::FunctionController ( )
00082   : m_plotter ( 0 ), 
00083     m_x ( 0 ), 
00084     m_y ( 0 ),
00085     m_confid_count ( 0 )
00086 {
00087   m_deltaXSq.resize( 6 );
00088 
00089   m_deltaXSq[ 0 ] = 15.1;
00090   m_deltaXSq[ 1 ] = 18.4;
00091   m_deltaXSq[ 2 ] = 21.1;
00092   m_deltaXSq[ 3 ] = 23.5;
00093   m_deltaXSq[ 4 ] = 25.7;
00094   m_deltaXSq[ 5 ] = 27.8;
00095 }
00096 
00097 FunctionController::~FunctionController ( )
00098 {
00099 }
00100 
00101 FunctionController * FunctionController::instance ( )
00102 {
00103   if ( s_instance == 0 ) {
00104     s_instance = new FunctionController ( );
00105   }
00106   return s_instance;
00107 }
00108 
00109 const vector < string > &
00110 FunctionController::
00111 getFitterNames () const
00112 {
00113   FitterFactory * factory = FitterFactory::instance ();
00114 
00115   return factory -> names ();
00116 }
00117 
00118 int FunctionController::
00119 getUniqueNonFunctionIndex ( const PlotterBase * plotter ) const
00120 {
00121   int index = -1;
00122   int count = 0;
00123 
00124   int number = plotter->getNumDataReps ();
00125   for ( int i = 0; i < number; i++ ) {
00126     DataRep * r = plotter->getDataRep ( i );
00127     FunctionRep * fr = dynamic_cast < FunctionRep * > ( r );
00128     if ( fr != 0 ) continue;
00129     index = i;
00130     count++;
00131   }
00132   if ( count != 1 ) index = -1;
00133 
00134   return index;
00135 }
00136 
00137 void
00138 FunctionController::
00139 findFunctions ( const PlotterBase * plotter ) const
00140 {
00141   m_func_reps.clear ();
00142   int number = plotter->getNumDataReps ();
00143 
00144   for ( int i = 0; i < number; i++ ) {
00145     DataRep * rep = plotter->getDataRep ( i );
00146     FunctionRep * frep = dynamic_cast < FunctionRep * > ( rep );
00147     if ( frep == 0 ) continue;
00148     m_func_reps.push_back ( frep );
00149   }
00150 }
00151 
00152 FunctionRep * 
00153 FunctionController::
00154 createFunctionRep ( const std::string & name,
00155                     DataRep * rep )
00156 {
00157   FunctionRep * frep = new FunctionRep ( name, rep );
00158 
00159   return frep;
00160 }
00161 
00162 FunctionRep * 
00163 FunctionController::
00164 createFunctionRep ( FunctionBase * function, 
00165                     DataRep * rep )
00166 {
00167   FunctionRep * frep = new FunctionRep ( function, rep );
00168 
00169   const vector < string > & fitters = getFitterNames ();
00170   setFitter ( frep, fitters[0] );
00171 
00172   return frep;
00173 }
00174 
00175 FunctionBase *
00176 FunctionController::
00177 addFunction ( PlotterBase * plotter, const std::string & name )
00178 {
00179   DataRep * rep = plotter -> getDataRep ( 0 );
00180   addFunction ( plotter, name, rep );
00181   FunctionRep * frep = getFunctionRep ( plotter );
00182 
00183   return frep -> getFunction ();
00184 }
00185 
00186 int FunctionController::addFunction ( PlotterBase * plotter,
00187                                       const std::string & name, 
00188                                       DataRep * rep )
00189 {
00190   FunctionRep * func_rep = createFunctionRep ( name, rep );
00191   func_rep -> initializeWith ( rep );
00192   return addFunctionRep ( plotter, rep, func_rep );
00193 }
00194 
00195 int FunctionController::addFunction ( PlotterBase * plotter, 
00196                                       FunctionRep * func_rep )
00197 {
00198   int index = plotter->activePlotIndex ();
00199 
00200   if ( index < 0 ) {
00201     index = getUniqueNonFunctionIndex ( plotter );
00202   }
00203   if ( index < 0 ) return -1;
00204   plotter->setActivePlot ( index, false );
00205   DataRep * drep = plotter->getDataRep ( index );
00206   func_rep -> initializeWith ( drep );
00207   return addFunctionRep ( plotter, drep, func_rep );
00208 }
00209 
00210 
00211 void
00212 FunctionController::
00213 addDataRep ( PlotterBase * plotter, DataRep * rep )
00214 {
00215   FunctionRep * frep = dynamic_cast < FunctionRep * > ( rep );
00216   if ( frep == 0 ) { // not a function rep
00217     DisplayController * controller = DisplayController::instance ();
00218     controller -> addDataRep ( plotter, rep );
00219   }
00220   else { // a function rep
00221     if ( frep -> isComposite () == false ) {
00222       DataRep * target = frep -> getTarget ();
00223       addFunctionRep ( plotter, target, frep );
00224     }
00225   }
00226 }
00227 
00228 int
00229 FunctionController::
00230 addFunctionRep ( PlotterBase * plotter,
00231                  DataRep * drep,
00232                  FunctionRep * func_rep )
00233 {
00234   plotter->addDataRep ( func_rep );
00235   findFunctions ( plotter ); // to re-cache
00236 
00237   FunctionBase * function = func_rep->getFunction ();
00238   if ( function->isComposite () ) {
00239     buildComposite ( function );
00240   }
00241   func_rep->notifyObservers ();
00242   const vector < string > & fitters = getFitterNames ();
00243   setFitter ( func_rep, fitters[0] );
00244 
00245   // Check the list of functions. If there are 2 or more functionReps, and
00246   // all are non LinearSum, and the function you added right now is not a
00247   // linearSum, then add a linearSum functionrep.
00248   
00249   // Allow at most one Linear Sum in the list of all functionreps on a
00250   // plotter. If a Linear sum is already present, then add the current
00251   // function to that composite.
00252 
00253   if ( function->isComposite () == false ) {
00254     int count = 0;
00255     vector< FunctionRep * >:: const_iterator it = m_func_reps.begin (); 
00256     for ( ; it != m_func_reps.end (); ++it ) {
00257       FunctionRep * localfp = *it;
00258       FunctionBase * localfunction = localfp->getFunction ();
00259       const string & name = localfunction->name ();
00260 
00261       if ( name != "Linear Sum" ){
00262         count ++;
00263       }
00264       else{
00265         // The current function is a Linear Sum. So add the new function
00266         // to its list of functions.
00267         localfunction->addToComposite ( function );
00268         count = 0;
00269         break;
00270       }
00271     }
00272     
00273     if ( count > 1 ){
00274       addFunction ( plotter, "Linear Sum", drep );
00275     }
00276   
00277   }
00278 
00279   int retval = findIndex ( func_rep );
00280   return retval;
00281 
00282 }
00283 
00284 void FunctionController::buildComposite ( const PlotterBase * plotter )
00285 {
00286   FunctionRep * composite_rep = getComposite ( plotter );
00287   if ( composite_rep == 0 ) return;
00288 
00289   FunctionBase * composite = composite_rep->getFunction ();
00290   buildComposite ( composite );
00291 }
00292 
00293 void FunctionController::buildComposite ( FunctionBase * composite )
00294 {
00295   vector< FunctionRep * > :: const_iterator it = m_func_reps.begin ();
00296 
00297   for ( ; it != m_func_reps.end (); ++it ) {
00298     FunctionBase * function = (*it)->getFunction ();
00299     if ( function != composite ) {
00300       composite->addToComposite ( function );
00301     }
00302   }
00303 }
00304 
00305 void FunctionController::removeFunction ( PlotterBase * plotter,
00306                                           unsigned int index )
00307 {
00308   findFunctions ( plotter );
00309   assert ( index < m_func_reps.size () );
00310 
00311   vector < FunctionRep * > :: iterator it = m_func_reps.begin () + index;
00312   FunctionRep * frep = *it;
00313   m_func_reps.erase ( it );
00314 
00315   plotter->removeDataRep ( frep );
00316 
00317   FunctionBase * function = frep -> getFunction();  
00318 
00319   for ( unsigned int i = 0; i < m_func_reps.size(); i++ ){
00320     FunctionBase * curFunction = m_func_reps[i]->getFunction();
00321     if ( curFunction->isComposite() ){
00322       curFunction->removeFromComposite ( function );
00323       m_func_reps[i]->setDirty ( true );
00324     }
00325   }
00326 
00327   // Remove all composites who now have one or none functions within them.
00328   
00329   vector < FunctionRep * >::iterator iter = m_func_reps.begin ();
00330   
00331   // This while loop is tricky because modifying the vector that we
00332   // are iterating over.   
00333   while ( iter != m_func_reps.end() ){
00334     FunctionBase * func = ( *iter )->getFunction();
00335     if ( func->isComposite() ) {
00336       if ( func->count() < 2 ) {
00337         plotter->removeDataRep ( *iter );
00338         delete *iter;
00339         iter = m_func_reps.erase ( iter ); // updates iter 
00340       }
00341       else {
00342         iter ++;
00343       }
00344     }
00345     else {
00346       iter ++;
00347     }
00348   }
00349   delete frep; // the functionrep
00350 }
00351 
00352 int FunctionController::findIndex ( const FunctionRep * fp )
00353 {
00354   vector< FunctionRep * >::iterator it
00355     = find ( m_func_reps.begin (), m_func_reps.end (), fp );
00356 
00357   if ( it == m_func_reps.end () ) return -1;
00358 
00359 #ifdef DISTANCE_DEFECT
00360   return it - m_func_reps.begin ();
00361 #else
00362   return distance ( m_func_reps.begin (), it );
00363 #endif
00364 }
00365 
00366 bool
00367 FunctionController::
00368 hasFunction ( const PlotterBase * plotter, const DataRep * rep )
00369 {
00370   bool yes = false;
00371   assert ( plotter != 0 );
00372 
00373   findFunctions ( plotter );
00374 
00375   if ( m_func_reps.empty () == false ) {
00376     if ( rep != 0 ) {
00377       vector< FunctionRep * >:: const_iterator it = m_func_reps.begin ();
00378 
00379       for ( ; it != m_func_reps.end (); ++it ) {
00380         FunctionRep * fp = *it;
00381         if ( fp->getTarget() == rep ) {
00382           yes = true;
00383           break;
00384         }
00385       }
00386     } 
00387     else {
00388       yes = true;
00389     }
00390   }
00391 
00392   return yes;
00393 }
00394 
00395 const vector< string > & 
00396 FunctionController::
00397 functionNames ( PlotterBase * plotter, DataRep * rep )
00398 {
00399   findFunctions ( plotter );
00400 
00401   m_f_names.clear ();
00402   vector< FunctionRep * >:: const_iterator it = m_func_reps.begin ();
00403 
00404   for ( ; it != m_func_reps.end (); ++it ) {
00405     FunctionRep * fp = *it;
00406     if ( rep != 0 && fp->getTarget() != rep ) continue;
00407     FunctionBase * function = fp->getFunction ();
00408     const string & name = function->name ();
00409     m_f_names.push_back ( name );
00410   }
00411 
00412   return m_f_names;
00413 }
00414 
00415 const std::vector < FunctionRep * > & 
00416 FunctionController::
00417 getFunctionReps ( const PlotterBase * plotter ) const
00418 {
00419   FunctionController * tmp = const_cast< FunctionController * > ( this );
00420   tmp->findFunctions ( plotter );
00421   
00422   return m_func_reps;
00423 }
00424 
00425 FunctionRep *
00426 FunctionController::
00427 getComposite ( const PlotterBase * plotter ) const
00428 {
00429   FunctionController * tmp = const_cast< FunctionController * > ( this );
00430   tmp->findFunctions ( plotter );
00431 
00432 #ifdef MEMFUN_DEFECT
00433   vector < FunctionRep * >::iterator first = m_func_reps.begin();
00434   while ( first != m_func_reps.end() ) {
00435           FunctionRep * frep = *first++;
00436           if ( frep->isComposite () ) break;
00437   }
00438 #else
00439   vector < FunctionRep * >::const_iterator first
00440     = find_if ( m_func_reps.begin(), m_func_reps.end(),
00441                 mem_fun ( &FunctionRep::isComposite ) );
00442 #endif
00443 
00444   if ( first == m_func_reps.end() ) return 0;
00445 
00446   return *first;
00447 }
00448 
00449 const vector < double > &
00450 FunctionController::
00451 getErrors ( const PlotterBase * plotter )
00452 {
00453   FunctionRep * rep = getFunctionRep ( plotter );
00454 
00455   return rep -> principleErrors ();
00456 }
00457 
00458 void
00459 FunctionController::
00460 setErrorsFromComposite ( const PlotterBase * plotter,
00461                          const FunctionRep * composite )
00462 {
00463   const vector < double > & errors = composite -> principleErrors();
00464   vector < double >::const_iterator begin = errors.begin();
00465 
00466   getFunctionReps ( plotter );
00467   vector < FunctionRep * >::iterator first = m_func_reps.begin();
00468 
00469   while ( first != m_func_reps.end() ) {
00470     FunctionRep * rep = *first++;
00471     if ( rep -> isComposite() ) continue;
00472     ProjectorBase * pbase = rep -> getProjector ();
00473     FunctionProjector * projector 
00474       = dynamic_cast < FunctionProjector * > ( pbase );
00475     assert ( projector );
00476     const vector < double > & t = projector -> principleErrors ();
00477     unsigned int number = t.size();
00478     projector->setPrincipleErrors ( begin, 
00479                                     begin + number );
00480     begin += number;
00481   }
00482 
00483 }
00484 
00485 bool
00486 FunctionController::
00487 fitFunction ( PlotterBase * plotter, unsigned int )
00488 {
00489   FunctionRep * rep = getFunctionRep ( plotter );
00490 
00491   return fitFunction ( plotter, rep );
00492 }
00493 
00494 bool
00495 FunctionController::
00496 fitFunction ( PlotterBase * plotter, FunctionRep * rep )
00497 {
00498   FunctionRep * composite = getComposite ( plotter );
00499   bool ok = false;
00500   if ( composite != 0 ) {
00501     ok = composite -> fitFunction ();
00502     setErrorsFromComposite ( plotter, composite );
00503   }
00504   else {
00505     ok = rep -> fitFunction ();
00506   }
00507 
00508   return ok;
00509 }
00510 
00511 void
00512 FunctionController::
00513 tryFitFunction ( PlotterBase * plotter, const DataRep * datarep )
00514 {
00515   saveParameters ( plotter );
00516   double chi_sq = getObjectiveValue ( plotter, datarep );
00517   FunctionRep * func_rep = getFunctionRep ( plotter, datarep );
00518   bool ok = fitFunction ( plotter, func_rep );
00519   if ( ok ) {
00520     double new_chi_sq = getObjectiveValue ( plotter, datarep );
00521     if ( new_chi_sq > chi_sq ) {
00522       restoreParameters ( plotter );
00523     }
00524   } else {
00525     restoreParameters ( plotter );
00526   }
00527 }
00528 
00529 void
00530 FunctionController::
00531 fitFunctions ( PlotterBase * plotter )
00532 {
00533   if ( hasFunction ( plotter, 0 ) ) {
00534     buildComposite ( plotter );
00535     FunctionRep * frep = getFunctionRep ( plotter );
00536     fitFunction ( plotter, frep );
00537   }}
00538 
00539 void
00540 FunctionController::
00541 setFitRange ( PlotterBase * plotter, const Range & range )
00542 {
00543   if ( hasFunction ( plotter, 0 ) ) {
00544     FunctionRep * frep = getFunctionRep ( plotter );
00545     frep -> setCutRange ( range );
00546     plotter -> update ();
00547   }
00548 }
00549 
00550 void
00551 FunctionController::
00552 setFitRange ( PlotterBase * plotter, double low, double high )
00553 {
00554   const Range range ( low, high );
00555   setFitRange ( plotter, range );
00556 }
00557 
00558 const std::vector < double >
00559 FunctionController::
00560 parameters ( const PlotterBase * plotter, unsigned int )
00561 {
00562   FunctionRep * rep = getFunctionRep ( plotter );
00563 
00564   return rep -> parameters ();
00565 }
00566 
00567 const std::vector < double >
00568 FunctionController::
00569 principleErrors ( const PlotterBase * plotter, unsigned int )
00570 {
00571   FunctionRep * rep = getFunctionRep ( plotter );
00572 
00573   return rep -> principleErrors ();
00574 }
00575 
00576 void FunctionController::saveParameters ( PlotterBase * plotter )
00577 {
00578   findFunctions ( plotter );
00579   vector< FunctionRep * >::iterator it = m_func_reps.begin ();
00580 
00581   for ( ; it != m_func_reps.end (); ++it ) {
00582     FunctionRep * frep = *it;
00583     FunctionBase * function = frep->getFunction ();
00584     if ( function->isComposite () ) continue;
00585     frep->saveParameters ();
00586   }
00587 }
00588 
00589 void FunctionController::restoreParameters ( PlotterBase * plotter )
00590 {
00591   findFunctions ( plotter );
00592   vector< FunctionRep * >::iterator it = m_func_reps.begin ();
00593 
00594   for ( ; it != m_func_reps.end (); ++it ) {
00595     FunctionRep * frep = *it;
00596     FunctionBase * function = frep->getFunction ();
00597     if ( function->isComposite () ) continue;
00598     frep->restoreParameters ();
00599   }
00600 
00601 }
00602 
00603 FunctionRep *
00604 FunctionController::
00605 getFunctionRep ( const PlotterBase * plotter ) const
00606 {
00607   FunctionRep * frep = 0;
00608   DataRep * rep = 0;
00609   int index = plotter->activePlotIndex ();
00610 
00611   if ( index >= 0 ) {
00612     rep = plotter -> getDataRep ( index );
00613   }
00614   else {
00615     rep = plotter -> getTarget ();
00616   }
00617 
00618   FunctionRep * test = dynamic_cast < FunctionRep * > ( rep );
00619   if ( test != 0 ) { // if ctrl-clicked, could be the function
00620     frep = test;
00621   }
00622   else {
00623     frep = getFunctionRep ( plotter, rep );
00624   }
00625 
00626   return frep;
00627 }
00628 
00629 FunctionRep *
00630 FunctionController::
00631 getFunctionRep ( const PlotterBase * plotter, const DataRep * datarep ) const
00632 {
00633   FunctionRep * frep = 0;
00634 
00635   findFunctions ( plotter ); 
00636 
00637   for ( unsigned int i = 0; i < m_func_reps.size(); i++ ) {
00638     FunctionRep * rep = m_func_reps[i];
00639     const DataRep * drep = rep -> getTarget ();
00640     if ( drep != datarep ) continue;
00641     frep = rep;
00642     if ( frep -> isComposite () ) break; // use composite if found
00643   }
00644 
00645   return frep;
00646 }
00647 
00648 ViewBase * FunctionController::
00649 createFuncView ( const ViewFactory * factory,
00650                  PlotterBase * plotter,
00651                  const std::string & name )
00652 {
00653   FunctionRep * frep = getFunctionRep ( plotter );
00654   assert ( frep != 0 );
00655 
00656   DisplayController * controller = DisplayController::instance ();
00657   string nullstring ("");
00658 
00659   return controller->createTextView ( factory, frep, name, nullstring );
00660 }
00661 
00662 bool
00663 FunctionController::
00664 setFitter ( const PlotterBase * plotter, const std::string & name )
00665 {
00666   FunctionRep * frep = getFunctionRep ( plotter );
00667   bool ok = false;
00668   if ( frep != 0 ) {
00669     ok = setFitter ( frep, name );
00670   }
00671 
00672   return ok;
00673 }
00674 
00675 const string &
00676 FunctionController::
00677 getFitterName ( const PlotterBase * plotter )
00678 {
00679   FunctionRep * frep = getFunctionRep ( plotter );
00680   Fitter * fitter = frep -> getFitter ();
00681 
00682   return fitter -> name ();
00683 }
00684 
00685 Fitter *
00686 FunctionController::
00687 getFitter ( const PlotterBase * plotter )
00688 {
00689   FunctionRep * frep = getFunctionRep ( plotter );
00690   Fitter * fitter = frep -> getFitter ();
00691 
00692   return fitter;
00693 }
00694 
00695 
00696 bool
00697 FunctionController::
00698 setFitter ( FunctionRep * frep, const std::string & name )
00699 {
00700   FitterFactory * factory = FitterFactory::instance ();
00701   Fitter * fitter = factory -> create ( name );
00702 
00703   return setFitter ( frep, fitter );
00704 }
00705 
00706 bool
00707 FunctionController::
00708 setFitter ( FunctionRep * frep, Fitter * fitter )
00709 {
00710   DataRep * drep = frep -> getTarget ();
00711   FunctionBase * function = frep -> getFunction ();
00712   StatedFCN * fcn = fitter -> getFCN ();
00713 
00714   if ( fcn -> needsIntegrated () == true ) {
00715     bool yes = drep -> isAxisBinned ( Axes::X );
00716     if ( ! yes ) return false;
00717   }
00718 
00719   fcn -> setFunction ( function );
00720 
00721   NTupleFCN * ntfcn = dynamic_cast < NTupleFCN * > ( fcn );
00722   assert ( ntfcn != 0 );
00723 
00724   const DataSource * target = drep -> getProjectedValues ();
00725   ntfcn -> setDataSource ( target );
00726   ntfcn -> setUseErrors ( );
00727 
00728   frep -> setFitter ( fitter );
00729 
00730   return true;
00731 }
00732 
00733 double
00734 FunctionController::
00735 getObjectiveValue ( const PlotterBase * plotter, const DataRep * datarep )
00736 {
00737   FunctionRep * rep = getFunctionRep ( plotter, datarep );
00738 
00739   ProjectorBase * pbase = rep->getProjector ( );
00740   FunctionProjector * projector 
00741     = dynamic_cast < FunctionProjector * > ( pbase );
00742 
00743   return projector -> objectiveValue ();
00744 }
00745 
00746 const vector < vector < double > > &
00747 FunctionController::
00748 getCovarianceMatrix ( const PlotterBase * plotter )
00749 {
00750   FunctionRep * rep = getFunctionRep ( plotter );
00751 
00752   ProjectorBase * pbase = rep->getProjector ( );
00753   FunctionProjector * projector 
00754     = dynamic_cast < FunctionProjector * > ( pbase );
00755 
00756   return projector -> covariance ();
00757 }
00758 
00763 double
00764 FunctionController::
00765 getChiSquared ( const PlotterBase * plotter )
00766 {
00767   const DataRep * rep = plotter -> getTarget ();
00768 
00769   return getObjectiveValue ( plotter, rep );
00770 }
00771 
00772 int
00773 FunctionController::
00774 getDegreesOfFreedom ( const PlotterBase * plotter )
00775 {
00776   FunctionRep * rep = getFunctionRep ( plotter );
00777 
00778   ProjectorBase * pbase = rep->getProjector ( );
00779   FunctionProjector * projector 
00780     = dynamic_cast < FunctionProjector * > ( pbase );
00781 
00782   return projector -> degreesOfFreedom ();
00783 }
00784 
00785 NTuple *
00786 FunctionController::
00787 createNTuple ( PlotterBase * plotter )
00788 {
00789   int old_index = plotter -> activePlotIndex ();
00790 
00791   int index = getUniqueNonFunctionIndex ( plotter );
00792   if ( index < 0 ) return 0;
00793 
00794   int saved_index = plotter -> activePlotIndex ();
00795   plotter -> setActivePlot ( index, false ); // no redraw
00796   NTuple * ntuple = plotter -> createNTuple ();
00797   plotter -> setActivePlot ( saved_index, false );
00798 
00799   FunctionRep * rep = getFunctionRep ( plotter );
00800   if ( rep == 0 ) return ntuple;
00801 
00802   ProjectorBase * pbase = rep->getProjector ( );
00803   FunctionProjector * projector 
00804     = dynamic_cast < FunctionProjector * > ( pbase );
00805   FunctionBase * function = projector -> function();
00806 
00807   vector < double > & x = ntuple -> getColumn ( 0 ); // X coordinate
00808   vector < double > & y = ntuple -> getColumn ( 1 ); // Y coordingate
00809   unsigned int size = ntuple -> rows ();
00810   vector < double > values ( size );
00811   vector < double > residuals ( size );
00812   
00813   for ( unsigned int i = 0; i < x.size(); i++ ) {
00814     values [i] = function -> operator () ( x[i] );
00815     residuals [i] =  y[i] - values [i];
00816   }
00817 
00818   ntuple -> addColumn ( function->name (), values );
00819   ntuple -> addColumn ( "Residuals", residuals );
00820 
00821   plotter -> setActivePlot ( old_index, true );
00822 
00823   return ntuple;
00824 }
00825  
00826 PlotterBase *
00827 FunctionController::
00828 createResidualsDisplay ( PlotterBase * plotter )
00829 {
00830   NTuple * ntuple = createNTuple ( plotter );
00831   ntuple -> setTitle ( plotter -> getTitle () );
00832   DataSourceController::instance () -> registerNTuple ( ntuple );
00833   vector < string > bindings ( 4 );
00834   bindings[0] = ntuple -> getLabelAt ( 0 );
00835   bindings[1] = "Residuals";
00836   bindings[2] = "nil";
00837   bindings[3] = ntuple -> getLabelAt ( 3 );
00838 
00839   DisplayController * controller = DisplayController::instance ();
00840 
00841 // Make scaling of x-axis match that of the original plot.
00842   PlotterBase * new_plotter = controller -> createDisplay ( "XY Plot",
00843                                                             *ntuple,
00844                                                             bindings );
00845   controller->setLog( new_plotter, "x", 
00846                       controller -> getLog( plotter, "x" ) );
00847   
00848   return new_plotter;
00849 }
00850 
00851 PlotterBase *
00852 FunctionController::
00853 createNewEllipsoidDisplay ( PlotterBase * masterPlot )
00854 {
00855   int n = 100;
00856   double xmin, xmax, ymin, ymax;
00857   
00858   // Set up the NTuple
00859   NTuple* ntuple = new( NTuple );
00860   ellipsoidNTuple ( masterPlot, ntuple, n, xmin, xmax, ymin, ymax );
00861   ntuple -> setTitle ( masterPlot -> getTitle () );
00862   
00863   vector < string > bindings ( 1 );
00864   bindings[0] = ntuple ->  getLabelAt ( 0 );
00865   
00866   DisplayController * dcontroller = DisplayController::instance ();
00867 
00868   // Z plot. X and Y coordinates are merely inidices
00869   PlotterBase * ellipsePlot = dcontroller ->
00870     createDisplay ( "Z Plot", *ntuple, bindings );
00871   
00872   // Rescale and translate the Z plot so that  the plot
00873   // becomes contained in the rectangle bound by xmin, xmax
00874   // ymin and ymax.
00875   ellipsePlot -> setBinWidth( "x", ( xmax - xmin ) / ( n - 1.0 ) );
00876   ellipsePlot -> setBinWidth( "y", ( ymax - ymin ) / ( n - 1.0 ) );
00877   
00878   ellipsePlot -> setOffsets ( xmin, ymin );
00879   
00880   ellipsePlot -> setRange ( string( "X" ), xmin, xmax );
00881   ellipsePlot -> setRange ( string( "Y" ), ymin, ymax );
00882   
00883   // Establish the relation between source masterPlot and
00884   // this new plot. This relationship shall be exploited
00885   // when we refresh the error plots.
00886   int index = dcontroller -> activeDataRepIndex( masterPlot );
00887   ellipsePlot -> setParentDataRepIndex( index );
00888   ellipsePlot -> setParentPlotter( masterPlot );
00889   
00890   return ellipsePlot;
00891 }
00892 
00893 
00894 void
00895 FunctionController::
00896 ellipsoidNTuple ( PlotterBase* masterPlot,
00897                   NTuple* nt, int n,
00898                   double & xmin, double & xmax,
00899                   double & ymin, double & ymax )
00900 {
00901 #ifdef SSTREAM_DEFECT
00902   ostrstream strm_text;
00903 #else
00904   ostringstream strm_text;
00905 #endif
00906   strm_text << "Confidence ellipse ";
00907   m_confid_count++;
00908   strm_text << m_confid_count;
00909   const string str_text ( strm_text.str() );
00910   nt -> setName ( str_text );
00911 
00912   DataSourceController * controller = DataSourceController::instance ();
00913   controller -> registerNTuple ( nt );
00914 
00915   // Function Rep associated with the selected datarep
00916   FunctionRep * frep = getFunctionRep ( masterPlot );
00917   assert( frep );
00918   
00919   ProjectorBase * pbase = frep -> getProjector ( );
00920   FunctionProjector * fprojector 
00921     = dynamic_cast < FunctionProjector * > ( pbase );
00922   
00923   // Get projected covarience i.e. take the submatrix
00924   // out of the covarience matrix which corrosponds
00925   // to the 2 parameters of intrest whose correlation
00926   // we would like to see.
00927   vector< vector< double > > Sigma( 2 );
00928   Sigma[0].resize( 2, 0.0 );
00929   Sigma[1].resize( 2, 0.0 );
00930 
00931   const vector < vector < double > > & covariance 
00932     = fprojector -> covariance ();  
00933 
00934   Sigma[0][0] = covariance [m_x][m_x];
00935   Sigma[0][1] = covariance [m_x][m_y];
00936   Sigma[1][0] = covariance [m_y][m_x];
00937   Sigma[1][1] = covariance [m_y][m_y];
00938 
00939   // Invert the projected covarience 
00940   vector< vector< double > > SigmaInv;
00941   invertMatrix( Sigma, SigmaInv );
00942   
00943   // Decide the center of the ellipse to be parameter
00944   // value of the 2 parameters of intrest whose correlation
00945   // we would like to see.
00946   vector< double > xbar( 2 );
00947   
00948   const Fitter * fitter = getFitter ( masterPlot );
00949   vector < double > free_parms;
00950   fitter -> fillFreeParameters ( free_parms );
00951   xbar[ 0 ] = free_parms [ m_x ];
00952   xbar[ 1 ] = free_parms [ m_y ];
00953   
00954   // Get the bounding ellipse and its bounds. Bounding ellipse is the
00955   // 99.99% confidence ellipsoid. For mu = 2 the delta chi-square turns from 
00956   // Numerical Recipies in C as 18.4. etc etc.
00957   unsigned int mu = free_parms.size();
00958   NTuple * boundingTuple = ellipse( xbar, SigmaInv, m_deltaXSq[ mu - 1 ] ); 
00959   
00960   xmin = boundingTuple -> minElement ( 0 );
00961   xmax = boundingTuple -> maxElement ( 0 );
00962   ymin = boundingTuple -> minElement ( 1 );
00963   ymax = boundingTuple -> maxElement ( 1 );
00964   
00965   delete boundingTuple; // Served its purpose
00966   
00967   // Create the ntuple for the contour plot
00968   // This ntuple is to be build column-wise
00969   // keeping in view the way Z-plot works.
00970   vector< double > p( n * n ), a( 2 );
00971   
00972   double dx    = ( xmax - xmin ) / ( n - 1.0 );
00973   double dy    = ( ymax - ymin ) / ( n - 1.0 );
00974   double delta = 0.0;
00975   
00976   for( int i = 0; i < n; i++ )
00977     for( int j = 0; j < n; j++ )
00978       {
00979         a[ 0 ] = xmin + i * dx - xbar[ 0 ] ;
00980         a[ 1 ] = ymin + j * dy - xbar[ 1 ];
00981         delta  = quadraticProduct( SigmaInv, a );
00982         p[ n * i + j ] = 1 - gammq( mu / 2.0, delta / 2.0 ); 
00983       }
00984 
00985   nt -> clear();
00986   nt -> addColumn( "Percent", 100 * p );
00987   
00988   return;
00989 }
00990 
00991 PlotterBase *
00992 FunctionController::
00993 refreshEllipsoidDisplay ( PlotterBase * plot )
00994 {
00995   int n = 100;
00996   double xmin, xmax, ymin, ymax;
00997   
00998   PlotterBase* masterPlot = plot->getParentPlotter();
00999 
01000   // Set up the NTuple
01001   NTuple* ntuple = new( NTuple );
01002   ellipsoidNTuple ( masterPlot, ntuple, n, xmin, xmax, ymin, ymax );
01003   ntuple -> setTitle ( masterPlot -> getTitle () );
01004   
01005   // First get the selected datarep from the plotter. The DataRep 
01006   // will have a projector that is a NTupleProjector. It doesn't
01007   // know, but we do, so we downcast and set the ntuple.
01008   DataRep * drep = plot -> selectedDataRep();
01009   NTupleProjector * ntProjector =
01010     dynamic_cast < NTupleProjector * > ( drep -> getProjector() );
01011   ntProjector -> setNTuple ( ntuple );
01012   
01013   NTuple * nt = const_cast < NTuple * > ( ntuple );
01014   nt  -> addObserver ( ntProjector );
01015     
01016   // Rescale and translate the Z plot so that  the plot
01017   // becomes contained in the rectangle bound by xmin, xmax
01018   // ymin and ymax.
01019   plot -> setBinWidth( "x", ( xmax - xmin ) / ( n - 1.0 ) );
01020   plot -> setBinWidth( "y", ( ymax - ymin ) / ( n - 1.0 ) );
01021   
01022   plot -> setOffsets ( xmin, ymin );
01023   
01024   plot -> setRange ( string( "X" ), xmin, xmax );
01025   plot -> setRange ( string( "Y" ), ymin, ymax );
01026     
01027   return plot;
01028 }
01029 
01030 NTuple * 
01031 FunctionController::
01032 ellipse ( const std::vector< double > & xbar,
01033           std::vector< std::vector < double > > & SigmaInv,
01034           double Csquare )
01035 {
01036   // First agrument should be a 2 D vector, the center of the ellipse //
01037   assert( xbar.size() == 2 );
01038 
01039   // Second argument should be a 2 x 2 SPD matrix i.e. two rows two cols //
01040   assert( SigmaInv.size() == 2 );
01041   assert( SigmaInv[0].size() == 2 || SigmaInv[1].size() == 2 );
01042   
01043   // Second argument should be a 2 x 2 -- Symmetric --  PD matrix
01044   // Under numerical roundoffs it might not be true so we take mean of the
01045   // enteries.
01046   double temp = ( SigmaInv[0][1] + SigmaInv[1][0] ) / 2;
01047   SigmaInv[0][1] = temp;
01048   SigmaInv[1][0] = temp;
01049   
01050   // Third argument should be a positive scalar "c^2", Square of "Radius" // 
01051   assert( Csquare > DBL_EPSILON );
01052   
01053   // The eigenvalues of the SigmaInv matrix
01054   double b = -( SigmaInv[0][0] + SigmaInv[1][1] );
01055   double c = SigmaInv[0][0] * SigmaInv[1][1] - SigmaInv[0][1] * SigmaInv[1][0];
01056 
01057   double lambda1 = ( -b + sqrt( b * b - 4 * c ) ) / 2;
01058   double lambda2 = ( -b - sqrt( b * b - 4 * c ) ) / 2;
01059     
01060   // Determinig the angles the ellipse axis make with X-axis
01061   double alpha1 =  atan( (SigmaInv[0][0] - lambda1) / SigmaInv[0][1] );
01062   double a      =  sqrt( Csquare / lambda1 );
01063   b             =  sqrt( Csquare / lambda2 );
01064 
01065   // Creating a rotation matrix
01066   double Rot00 =  cos( alpha1 );
01067   double Rot11 =  cos( alpha1 );
01068   double Rot01 = -sin( alpha1 );
01069   double Rot10 =  sin( alpha1 );
01070 
01071   // Generating N-points on the ellipse
01072   int N = 100;
01073   vector< double > x, y;
01074   
01075   x.resize( N, 0.0 );
01076   y.resize( N, 0.0 );
01077   
01078   for( int i = 0; i < N; i++)
01079     {
01080       // Unrotated untranslated point
01081       double theta = ( 2 * M_PI * i ) / ( (double) (N-1) );
01082       double x0 = a * cos( theta );
01083       double x1 = b * sin( theta );
01084       
01085       //x = Rot * x; i.e. force in a rotation
01086       double xrot0 = Rot00 * x0 + Rot01 * x1;
01087       double xrot1 = Rot10 * x0 + Rot11 * x1;
01088       
01089       //x = x + xbar; i.e. force in a translation
01090       x[i] = xrot0 + xbar[0];
01091       y[i] = xrot1 + xbar[1];
01092     }
01093   
01094   // Create an Ntuple out of the above vector
01095   NTuple* ntuple = new( NTuple );
01096   ntuple -> addColumn( "X", x );
01097   ntuple -> addColumn( "Y", y );
01098   
01099   return ntuple;
01100 }
01101 
01102 int FunctionController::setEllpsoidParamIndex( hippodraw::Axes::Type axes,
01103                                                int index )
01104 {
01105   assert( axes == Axes::X || axes == Axes::Y );
01106 
01107   if( axes == Axes::X )
01108     m_x = index;
01109   
01110   if( axes == Axes::Y )
01111     m_y = index;
01112       
01113   return EXIT_SUCCESS;
01114 }
01115 
01116 bool
01117 FunctionController::
01118 functionExists ( const std::string & name )
01119 {
01120   FunctionFactory * factory = FunctionFactory::instance ();
01121 
01122   return factory -> exists ( name );
01123 }
01124 
01125 bool
01126 FunctionController::
01127 isCompatible ( const std::string & function,
01128                const std::string & fitter )
01129 {
01130   bool yes = true;
01131 
01132   FunctionFactory * fun_fac = FunctionFactory::instance ();
01133   FunctionBase * fun_proto = fun_fac -> prototype ( function );
01134 
01135   FitterFactory * fit_fac = FitterFactory::instance ();
01136   Fitter * fit_proto = fit_fac -> prototype ( fitter );
01137 
01138   if ( fit_proto -> needsDerivatives () == true  &&
01139        fun_proto -> hasDerivatives () == false ) {
01140     yes = false;
01141   }
01142 
01143   return yes;
01144 }

Generated for HippoDraw-1.14.8.5 by doxygen 1.4.3