00001
00002
00003
00004 #include <stdio.h>
00005 #include <time.h>
00006 #include <stdlib.h>
00007 #include <ctype.h>
00008 #include <string.h>
00009 #include <locale.h>
00010
00011 #include "common.h"
00012 #include "logic.h"
00013 #include "data.h"
00014 #include "model.h"
00015 #include "ui.h"
00016 #include "fit.h"
00017 #include "guess.h"
00018 #include "settings.h"
00019 #include "mgr.h"
00020 #include "func.h"
00021 #include "tplate.h"
00022 #include "lexer.h"
00023
00024 using namespace std;
00025
00026 DataAndModel::DataAndModel(Ftk *F, Data* data)
00027 : data_(data ? data : new Data(F)), model_(new Model(F))
00028 {}
00029
00030 bool DataAndModel::has_any_info() const
00031 {
00032 return data()->has_any_info() ||
00033 !model()->get_ff().empty() ||
00034 !model()->get_zz().empty();
00035 }
00036
00037
00038 Ftk::Ftk()
00039 : VariableManager(this),
00040 view(this),
00041 default_relative_domain_width(0.1)
00042 {
00043
00044 setlocale(LC_NUMERIC, "C");
00045 ui_ = new UserInterface(this);
00046 initialize();
00047 }
00048
00049 Ftk::~Ftk()
00050 {
00051 destroy();
00052 delete ui_;
00053 }
00054
00055
00056 void Ftk::initialize()
00057 {
00058 fit_container_ = new FitMethodsContainer(this);
00059
00060 settings_mgr_ = new SettingsMgr(this);
00061 tplate_mgr_ = new TplateMgr;
00062 tplate_mgr_->add_builtin_types(ui_->parser());
00063 view = View(this);
00064 dirty_plot_ = true;
00065 append_dm();
00066 default_dm_ = 0;
00067 settings_mgr()->do_srand();
00068 }
00069
00070
00071 void Ftk::destroy()
00072 {
00073 purge_all_elements(dms_);
00074 VariableManager::do_reset();
00075 delete fit_container_;
00076 delete settings_mgr_;
00077 delete tplate_mgr_;
00078 }
00079
00080
00081 void Ftk::reset()
00082 {
00083 int verbosity = get_settings()->verbosity;
00084 bool autoplot = get_settings()->autoplot;
00085 destroy();
00086 initialize();
00087 if (verbosity != get_settings()->verbosity)
00088 settings_mgr()->set_as_number("verbosity", verbosity);
00089 if (autoplot != get_settings()->autoplot)
00090 settings_mgr()->set_as_number("autoplot", autoplot);
00091 }
00092
00093 int Ftk::append_dm(Data *data)
00094 {
00095 DataAndModel* dm = new DataAndModel(this, data);
00096 dms_.push_back(dm);
00097 return dms_.size() - 1;
00098 }
00099
00100 void Ftk::remove_dm(int d)
00101 {
00102 if (d < 0 || d >= size(dms_))
00103 throw ExecuteError("there is no such dataset: @" + S(d));
00104 delete dms_[d];
00105 dms_.erase(dms_.begin() + d);
00106 if (dms_.empty())
00107 append_dm();
00108 }
00109
00110
00111 void Ftk::warn(string const &s) const
00112 {
00113 get_ui()->output_message(UserInterface::kWarning, s);
00114 }
00115
00116
00117 void Ftk::rmsg(string const &s) const
00118 {
00119 get_ui()->output_message(UserInterface::kNormal, s);
00120 }
00121
00122
00123 void Ftk::msg(string const &s) const
00124 {
00125 if (get_verbosity() >= 0)
00126 get_ui()->output_message(UserInterface::kNormal, s);
00127 }
00128
00129
00130 void Ftk::vmsg(string const &s) const
00131 {
00132 if (get_verbosity() >= 1)
00133 get_ui()->output_message(UserInterface::kNormal, s);
00134 }
00135
00136
00137 UserInterface::Status Ftk::exec(string const &s)
00138 {
00139 return get_ui()->exec_and_log(s);
00140 }
00141
00142 Fit* Ftk::get_fit() const
00143 {
00144 string method_name = get_settings()->fitting_method;
00145 v_foreach(Fit*, i, get_fit_container()->methods())
00146 if ((*i)->name == method_name)
00147 return *i;
00148 assert(0);
00149 return NULL;
00150 }
00151
00152 namespace {
00153
00154 int atoi_all(string const& s)
00155 {
00156 char *endptr;
00157 int n = strtol(s.c_str(), &endptr, 10);
00158 if (*endptr != 0)
00159 throw ExecuteError("integral number expected, got: " + s);
00160 return n;
00161 }
00162
00163
00164
00165
00166
00167 vector<int> parse_int_range(string const& s, int maximum)
00168 {
00169 vector<int> values;
00170 vector<string> t = split_string(s, ",");
00171 v_foreach (string, i, t) {
00172 string::size_type dots = i->find("..");
00173 if (dots == string::npos) {
00174 int n = atoi_all(*i);
00175 values.push_back(n);
00176 }
00177 else {
00178 int m = atoi_all(i->substr(0, dots));
00179 string n_ = i->substr(dots+2);
00180 int n = n_.empty() ? maximum : atoi_all(i->substr(dots+2));
00181 if (m < 0)
00182 m += maximum;
00183 if (n < 0)
00184 n += maximum;
00185 if (m < 0 || n < 0)
00186 throw ExecuteError("Negative number found in range: " + s);
00187 if (m <= n)
00188 for (int j = m; j <= n; ++j)
00189 values.push_back(j);
00190 else
00191 for (int j = m; j >= n; --j)
00192 values.push_back(j);
00193 }
00194 }
00195 return values;
00196 }
00197 }
00198
00199
00200 void Ftk::import_dataset(int slot, string const& filename,
00201 string const& format, string const& options)
00202 {
00203 const bool new_dataset = (slot == Lexer::kNew);
00204
00205
00206
00207 int count_colons = count(filename.begin(), filename.end(), ':');
00208 string fn;
00209 vector<int> indices[3];
00210 vector<int> block_range;
00211 if (count_colons >= 4) {
00212
00213 string::size_type fn_end = string::npos;
00214 for (int i = 0; i < 4; ++i)
00215 fn_end = filename.rfind(':', fn_end - 1);
00216 fn = filename.substr(0, fn_end);
00217
00218
00219 string::size_type end_pos = filename.size();
00220 string::size_type bpos = filename.rfind(':', end_pos - 1);
00221 string::size_type blen = end_pos - bpos - 1;
00222 if (blen > 0) {
00223 int block_count = Data::count_blocks(fn, format, options);
00224 string range = filename.substr(bpos+1, blen);
00225 block_range = parse_int_range(range, block_count-1);
00226 }
00227 end_pos = bpos;
00228
00229 int first_block = block_range.empty() ? 0 : block_range[0];
00230 int col_count = Data::count_columns(fn, format, options, first_block);
00231 for (int i = 2; i >= 0; --i) {
00232 string::size_type pos = filename.rfind(':', end_pos - 1);
00233 string::size_type len = end_pos - pos - 1;
00234 if (len > 0) {
00235 string range = filename.substr(pos+1, len);
00236 indices[i] = parse_int_range(range, col_count);
00237 }
00238 end_pos = pos;
00239 }
00240 assert(fn_end == end_pos);
00241 }
00242 else {
00243 fn = filename;
00244 }
00245
00246 if (indices[0].size() > 1)
00247 throw ExecuteError("Only one column x can be specified");
00248 if (indices[2].size() > 1)
00249 throw ExecuteError("Only one column sigma can be specified");
00250 if (indices[1].size() > 1 && !new_dataset)
00251 throw ExecuteError("Multiple y columns can be specified only with @+");
00252
00253 int idx_x = indices[0].empty() ? INT_MAX : indices[0][0];
00254 if (indices[1].empty())
00255 indices[1].push_back(INT_MAX);
00256 int idx_s = indices[2].empty() ? INT_MAX : indices[2][0];
00257
00258 for (size_t i = 0; i < indices[1].size(); ++i) {
00259 if (new_dataset && (get_dm_count() != 1 || get_dm(0)->has_any_info())) {
00260
00261 auto_ptr<Data> data(new Data(this));
00262 data->load_file(fn, idx_x, indices[1][i], idx_s,
00263 block_range, format, options);
00264 append_dm(data.release());
00265 }
00266 else {
00267
00268 int n = new_dataset ? 0 : slot;
00269 get_data(n)->load_file(fn, idx_x, indices[1][i], idx_s,
00270 block_range, format, options);
00271 }
00272 }
00273
00274 if (get_dm_count() == 1) {
00275 RealRange r;
00276 view.change_view(r, r, vector1(0));
00277 }
00278 }
00279
00280 void Ftk::outdated_plot()
00281 {
00282 dirty_plot_ = true;
00283 fit_container_->outdated_error_cache();
00284 }
00285