00001
00002
00003
00004 #include "common.h"
00005 #include "data.h"
00006
00007 #include "numfuncs.h"
00008 #include "settings.h"
00009 #include "logic.h"
00010
00011 #include <math.h>
00012 #include <string.h>
00013 #include <stdlib.h>
00014 #include <algorithm>
00015
00016 #include <xylib/xylib.h>
00017 #include <xylib/cache.h>
00018
00019 using namespace std;
00020
00021
00022 string get_file_basename(const string& path)
00023 {
00024 string::size_type last_sep = path.rfind(PATH_COMPONENT_SEP);
00025 string::size_type last_dot = path.rfind('.');
00026 size_t basename_begin = (last_sep == string::npos ? 0 : last_sep + 1);
00027 if (last_dot != string::npos && last_dot > basename_begin)
00028 return string(path, basename_begin, last_dot-basename_begin);
00029 else
00030 return string(path, basename_begin);
00031 }
00032
00033
00034 string Data::get_info() const
00035 {
00036 string s;
00037 if (p_.empty())
00038 s = "No data points.";
00039 else
00040 s = S(p_.size()) + " points, " + S(active_.size()) + " active.";
00041 if (!filename_.empty())
00042 s += "\nFilename: " + filename_;
00043 if (given_x_ != INT_MAX || given_y_ != INT_MAX || given_s_ != INT_MAX)
00044 s += "\nColumns: " + (given_x_ != INT_MAX ? S(given_x_) : S("_"))
00045 + ", " + (given_y_ != INT_MAX ? S(given_y_) : S("_"));
00046 if (given_s_ != INT_MAX)
00047 s += ", " + S(given_s_);
00048 if (!title_.empty())
00049 s += "\nData title: " + title_;
00050 if (active_.size() != p_.size())
00051 s += "\nActive data range: " + range_as_string();
00052 return s;
00053 }
00054
00055 void Data::clear()
00056 {
00057 filename_ = "";
00058 title_ = "";
00059 given_x_ = given_y_ = given_s_ = INT_MAX;
00060 given_options_.clear();
00061 given_blocks_.clear();
00062 p_.clear();
00063 x_step_ = 0;
00064 active_.clear();
00065 has_sigma_ = false;
00066 }
00067
00068 void Data::post_load()
00069 {
00070 if (p_.empty())
00071 return;
00072 string inf = S(p_.size()) + " points.";
00073 if (!has_sigma_) {
00074 string dds = F_->get_settings()->default_sigma;
00075 if (dds == "sqrt") {
00076 for (vector<Point>::iterator i = p_.begin(); i < p_.end(); i++)
00077 i->sigma = i->y > 1. ? sqrt (i->y) : 1.;
00078 inf += " No explicit std. dev. Set as sqrt(y)";
00079 }
00080 else if (dds == "one") {
00081 for (vector<Point>::iterator i = p_.begin(); i < p_.end(); i++)
00082 i->sigma = 1.;
00083 inf += " No explicit std. dev. Set as equal 1.";
00084 }
00085 else
00086 assert(0);
00087 }
00088 F_->msg(inf);
00089 update_active_p();
00090 }
00091
00092 int Data::load_arrays(const vector<realt> &x, const vector<realt> &y,
00093 const vector<realt> &sigma, const string &data_title)
00094 {
00095 assert(x.size() == y.size());
00096 assert(sigma.empty() || sigma.size() == y.size());
00097 clear();
00098 title_ = data_title;
00099 p_.resize(y.size());
00100 if (sigma.empty())
00101 for (size_t i = 0; i != y.size(); ++i)
00102 p_[i] = Point(x[i], y[i]);
00103 else {
00104 for (size_t i = 0; i != y.size(); ++i)
00105 p_[i] = Point(x[i], y[i], sigma[i]);
00106 has_sigma_ = true;
00107 }
00108 sort_points();
00109 find_step();
00110 post_load();
00111 return p_.size();
00112 }
00113
00114 void Data::set_points(const vector<Point> &p)
00115 {
00116 p_ = p;
00117 sort_points();
00118 after_transform();
00119 }
00120
00121 void Data::revert()
00122 {
00123 if (filename_.empty())
00124 throw ExecuteError("Dataset can't be reverted, it was not loaded "
00125 "from file");
00126 string old_title = title_;
00127 string old_filename = filename_;
00128
00129
00130 load_file(old_filename, given_x_, given_y_, given_s_,
00131 given_blocks_, given_format_, given_options_);
00132 title_ = old_title;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 void Data::add_one_point(realt x, realt y, realt sigma)
00165 {
00166 Point pt(x, y, sigma);
00167 vector<Point>::iterator a = upper_bound(p_.begin(), p_.end(), pt);
00168 int idx = a - p_.begin();
00169 p_.insert(a, pt);
00170 active_.insert(upper_bound(active_.begin(), active_.end(), idx), idx);
00171
00172 if (p_.size() < 2)
00173 x_step_ = 0.;
00174 else if (p_.size() == 2)
00175 x_step_ = p_[1].x - p_[0].x;
00176 else if (x_step_ != 0) {
00177
00178 double max_diff = 1e-4 * fabs(x_step_);
00179 if (idx == 0 && fabs((p_[1].x - p_[0].x) - x_step_) < max_diff)
00180 ;
00181 else if (idx == size(p_) - 1
00182 && fabs((p_[idx].x - p_[idx-1].x) - x_step_) < max_diff)
00183 ;
00184 else
00185 x_step_ = 0.;
00186 }
00187 }
00188
00189 void Data::update_active_for_one_point(int idx)
00190 {
00191 vector<int>::iterator a = lower_bound(active_.begin(), active_.end(), idx);
00192 bool present = (a < active_.end() && *a == idx);
00193
00194 assert(present != p_[idx].is_active);
00195 if (present)
00196 active_.erase(a);
00197 else
00198 active_.insert(a, idx);
00199 }
00200
00201
00202 static string tr_opt(string options)
00203 {
00204 size_t pos = 0;
00205 while ((pos = options.find('_', pos)) != string::npos)
00206 {
00207 options[pos] = '-';
00208 ++pos;
00209 }
00210 return options;
00211 }
00212
00213 int Data::count_blocks(const string& fn,
00214 const string& format, const string& options)
00215 {
00216 try {
00217 shared_ptr<const xylib::DataSet> xyds(
00218 xylib::cached_load_file(fn, format, tr_opt(options)));
00219 return xyds->get_block_count();
00220 } catch (const runtime_error& e) {
00221 throw ExecuteError(e.what());
00222 }
00223 }
00224
00225 int Data::count_columns(const string& fn,
00226 const string& format, const string& options,
00227 int first_block)
00228 {
00229 try {
00230 shared_ptr<const xylib::DataSet> xyds(
00231 xylib::cached_load_file(fn, format, tr_opt(options)));
00232 return xyds->get_block(first_block)->get_column_count();
00233 } catch (const runtime_error& e) {
00234 throw ExecuteError(e.what());
00235 }
00236 }
00237
00238
00239 void Data::load_file (const string& fn,
00240 int idx_x, int idx_y, int idx_s,
00241 const vector<int>& blocks,
00242 const string& format, const string& options)
00243 {
00244 if (fn.empty())
00245 return;
00246
00247 string block_name;
00248 try {
00249 shared_ptr<const xylib::DataSet> xyds(
00250 xylib::cached_load_file(fn, format, tr_opt(options)));
00251 clear();
00252 vector<int> bb = blocks.empty() ? vector1(0) : blocks;
00253
00254 v_foreach (int, b, bb) {
00255 assert(xyds);
00256 const xylib::Block* block = xyds->get_block(*b);
00257 const xylib::Column& xcol
00258 = block->get_column(idx_x != INT_MAX ? idx_x : 1);
00259 const xylib::Column& ycol
00260 = block->get_column(idx_y != INT_MAX ? idx_y : 2);
00261 int n = block->get_point_count();
00262 if (n < 5 && bb.size() == 1)
00263 F_->warn("Only " + S(n) + " data points found in file.");
00264
00265 if (idx_s == INT_MAX) {
00266 for (int i = 0; i < n; ++i) {
00267 p_.push_back(Point(xcol.get_value(i), ycol.get_value(i)));
00268 }
00269 }
00270 else {
00271 const xylib::Column& scol
00272 = block->get_column(idx_s != INT_MAX ? idx_s : 2);
00273 for (int i = 0; i < n; ++i) {
00274 p_.push_back(Point(xcol.get_value(i), ycol.get_value(i),
00275 scol.get_value(i)));
00276 }
00277 has_sigma_ = true;
00278 }
00279 if (xcol.get_step() != 0.) {
00280 x_step_ = xcol.get_step();
00281 if (x_step_ < 0) {
00282 reverse(p_.begin(), p_.end());
00283 x_step_ = -x_step_;
00284 }
00285 }
00286 if (!ycol.get_name().empty()) {
00287 if (!block_name.empty())
00288 block_name += "/";
00289 block_name += ycol.get_name();
00290 if (!xcol.get_name().empty())
00291 block_name += "(" + xcol.get_name() + ")";
00292 }
00293 else if (!block->get_name().empty()) {
00294 if (!block_name.empty())
00295 block_name += "/";
00296 block_name += block->get_name();
00297 }
00298 }
00299 } catch (const runtime_error& e) {
00300 throw ExecuteError(e.what());
00301 }
00302
00303 if (!block_name.empty())
00304 title_ = block_name;
00305 else {
00306 title_ = get_file_basename(fn);
00307 if (idx_x != INT_MAX && idx_y != INT_MAX)
00308 title_ += ":" + S(idx_x) + ":" + S(idx_y);
00309 }
00310
00311 if (x_step_ == 0) {
00312 sort_points();
00313 find_step();
00314 }
00315
00316 filename_ = fn;
00317 given_x_ = idx_x;
00318 given_y_ = idx_y;
00319 given_s_ = idx_s;
00320 given_blocks_ = blocks;
00321 given_options_ = options;
00322
00323 post_load();
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 template <typename T>
00342 bool is_vector_sorted(const vector<T>& v)
00343 {
00344 if (v.size() <= 1)
00345 return true;
00346 for (typename vector<T>::const_iterator i = v.begin()+1; i != v.end(); ++i)
00347 if (*i < *(i-1))
00348 return false;
00349 return true;
00350 }
00351
00352 void Data::after_transform()
00353 {
00354 if (!is_vector_sorted(p_))
00355 sort_points();
00356 find_step();
00357 update_active_p();
00358 }
00359
00360 void Data::update_active_p()
00361
00362
00363 {
00364 active_.clear();
00365 for (int i = 0; i < size(p_); i++)
00366 if (p_[i].is_active)
00367 active_.push_back(i);
00368 }
00369
00370
00371
00372 string Data::range_as_string() const
00373 {
00374 if (active_.empty()) {
00375 F_->warn ("File not loaded or all points inactive.");
00376 return "[]";
00377 }
00378 vector<Point>::const_iterator old_p = p_.begin() + active_[0];
00379 double left = old_p->x;
00380 string s = "[" + S (left) + " : ";
00381 for (vector<int>::const_iterator i = active_.begin() + 1;
00382 i != active_.end(); i++) {
00383 if (p_.begin() + *i != old_p + 1) {
00384 double right = old_p->x;
00385 left = p_[*i].x;
00386 s += S(right) + "] + [" + S(left) + " : ";
00387 }
00388 old_p = p_.begin() + *i;
00389 }
00390 double right = old_p->x;
00391 s += S(right) + "]";
00392 return s;
00393 }
00394
00395
00396 void Data::find_step()
00397 {
00398 const double tiny_relat_diff = 1e-4;
00399 size_t len = p_.size();
00400 if (len < 2) {
00401 x_step_ = 0.;
00402 return;
00403 }
00404 else if (len == 2) {
00405 x_step_ = p_[1].x - p_[0].x;
00406 return;
00407 }
00408
00409
00410 double s1 = p_[1].x - p_[0].x;
00411 double s2 = p_[len-1].x - p_[len-2].x;
00412 if (fabs(s2 - s1) > tiny_relat_diff * fabs(s2+s1)) {
00413 x_step_ = 0.;
00414 return;
00415 }
00416
00417 double min_step, max_step, step;
00418 min_step = max_step = p_[1].x - p_[0].x;
00419 for (vector<Point>::iterator i = p_.begin() + 2; i < p_.end(); i++) {
00420 step = i->x - (i-1)->x;
00421 min_step = min (min_step, step);
00422 max_step = max (max_step, step);
00423 }
00424 double avg = (max_step + min_step) / 2;
00425 if ((max_step - min_step) < tiny_relat_diff * fabs(avg))
00426 x_step_ = avg;
00427 else
00428 x_step_ = 0.;
00429 }
00430
00431 void Data::sort_points()
00432 {
00433 sort(p_.begin(), p_.end());
00434 }
00435
00436 int Data::get_lower_bound_ac(double x) const
00437 {
00438
00439 int pit = lower_bound(p_.begin(), p_.end(), Point(x,0)) - p_.begin();
00440 return lower_bound(active_.begin(), active_.end(), pit) - active_.begin();
00441 }
00442
00443 int Data::get_upper_bound_ac(double x) const
00444 {
00445
00446 int pit = upper_bound(p_.begin(), p_.end(), Point(x,0)) - p_.begin();
00447 return upper_bound(active_.begin(), active_.end(), pit) - active_.begin();
00448 }
00449
00450 vector<Point>::const_iterator Data::get_point_at(double x) const
00451 {
00452 return lower_bound (p_.begin(), p_.end(), Point(x,0));
00453 }
00454
00455 double Data::get_x_min() const
00456 {
00457 v_foreach (Point, i, p_)
00458 if (is_finite(i->x))
00459 return i->x;
00460 return 0.;
00461 }
00462
00463 double Data::get_x_max() const
00464 {
00465 if (p_.empty())
00466 return 180.;
00467 for (vector<Point>::const_reverse_iterator i = p_.rbegin();
00468 i != p_.rend(); ++i)
00469 if (is_finite(i->x))
00470 return i->x;
00471 return 180.;
00472 }
00473