Q:/Codes/PPF/FullPPF/ppfdatatype.cpp

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <fstream>
00003 #include <cstdlib>
00004 #include <string>
00005 #include "ppftypes.hpp"
00006 #include "ppfdatatype.hpp"
00007 
00008 using namespace std;
00009 
00010 namespace ppf
00011 {
00012         datatype::datatype()
00013         {
00014                 xunit = "";
00015                 tunit = "";
00016                 dataunit = "";
00017                 comment = "";
00018                 userdtstatus = 0;
00019                 sysddastatus = 0;
00020                 sysdtstatus = 0;
00021         }
00022 
00023         datatype::datatype(string filename)
00024         {
00025                 this->readLocal(filename);
00026         }
00027 
00028         // this method is currently quite crude (see ppf::write(filename) comment)
00029         void datatype::readLocal(string filename)
00030         {
00031                 const string header = "PPFLDF";
00032                 const short majorver = 1;
00033                 const short minorver = 0;
00034                 ifstream file;
00035                 short tempsi;
00036                 int tempi;
00037                 char tempca[24];
00038                 string tempst;
00039 
00040                 // open file
00041                 file.open(filename.c_str(), ios::binary);
00042                 
00043                 // check if file is open, report any errors
00044                 if(!file.is_open()) throw ppf_error("Could not open specified local PPF file.");
00045 
00046                 // read in header, check it is correct, report an error if it isn't
00047                 file.read(tempca, 6);
00048                 tempst.assign(tempca, 6);
00049                 if (tempst != header)
00050                 {
00051                         file.close();
00052                         throw ppf_error("Specified file is not a local PPF file.");
00053                 }
00054                 file.read((char*) &tempsi, sizeof(short));
00055                 if (tempsi != majorver)
00056                 {
00057                         file.close();
00058                         throw ppf_error("The version number of the specified local PPF file is not supported.");
00059                 }
00060                 file.read((char*) &tempsi, sizeof(short));
00061                 if (tempsi != minorver)
00062                 {
00063                         file.close();
00064                         throw ppf_error("The version number of the specified local PPF file is not supported.");
00065                 }
00066                 
00067                 // read t unit string (8 chars)
00068                 file.read(tempca, 8);
00069                 tunit.assign(tempca, 8);
00070 
00071                 // read x unit string (8 chars)
00072                 file.read(tempca, 8);
00073                 xunit.assign(tempca, 8);
00074 
00075                 // read data unit string (8 chars)
00076                 file.read(tempca, 8);
00077                 dataunit.assign(tempca, 8);
00078 
00079                 // read comment string (24 chars)
00080                 file.read(tempca, 24);
00081                 comment.assign(tempca, 24);
00082 
00083                 // read status values
00084                 file.read((char*) &tempi, sizeof(int));
00085                 userdtstatus = tempi;
00086                 file.read((char*) &tempi, sizeof(int));
00087                 sysddastatus = tempi;
00088                 file.read((char*) &tempi, sizeof(int));
00089                 sysdtstatus = tempi;
00090 
00091                 // read data t and x dimensions and set vector sizes
00092                 file.read((char*) &tempi, sizeof(int)); // t dimension
00093                 t.resize(tempi);
00094                 data.resize(tempi);
00095                 file.read((char*) &tempi, sizeof(int)); // x dimension
00096                 x.resize(tempi);
00097                 for(int i=0;i<data.size();i++) data[i].resize(tempi);
00098 
00099                 // read t, x and data vectors
00100                 for(int i=0;i<t.size();i++) file.read((char*) &t[i], sizeof(float));
00101                 for(int i=0;i<x.size();i++) file.read((char*) &x[i], sizeof(float));
00102                 for(int i=0;i<t.size();i++) for(int j=0;j<x.size();j++) file.read((char*) &data[i][j], sizeof(float));
00103 
00104                 // close file
00105                 file.close();
00106         }
00107 
00108         // this method is currently quite crude, it writes the X and T vectors even if they are not being used (ie all zeros)
00109         void datatype::writeLocal(string filename)
00110         {
00111                 const string header = "PPFLDF";
00112                 const short majorver = 1;
00113                 const short minorver = 0;
00114                 ofstream file;
00115                 int temp;
00116 
00117                 // open file
00118                 file.open(filename.c_str(), ios::binary);
00119 
00120                 // check if file is open, report any errors
00121                 if(!file.is_open()) throw ppf_error("The local PPF file could not be created.");
00122 
00123                 // write header
00124                 file.write(header.c_str(), 6);
00125                 file.write((char*) &majorver, sizeof(short));
00126                 file.write((char*) &minorver, sizeof(short));
00127                 
00128                 // write t unit string (8 chars)
00129                 if (tunit.size() != 8) tunit.resize(8);
00130                 file.write(tunit.c_str(), 8);
00131 
00132                 // write x unit string (8 chars)
00133                 if (xunit.size() != 8) xunit.resize(8);
00134                 file.write(xunit.c_str(), 8);
00135 
00136                 // write data unit string (8 chars)
00137                 if (dataunit.size() != 8) dataunit.resize(8);
00138                 file.write(dataunit.c_str(), 8);
00139 
00140                 // write comment string (24 chars)
00141                 if (comment.size() != 24) comment.resize(24);
00142                 file.write(comment.c_str(), 24);
00143 
00144                 // write status values
00145                 file.write((char*) &userdtstatus, sizeof(int));
00146                 file.write((char*) &sysddastatus, sizeof(int));
00147                 file.write((char*) &sysdtstatus, sizeof(int));
00148 
00149                 // write data t and x dimensions
00150                 temp = t.size();
00151                 file.write((char*) &temp, sizeof(int));
00152                 temp = x.size();
00153                 file.write((char*) &temp, sizeof(int));
00154                 
00155                 // write t, x and data vectors
00156                 for(int i=0;i<t.size();i++) file.write((char*) &t[i], sizeof(float));
00157                 for(int i=0;i<x.size();i++) file.write((char*) &x[i], sizeof(float));
00158                 for(int i=0;i<t.size();i++) for(int j=0;j<x.size();j++) file.write((char*) &data[i][j], sizeof(float));
00159 
00160                 // close file
00161                 file.close();
00162         }
00163 
00164         int datatype::getTDim()
00165         {
00166                 return t.size();
00167         }
00168 
00169         int datatype::getXDim()
00170         {
00171                 return x.size();
00172         }
00173 
00174         string datatype::getTUnit()
00175         {
00176                 return tunit;
00177         }
00178 
00179         string datatype::getXUnit()
00180         {
00181                 return xunit;
00182         }
00183 
00184         string datatype::getDataUnit()
00185         {
00186                 return dataunit;
00187         }
00188 
00189         string datatype::getComment()
00190         {
00191                 return comment;
00192         }
00193         
00194         int datatype::getUserDTStatus()
00195         {
00196                 return userdtstatus;
00197         }
00198 
00199         int datatype::getSysDDAStatus()
00200         {
00201                 return sysddastatus;
00202         }
00203 
00204         int datatype::getSysDTStatus()
00205         {
00206                 return sysdtstatus;
00207         }
00208 
00209         float datatype::getT(int It)
00210         {
00211                 return t[It];
00212         }
00213 
00214         float datatype::getX(int Ix)
00215         {
00216                 return x[Ix];
00217         }
00218 
00219         float datatype::getDataIt(int It)
00220         {
00221                 return data[It][0];
00222         }
00223 
00224         float datatype::getDataIx(int Ix)
00225     {
00226                 return data[0][Ix];
00227     }
00228 
00229         float datatype::getDataItIx(int It, int Ix)
00230         {
00231                 return data[It][Ix];
00232         }
00233 
00234         int datatype::getIt(float t)
00235         {
00236                 int Ilower, Iupper;
00237 
00238                 // find and return nearest index
00239                 findNearest(this->t, 0, this->t.size()-1, t, Ilower, Iupper);
00240                 if (Ilower == Iupper) return Ilower;
00241                 if ((this->t[Iupper] - t) <= (t - this->t[Ilower])) return Iupper;
00242                 else return Ilower;
00243         }
00244 
00245         int datatype::getIx(float x)
00246         {
00247                 int Ilower, Iupper;
00248 
00249                 // find and return nearest index
00250                 findNearest(this->x, 0, this->x.size()-1, x, Ilower, Iupper);
00251                 if (Ilower == Iupper) return Ilower;
00252                 if ((this->x[Iupper] - x) <= (x - this->x[Ilower])) return Iupper;
00253                 else return Ilower;
00254         }
00255 
00256         float datatype::getDataT(float t)
00257         {
00258                 return getDataT(t, ppf::linear);
00259         }
00260         
00261         float datatype::getDataT(float t, processflag flag)
00262         {
00263                 float ta, v;
00264 
00265                 getDataTIx(t, 0, flag, ta, v);
00266                 return v;
00267         }
00268 
00269         coord datatype::getDataCT(float t, processflag flag)
00270         {
00271                 float ta, v;
00272                 coord c;
00273                 
00274                 getDataTIx(t, 0, flag, ta, v);
00275                 c.t = ta;
00276                 c.x = x[0];
00277                 c.d = v;
00278                 return c;
00279         }
00280 
00281         float datatype::getDataX(float x)
00282         {
00283                 return getDataX(x, ppf::linear);
00284         }
00285 
00286         float datatype::getDataX(float x, processflag flag)
00287         {
00288                 float xa, v;
00289 
00290                 getDataItX(0, x, flag, xa, v);
00291                 return v;
00292         }
00293 
00294         coord datatype::getDataCX(float x, processflag flag)
00295         {
00296                 float xa, v;
00297                 coord c;
00298 
00299                 getDataItX(0, x, flag, xa, v);
00300                 c.t = t[0];
00301                 c.x = xa;
00302                 c.d = v;
00303                 return c;
00304         }
00305 
00306         float datatype::getDataTIx(float t, long Ix)
00307         {
00308                 return getDataTIx(t, Ix, ppf::linear);
00309         }
00310 
00311         float datatype::getDataTIx(float t, long Ix, processflag t_flag)
00312         {
00313                 float ta, v;
00314 
00315                 getDataTIx(t, Ix, t_flag, ta, v);
00316                 return v;
00317         }
00318 
00319         coord datatype::getDataCTIx(float t, long Ix, processflag t_flag)
00320         {
00321                 float ta, v;
00322                 coord c;
00323 
00324                 getDataTIx(t, Ix, t_flag, ta, v);
00325                 c.t = ta;
00326                 c.x = x[Ix];
00327                 c.d = v;
00328                 return c;
00329         }
00330 
00331         float datatype::getDataItX(long It, float x)
00332         {
00333                 return getDataItX(It, x, ppf::linear);
00334         }
00335 
00336         float datatype::getDataItX(long It, float x, processflag x_flag)
00337         {
00338                 float xa, v;
00339 
00340                 getDataItX(It, x, x_flag, xa, v);
00341                 return v;
00342         }
00343 
00344         coord datatype::getDataCItX(long It, float x, processflag x_flag)
00345         {
00346                 float xa, v;
00347                 coord c;
00348 
00349                 getDataItX(It, x, x_flag, xa, v);
00350                 c.t = t[It];
00351                 c.x = xa;
00352                 c.d = v;
00353                 return c;
00354         }
00355 
00356         float datatype::getDataTX(float t, float x)
00357         {
00358                 return getDataTX(t, x, ppf::linear, ppf::linear);
00359         }
00360 
00361         float datatype::getDataTX(float t, float x, processflag t_flag, processflag x_flag)
00362         {
00363                 float ta ,xa, v;
00364 
00365                 getDataTX(t, x, t_flag, x_flag, ta, xa, v);
00366                 return v;
00367         }
00368 
00369         coord datatype::getDataCTX(float t, float x, processflag t_flag, processflag x_flag)
00370         {
00371                 float ta ,xa, v;
00372                 coord c;
00373 
00374                 getDataTX(t, x, t_flag, x_flag, ta, xa, v);
00375                 c.t = ta;
00376                 c.x = xa;
00377                 c.d = v;
00378                 return c;
00379         }
00380         
00381         void datatype::setT(int It, float v)
00382         {
00383                 t[It] = v;
00384         }
00385 
00386         void datatype::setX(int Ix, float v)
00387         {
00388                 x[Ix] = v;
00389         }
00390 
00391         void datatype::setDataIt(int It, float v)
00392         {
00393                 data[It][0] = v;
00394         }
00395 
00396         void datatype::setDataIx(int Ix, float v)
00397         {
00398                 data[0][Ix] = v;
00399         }
00400 
00401         void datatype::setDataItIx(int It, int Ix, float v)
00402         {
00403                 data[It][Ix] = v;
00404         }
00405 
00406         void datatype::findNearest(vector<float> &v, int Imin, int Imax, float f, int &Ilower, int &Iupper)
00407         {
00408         // future work: add a linear prediction for the index of f from the gradient between the end points to give a mid point close to f = faster search, especialy for linear series!
00409 
00410                 int t, b, m;    // top index, bottom index, middle index (for divide and conquer routine)
00411 
00412                 // divide and conquer as appropriate
00413                 if (v[Imin] < v[Imax]) // series is increasing
00414                 {
00415                         // do basic checks
00416                         if (f <= v[Imin])
00417                         {
00418                                 Ilower = Iupper = Imin;
00419                                 return;
00420                         }
00421                         if (f >= v[Imax])
00422                         {
00423                                 Ilower = Iupper = Imax;
00424                                 return;
00425                         }
00426 
00427                         // answer is within specified range, so find it
00428                         t = Imax;
00429                         b = Imin;
00430                         while(t != (b+1))
00431                         {
00432                                 // find midpoint of range
00433                                 m = b + (t-b)/2; // note the integer divide
00434 
00435                                 // check if f was found, if not move the relevant side of the range inwards
00436                                 if (v[m] == f)
00437                                 {
00438                                         Ilower = Iupper = m;
00439                                         return;
00440                                 }
00441                                 if (v[m] < f) b = m;
00442                                 else t = m;
00443                         }
00444 
00445                         // return bounds
00446                         Ilower = b;
00447                         Iupper = t;
00448                 }
00449                 else // series is decreasing
00450                 {
00451                         // do basic checks
00452                         if (f >= v[Imin])
00453                         {
00454                                 Ilower = Iupper = Imin;
00455                                 return;
00456                         }
00457                         if (f <= v[Imax])
00458                         {
00459                                 Ilower = Iupper = Imax;
00460                                 return;
00461                         }
00462                         
00463                         // answer is within specified range, so find it
00464                         t = Imax;
00465                         b = Imin;
00466                         while(t != (b+1))
00467                         {
00468                                 // find midpoint of range
00469                                 m = b + (t-b)/2; // note the integer divide
00470 
00471                                 // check if f was found, if not move the relevant side of the range inwards
00472                                 if (v[m] == f)
00473                                 {
00474                                         Ilower = Iupper = m;
00475                                         return;
00476                                 }
00477                                 if (v[m] > f) b = m;
00478                                 else t = m;
00479                         }
00480 
00481                         // return bounds
00482                         Ilower = t;
00483                         Iupper = b;
00484                 }
00485         }
00486 
00487         double datatype::interpolateLinear(double p1, double v1, double p2, double v2, double pt)
00488         {
00489                 return (v1 + ((v2-v1)/(p2-p1))*(pt-p1));
00490         }
00491 /*
00492         double ppf::interpolateCubic(double p1, double g1, double v1, double p2, double g2, double v2, double pt)
00493         {
00494 //              IMPLIMENT ME!
00495                 return 0;
00496         }
00497 */
00498 
00499         void datatype::getDataTIx(float t, long Ix, processflag t_flag, float &ta, float &v)
00500         {
00501                 int Ilower, Iupper;
00502 
00503                 if(t_flag == ppf::nearest)    // FIND NEAREST POINT
00504                 {
00505                         // find nearest index and return its corresponding data value
00506                         findNearest(this->t, 0, this->t.size()-1, t, Ilower, Iupper);
00507                         if (Ilower == Iupper)
00508                         {
00509                                 ta = this->t[Ilower];
00510                                 v = this->data[Ilower][Ix];
00511                         }
00512                         else if ((this->t[Iupper] - t) <= (t - this->t[Ilower]))
00513                         {
00514                                 ta = this->t[Iupper];
00515                                 v = this->data[Iupper][Ix];
00516                         }
00517                         else
00518                         {
00519                                 ta = this->t[Ilower];
00520                                 v = this->data[Ilower][Ix];
00521                         }
00522                 }
00523                 else if(t_flag == ppf::linear)    // LINEAR INTERPOLATION
00524                 {
00525                         // linearly interpolate if appropriate (not at end of array) and return values
00526                         findNearest(this->t, 0, this->t.size()-1, t, Ilower, Iupper);
00527                         if (Ilower == Iupper)
00528                         {
00529                                 // value has been exactly identified so return it
00530                                 ta = this->t[Ilower];
00531                                 v = this->data[Ilower][Ix];
00532                         }
00533                         else
00534                         {
00535                                 // interpolate
00536                                 ta = t;
00537                                 v = interpolateLinear(this->t[Ilower], this->data[Ilower][Ix], this->t[Iupper], this->data[Iupper][Ix], t);
00538                         }
00539                 }
00540 //              else if(t_flag == ppf::cubic)    // CUBIC INTERPOLATION
00541 //              {
00542 //                      IMPLIMENT ME!
00543 //              }
00544                 else throw ppf_error("Invalid process flag.");
00545         }
00546 
00547         void datatype::getDataItX(long It, float x, processflag x_flag, float &xa, float &v)
00548         {
00549                 int Ilower, Iupper;
00550 
00551                 if(x_flag == ppf::nearest)    // FIND NEAREST POINT
00552                 {
00553                         // find nearest index and return its corresponding data value
00554                         findNearest(this->x, 0, this->x.size()-1, x, Ilower, Iupper);
00555                         if (Ilower == Iupper)
00556                         {
00557                                 xa = this->x[Ilower];
00558                                 v = this->data[It][Ilower];
00559                         }
00560                         else if ((this->x[Iupper] - x) <= (x - this->x[Ilower]))
00561                         {
00562                                 xa = this->x[Iupper];
00563                                 v = this->data[It][Iupper];
00564                         }
00565                         else
00566                         {
00567                                 xa = this->x[Ilower];
00568                                 v = this->data[It][Ilower];
00569                         }
00570                 }
00571                 else if(x_flag == ppf::linear)    // LINEAR INTERPOLATION
00572                 {
00573                         // linearly interpolate if appropriate (not at end of array) and return values
00574                         findNearest(this->x, 0, this->x.size()-1, x, Ilower, Iupper);
00575                         if (Ilower == Iupper)
00576                         {
00577                                 // value has been exactly identified so return it
00578                                 xa = this->x[Ilower];
00579                                 v = this->data[It][Ilower];
00580                         }
00581                         else
00582                         {
00583                                 // interpolate
00584                                 xa = x;
00585                                 v = interpolateLinear(this->x[Ilower], this->data[It][Ilower], this->x[Iupper], this->data[It][Iupper], x);
00586                         }
00587                 }
00588 //              else if(x_flag == ppf::cubic)    // CUBIC INTERPOLATION
00589 //              {
00590 //                      IMPLIMENT ME!
00591 //              }
00592                 else throw ppf_error("Invalid process flag.");
00593         }
00594 
00595         void datatype::getDataTX(float t, float x, processflag t_flag, processflag x_flag, float &ta, float &xa, float &v)
00596         {
00597                 int Ilower, Iupper;
00598 
00599                 if(x_flag == ppf::nearest)        // FIND NEAREST POINT (X)
00600                 {
00601                         // find nearest X indicies
00602                         findNearest(this->x, 0, this->x.size()-1, x, Ilower, Iupper);
00603                         if (Ilower == Iupper)
00604                         {
00605                                 // set xa, call routine to get ta and v as per process flag
00606                                 xa = this->x[Ilower];
00607                                 getDataTIx(t, Ilower, t_flag, ta, v);
00608                         }
00609                         else if ((this->x[Iupper] - x) <= (x - this->x[Ilower]))
00610                         {
00611                                 // upper value is nearer, call routine for ta and v
00612                                 xa = this->x[Iupper];
00613                                 getDataTIx(t, Iupper, t_flag, ta, v);
00614                         }
00615                         else
00616                         {
00617                                 // lower value is nearer, call routine for ta and v
00618                                 xa = this->x[Ilower];
00619                                 getDataTIx(t, Ilower, t_flag, ta, v);
00620                         }
00621                 }
00622                 else if (x_flag == ppf::linear)   // LINEAR INTERPOLATION (X)
00623                 {
00624                         // linearly interpolate if appropriate (not at end of array) and return values
00625                         findNearest(this->x, 0, this->x.size()-1, x, Ilower, Iupper);
00626                         if (Ilower == Iupper)
00627                         {
00628                                 // value has been exactly identified so return it, call routine to get ta and v
00629                                 xa = this->x[Ilower];
00630                                 getDataTIx(t, Ilower, t_flag, ta, v);
00631                         }
00632                         else
00633                         {
00634                                 float tl, tu, vl, vu;
00635 
00636                                 // collect the processed t values
00637                                 getDataTIx(t, Ilower, t_flag, tl, vl);
00638                                 getDataTIx(t, Iupper, t_flag, tu, vu);
00639 
00640                                 // interpolate and return data
00641                                 xa = x;
00642                                 ta = tl;
00643                                 v = interpolateLinear(this->x[Ilower], vl, this->x[Iupper], vu, x);
00644                         }
00645                 }
00646 /*              else if(x_flag == ppf::cubic)    // CUBIC INTERPOLATION (X)
00647                 {
00648 //                      IMPLIMENT ME!
00649 
00650                         // find nearest indicies
00651                         // if exact Ix then process y
00652                         // process t for both I1 and I2
00653                         // need I0 and I3, extrapolate if end of array else set index (remember index order different if array increases or decreases)
00654                         // process t for both I0 and I3 if required
00655                         // do cubic interp in x and return values
00656                 }
00657 */              else throw ppf_error("Invalid process flag.");
00658         
00659         }
00660 
00661         datatype::~datatype()
00662         {
00663         }
00664 };

Generated on Tue May 23 15:11:51 2006 for PPF C++ by  doxygen 1.4.6-NO