SNAP Library 2.0, User Reference  2013-05-13 16:33:57
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
gnuplot.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "gnuplot.h"
00003 
00005 // GNU-Plot-Chart
00006 /*#ifdef GLib_WIN
00007   TStr TGnuPlot::GnuPlotPath = "\\Dev\\GLib\\gnuplot\\bin\\";
00008 #else
00009   TStr TGnuPlot::GnuPlotPath = "/usr/bin/";
00010 #endif*/
00011 
00012 // Determines the gnuplot version and the tics command syntax.
00013 // Gnuplot changed the syntax with version 4.2:
00014 // - before 4.2: set ticscale 2 1
00015 // - 4.2 and later: set tics 2
00016 int TGnuPlot::GetTics42() {
00017 #ifdef GLib_WIN
00018   return -1;
00019 #else   
00020   FILE* p;
00021   char Buf[1024];
00022   char Version[1024];
00023   size_t n;
00024 
00025   // get gnuplot version
00026   p = popen("gnuplot -V","r");
00027   if (p == NULL) {
00028     return -1;
00029   }
00030   n = fread(Buf, 1, 100, p);
00031   if (n <= 0) {
00032     return -1;
00033   }
00034   Buf[n] = '\0';
00035   pclose(p);
00036 
00037   // printf("Buf %d .%s.\n", n, Buf);
00038   n = sscanf(Buf, "gnuplot %s", Version);
00039   if (n <= 0) {
00040     return -1;
00041   }
00042   // printf("Version %d .%s.\n", n, Version);
00043   if ((strlen(Version) < 3) || (Version[1] != '.')) {
00044     return -1;
00045   }
00046 
00047   // test version < 4.2
00048   if ((Version[0] < '4') || ((Version[0] == '4') && (Version[2] < '2'))) {
00049     // printf("TGnuPlot::GetTics42 0\n");
00050     return 0;
00051   }
00052   // printf("TGnuPlot::GetTics42 1\n");
00053   return 1;
00054 #endif
00055 }
00056 
00057 int TGnuPlot::Tics42 = TGnuPlot::GetTics42();
00058 
00059 TStr TGnuPlot::DefPlotFNm = "GnuPlot.plt";
00060 TStr TGnuPlot::DefDataFNm = "GnuPlot.tab";
00061 
00062 TGnuPlot::TGpSeries::TGpSeries(const TGnuPlot::TGpSeries& Gps) :
00063   SeriesTy(Gps.SeriesTy), XYValV(Gps.XYValV), ZValV(Gps.ZValV),
00064   Label(Gps.Label), WithStyle(Gps.WithStyle), DataFNm(Gps.DataFNm),
00065   XCol(Gps.XCol), YCol(Gps.YCol), ZCol(Gps.ZCol) {
00066 }
00067 
00068 TGnuPlot::TGpSeries& TGnuPlot::TGpSeries::operator = (const TGnuPlot::TGpSeries& Gps) {
00069   if(this != &Gps) {
00070     SeriesTy = Gps.SeriesTy;
00071     XYValV = Gps.XYValV;  ZValV = Gps.ZValV;
00072     Label = Gps.Label;
00073     DataFNm = Gps.DataFNm;
00074     WithStyle = Gps.WithStyle;
00075     XCol = Gps.XCol;  YCol = Gps.YCol;  ZCol = Gps.ZCol;
00076   }
00077   return *this;
00078 }
00079 
00080 bool TGnuPlot::TGpSeries::operator < (const TGpSeries& Gps) const {
00081   return (XYValV < Gps.XYValV) || ((XYValV == Gps.XYValV) && (Label < Gps.Label));
00082 }
00083 
00084 TGnuPlot::TGnuPlot(const TStr& FileNm, const TStr& PlotTitle, const bool& Grid) :
00085  DataFNm(FileNm+".tab"), PlotFNm(FileNm+".plt"), Title(PlotTitle), LblX(), LblY(), ScaleTy(gpsAuto),
00086  YRange(0, 0), XRange(0, 0), SetGrid(Grid), SetPause(true),
00087  SeriesV(), MoreCmds() {
00088   IAssert(! FileNm.Empty());
00089 }
00090 
00091 TGnuPlot::TGnuPlot(const TStr& DataFileNm, const TStr& PlotFileNm, const TStr& PlotTitle, const bool& Grid) :
00092   DataFNm(DataFileNm.Empty() ? DefDataFNm : DataFileNm),
00093   PlotFNm(PlotFileNm.Empty() ? DefPlotFNm : PlotFileNm),
00094   Title(PlotTitle), LblX(), LblY(), ScaleTy(gpsAuto),
00095   YRange(0, 0), XRange(0, 0), SetGrid(Grid), SetPause(true), SeriesV(), MoreCmds() {
00096 }
00097 
00098 TGnuPlot::TGnuPlot(const TGnuPlot& GnuPlot) : DataFNm(GnuPlot.DataFNm), PlotFNm(GnuPlot.PlotFNm),
00099   Title(GnuPlot.Title), LblX(GnuPlot.LblX), LblY(GnuPlot.LblY), ScaleTy(GnuPlot.ScaleTy), YRange(GnuPlot.YRange),
00100   XRange(GnuPlot.XRange), SetGrid(GnuPlot.SetGrid), SetPause(GnuPlot.SetPause), SeriesV(GnuPlot.SeriesV),
00101   MoreCmds(GnuPlot.MoreCmds) {
00102 }
00103 
00104 TGnuPlot& TGnuPlot::operator = (const TGnuPlot& GnuPlot) {
00105   if (this != &GnuPlot) {
00106     DataFNm = GnuPlot.DataFNm;
00107     PlotFNm = GnuPlot.PlotFNm;
00108     Title = GnuPlot.Title;
00109     LblX = GnuPlot.LblX;
00110     LblY = GnuPlot.LblY;
00111     ScaleTy = GnuPlot.ScaleTy;
00112     YRange = GnuPlot.YRange;
00113     XRange = GnuPlot.XRange;
00114     SetGrid = GnuPlot.SetGrid;
00115     SetPause = GnuPlot.SetPause;
00116     SeriesV = GnuPlot.SeriesV;
00117     MoreCmds = GnuPlot.MoreCmds;
00118   }
00119   return *this;
00120 }
00121 
00122 TStr TGnuPlot::GetSeriesPlotStr(const int& SeriesId) {
00123   TChA PlotStr;
00124   TGpSeries& Series = SeriesV[SeriesId];
00125   if (SeriesId != 0) PlotStr += ",\\\n\t";
00126   if (Series.XCol >= 0) {
00127     PlotStr += "\"" + Series.DataFNm + "\" using " + TInt::GetStr(Series.XCol);
00128     if (Series.YCol != 0) { PlotStr += ":" + TInt::GetStr(Series.YCol); }
00129     if (Series.ZCol != 0) { PlotStr += ":" + TInt::GetStr(Series.ZCol); }
00130     else if (Series.SeriesTy==gpwFilledCurves) { PlotStr += ":(0)"; } // filled curves requres 3rd column
00131   } else {
00132     // function
00133     //IAssertR(Series.DataFNm.SearchCh('=') != -1, TStr::Fmt("Expression %s is not a function", Series.DataFNm.CStr()));
00134     PlotStr += Series.DataFNm;
00135   }
00136   PlotStr += " title \"" + Series.Label + "\"";
00137   // hard coded line style
00138   if (Series.WithStyle.Empty()) {
00139     if (Series.SeriesTy == gpwLines) Series.WithStyle = "lw 1";
00140     //if (Series.SeriesTy == gpwPoints) Series.WithStyle = "pt 6 ps 1 lw 1"; // circles
00141     //if (Series.SeriesTy == gpwLinesPoints) Series.WithStyle = "pt 6 ps 1 lw 1"; // circles
00142     if (Series.SeriesTy == gpwBoxes) Series.WithStyle = "fill solid 0.3";
00143   }
00144   PlotStr += " with " + GetSeriesTyStr(Series.SeriesTy) + " " + Series.WithStyle;
00145   return PlotStr;
00146 }
00147 
00148 //GP.AddFunc("2*x**-2+4", gpwLines, "2*x^-2+4");
00149 int TGnuPlot::AddFunc(const TStr& FuncStr, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00150   const int Id = SeriesV.Len();
00151   TGpSeries Plot;
00152   Plot.SeriesTy = SeriesTy;
00153   Plot.Label = Label;
00154   if (! FuncStr.Empty()) { Plot.DataFNm = TStr::Fmt("f%d(x)=%s, f%d(x)", Id, FuncStr.CStr(), Id); }
00155   else { Plot.DataFNm = TStr::Fmt("f%d(x)", Id); }
00156   Plot.XCol = -1;
00157   Plot.WithStyle = Style;
00158   SeriesV.Add(Plot);
00159   return Id;
00160 }
00161 
00162 int TGnuPlot::AddPlot(const TStr& DataFNm, const int& ColY,
00163                       const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00164   return AddPlot(DataFNm, 0, ColY, SeriesTy, Label, Style);
00165 }
00166 
00167 int TGnuPlot::AddPlot(const TStr& DataFNm, const int& ColX, const int& ColY,
00168                       const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00169   IAssert(ColY > 0);  IAssert(ColX >= 0);
00170   TGpSeries Plot;
00171   Plot.SeriesTy = SeriesTy;
00172   Plot.Label = Label;
00173   Plot.DataFNm = DataFNm;  Plot.DataFNm.ChangeStrAll("\\", "\\\\");
00174   Plot.XCol = ColX;  Plot.YCol = ColY;  Plot.ZCol = 0;
00175   Plot.WithStyle = Style;
00176   SeriesV.Add(Plot);
00177   return SeriesV.Len() - 1;
00178 }
00179 
00180 int TGnuPlot::AddPlot(const TIntV& YValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00181   TFltKdV XYValV(YValV.Len(), 0);
00182   for (int i = 0; i < YValV.Len(); i++) {
00183     XYValV.Add(TFltKd(TFlt(i+1), TFlt(YValV[i])));
00184   }
00185   return AddPlot(XYValV, SeriesTy, Label, Style);
00186 }
00187 
00188 int TGnuPlot::AddPlot(const TFltV& YValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00189   TFltKdV XYValV(YValV.Len(), 0);
00190   for (int i = 0; i < YValV.Len(); i++) {
00191     XYValV.Add(TFltKd(TFlt(i+1), TFlt(YValV[i])));
00192   }
00193   return AddPlot(XYValV, SeriesTy, Label, Style);
00194 }
00195 
00196 int TGnuPlot::AddPlot(const TFltV& XValV, const TFltV& YValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00197   IAssert(XValV.Len() == YValV.Len());
00198   TFltKdV XYValV(XValV.Len(), 0);
00199   for (int i = 0; i < YValV.Len(); i++) {
00200     XYValV.Add(TFltKd(TFlt(XValV[i]), TFlt(YValV[i])));
00201   }
00202   return AddPlot(XYValV, SeriesTy, Label, Style);
00203 }
00204 
00205 int TGnuPlot::AddPlot(const TIntPrV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00206   TFltKdV XYFltValV(XYValV.Len(), 0);
00207   for (int i = 0; i < XYValV.Len(); i++) {
00208     XYFltValV.Add(TFltKd(TFlt(XYValV[i].Val1), TFlt(XYValV[i].Val2)));
00209   }
00210   return AddPlot(XYFltValV, SeriesTy, Label, Style);
00211 }
00212 
00213 int TGnuPlot::AddPlot(const TFltPrV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00214   TFltKdV XYFltValV(XYValV.Len(), 0);
00215   for (int i = 0; i < XYValV.Len(); i++) {
00216     XYFltValV.Add(TFltKd(XYValV[i].Val1, XYValV[i].Val2));
00217   }
00218   return AddPlot(XYFltValV, SeriesTy, Label, Style);
00219 }
00220 
00221 int TGnuPlot::AddPlot(const TIntKdV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00222   TFltKdV XYFltValV(XYValV.Len(), 0);
00223   for (int i = 0; i < XYValV.Len(); i++) {
00224     XYFltValV.Add(TFltKd(TFlt(XYValV[i].Key), TFlt(XYValV[i].Dat)));
00225   }
00226   return AddPlot(XYFltValV, SeriesTy, Label, Style);
00227 }
00228 
00229 int TGnuPlot::AddPlot(const TIntFltKdV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00230   TFltKdV XYFltValV(XYValV.Len(), 0);
00231   for (int i = 0; i < XYValV.Len(); i++) {
00232     XYFltValV.Add(TFltKd(TFlt(XYValV[i].Key), TFlt(XYValV[i].Dat)));
00233   }
00234   return AddPlot(XYFltValV, SeriesTy, Label, Style);
00235 }
00236 
00237 int TGnuPlot::AddPlot(const TIntFltPrV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00238   TFltKdV XYFltValV(XYValV.Len(), 0);
00239   for (int i = 0; i < XYValV.Len(); i++) {
00240     XYFltValV.Add(TFltKd(TFlt(XYValV[i].Val1), TFlt(XYValV[i].Val2)));
00241   }
00242   return AddPlot(XYFltValV, SeriesTy, Label, Style);
00243 }
00244 
00245 int TGnuPlot::AddPlot(const TFltKdV& XYValV, const TGpSeriesTy& SeriesTy, const TStr& Label, const TStr& Style) {
00246   if (XYValV.Empty()) {
00247     printf("***AddPlot: empty plot (%s) %s\n", DataFNm.CStr(), Title.CStr());
00248     return -1;
00249   }
00250   TGpSeries Plot;
00251   Plot.SeriesTy = SeriesTy;
00252   Plot.Label = Label;
00253   Plot.XYValV = XYValV;
00254   Plot.WithStyle = Style;
00255   SeriesV.Add(Plot);
00256   return SeriesV.Len() - 1;
00257 }
00258 
00259 int TGnuPlot::AddErrBar(const TFltTrV& XYDValV, const TStr& Label) {
00260   TFltKdV XYFltValV(XYDValV.Len(), 0);
00261   TFltV DeltaV(XYDValV.Len(), 0);
00262   for (int i = 0; i < XYDValV.Len(); i++) {
00263     XYFltValV.Add(TFltKd(XYDValV[i].Val1, XYDValV[i].Val2));
00264     DeltaV.Add(XYDValV[i].Val3);
00265   }
00266   return AddErrBar(XYFltValV, DeltaV, Label);
00267 }
00268 
00269 int TGnuPlot::AddErrBar(const TFltTrV& XYDValV, const TStr& DatLabel, const TStr& ErrLabel) {
00270   TFltKdV XYFltValV(XYDValV.Len(), 0);
00271   TFltV DeltaV(XYDValV.Len(), 0);
00272   for (int i = 0; i < XYDValV.Len(); i++) {
00273     XYFltValV.Add(TFltKd(XYDValV[i].Val1, XYDValV[i].Val2));
00274     DeltaV.Add(XYDValV[i].Val3);
00275   }
00276   const int PlotId = AddPlot(XYFltValV, gpwLinesPoints, DatLabel);
00277   AddErrBar(XYFltValV, DeltaV, ErrLabel);
00278   return PlotId;
00279 }
00280 
00281 int TGnuPlot::AddErrBar(const TFltV& YValV, const TFltV& DeltaYV, const TStr& Label) {
00282   IAssert(YValV.Len() == DeltaYV.Len());
00283   TFltKdV XYFltValV(YValV.Len(), 0);
00284   for (int i = 0; i < YValV.Len(); i++) {
00285     XYFltValV.Add(TFltKd(TFlt(i+1), YValV[i]));
00286   }
00287   return AddErrBar(XYFltValV, DeltaYV, Label);
00288 }
00289 
00290 int TGnuPlot::AddErrBar(const TFltV& XValV, const TFltV& YValV, const TFltV& DeltaYV, const TStr& Label) {
00291   IAssert(XValV.Len() == YValV.Len());
00292   IAssert(XValV.Len() == DeltaYV.Len());
00293   TFltKdV XYFltValV(XValV.Len(), 0);
00294   for (int i = 0; i < XValV.Len(); i++) {
00295     XYFltValV.Add(TFltKd(XValV[i], YValV[i]));
00296   }
00297   return AddErrBar(XYFltValV, DeltaYV, Label);
00298 }
00299 
00300 int TGnuPlot::AddErrBar(const TFltPrV& XYValV, const TFltV& DeltaYV, const TStr& Label) {
00301   TFltKdV XYFltValV(XYValV.Len(), 0);
00302   for (int i = 0; i < XYValV.Len(); i++) {
00303     XYFltValV.Add(TFltKd(XYValV[i].Val1, XYValV[i].Val2));
00304   }
00305   return AddErrBar(XYFltValV, DeltaYV, Label);
00306 }
00307 
00308 int TGnuPlot::AddErrBar(const TFltPrV& XYValV, const TFltV& DeltaV, const TStr& DatLabel, const TStr& ErrLabel) {
00309   TFltKdV XYFltValV(XYValV.Len(), 0);
00310   for (int i = 0; i < XYValV.Len(); i++) {
00311     XYFltValV.Add(TFltKd(XYValV[i].Val1, XYValV[i].Val2));
00312   }
00313   const int PlotId = AddPlot(XYFltValV, gpwLinesPoints, DatLabel);
00314   AddErrBar(XYFltValV, DeltaV, ErrLabel);
00315   return PlotId;
00316 }
00317 
00318 int TGnuPlot::AddErrBar(const TFltKdV& XYValV, const TFltV& DeltaYV, const TStr& Label) {
00319   if (XYValV.Empty()) {
00320     printf("***AddErrBar: empty plot (%s) %s\n", DataFNm.CStr(), Title.CStr());
00321     return -1;
00322   }
00323   IAssert(XYValV.Len() == DeltaYV.Len());
00324   TGpSeries Plot;
00325   Plot.SeriesTy = gpwErrBars;
00326   Plot.Label = Label;
00327   Plot.XYValV = XYValV;
00328   Plot.ZValV = DeltaYV;
00329   SeriesV.Add(Plot);
00330   return SeriesV.Len() - 1;
00331 }
00332 
00333 int TGnuPlot::AddLinFit(const int& PlotId, const TGpSeriesTy& SeriesTy, const TStr& Style) {
00334   if (PlotId < 0 || PlotId >= SeriesV.Len()) return -1;
00335   const TGpSeries& Plot = SeriesV[PlotId];
00336   if(Plot.XYValV.Empty()) return -1;
00337   const TFltKdV& XY = Plot.XYValV;
00338   double A, B, R2, SigA, SigB, Chi2;
00339   // linear fit
00340   TFltPrV XYPr;
00341   int s;
00342   for (s = 0; s < XY.Len(); s++) {
00343     XYPr.Add(TFltPr(XY[s].Key, XY[s].Dat));
00344   }
00345   TSpecFunc::LinearFit(XYPr, A, B, SigA, SigB, Chi2, R2);
00346   TStr StyleStr=Style;
00347   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00348   const int FitId = AddFunc(TStr::Fmt("%f+%f*x", A, B),
00349     SeriesTy, TStr::Fmt("%.4g + %.4g x  R^2:%.2g", A, B, R2), StyleStr);
00350   return FitId;
00351   /*SeriesV.Add();
00352   TGpSeries& NewPlot = SeriesV.Last();
00353   TFltKdV& EstXY = NewPlot.XYValV;
00354   for (s = 0; s < XY.Len(); s++) {
00355     EstXY.Add(TFltKd(XY[s].Key, A + B*XYPr[s].Val1));
00356   }
00357   NewPlot.Label = TStr::Fmt("%.4g + %.4g x  R^2:%.2g", A, B, R2);
00358   NewPlot.SeriesTy = SeriesTy;
00359   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00360   else { NewPlot.WithStyle = Style; }
00361   return SeriesV.Len() - 1;*/
00362 }
00363 
00364 int TGnuPlot::AddPwrFit(const int& PlotId, const TGpSeriesTy& SeriesTy, const TStr& Style) {
00365   const int PlotId1 = AddPwrFit3(PlotId, SeriesTy);
00366   AddPwrFit2(PlotId, SeriesTy, 5.0);
00367   return PlotId1;
00368 }
00369 
00370 // linear fit on log-log scales{%
00371 int TGnuPlot::AddPwrFit1(const int& PlotId, const TGpSeriesTy& SeriesTy, const TStr& Style) {
00372   if (PlotId < 0 || PlotId >= SeriesV.Len()) return -1;
00373   const TGpSeries& Plot = SeriesV[PlotId];
00374   if(Plot.XYValV.Empty()) return -1;
00375   const TFltKdV& XY = Plot.XYValV;
00376   double A, B, R2, SigA, SigB, Chi2, MinY = TFlt::Mx, MinX = TFlt::Mx;
00377   // power fit
00378   TFltPrV XYPr;
00379   int s;
00380   for (s = 0; s < XY.Len(); s++) {
00381     if (XY[s].Key > 0) {
00382       XYPr.Add(TFltPr(XY[s].Key, XY[s].Dat)); 
00383       MinX = TMath::Mn(MinX, XY[s].Key());
00384       MinY = TMath::Mn(MinY, XY[s].Dat());
00385     }
00386   }
00387   MinY = TMath::Mn(1.0, MinY);
00388   TSpecFunc::PowerFit(XYPr, A, B, SigA, SigB, Chi2, R2);
00389   TStr StyleStr=Style;
00390   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00391   const int FitId = AddFunc(TStr::Fmt("%f*x**%f", A, B),
00392     SeriesTy, TStr::Fmt("%.1g * x^{%.4g}  R^2:%.2g", A, B, R2), StyleStr);
00393   return FitId;
00394   /*SeriesV.Add();
00395   TGpSeries& NewPlot = SeriesV.Last();
00396   const int FitId = SeriesV.Len() - 1;
00397   NewPlot.DataFNm = ;
00398   TFltKdV& EstXY = NewPlot.XYValV;
00399   for (s = 0; s < XYPr.Len(); s++) {
00400     const double YVal = A*pow(XYPr[s].Val1(), B);
00401     if (YVal < MinY) continue;
00402     EstXY.Add(TFltKd(XYPr[s].Val1, YVal));
00403   }
00404   NewPlot.Label = ;
00405   NewPlot.SeriesTy = SeriesTy;
00406   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00407   else { NewPlot.WithStyle = Style; }
00408   //if (MinX < 5.0) MinX = 5.0;
00409   //AddPwrFit2(PlotId, SeriesTy, MinX);*/
00410 }
00411 
00412 // MLE power-coefficient
00413 int TGnuPlot::AddPwrFit2(const int& PlotId, const TGpSeriesTy& SeriesTy, const double& MinX, const TStr& Style) {
00414   const TGpSeries& Plot = SeriesV[PlotId];
00415   if(Plot.XYValV.Empty()) return -1;
00416   const TFltKdV& XY = Plot.XYValV;
00417   // power fit
00418   TFltPrV XYPr;
00419   double MinY = TFlt::Mx;
00420   for (int s = 0; s < XY.Len(); s++) {
00421     if (XY[s].Key > 0.0) {
00422       XYPr.Add(TFltPr(XY[s].Key, XY[s].Dat));
00423       MinY = TMath::Mn(MinY, XY[s].Dat());
00424     }
00425   }
00426   if (XYPr.Empty()) return -1;
00427   MinY = TMath::Mn(1.0, MinY);
00428   // determine the sign of power coefficient
00429   double CoefSign = 0.0;
00430   { double A, B, R2, SigA, SigB, Chi2;
00431   TSpecFunc::PowerFit(XYPr, A, B, SigA, SigB, Chi2, R2);
00432   CoefSign = B > 0.0 ? +1.0 : -1.0; }
00433   const double PowerCf = CoefSign * TSpecFunc::GetPowerCoef(XYPr, MinX);
00434   int Mid = (int) exp(log((double)XYPr.Len())/2.0);
00435   if (Mid >= XYPr.Len()) { Mid = XYPr.Len()-1; }
00436   const double MidX = XYPr[Mid].Val1();
00437   const double MidY = XYPr[Mid].Val2();
00438   const double B = MidY / pow(MidX, PowerCf);
00439   TStr StyleStr=Style;
00440   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00441   const int FitId = AddFunc(TStr::Fmt("%f*x**%f", B, PowerCf),
00442     SeriesTy, TStr::Fmt("MLE = x^{%.4g}", PowerCf), StyleStr);
00443   return FitId;
00444   /*SeriesV.Add();
00445   TGpSeries& NewPlot = SeriesV.Last();
00446   TFltKdV& XYFit = NewPlot.XYValV;
00447   XYFit.Gen(XYPr.Len(), 0);
00448   for (int s = 0; s < XYPr.Len(); s++) {
00449     const double XVal = XYPr[s].Val1;
00450     const double YVal = B * pow(XYPr[s].Val1(), PowerCf);
00451     if (YVal < MinY || XVal < MinX) continue;
00452     XYFit.Add(TFltKd(XVal, YVal));
00453   }
00454   NewPlot.Label = TStr::Fmt("PowerFit: %g", PowerCf);
00455   NewPlot.SeriesTy = SeriesTy;
00456   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00457   else { NewPlot.WithStyle = Style; }
00458   return SeriesV.Len() - 1;*/
00459 }
00460 
00461 int TGnuPlot::AddPwrFit3(const int& PlotId, const TGpSeriesTy& SeriesTy, const double& MinX, const TStr& Style) {
00462   double Intercept, Slope, R2;
00463   return AddPwrFit3(PlotId, SeriesTy, MinX, Style, Intercept, Slope, R2);
00464 }
00465 
00466 // some kind of least squares power-law fitting that cutts the tail until the fit is good
00467 int TGnuPlot::AddPwrFit3(const int& PlotId, const TGpSeriesTy& SeriesTy, const double& MinX, const TStr& Style, double& Intercept, double& Slope, double& R2) {
00468   if (PlotId < 0 || PlotId >= SeriesV.Len()) return -1;
00469   const TGpSeries& Plot = SeriesV[PlotId];
00470   if(Plot.XYValV.Empty()) return -1;
00471   double A, B, SigA, SigB, Chi2, MinY=TFlt::Mx;
00472   const TFltKdV& XY = Plot.XYValV;
00473   //SeriesV.Add();
00474   //TGpSeries& NewPlot = SeriesV.Last();
00475   //TFltKdV& EstXY = NewPlot.XYValV;
00476   TFltPrV FitXY, NewFitXY;
00477   for (int s = 0; s < XY.Len(); s++) {
00478     if (XY[s].Key > 0 && XY[s].Key >= MinX) {
00479       FitXY.Add(TFltPr(XY[s].Key, XY[s].Dat)); 
00480       MinY = TMath::Mn(MinY, XY[s].Dat());
00481     }
00482   }
00483   MinY = TMath::Mn(1.0, MinY);
00484   // power fit (if tail is too fat, cut everything where
00485   // extrapolation sets the value < MinY
00486   while (true) {
00487     TSpecFunc::PowerFit(FitXY, A, B, SigA, SigB, Chi2, R2);
00488     NewFitXY.Clr(false);
00489     //EstXY.Clr(false);
00490     for (int s = 0; s < FitXY.Len(); s++) {
00491       const double YVal = A*pow(FitXY[s].Val1(), B);
00492       if (YVal < MinY) continue;
00493       //EstXY.Add(TFltKd(FitXY[s].Val1, YVal));
00494       NewFitXY.Add(TFltPr(FitXY[s].Val1, FitXY[s].Val2));
00495     }
00496     if (NewFitXY.Len() < 10 || FitXY.Last().Val1 < 1.2 * NewFitXY.Last().Val1) { break; }
00497     else { FitXY.Swap(NewFitXY); }
00498   }
00499   TStr StyleStr=Style;
00500   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00501   const int FitId = AddFunc(TStr::Fmt("%f*x**%f", A, B),
00502     SeriesTy, TStr::Fmt("%.1g * x^{%.4g}  R^2:%.2g", A, B, R2), StyleStr);
00503   return FitId;
00504   /*NewPlot.Label = TStr::Fmt("%.1g * x^{%.4g}  R^2:%.2g", A, B, R2);
00505   Intercept = A;
00506   Slope = B;
00507   NewPlot.SeriesTy = SeriesTy;
00508   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00509   else { NewPlot.WithStyle = Style; }
00510   return SeriesV.Len() - 1;*/
00511 }
00512 
00513 int TGnuPlot::AddLogFit(const int& PlotId, const TGpSeriesTy& SeriesTy, const TStr& Style) {
00514   const TGpSeries& Plot = SeriesV[PlotId];
00515   if(Plot.XYValV.Empty()) return -1;
00516   const TFltKdV& XY = Plot.XYValV;
00517   double A, B, R2, SigA, SigB, Chi2;
00518   // power fit
00519   TFltPrV XYPr;
00520   int s;
00521   for (s = 0; s < XY.Len(); s++) {
00522     if (XY[s].Key > 0) {
00523       XYPr.Add(TFltPr(XY[s].Key, XY[s].Dat)); } 
00524   }
00525   TSpecFunc::LogFit(XYPr, A, B, SigA, SigB, Chi2, R2);
00526   TStr StyleStr=Style;
00527   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00528   const int FitId = AddFunc(TStr::Fmt("%f+%f*log(x)", A, B),
00529     SeriesTy, TStr::Fmt("%.4g + %.4g log(x)  R^2:%.2g", A, B, R2), StyleStr);
00530   return FitId;
00531   /*SeriesV.Add();
00532   TGpSeries& NewPlot = SeriesV.Last();
00533   TFltKdV& EstXY = NewPlot.XYValV;
00534   for (s = 0; s < XYPr.Len(); s++) {
00535     EstXY.Add(TFltKd(XYPr[s].Val1, A+B*log((double)XYPr[s].Val1)));
00536   }
00537   NewPlot.Label = TStr::Fmt("%.4g + %.4g log(x)  R^2:%.2g", A, B, R2);
00538   NewPlot.SeriesTy = SeriesTy;
00539   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00540   else { NewPlot.WithStyle = Style; }
00541   return SeriesV.Len() - 1;*/
00542 }
00543 
00544 int TGnuPlot::AddExpFit(const int& PlotId, const TGpSeriesTy& SeriesTy, const double& FitXOffset, const TStr& Style) {
00545   const TGpSeries& Plot = SeriesV[PlotId];
00546   if(Plot.XYValV.Empty()) return -1;
00547   const TFltKdV& XY = Plot.XYValV;
00548   double A, B, R2, SigA, SigB, Chi2;
00549   // power fit
00550   TFltPrV XYPr;
00551   int s;
00552   for (s = 0; s < XY.Len(); s++) {
00553     if (XY[s].Key-FitXOffset > 0) {
00554       XYPr.Add(TFltPr(XY[s].Key-FitXOffset, XY[s].Dat)); } 
00555   }
00556   TSpecFunc::ExpFit(XYPr, A, B, SigA, SigB, Chi2, R2);
00557   TStr Label, StyleStr=Style;
00558   if (FitXOffset == 0) { Label = TStr::Fmt("%.4g exp(%.4g x)  R^2:%.2g", A, B, R2); }
00559   else { Label = TStr::Fmt("%.4g exp(%.4g x - %g)  R^2:%.2g", A, B, FitXOffset, R2); }
00560   if (StyleStr.Empty()) { StyleStr = "linewidth 3"; }
00561   const int FitId = AddFunc(TStr::Fmt("%f*exp(%f*x-%f)", A, B, FitXOffset),
00562     SeriesTy, Label, StyleStr);
00563   return FitId;
00564   /*SeriesV.Add();
00565   TGpSeries& NewPlot = SeriesV.Last();
00566   TFltKdV& EstXY = NewPlot.XYValV;
00567   for (s = 0; s < XYPr.Len(); s++) {
00568     EstXY.Add(TFltKd(XYPr[s].Val1+FitXOffset, A*exp(B*XYPr[s].Val1)));
00569   }
00570   NewPlot.SeriesTy = SeriesTy;
00571   if (Style.Empty()) { NewPlot.WithStyle = "linewidth 3"; }
00572   else { NewPlot.WithStyle = Style; }
00573   return SeriesV.Len() - 1;*/
00574 }
00575 
00576 void TGnuPlot::SavePng(const TStr& FNm, const int& SizeX, const int& SizeY, const TStr& Comment, const TStr& Terminal) {
00577   if (Terminal.Empty()) {
00578     //#ifdef GLib_WIN
00579     #ifndef GLib_MACOSX  // The standard GNUPlot for MacOS does not support PNG
00580     AddCmd(TStr::Fmt("set terminal png small size %d,%d", SizeX, SizeY));
00581     AddCmd(TStr::Fmt("set output '%s'", FNm.CStr()));
00582     #else // EPS
00583     AddCmd("set terminal postscript eps 10 enhanced color");
00584     AddCmd(TStr::Fmt("set output '%s.eps'", FNm.GetFMid().CStr()));
00585     #endif
00586   } else {
00587     AddCmd(Terminal);
00588     AddCmd(TStr::Fmt("set output '%s'", FNm.CStr()));
00589   }
00590   Pause(false);
00591   CreatePlotFile(Comment.Empty()? Title : Comment);
00592   RunGnuPlot();
00593   MoreCmds.DelLast();
00594   MoreCmds.DelLast();
00595 }
00596 
00597 void TGnuPlot::SaveEps(const TStr& FNm, const int& FontSz, const TStr& Comment) {
00598   AddCmd(TStr::Fmt("set terminal postscript enhanced eps %d color", FontSz));
00599   AddCmd(TStr::Fmt("set output '%s'", FNm.CStr()));
00600   Pause(false);
00601   CreatePlotFile(Comment.Empty()? Title : Comment);
00602   RunGnuPlot();
00603   MoreCmds.DelLast();
00604   MoreCmds.DelLast();
00605 }
00606 
00607 void TGnuPlot::MakeExpBins(const TFltPrV& XYValV, TFltPrV& ExpXYValV, const double& BinFactor, const double& MinYVal) {
00608   TFltKdV KdV(XYValV.Len(), 0), OutV;
00609   for (int i = 0; i < XYValV.Len(); i++) {
00610     KdV.Add(TFltKd(XYValV[i].Val1, XYValV[i].Val2)); }
00611   KdV.Sort();
00612   TGnuPlot::MakeExpBins(KdV, OutV, BinFactor, MinYVal);
00613   ExpXYValV.Gen(OutV.Len(), 0);
00614   for (int i = 0; i < OutV.Len(); i++) {
00615     ExpXYValV.Add(TFltPr(OutV[i].Key, OutV[i].Dat)); }
00616 }
00617 
00618 void TGnuPlot::MakeExpBins(const TFltKdV& XYValV, TFltKdV& ExpXYValV, const double& BinFactor, const double& MinYVal) {
00619   if (XYValV.Empty()) { ExpXYValV.Clr(false); return; }
00620   IAssert(! XYValV.Empty());
00621   IAssert(XYValV.IsSorted());
00622   const TFlt MxX = XYValV.Last().Key;
00623   // find buckets
00624   TFltV BucketEndV; BucketEndV.Add(1);
00625   double PrevBPos = 1, BPos = 1;
00626   while (BPos <= MxX) {
00627     PrevBPos = (uint) floor(BPos);
00628     BPos *= BinFactor;
00629     if (floor(BPos) == PrevBPos) {
00630       BPos = PrevBPos + 1; }
00631     BucketEndV.Add(floor(BPos));
00632   }
00633   //printf("buckets:\n"); for (int i = 0; i < BucketEndV.Len(); i++) { printf("\t%g\n", BucketEndV[i]);}
00634   ExpXYValV.Gen(BucketEndV.Len(), 0);
00635   int CurB = 0;
00636   double AvgPos=0, Cnt=0, AvgVal=0;
00637   for (int v = 0; v < XYValV.Len(); v++) {
00638     if (XYValV[v].Key() == 0.0) { continue; }
00639     AvgPos += XYValV[v].Key ;//* XYValV[v].Dat;  // x
00640     AvgVal += XYValV[v].Dat;  // y
00641     Cnt++;
00642     if (v+1 == XYValV.Len() || XYValV[v+1].Key > BucketEndV[CurB]) {
00643       if (Cnt != 0) {
00644         //AvgPos /= AvgVal;
00645         //AvgVal /= (BucketEndV[CurB]-BucketEndV[CurB-1]);
00646         AvgPos /= (double) Cnt;
00647         AvgVal /= (double) Cnt;
00648         if (AvgVal < MinYVal) { AvgVal = MinYVal; }
00649         ExpXYValV.Add(TFltKd(AvgPos, AvgVal));
00650         //printf("b: %6.2f\t%6.2f\n", AvgPos, AvgVal);
00651         AvgPos = 0;  AvgVal = 0;  Cnt = 0;
00652       }
00653       CurB++;
00654     }
00655   }
00656 }
00657 
00658 void TGnuPlot::LoadTs(const TStr& FNm, TStrV& ColNmV, TVec<TFltKdV>& ColV) {
00659   PSs Ss = TSs::LoadTxt(ssfTabSep, FNm);
00660   int row = 0;
00661   ColNmV.Clr();
00662   while (Ss->At(0, row)[0] == '#') { row++; }
00663   for (int c = 1; c < Ss->GetXLen(row); c+=2) {
00664     ColNmV.Add(Ss->At(c, row));
00665   }
00666   row++;
00667   ColV.Gen(ColNmV.Len(), ColNmV.Len());
00668   for (; row < Ss->GetYLen(); row++) {
00669     for (int c = 0; c < Ss->GetXLen(row); c+=2) {
00670       if (Ss->At(c,row).Empty()) break;
00671       ColV[c/2].Add(TFltKd(Ss->At(c,row).GetFlt(), Ss->At(c+1,row).GetFlt()));
00672     }
00673   }
00674 }
00675 
00676 TStr TGnuPlot::GetScaleStr(const TGpScaleTy& ScaleTy) {
00677   switch(ScaleTy){
00678     case gpsNoAuto: return TStr("set noautoscale");
00679     case gpsAuto: return TStr("set autoscale");
00680     case gpsLog: return TStr("set logscale");
00681     case gpsLog2X: return TStr("set logscale x 2");
00682     case gpsLog2Y: return TStr("set logscale y 2");
00683     case gpsLog2XY: return TStr("set logscale xy 2");
00684     case gpsLog10X: return TStr("set logscale x 10");
00685     case gpsLog10Y: return TStr("set logscale y 10");
00686     case gpsLog10XY: return TStr("set logscale xy 10");
00687     default: Fail;
00688   }
00689   return TStr();
00690 }
00691 
00692 TStr TGnuPlot::GetSeriesTyStr(const TGpSeriesTy& SeriesTy) {
00693   switch(SeriesTy) {
00694     case gpwLines: return TStr("lines");
00695     case gpwPoints: return TStr("points");
00696     case gpwLinesPoints: return TStr("linespoints");
00697     case gpwImpulses: return TStr("impulses");
00698     case gpwDots: return TStr("dots");
00699     case gpwSteps: return TStr("steps");
00700     case gpwFSteps: return TStr("fsteps");
00701     case gpwHiSteps: return TStr("histeps");
00702     case gpwBoxes: return TStr("boxes");
00703     case gpwErrBars: return TStr("errorbars");
00704     case gpwFilledCurves: return TStr("filledcurves");
00705     default: Fail;
00706   }
00707   return TStr();
00708 }
00709 
00710 void TGnuPlot::SaveTs(const TIntKdV& KdV, const TStr& FNm, const TStr& HeadLn) {
00711   FILE *F = fopen(FNm.CStr(), "wt");
00712   EAssert(F);
00713   if (! HeadLn.Empty()) fprintf(F, "# %s\n", HeadLn.CStr());
00714   for (int i = 0; i < KdV.Len(); i++) {
00715     fprintf(F, "%d\t%d\n", KdV[i].Key(), KdV[i].Dat()); }
00716   fclose(F);
00717 }
00718 
00719 
00720 void TGnuPlot::SaveTs(const TIntFltKdV& KdV, const TStr& FNm, const TStr& HeadLn) {
00721   FILE *F = fopen(FNm.CStr(), "wt");
00722   EAssert(F);
00723   if (! HeadLn.Empty()) fprintf(F, "# %s\n", HeadLn.CStr());
00724   for (int i = 0; i < KdV.Len(); i++)
00725     fprintf(F, "%d\t%g\n", KdV[i].Key(), KdV[i].Dat());
00726   fclose(F);
00727 }
00728 
00729 void TGnuPlot::Test() {
00730   TFltV DeltaY;
00731   TFltPrV ValV1, ValV2, ValV3;
00732   for (int i = 1; i < 30; i++) {
00733     ValV1.Add(TFltPr(i, pow(double(i), 1.2)));
00734     DeltaY.Add(5*TInt::Rnd.GetUniDev());
00735     ValV2.Add(TFltPr(i, 5*i-1));
00736   }
00737   for (int i = -10; i < 20; i++) {
00738     ValV3.Add(TFltPr(i, 2*i + 2 + TInt::Rnd.GetUniDev()));
00739   }
00740   TGnuPlot GnuPlot("testDat", "TestPlot", true);
00741   GnuPlot.SetXYLabel("X", "Y");
00742   const int id2 = GnuPlot.AddPlot(ValV2, gpwPoints, "y=5*x-1");
00743   const int id3 = GnuPlot.AddPlot(ValV3, gpwPoints, "y=2*x+2");
00744   GnuPlot.AddErrBar(ValV1, DeltaY, "y=x^2", "Error bar");
00745   GnuPlot.AddLinFit(id2, gpwLines);
00746   GnuPlot.AddLinFit(id3, gpwLines);
00747   GnuPlot.Plot();
00748   GnuPlot.SavePng("testPlot.png");
00749 }
00750 
00751 int TGnuPlot::IsSameXCol(const int& CurId, const int& PrevId) const {
00752   //if (SerId < 1) { return -1; }
00753   if (SeriesV[CurId].XYValV.Len() != SeriesV[PrevId].XYValV.Len()) { return -1; }
00754   for (int x = 0; x < SeriesV[CurId].XYValV.Len(); x++) {
00755     if (SeriesV[CurId].XYValV[x] != SeriesV[PrevId].XYValV[x]) { return -1; }
00756   }
00757   IAssert(SeriesV[PrevId].XCol > 0);
00758   return SeriesV[PrevId].XCol;
00759 }
00760 
00761 void TGnuPlot::CreatePlotFile(const TStr& Comment) {
00762   time_t ltime;  time(&ltime);
00763   char* TimeStr = ctime(&ltime);  TimeStr[strlen(TimeStr) - 1] = 0;
00764   // rearrange columns so that longest are on the left
00765   //SeriesV.Sort(false);
00766   TIntV SerIdV(SeriesV.Len(), 0);
00767   for (int i = 0; i < SeriesV.Len(); i++) { SerIdV.Add(i); }
00768   SerIdV.SortCmp(TGpSeriesCmp(SeriesV));
00769   // set columns
00770   int ColCnt = 1;
00771   bool SaveData = false;
00772   for (int s = 0; s < SeriesV.Len(); s++) {
00773     TGpSeries& Plt = SeriesV[SerIdV[s]];
00774     if (Plt.XYValV.Empty()) { continue; }
00775     Plt.DataFNm = DataFNm;
00776     // plots use same X column
00777     const int PrevCol = s > 0 ? IsSameXCol(SerIdV[s], SerIdV[s-1]) : -1;
00778     if (PrevCol != -1) { Plt.XCol = PrevCol; }
00779     else { Plt.XCol = ColCnt;  ColCnt++; }
00780     Plt.YCol = ColCnt;  ColCnt++;
00781     if (! Plt.ZValV.Empty()) { Plt.ZCol = ColCnt;  ColCnt++; }
00782     if (! Plt.XYValV.Empty()) { SaveData=true; }
00783   }
00784   // save data file (skip duplicate X columns)
00785   if (SaveData) {
00786     FILE *F = fopen(DataFNm.CStr(), "wt");
00787     EAssertR(F != NULL, TStr("Can not open data file ")+DataFNm);
00788     fprintf(F, "#\n");
00789     fprintf(F, "# %s (%s)\n", Comment.CStr(), TimeStr);
00790     fprintf(F, "#\n");
00791     // column names
00792     for (int i = 0; i < SerIdV.Len(); i++) {
00793       const TGpSeries& Ser = SeriesV[SerIdV[i]];
00794       if (Ser.XYValV.Empty()) { continue; }
00795       if (i == 0) { fprintf(F, "# "); } else { fprintf(F, "\t"); }
00796       if (Ser.SaveXVals()) {
00797         if (! LblX.Empty()) { fprintf(F, "%s\t", LblX.CStr()); }
00798         else { fprintf(F, "XVals\t"); }
00799       }
00800       if (Ser.Label.Empty()) { fprintf(F, "%s", LblY.CStr()); }
00801       else { fprintf(F, "%s", SeriesV[SerIdV[i]].Label.CStr()); }
00802       if (Ser.ZCol > 0) fprintf(F, "\tDeltaY");
00803     }
00804     fprintf(F, "\n");
00805     // data
00806     for (int row = 0; row < SeriesV[SerIdV[0]].XYValV.Len(); row++) {
00807       for (int i = 0; i < SeriesV.Len(); i++) {
00808         const TGpSeries& Ser = SeriesV[SerIdV[i]];
00809         if (row < Ser.XYValV.Len()) {
00810           if (i > 0) { fprintf(F, "\t"); }
00811           if (Ser.SaveXVals()) { fprintf(F, "%g\t%g", Ser.XYValV[row].Key(), Ser.XYValV[row].Dat()); }
00812           else { fprintf(F, "%g", Ser.XYValV[row].Dat()); }
00813           if (! Ser.ZValV.Empty()) { fprintf(F, "\t%g", Ser.ZValV[row]()); }
00814         }
00815       }
00816       fprintf(F, "\n");
00817     }
00818     fclose(F);
00819   }
00820   // save plot file
00821   FILE *F = fopen(PlotFNm.CStr(), "wt");
00822   EAssertR(F != 0, TStr("Can not open plot file ")+PlotFNm);
00823   TStr CurDir = TDir::GetCurDir();
00824   CurDir.ChangeStrAll("\\", "\\\\");
00825   fprintf(F, "#\n");
00826   fprintf(F, "# %s (%s)\n", Comment.CStr(), TimeStr);
00827   fprintf(F, "#\n\n");
00828   if (! Title.Empty()) fprintf(F, "set title \"%s\"\n", Title.CStr());
00829   fprintf(F, "set key bottom right\n");
00830   fprintf(F, "%s\n", GetScaleStr(ScaleTy).CStr());
00831   if (ScaleTy==gpsLog || ScaleTy==gpsLog10X || ScaleTy==gpsLog10XY) {
00832     fprintf(F, "set format x \"10^{%%L}\"\n");
00833     fprintf(F, "set mxtics 10\n"); }
00834   if (ScaleTy==gpsLog || ScaleTy==gpsLog10Y || ScaleTy==gpsLog10XY) {
00835     fprintf(F, "set format y \"10^{%%L}\"\n");
00836     fprintf(F, "set mytics 10\n"); }
00837   if (ScaleTy==gpsLog2X || ScaleTy==gpsLog2XY) { fprintf(F, "set format x \"2^{%%L}\"\n"); }
00838   if (ScaleTy==gpsLog2Y || ScaleTy==gpsLog2XY) { fprintf(F, "set format y \"2^{%%L}\"\n"); }
00839   if (SetGrid) fprintf(F, "set grid\n");
00840   if (XRange.Val1 != XRange.Val2) fprintf(F, "set xrange [%g:%g]\n", XRange.Val1(), XRange.Val2());
00841   if (YRange.Val1 != YRange.Val2) fprintf(F, "set yrange [%g:%g]\n", YRange.Val1(), YRange.Val2());
00842   if (! LblX.Empty()) fprintf(F, "set xlabel \"%s\"\n", LblX.CStr());
00843   if (! LblY.Empty()) fprintf(F, "set ylabel \"%s\"\n", LblY.CStr());
00844   if (Tics42) {
00845     fprintf(F, "set tics scale 2\n"); // New in version 4.2
00846   } else {
00847     fprintf(F, "set ticscale 2 1\n"); // Old (deprecated)
00848   }
00849   // custom commands
00850   for (int i = 0; i < MoreCmds.Len(); i++) {
00851     fprintf(F, "%s\n", MoreCmds[i].CStr()); }
00852   // plot
00853   if (! SeriesV.Empty()) {
00854     fprintf(F, "plot \t");
00855     for (int i = 0; i < SeriesV.Len(); i++) {
00856       fprintf(F, "%s", GetSeriesPlotStr(i).CStr()); }
00857     fprintf(F, "\n");
00858   }
00859   if (SetPause) fprintf(F, "pause -1 \"Hit return to exit. %s\"\n", PlotFNm.CStr());
00860   fclose(F);
00861 }
00862 
00863 void TGnuPlot::RunGnuPlot() const {
00864   TStr GpFNm, GpPath;
00865   #if defined(GLib_WIN)
00866     GpFNm = "wgnuplot.exe";
00867     GpPath = "C:\\gnuplot\\";
00868   #elif defined(GLib_CYGWIN)
00869     GpFNm = "gnuplot.exe";
00870     GpPath = "/usr/bin/";
00871   #else
00872     GpFNm = "gnuplot";
00873     GpPath = "/usr/bin/";
00874   #endif
00875   if (system(TStr::Fmt("%s %s", GpFNm.CStr(), PlotFNm.CStr()).CStr())==0) { return; }
00876   #if defined(GLib_WIN)
00877   if (system(TStr::Fmt(".\\%s %s", GpFNm.CStr(), PlotFNm.CStr()).CStr())==0) { return; }
00878   #else
00879   if (system(TStr::Fmt("./%s %s", GpFNm.CStr(), PlotFNm.CStr()).CStr())==0) { return; }
00880   #endif
00881   if (system(TStr::Fmt("%s%s %s", GpPath.CStr(), GpFNm.CStr(), PlotFNm.CStr()).CStr())==0) { return; }
00882   //FailR(TStr::Fmt("Cat not find GnuPlot (%s) for plot %s. Set the PATH.", GpFNm.CStr(), PlotFNm.CStr()).CStr());
00883   //ErrNotify(TStr::Fmt("Cat not find GnuPlot (%s) for plot %s. Set the PATH.", GpFNm.CStr(), PlotFNm.CStr()).CStr());
00884   fprintf(stderr, "[%s:%d] Cat not find GnuPlot (%s) for plot %s. Set the PATH.\n", __FILE__, __LINE__, GpFNm.CStr(), PlotFNm.CStr());
00885 }