00001 #include "AtlfastEvent/Interpolator.h"
00002 #include <cmath>
00003
00004 namespace Atlfast{
00005
00006 Interpolator::Interpolator(string filename){
00007
00008 int level = 1;
00009 int jump = 0;
00010 vector<int> npoints;
00011 int nline = 0;
00012
00013
00014 ifstream ifs(filename.c_str());
00015 Setup(ifs,level,jump,npoints,nline);
00016
00017
00018
00019 findLimits(m_limits);
00020
00021
00022 setDefault(0);
00023
00024
00025
00026 int nlevelnames = m_levelnames.size();
00027 int nlevels = npoints.size();
00028 if ( nlevelnames && nlevelnames != nlevels ){
00029 std::cout << nlevelnames << " level identifiers given but "
00030 << nlevels << " levels detected, exiting" << std::endl;
00031 exit(1);
00032 }
00033
00034 m_contBounds = false;
00035
00036 }
00037
00038 Interpolator::Interpolator(double value, ifstream &ifs, int &level,
00039 int &jump, vector<int> &npoints, int &nline):
00040 m_value(value){
00041 ++level;
00042 Setup(ifs,level,jump,npoints,nline);
00043 }
00044
00045 void Interpolator::dump(){
00046 if (m_interpolators.size()){
00047 vector<Interpolator>::iterator viitr = m_interpolators.begin();
00048 for (;viitr!=m_interpolators.end();++viitr){
00049 std::cout << "Value = " << (*viitr).getValue() << std::endl;
00050 (*viitr).dump();
00051 }
00052 }else{
00053 vector<pair<double,double> >::iterator vdpitr = m_pairs.begin();
00054 for (;vdpitr!=m_pairs.end();++vdpitr){
00055 std::cout << "Value = " << (*vdpitr).first << ", eff = "
00056 << (*vdpitr).second << std::endl;
00057 }
00058 }
00059 }
00060
00061 void Interpolator::Setup(ifstream &ifs,int &level, int &jump,
00062 vector<int> &npoints, int &nline){
00063
00064
00065
00066
00067
00068
00069
00070
00071 if ( npoints.size() < static_cast<std::vector<int>::size_type>(level) ) npoints.push_back(0);
00072
00073 while (!ifs.eof()){
00074
00075 string read_line;
00076 double read_double;
00077
00078 getline(ifs,read_line); nline++;
00079 istringstream iss(read_line);
00080
00081
00082 int numbercount = 0;
00083 while (iss >> read_double) ++numbercount;
00084
00085 if (!numbercount){
00086
00087
00088
00089
00090
00091
00092 if (nline==1){
00093
00094
00095
00096
00097
00098 string level_name;
00099 int nlevel = 0;
00100 iss.clear(); iss.str(read_line);
00101 while (iss >> level_name){
00102 nlevel++;
00103 m_levelnames[level_name] = nlevel;
00104 }
00105 }
00106
00107 continue;
00108 }
00109
00110
00111 if (numbercount == 1){
00112
00113 Interpolator w(read_double,ifs,level,jump,npoints,nline);
00114 m_interpolators.push_back(w);
00115
00116
00117 if (jump){
00118 if (!npoints[level-1]) npoints[level-1] = m_interpolators.size();
00119 else if ( m_interpolators.size() != static_cast<std::vector<Interpolator>::size_type>(npoints[level-1]) ){
00120 string message("inconsistent number of points");
00121 exitParseWithMessage(message,nline,read_line);
00122 }
00123 --jump; --level;
00124 return;
00125 }
00126
00127 }else{
00128
00129
00130
00131
00132
00133 iss.clear(); iss.str(read_line);
00134 string read_second_line;
00135 getline(ifs,read_second_line); nline++;
00136 istringstream iss2(read_second_line);
00137 double read_second_double;
00138
00139
00140 while (iss >> read_double){
00141 if (!(iss2 >> read_second_double))
00142 exitParseWithMessage("#points > #values, reorganise input file",
00143 nline,read_second_line);
00144 pair<double,double> lowest_dim_value(read_double,read_second_double);
00145 m_pairs.push_back(lowest_dim_value);
00146 }
00147 if (iss2 >> read_second_double)
00148 exitParseWithMessage("#points < #values, reorganise input file",
00149 --nline,read_line);
00150 if (!npoints[level-1]) npoints[level-1] = m_pairs.size();
00151 else if ( m_pairs.size() != static_cast<std::vector<pair<double,double> >::size_type>(npoints[level-1]) ){
00152 exitParseWithMessage("inconsistent number of points in lowest dimension",
00153 --nline,read_line);
00154 }
00155
00156
00157 nDimensionsToJump(ifs,level,jump);
00158
00159 return;
00160 }
00161
00162 }
00163
00164 return;
00165 }
00166
00167 double Interpolator::interpolate(deque<double> values, bool performedchecks){
00168
00169 if ( !performedchecks && values.size() != m_limits.size()){
00170 std::cout << "Interpolator has " << m_limits.size()
00171 << " dimensions, supplied point exists in "
00172 << values.size() << " dimensions!" << std::endl;
00173 exit(1);
00174 }
00175
00176
00177 double def;
00178 if (!m_contBounds && !performedchecks && !inLimits(values,def))
00179 return def;
00180
00181 performedchecks = true;
00182
00183
00184 double fraction,value1,value2;
00185 double value = values.front();
00186
00187 if (m_interpolators.size()){
00188
00189
00190
00191
00192
00193 values.pop_front();
00194 ClosestInterpolators ci(value);
00195 vector<Interpolator>::iterator viitr = std::adjacent_find(m_interpolators.begin(),
00196 m_interpolators.end(),
00197 ci);
00198 vector<Interpolator>::iterator viitr2;
00199
00200 if (m_contBounds && viitr == m_interpolators.end()){
00201 if ( value < (*m_interpolators.begin()).getValue() ){
00202 viitr = m_interpolators.begin();
00203 }else{
00204 viitr = (m_interpolators.end()-1);
00205 }
00206 fraction = 0;
00207 value1 = (*viitr).interpolate(values,performedchecks);
00208 value2 = 0;
00209
00210 }else{
00211 viitr2 = viitr + 1;
00212
00213
00214 fraction = (value - (*viitr).getValue())/((*viitr2).getValue() - (*viitr).getValue());
00215 value1 = (*viitr).interpolate(values,performedchecks);
00216 value2 = (*viitr2).interpolate(values,performedchecks);
00217 }
00218
00219 }else{
00220
00221
00222
00223
00224 ClosestDoublePairs cdp(value);
00225 vector<pair<double,double> >::iterator vdpitr = std::adjacent_find(m_pairs.begin(),
00226 m_pairs.end(),
00227 cdp);
00228 vector<pair<double,double> >::iterator vdpitr2;
00229
00230 if (m_contBounds && vdpitr == m_pairs.end()){
00231 if ( value < (*m_pairs.begin()).first ){
00232 vdpitr = m_pairs.begin();
00233 }else{
00234 vdpitr = (m_pairs.end()-1);
00235 }
00236
00237 fraction = 0;
00238 value1 = (*vdpitr).second;
00239 value2 = 0;
00240 }else{
00241 vdpitr2 = vdpitr + 1;
00242
00243 fraction = (value - (*vdpitr).first)/((*vdpitr2).first - (*vdpitr).first);
00244 value1 = (*vdpitr).second;
00245 value2 = (*vdpitr2).second;
00246 }
00247
00248 }
00249
00250
00251 return value1 + fraction*(value2-value1);
00252 }
00253
00254 void Interpolator::findLimits(deque<pair<double,double> > &limits_deque){
00255
00256
00257
00258 pair<double,double> limits;
00259
00260 limits.first = (m_interpolators.size()) ?
00261 m_interpolators.front().getValue() :
00262 m_pairs.front().first;
00263
00264
00265
00266 limits.second = (m_interpolators.size()) ?
00267 m_interpolators.back().getValue():
00268 m_pairs.back().first;
00269
00270
00271
00272 limits_deque.push_back(limits);
00273
00274
00275 if (m_interpolators.size())
00276 m_interpolators.front().findLimits(limits_deque);
00277
00278 return;
00279
00280 }
00281
00282 void Interpolator::nDimensionsToJump(ifstream &ifs,int &level, int &jump){
00283
00284
00285
00286
00287
00288 int position = ifs.tellg();
00289
00290 int nsingleentries = 0;
00291 bool singleentry = true;
00292
00293
00294 while (singleentry && !ifs.eof()){
00295
00296 string read_line;
00297 getline(ifs,read_line);
00298 istringstream iss(read_line);
00299 int numbercount = 0;
00300 double read_double;
00301 while (iss >> read_double) ++numbercount;
00302 if (!numbercount) continue;
00303 if (numbercount == 1) ++nsingleentries;
00304 else singleentry = false;
00305
00306 }
00307
00308
00309
00310
00311 if (ifs.eof()) nsingleentries = level;
00312
00313 --level;
00314
00315
00316 ifs.seekg(position);
00317
00318
00319 jump = nsingleentries - 1;
00320
00321 return;
00322
00323 }
00324
00325 bool Interpolator::inLimits(deque<double> values, double& def){
00326
00327
00328
00329 deque<double> values_copy = values;
00330 deque<pair<double,double> > limits = m_limits;
00331 deque<pair<double,double> > defaults = m_defaults;
00332
00333
00334 while (values.size()){
00335 if ( values.front() < limits.front().first ){
00336 def = m_contBounds ? getNearestValue(values_copy) : defaults.front().first;
00337 return false;
00338 }
00339 if ( values.front() > limits.front().second ){
00340 def = m_contBounds ? getNearestValue(values_copy) : defaults.front().second;
00341 return false;
00342 }
00343 values.pop_front();
00344 limits.pop_front();
00345 defaults.pop_front();
00346 }
00347 return true;
00348 }
00349
00350 void Interpolator::setDefault(double def){
00351
00352
00353 int nlevels = m_limits.size();
00354
00355
00356 m_defaults.clear();
00357
00358
00359
00360 while (nlevels--){
00361 pair<double,double> default_pair(def,def);
00362 m_defaults.push_back(default_pair);
00363 }
00364
00365 return;
00366 }
00367
00368 void Interpolator::setDefault(int level, double def){
00369
00370 setDefault(level,def,def);
00371 return;
00372
00373 }
00374
00375 void Interpolator::setDefault(int level, double def_below, double def_above){
00376
00377 if (level < 1 || static_cast<std::deque<pair<double,double> >::size_type>(level) > m_limits.size()){
00378 std::cout << "Cannot set default for level " << level << std::endl;
00379 exit(1);
00380 }
00381
00382 pair<double,double> default_pair(def_below,def_above);
00383 m_defaults[level-1] = default_pair;
00384 return;
00385
00386 }
00387
00388 void Interpolator::setDefault(string levelname, double def){
00389 setDefault(levelname,def,def);
00390 return;
00391 }
00392
00393 void Interpolator::setDefault(string levelname, double def_below, double def_above){
00394
00395 if ( !m_levelnames.size()){
00396 std::cout << "No level names specified in input file, cannot set default with name" << std::endl;
00397 exit(1);
00398 }
00399
00400 if (!m_levelnames[levelname]){
00401 std::cout << "Level name " << levelname << " not found (typo?)" << std::endl;
00402 exit(1);
00403 }
00404
00405 setDefault(m_levelnames[levelname],def_below,def_above);
00406
00407 return;
00408 }
00409
00410 double Interpolator::getNearestValue(deque<double> values){
00411
00412 double value = values.front();
00413
00414 if (m_interpolators.size()){
00415
00416 values.pop_front();
00417 vector<Interpolator>::iterator closestPoint;
00418
00419 for (vector<Interpolator>::iterator intItr=m_interpolators.begin();
00420 intItr!=m_interpolators.end();++intItr){
00421 if (intItr==m_interpolators.begin() &&
00422 fabs(value-(*intItr).getValue()) < fabs(value-(*(intItr+1)).getValue()))
00423 closestPoint = intItr;
00424 else if (intItr==m_interpolators.end()-1 &&
00425 fabs(value-(*intItr).getValue()) < fabs(value-(*(intItr-1)).getValue()))
00426 closestPoint = intItr;
00427 else if (fabs(value-(*intItr).getValue()) < fabs(value-(*(intItr-1)).getValue()) &&
00428 fabs(value-(*intItr).getValue()) < fabs(value-(*(intItr+1)).getValue()))
00429 closestPoint = intItr;
00430 }
00431 return (*closestPoint).getNearestValue(values);
00432
00433 }else{
00434
00435 vector<pair<double,double> >::iterator closestPoint;
00436
00437 for (vector<pair<double,double> >::iterator vpdItr=m_pairs.begin();
00438 vpdItr!=m_pairs.end();++vpdItr){
00439 if (vpdItr==m_pairs.begin() &&
00440 fabs(value-(*vpdItr).first) < fabs(value-(*(vpdItr+1)).first))
00441 closestPoint = vpdItr;
00442 else if (vpdItr==m_pairs.end()-1 &&
00443 fabs(value-(*vpdItr).first) < fabs(value-(*(vpdItr-1)).first))
00444 closestPoint = vpdItr;
00445 else if (fabs(value-(*vpdItr).first) < fabs(value-(*(vpdItr-1)).first) &&
00446 fabs(value-(*vpdItr).first) < fabs(value-(*(vpdItr+1)).first))
00447 closestPoint = vpdItr;
00448 }
00449 return (*closestPoint).second;
00450
00451 }
00452 }
00453
00454 void Interpolator::exitParseWithMessage(string message, int nline, string line){
00455 std::cout << "Exiting Interpolator, " << message << std::endl;
00456 std::cout << "Problem occurred at about line " << nline << " of input file:" << std::endl;
00457 std::cout << line << std::endl;
00458 exit(1);
00459 }
00460
00461
00462
00463
00464
00465 ClosestInterpolators::ClosestInterpolators(double value): m_value(value){}
00466
00467 bool ClosestInterpolators::operator()(Interpolator &i1, Interpolator &i2){
00468 return (i1.getValue() <= m_value && i2.getValue() >= m_value) ? true : false;
00469 }
00470
00471
00472
00473
00474
00475 ClosestDoublePairs::ClosestDoublePairs(double value): m_value(value){}
00476
00477 bool ClosestDoublePairs::operator()(pair<double,double> &p1,
00478 pair<double,double> &p2){
00479 return (p1.first <= m_value && p2.first >= m_value) ? true : false;
00480 }
00481
00482 }