00001
00012 #ifdef _MSC_VER
00013 #include "msdevstudio/MSconfig.h"
00014 #endif
00015
00016 #include "NTupleProjector.h"
00017
00018 #include "axes/AxisModelBase.h"
00019
00020 #include "datasrcs/NTuple.h"
00021 #include "datasrcs/TupleCut.h"
00022
00023 #include <algorithm>
00024 #include <functional>
00025 #include <stdexcept>
00026 #include <climits>
00027
00028 #include <cassert>
00029
00030 #ifdef ITERATOR_MEMBER_DEFECT
00031 using namespace std;
00032 #else
00033 using std::distance;
00034 using std::find;
00035 using std::max;
00036 using std::max_element;
00037 using std::min;
00038 using std::min_element;
00039 using std::runtime_error;
00040 using std::string;
00041 using std::vector;
00042 #endif
00043
00044 using namespace hippodraw;
00045
00046 NTupleProjector::NTupleProjector ( unsigned int columns )
00047 : ProjectorBase (),
00048 m_is_valid ( true ),
00049 m_columns ( columns, UINT_MAX ),
00050 m_cut_list(0),
00051 m_min_bindings ( 0 )
00052 {
00053 m_ntuple = new NTuple ( true );
00054 }
00055
00056 NTupleProjector::NTupleProjector ( const NTupleProjector & projector )
00057 : ProjectorBase ( projector ),
00058 m_is_valid ( projector.m_is_valid ),
00059 m_binding_options ( projector.m_binding_options ),
00060 m_bindings ( projector.m_bindings),
00061 m_columns ( projector.m_columns ),
00062 m_ntuple ( projector.m_ntuple ),
00063 m_min_bindings ( projector.m_min_bindings )
00064 {
00065 if ( m_ntuple->isNull () ) {
00066 m_ntuple = new NTuple ( true );
00067 }
00068 m_binding_options = projector.m_binding_options;
00069 }
00070
00071 NTupleProjector::~NTupleProjector ()
00072 {
00073 if ( m_ntuple->isNull () ) {
00074 delete m_ntuple;
00075 }
00076 else {
00077 DataSource * source = const_cast < DataSource * > ( m_ntuple );
00078 source -> removeObserver ( this );
00079 }
00080 }
00081
00082 void NTupleProjector::update ( const Observable * )
00083 {
00084 setDirty ( true );
00085 notifyObservers ();
00086 }
00087
00088 void
00089 NTupleProjector::
00090 willDelete ( const Observable * observee )
00091 {
00092 if ( observee == m_ntuple ) {
00093 m_ntuple = new NTuple ( true );
00094 }
00095 }
00096
00097 const vector< string > & NTupleProjector::bindingOptions () const
00098 {
00099 return m_binding_options;
00100 }
00101
00102 unsigned int NTupleProjector::
00103 indexOfBindingOption ( const std::string & axis ) const
00104 {
00105 vector< string >::const_iterator first
00106 = find ( m_binding_options.begin(),
00107 m_binding_options.end(),
00108 axis );
00109 if ( first == m_binding_options.end () ) {
00110 std::string what = std::string("NTupleProjector::indexOfBindingOption: ")
00111 + std::string("no such binding option: ") + axis;
00112 throw runtime_error( what );
00113 }
00114
00115 #ifdef DISTANCE_DEFECT
00116 return first - m_binding_options.begin();
00117 #else
00118 return distance ( m_binding_options.begin(), first );
00119 #endif
00120 }
00121
00122 const std::vector < std::string > &
00123 NTupleProjector::
00124 getAxisBindings () const
00125 {
00126 m_bindings.clear();
00127 size_t size = m_columns.size ();
00128 for ( size_t i = 0; i < size; i++ ) {
00129 int column = m_columns[i];
00130 if ( column >= 0 ) {
00131 const string & label = m_ntuple->getLabelAt ( column );
00132 m_bindings.push_back ( label );
00133 } else {
00134 const string label = "nil";
00135 m_bindings.push_back ( label );
00136 }
00137 }
00138
00139 return m_bindings;
00140 }
00141
00142 int
00143 NTupleProjector::
00144 indexOf ( const std::string & label ) const
00145 {
00146 return m_ntuple->indexOf ( label );
00147 }
00148
00149 void NTupleProjector::setXErrorOption ( bool )
00150 {
00151 }
00152
00153 void NTupleProjector::setYErrorOption ( bool )
00154 {
00155 }
00156
00157 bool
00158 NTupleProjector::
00159 acceptRow ( unsigned int i, const CutList_t & cut_list ) const
00160 {
00161
00162 bool accept = true;
00163
00164 if ( cut_list.empty() == false ) {
00165 unsigned int size = cut_list.size();
00166 unsigned int j = 0;
00167 while ( j < size ) {
00168 const TupleCut * cut = cut_list[j++];
00169 if ( cut != 0 ) {
00170 if ( cut -> acceptRow ( m_ntuple, i ) == false ) {
00171 accept = false;
00172 break;
00173 }
00174 }
00175 }
00176 }
00177
00178 return accept;
00179 }
00180
00181 void
00182 NTupleProjector::
00183 setAxisBinding ( int axis, const std::string & label )
00184 {
00185 if ( label == "nil" ) {
00186 m_columns[axis] = UINT_MAX;
00187 }
00188 else {
00189 m_ntuple -> throwIfInvalidLabel ( label );
00190 int column = m_ntuple->indexOf ( label );
00191 m_columns[axis] = column;
00192 }
00193 m_is_valid = true;
00194 setDirty ( true );
00195 }
00196
00197 void NTupleProjector::setAxisBinding ( const std::string & axis,
00198 const std::string & label )
00199 {
00200 unsigned int index = indexOfBindingOption ( axis );
00201
00202 setAxisBinding ( index, label );
00203 }
00204
00205 void
00206 NTupleProjector::
00207 setAxisBindings ( const std::vector< std::string > & labels )
00208 {
00209 size_t size = labels.size();
00210
00211 if ( size < m_min_bindings ) {
00212 string what ( "NTupleProjector::setAxisBindings: " );
00213 what += "insufficient number of labels";
00214 throw runtime_error ( what );
00215 }
00216
00217 size_t cols = m_columns.size ();
00218 for ( unsigned int i = 0; i < cols; i++ ) {
00219 if ( i < size ) {
00220 const string & label = labels[i];
00221 setAxisBinding ( i, label );
00222 }
00223 else {
00224 const string nil ( "nil" );
00225 setAxisBinding ( i, nil );
00226 }
00227 }
00228 m_is_valid = true;
00229 }
00230
00231 void NTupleProjector::setNTuple ( const DataSource * ntuple )
00232 {
00233 assert ( ntuple != 0 );
00234
00235 if ( m_ntuple->isNull () ) {
00236 delete m_ntuple;
00237 m_ntuple = 0;
00238 }
00239
00240 if ( m_ntuple != 0 ) {
00241 DataSource * nt = const_cast < DataSource * > ( m_ntuple );
00242 nt->removeObserver ( this );
00243 }
00244 m_ntuple = ntuple;
00245 changedNTuple();
00246 m_is_valid = true;
00247 setDirty ( true );
00248 }
00249
00250
00251 const string & NTupleProjector::getTitle() const
00252 {
00253 return m_ntuple->title();
00254 }
00255
00256 const std::string & NTupleProjector::getXLabel() const
00257 {
00258 return m_ntuple->getLabelAt( m_columns[0] );
00259 }
00260
00261 const string & NTupleProjector::getYLabel ( bool ) const
00262 {
00263 return m_ntuple->getLabelAt( m_columns[1] );
00264 }
00265
00266 Range NTupleProjector::dataRangeWithError ( int data, int error ) const
00267 {
00268 assert ( !( data < 0 ) &&
00269 static_cast<size_t> ( data ) < m_ntuple->columns () );
00270 assert ( !( error < 0 ) &&
00271 static_cast<size_t> ( error ) < m_ntuple->columns () );
00272
00273 double lo = DBL_MAX;
00274 double hi = DBL_MIN;
00275
00276 unsigned int size = m_ntuple -> rows ();
00277 for ( unsigned int row = 0; row < size; row++ ) {
00278 double value = m_ntuple -> valueAt ( row, data );
00279 double err = m_ntuple -> valueAt ( row, error );
00280 lo = min ( value - err, lo );
00281 hi = max ( value + err, hi );
00282 }
00283
00284 double pos = getPosWithError( data, error );
00285
00286 return Range ( lo, hi, pos );
00287 }
00288
00289 Range
00290 NTupleProjector::
00291 dataRange ( int column ) const
00292 {
00293 assert ( m_ntuple );
00294 assert ( !( column < 0 ) &&
00295 static_cast<size_t> (column) < m_ntuple->columns() );
00296
00297 Range range;
00298 bool isValid = m_ntuple -> fillRange ( column, range );
00299 m_is_valid &= isValid;
00300
00301 return range;
00302 }
00303
00304 double NTupleProjector::getPosWithError ( int data, int error ) const
00305 {
00306 assert ( !( data < 0 ) &&
00307 static_cast<size_t> ( data ) < m_ntuple->columns () );
00308 assert ( !( error < 0 ) &&
00309 static_cast<size_t> ( error ) < m_ntuple->columns () );
00310
00311 double pos = DBL_MAX;
00312
00313 unsigned int size = m_ntuple -> rows ();
00314 for ( unsigned int row = 0; row < size; row++ ) {
00315 double value = m_ntuple -> valueAt ( row, data );
00316 double err = m_ntuple -> valueAt ( row, error );
00317 if ( value > 0. ) {
00318 double x = value - err;
00319 if ( x > 0.0 ) {
00320 pos = min ( x, pos );
00321 }
00322 else {
00323 if ( value != 0.0 ) pos = min ( 0.1 * value, pos );
00324 }
00325 }
00326 }
00327
00328 return pos;
00329 }
00330
00331 double
00332 NTupleProjector::
00333 getPos ( int column ) const
00334 {
00335 assert ( m_ntuple );
00336 assert ( !( column < 0 ) &&
00337 static_cast<size_t> (column) < m_ntuple->columns() );
00338
00339 double pos = DBL_MAX;
00340
00341 unsigned int size = m_ntuple -> rows ();
00342
00343 for ( unsigned int row = 0; row < size; row++ ) {
00344 double value = m_ntuple -> valueAt ( row, column );
00345 if ( value < pos && value > 0.0 ) pos = value;
00346 }
00347
00348 return pos;
00349 }
00350
00351 void NTupleProjector::addCut ( const TupleCut * cut )
00352 {
00353 m_cut_list.push_back ( cut );
00354 }
00355
00356 void NTupleProjector::removeCut ( const TupleCut * cut )
00357 {
00358 CutList_t ::iterator first
00359 = find ( m_cut_list.begin(), m_cut_list.end(), cut );
00360 assert ( first != m_cut_list.end() );
00361
00362 m_cut_list.erase ( first );
00363 }
00364
00365 const vector < const TupleCut * > & NTupleProjector::getCutList () const
00366 {
00367 return m_cut_list;
00368 }
00369
00370 int
00371 NTupleProjector::
00372 getNumberOfEntries () const
00373 {
00374 unsigned int size = m_ntuple->rows ();
00375 int number = 0;
00376 for ( unsigned int i = 0; i < size; i++ ) {
00377 if ( acceptRow ( i, m_cut_list ) &&
00378 inRange ( i ) )
00379 {
00380 number++;
00381 }
00382 }
00383
00384 return number;
00385 }
00386
00387 int
00388 NTupleProjector::
00389 getUnderflow () const
00390 {
00391 return -1;
00392 }
00393
00394 int
00395 NTupleProjector::
00396 getOverflow () const
00397 {
00398 return -1;
00399 }
00400
00401
00402 bool
00403 NTupleProjector::
00404 inRange ( int row ) const
00405 {
00406 unsigned int size = m_columns.size();
00407 bool yes = true;
00408 for ( unsigned int i = 0; i < size; i++ ) {
00409 if ( m_columns[i] == UINT_MAX ) break;
00410
00411 AxisModelBase * axis_model = 0;
00412 if ( i == 0 ) axis_model = m_x_axis;
00413 else if ( i == 1 ) axis_model = m_y_axis;
00414 else if ( i == 2 ) axis_model = m_z_axis;
00415 if ( axis_model == 0 ) break;
00416
00417 unsigned int column = m_columns[i];
00418 const Range & range = axis_model->getRange ( false );
00419 double value = m_ntuple -> valueAt ( row, column );
00420 if ( range.excludes ( value ) ) return false;
00421 }
00422
00423 return yes;
00424 }
00425
00428 const DataSource *
00429 NTupleProjector::
00430 getNTuple () const
00431 {
00432 return m_ntuple;
00433 }
00434
00437 DataSource *
00438 NTupleProjector::getNTuple ()
00439 {
00440 return const_cast < DataSource * > ( m_ntuple );
00441 }
00442
00443 const string & NTupleProjector::getNTupleName () const
00444 {
00445 return m_ntuple->getName ();
00446 }
00447
00448 double
00449 NTupleProjector::
00450 getAverage ( hippodraw::Axes::Type axis ) const
00451 {
00452
00453 double sum = 0.0;
00454 double number = 0.0;
00455
00456 string label = "";
00457
00458
00459 switch ( axis ) {
00460 case Axes::X:
00461 label = getXLabel();
00462 break;
00463 case Axes::Y:
00464 label = getYLabel();
00465 break;
00466 case Axes::Z:
00467 label = getZLabel();
00468 break;
00469 default:
00470 break;
00471 }
00472
00473
00474 const DataSource * tuple = getNTuple();
00475 if ( tuple -> empty () ) {
00476 return 0.0;
00477 }
00478
00479
00480
00481
00482 unsigned int column = tuple -> indexOf ( label );
00483
00484 const Range & r = getRange ( axis );
00485 unsigned int size = m_ntuple -> rows ();
00486 for ( unsigned int i = 0; i < size; i++ ) {
00487
00488 if ( !acceptRow ( i, m_cut_list ) )continue;
00489 double value = m_ntuple -> valueAt ( i, column );
00490
00491 if ( r.includes ( value ) ) {
00492 sum += value;
00493 number ++;
00494 }
00495
00496 }
00497
00498 return (sum / number);
00499 }
00500
00501 bool
00502 NTupleProjector::
00503 isEmpty () const
00504 {
00505 return m_ntuple -> empty ();
00506 }
00507
00508 NTuple *
00509 NTupleProjector::
00510 createEmptyNTuple () const
00511 {
00512 unsigned int columns = m_ntuple->columns();
00513
00514 NTuple * ntuple = new NTuple ( columns );
00515
00516 const vector < string > & labels = m_ntuple->getLabels();
00517 ntuple->setLabels ( labels );
00518
00519 unsigned int size = m_ntuple->rows();
00520 ntuple -> reserve ( size );
00521 return ntuple;
00522 }
00523
00524 void
00525 NTupleProjector::
00526 fillNTuple ( NTuple * ntuple, const CutList_t & cut_list ) const
00527 {
00528 unsigned int size = m_ntuple->rows();
00529
00530 for ( unsigned int i = 0; i < size; i++ ) {
00531 if ( acceptRow ( i, cut_list ) ) {
00532 const vector < double > & row = m_ntuple -> getRow ( i );
00533 ntuple -> addRow ( row );
00534 }
00535 }
00536 }
00537
00538 NTuple *
00539 NTupleProjector::
00540 getNTupleAfterCuts () const
00541 {
00542 NTuple * ntuple = createEmptyNTuple ();
00543 fillNTuple ( ntuple, m_cut_list );
00544
00545 return ntuple;
00546 }
00547
00548 void
00549 NTupleProjector::
00550 fillColumnAfterCuts(const std::string & column,
00551 std::vector<double> & columnData) const {
00552
00553 const std::vector<double> & coldata(m_ntuple->getColumn(column));
00554
00555 size_t nrows = m_ntuple->rows();
00556 for ( size_t i = 0 ; i < nrows ; i++ ) {
00557 if ( acceptRow( i, m_cut_list ) ) {
00558 columnData.push_back( coldata[i] );
00559 }
00560 }
00561 }
00562
00563 NTuple *
00564 NTupleProjector::
00565 createNTupleWith ( const std::vector < TupleCut > & tuple_cuts ) const
00566 {
00567 NTuple * ntuple = createEmptyNTuple ();
00568 vector < const TupleCut * > cut_list;
00569 for ( unsigned int i = 0; i < tuple_cuts.size(); i++ ) {
00570 const TupleCut & cut = tuple_cuts[i];
00571 cut_list.push_back ( & cut );
00572 }
00573 fillNTuple ( ntuple, cut_list );
00574
00575 return ntuple;
00576 }
00577
00578 bool
00579 NTupleProjector::
00580 isDataValid () const
00581 {
00582 return m_is_valid;
00583 }
00584
00585 bool
00586 NTupleProjector::
00587 hasDataSourceBindings () const
00588 {
00589 return true;
00590 }