Newer
Older
//**************************************************************************************************
//* FRIDA: fast reliable interactive data analysis
//* (C) Joachim Wuttke 1990-, v2(C++) 2001-
//* http://apps.jcns.fz-juelich.de/frida
//**************************************************************************************************
//! \file gnuplotter.cpp
//! \brief Implements class CPS_Plotter.
#include <cmath>
#include <fstream>
#include <boost/format.hpp>
#include "../trivia/file_ops.hpp"
#include "../trivia/string_convs.hpp"
#include "axis.hpp"
#include "ps_plotter.hpp"
using std::string;
using std::vector;
using boost::format;
namespace {
string ps_ticktack(
const vector<double>& Tacks, const int ntpt, const double* ticklim, const CAxis* A);
string ps_coord(const CAxis* A, const char a);
string ps_axis(const CAxis* A, const string& label, const char a);
string ps_horiz();
string ps_verti();
string ps_colorscale();
string ps_slice_header(
bool as_line, int slice_no, int style_no, const vector<string>& zentries,
const string& xco, const string& yco);
string ps_data_block(
const CAxis* X, const CAxis* Y,
const vector<double>& xp, const vector<double>& yp, const vector<double>& dyp);
string ps_footer(
const string& fname, const string& doc_lines);
const string& caller, const CAxis& _X, const CAxis& _Y,
const string& xlabel, const string& ylabel)
X = &_X;
Y = &_Y;
ps_snum = 0;
ps_Doc = "";
ps_accu = "\n%% output created by " + caller + "\n\n";
ps_accu += ps_coord(X, 'x');
ps_accu += ps_coord(Y, 'y');
ps_accu += ps_axis(X, xlabel, 'x') + ps_horiz();
ps_accu += ps_axis(Y, ylabel, 'y') + ps_verti();
const std::string& caller, const CAxis& _X, const CAxis& _Z, const CAxis& _Y)
{
p2D = true;
X = &_X;
Z = &_Z;
Y = &_Y;
ps_snum = 0;
ps_Doc = "";
ps_accu = "\n%% output created by " + caller + "\n\n";
ps_accu += ps_coord(X, 'x');
ps_accu += ps_coord(Z, 'y');
ps_accu += ps_coord(Y, 'h');
ps_accu += "\n";
}
void CPS_Plotter::close_frame2D(
const CAxis& _X, const CAxis& _Z, const CAxis& _Y,
const std::string& xlabel, const std::string& zlabel, const std::string& ylabel)
{
ps_accu += "/linsetTic {white 1 setline} def\n";
ps_accu += "/linsetTac {white 1.3 setline} def\n\n";
ps_accu += ps_axis(X, xlabel, 'x') + ps_horiz();
ps_accu += ps_axis(Z, zlabel, 'y') + ps_verti();
ps_accu += ps_axis(Y, ylabel, 'h') + ps_colorscale();
}
void CPS_Plotter::add_spec(
bool as_line, bool new_slice, int style_no,
const vector<double>& xp, const vector<double>& yp,
const vector<double>& dyp, const vector<string>& zentries,
const string& xco, const string& yco, const string& info)
{
// Postscript copy:
if (new_slice)
ps_accu += ps_slice_header(as_line, ++ps_snum, style_no, zentries, xco, yco);
else
ps_accu += ps_data_block(X, Y, xp, yp, dyp);
void CPS_Plotter::main_line(const string& line)
{
ps_accu += line + "\n";
}
void CPS_Plotter::doc_line(const string& line)
{
ps_Doc += line + "\n";
}
void CPS_Plotter::copy_header(
const string& mode, const string& fname,
const string& ps_head, const string& ps_cont, const string& ps_dict)
{
// copy headers to output file
string cmd;
if (mode=="append") {
if (!triv::file_exists(fname))
throw "Cannot append graphic: file " + fname + " not found";
cmd = "cat " + ps_cont + " >> " + fname;
} else {
if (mode=="create") {
if (triv::file_exists(fname))
throw "File " + fname + " already exists. Use "
+ (ps_dict=="" ? "gf!" : "gp!") + " to overwrite";
} else if (mode=="overwrite") {
} else
throw "BUG: unexpected mode";
cmd = "cat " + ps_dict + " " + ps_head + " > " + fname;
}
triv::system(cmd);
void CPS_Plotter::write_data(const string& fname)
{
// append specific output to output file:
if (!triv::file_exists(fname))
throw "BUG: after copying headers, graphic output file " + fname + " still doesn't exist";
std::fstream fs(fname, std::fstream::out | std::fstream::app);
fs << ps_accu;
fs << ps_footer(fname, ps_Doc);
fs.close();
}
//**************************************************************************************************
// static functions
//**************************************************************************************************
namespace {
//! Format ticks and tacks for postscript file.
string ps_ticktack(
const vector<double>& Tacks, const int ntpt, const double* ticklim, const CAxis* A)
{
string ret;
int ntack = Tacks.size();
if (ntack > 0) {
if (A->logflag && (Tacks[0] < 1e-3 || Tacks[ntack - 1] > 1e3)) {
for (int i = 0; i < ntack; i++)
% A->pc(Tacks[i])
% (int)(log10(Tacks[i]))
% (float)Tacks[i]);
} else {
for (int i = 0; i < ntack; i++)
% A->pc(Tacks[i])
% (float)Tacks[i]);
}
ret += " ] SetTacVec\n";
ret += str(format("%g %g %i %i SetTicVec%s\n")
% A->pc(ticklim[0])
% A->pc(ticklim[1])
% (ntack + 2)
% ntpt
% (A->logflag ? "Log" : "Lin"));
return ret;
}
{
return str(format("%1i %g %g %cSetCoord\n") % A->logflag % A->inf % A->sup % a);
}
string ps_axis(const CAxis* A, const string& label, const char a)
{
string ret;
int ntpt;
double ticklim[2];
vector<double> Tacks;
if (A->logflag && A->inf <= 0)
throw "BUG: log incompatible with limits " + A->str();
A->calc_ticks(Tacks, &ntpt, ticklim);
ret += ps_ticktack(Tacks, ntpt, ticklim, A);
return ret;
}
string ps_horiz()
{
return
" 0 10 0 0 0 90 OneAxx Axx Tic Tac xNumL %% low x axis\n"
" 0 10 0 10 0 270 OneAxx Axx Tic Tac %% top x axis\n"
"xCL\n\n";
" 0 10 0 0 90 0 OneAxx Axx Tic Tac yNumL %% left y axis\n"
" 0 10 10 0 90 180 OneAxx Axx Tic Tac %% right y axis\n"
"yCL\n\n";
return
"/hxlow 11.3 def\n"
"/hxhig 12.3 def\n"
" hxlow hxhig 0 0 0 90 OneAxx Axx %% low x line\n"
" hxlow hxhig 0 10 0 90 OneAxx Axx %% low x line\n"
" 0 10 hxlow 0 90 0 OneAxx Tic Tac Axx %% left y axis\n"
" 0 10 hxhig 0 90 180 OneAxx Tic Tac Axx yNumH %% right y axis\n"
"hxhig YCH\n\n";
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
}
string ps_slice_header(
bool as_line, int slice_no, int style_no, const vector<string>& zentries,
const string& xco, const string& yco)
{
string ret;
ret += str(format("\n%3u [") % slice_no);
for (string zentry: zentries)
ret += " " + zentry;
ret += " ] zValues\n";
ret += str(format("%2i %cstyle %% (%s -> %s)\n")
% style_no
% (as_line ? 'c' : 'p')
% xco
% yco);
return ret;
}
string ps_data_block(
const CAxis* X, const CAxis* Y,
const vector<double>& xp, const vector<double>& yp, const vector<double>& dyp)
{
string ret;
int np = xp.size();
for (int i = 0; i < np; i++)
ret += str(format("%8.5f %8.5f %8.5f t%c %% %13.7g wx %13.7g wy\n")
% X->pc(xp[i])
% Y->pc(yp[i])
% (dyp.size() ? Y->pcerr(yp[i], dyp[i]) : 0)
% (i == 0 ? 'i' : i == np - 1 ? 'f' : ' ')
% xp[i]
% yp[i]);
return ret;
}
string ps_footer(const string& fname, const string& doc_lines)
{
return "\n{ black 0 -3 13 1.65 NewList\n"
+ doc_lines
+ " {(plot -> " + fname + ")} TxLine\n"
+ "} oooinfo 1 eq { exec } { pop } ifelse\n\n"
+ "EndFrame\n";
}
} // anonymous namespace