source: Sophya/trunk/SophyaLib/NTools/slininterp.cc@ 3890

Last change on this file since 3890 was 3874, checked in by ansari, 15 years ago

Ajout gestion lignes commentaires ds les fichiers input de SLinInterp1D, Reza 07/09/2010

File size: 9.1 KB
Line 
1/*
2 --- SOPHYA software - NTools module ---
3 --- Class SLinInterp1D : Simple linear 1D interpolation class
4 R. Ansari , C. Magneville 2000-2010
5 (C) UPS+LAL IN2P3/CNRS (C) IRFU-SPP/CEA
6*/
7
8#include "slininterp.h"
9#include <fstream>
10
11namespace SOPHYA {
12
13/*!
14 \class SLinInterp1D
15 \ingroup NTools
16 \brief Simple linear interpolation class
17
18 \code
19 #include "slininterp.h"
20 #include "srandgen.h"
21
22 ...
23 vector<double> ys;
24 double xmin = 0.5;
25 double xmax = 0.;
26 for(int i=0; i<=12; i++) {
27 xmax = xmin+i*0.1;
28 yreg.push_back(sin(xmax)*cos(2.2*xmax));
29 }
30 SLinInterp1D interpYR(xmin, xmax, yreg);
31 cout << interpYR
32 for(int i=0; i<=12; i++) {
33 double x = drand01()*2.;
34 cout << " Interpol result for X=" << x << " -> " << interpYR(x) << " ?= " << sin(x)*cos(2.2*x) << endl;
35 }
36 \endcode
37*/
38
39/* --Methode-- */
40SLinInterp1D::SLinInterp1D()
41 : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0)
42{
43 xs_.push_back(0.);
44 xs_.push_back(1.);
45 ys_.push_back(0.);
46 ys_.push_back(1.);
47}
48
49/*!
50 \brief Constructor from regularly spaced points in X with Y values defined by yreg
51
52 \b xmin and \b xmax are the two extreme points in X corresponding to yreg.
53 Example: xmin=1, xmax=10, with yreg.size()=10 ,
54 yreg[0]=Y(1) , yreg[1]=Y(2) ... yreg[9]=Y(10)
55*/
56SLinInterp1D::SLinInterp1D(double xmin, double xmax, vector<double>& yreg)
57 : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0)
58{
59 DefinePoints(xmin, xmax, yreg);
60}
61
62
63/*!
64 \brief Constructor from a set of \b (xs[i],ys[i]) pairs.
65
66 if (npt > 0), interpolates to a finer regularly spaced grid, from \b xmin to \b xmax
67 with npt points. use \b (xs[0],xs[xs.size()-1]) as limits if \b xmax<xmin
68*/
69SLinInterp1D::SLinInterp1D(vector<double>& xs, vector<double>& ys, double xmin, double xmax, size_t npt)
70 : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0)
71{
72 DefinePoints(xs, ys, xmin, xmax, npt);
73}
74
75/* --Methode-- */
76double SLinInterp1D::YInterp(double x) const
77{
78 if (npoints_>0) { // on utilise les points regulierement espace
79 long i = (long)((x-xmin_)/dx_);
80 if (i<0) return ( yreg_[0]+(x-xmin_)*(yreg_[1]-yreg_[0])/dx_ );
81 if (i>=npoints_) return ( yreg_[npoints_]+(x-xmax_)*(yreg_[npoints_]-yreg_[npoints_-1])/dx_ );
82 return (yreg_[i]+(x-X(i))/dx_*(yreg_[i+1]-yreg_[i]));
83 }
84 else { // On utilise les points xs_,ys_ directement
85 if (x<=xs_[0]) return ( ys_[0]+(x-xs_[0])*(ys_[1]-ys_[0])/(xs_[1]-xs_[0]) );
86 if (x>=xs_[ksmx_]) return ( ys_[ksmx_]+(x-xs_[ksmx_])*(ys_[ksmx_]-ys_[ksmx_-1])/(xs_[ksmx_]-xs_[ksmx_-1]) );
87
88 size_t k=1;
89 while(x>xs_[k]) k++;
90 if (k>=xs_.size()) { // ne devrait pas arriver ...
91 string emsg = " SLinInterp1D::YInterp() out of range k -> BUG in code ";
92 throw out_of_range(emsg);
93 }
94
95 double rv=ys_[k-1]+(x-xs_[k-1])*(ys_[k]-ys_[k-1])/(xs_[k]-xs_[k-1]);
96 // cout << " DBG- x=" << x << " k=" << k << " xs[k]=" << xs_[k] << " ys[k]" << ys_[k]
97 // << " rv=" << rv << endl;
98 return rv;
99 }
100}
101
102/*!
103 \brief Defines the interpolation points from regularly spaced points in X with Y values defined by yreg
104
105 \b xmin and \b xmax are the two extreme points in X corresponding to yreg.
106 Example: xmin=1, xmax=10, with yreg.size()=10 ,
107 yreg[0]=Y(1) , yreg[1]=Y(2) ... yreg[9]=Y(10)
108*/
109void SLinInterp1D::DefinePoints(double xmin, double xmax, vector<double>& yreg)
110{
111 if (yreg.size()<2) {
112 string emsg = "SLinInterp1D::DefinePoints(xmin,xmax,yreg) Bad parameters yreg.size()<2 ";
113 throw range_error(emsg);
114 }
115 xmin_ = xmin;
116 xmax_ = xmax;
117 npoints_ = yreg.size()-1;
118 dx_ = (xmax_-xmin_)/(double)npoints_;
119 yreg_ = yreg;
120}
121
122
123/*!
124 \brief Define the interpolation points from a set of \b (xs[i],ys[i]) pairs.
125
126 if (npt > 0), interpolates to a finer regularly spaced grid, from \b xmin to \b xmax
127 with npt points. use \b (xs[0],xs[xs.size()-1]) as limits if \b xmax<xmin
128*/
129void SLinInterp1D::DefinePoints(vector<double>& xs, vector<double>& ys, double xmin, double xmax, size_t npt)
130{
131 if ((xs.size() != ys.size())||(xs.size()<2)) {
132 string emsg = "SLinInterp1D::DefinePoints() Bad parameters (xs.size() != ys.size())||(xs.size()<2) ";
133 throw range_error(emsg);
134 }
135 for(size_t k=1; k<xs.size(); k++) {
136 if (xs[k-1]>=xs[k]) {
137 string emsg = "SLinInterp1D::DefinePoints() unsorted xs ";
138 throw range_error(emsg);
139 }
140 }
141 xs_=xs;
142 ys_=ys;
143 ksmx_=xs_.size()-1;
144 npoints_ = npt;
145 if (xmin>=xmax) {
146 xmin_ = xs_[0];
147 xmax_ = xs_[ksmx_];
148 }
149 else {
150 xmin_ = xmin;
151 xmax_ = xmax;
152 }
153 if (npoints_<1) {
154 dx_=(xmax_-xmin_)/(double)(xs_.size()-1);
155 return;
156 }
157 dx_ = (xmax_-xmin_)/(double)npoints_;
158 yreg_.resize(npoints_+1);
159
160 // Compute the the y values for regularly spaced x xmin <= x <= xmax
161 // and keep values in the yreg vector
162 yreg_[0] = ys_[0];
163 yreg_[npoints_] = ys_[ksmx_];
164 size_t k=1;
165 for(size_t i=0; i<npoints_; i++) {
166 double x = X(i);
167 while(x>xs_[k]) k++;
168 if (k>=xs_.size()) k=xs_.size()-1;
169 yreg_[i] = ys_[k-1]+(x-xs_[k-1])*(ys_[k]-ys_[k-1])/(xs_[k]-xs_[k-1]);
170 //DBG cout << " DBG* i=" << i << " X(i)=" << X(i) << " yreg_[i]= " << yreg_[i] << " X^2= " << X(i)*X(i)
171 //DBG << " k=" << k << " xs[k]=" << xs_[k] << endl;
172 }
173 return;
174}
175
176
177/*!
178 \brief Read Y values from the file \b filename
179
180 Read Y values ( one/line) for regularly spaced X's from file \b filename and call
181 DefinePoints(xmin, xmax, yreg). Return the number of Y values read.
182 \param filename : input file name
183 \param xmin,xamx : X range limits
184 \param clm : comment character, lines starting with \b clm are ignored
185*/
186size_t SLinInterp1D::ReadYFromFile(string const& filename, double xmin, double xmax, char clm)
187{
188 ifstream inputFile;
189 inputFile.open(filename.c_str(), ifstream::in);
190#ifndef __DECCXX
191// ifstream.is_open() ne passe pas avec OSF-cxx
192 if(! inputFile.is_open()) {
193 string emsg = " SLinInterp1D::ReadYFromFile() problem opening file ";
194 emsg += filename;
195 throw runtime_error(emsg);
196 }
197#endif
198
199 vector<double> xsv, ysv;
200 size_t cnt=0;
201 double cola;
202 string eline;
203 while(!inputFile.eof()) {
204 inputFile.clear();
205 if (inputFile.peek() == (int)clm) { // skip comment lines
206 getline(inputFile, eline);
207 continue;
208 }
209 inputFile >> cola;
210 if ( (!inputFile.good()) || inputFile.eof()) break;
211 inputFile.ignore(1024,'\n'); // make sure we go to the next line
212 //cout << cola<< " "<<colb<<endl;
213 ysv.push_back(cola);
214 cnt++;
215 }
216 inputFile.close();
217 cout << " SLinInterp1D::ReadYFromFile()/Info: " << cnt << " Y-values read from file " << filename << endl;
218 DefinePoints(xmin, xmax, ysv);
219 return cnt;
220}
221
222/*!
223 \brief Read pairs of ( X Y ) values from file \b filename
224
225 Read pairs of (X Y) values, one pair / line from the specified file and call DefinePoints(xs, ys ...).
226 One pair of space or tab separated numbers on each line. Return the number of Y values read.
227 \param filename : input file name
228 \param xmin,xamx : X range limits. use the X limits from the file if xmax<xmin
229 \param npt : number of points for regularly spaced interpolation points
230 \param clm : comment character, lines starting with \b clm are ignored
231*/
232size_t SLinInterp1D::ReadXYFromFile(string const& filename, double xmin, double xmax, size_t npt, char clm)
233{
234 ifstream inputFile;
235 inputFile.open(filename.c_str(), ifstream::in);
236#ifndef __DECCXX
237// ifstream.is_open() ne passe pas avec OSF-cxx
238 if(! inputFile.is_open()) {
239 string emsg = " SLinInterp1D::ReadXYFromFile() problem opening file ";
240 emsg += filename;
241 throw runtime_error(emsg);
242 }
243#endif
244
245 vector<double> xsv, ysv;
246 size_t cnt=0;
247 double cola, colb;
248 string eline;
249 while(!inputFile.eof()) {
250 inputFile.clear();
251 if (inputFile.peek() == (int)clm) { // skip comment lines
252 getline(inputFile, eline);
253 continue;
254 }
255 inputFile >> cola >> colb;
256 if ( (!inputFile.good()) || inputFile.eof()) break;
257 inputFile.ignore(1024,'\n'); // make sure we go to the next line
258 // cout << " DEBUG-GCount " << inputFile.gcount() << endl;
259 // cout << " DEBUG - cnt=" << cnt << " x=" << cola << " y= "<<colb<<endl;
260 xsv.push_back(cola);
261 ysv.push_back(colb);
262 cnt++;
263 }
264 inputFile.close();
265 cout << " SLinInterp1D::ReadXYFromFile()/Info: " << cnt << " (x,y) pairs read from file " << filename << endl;
266 DefinePoints(xsv, ysv, xmin, xmax, npt);
267 return cnt;
268}
269
270
271/* --Methode-- */
272ostream& SLinInterp1D::Print(ostream& os, int lev) const
273{
274 os << " ---- SLinInterp1D::Print() XMin=" << XMin() << " XMax=" << XMax() << " NPoints=" << npoints_ << endl;
275 os << " xs_.size()= " << xs_.size() << " ys_.size()= " << ys_.size() << " yreg_.size()= " << yreg_.size() << endl;
276 if ((lev>0)&&(xs_.size()>0)) {
277 for(size_t i=0; i<xs_.size(); i++)
278 os << " xs[" << i << " ]=" << xs_[i] << " -> ys[" << i << "]=" << ys_[i] << endl;
279 }
280 if ((lev>0)&&(yreg_.size()>0)) {
281 for(size_t i=0; i<yreg_.size(); i++)
282 os << " Regularly Spaced X(" << i << " )=" << X(i) << " -> yreg_[" << i << "]=" << yreg_[i] << endl;
283 }
284 os << " -----------------------------------------------------------------------" << endl;
285}
286
287} // End namespace SOPHYA
288
Note: See TracBrowser for help on using the repository browser.