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