Forked from
mlz / Frida
414 commits behind the upstream repository.
-
Wuttke, Joachim authoredWuttke, Joachim authored
ps_plotter.cpp 8.22 KiB
//**************************************************************************************************
//* 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);
}
void CPS_Plotter::start_frame1D(
const string& caller, const CAxis& _X, const CAxis& _Y,
const string& xlabel, const string& ylabel)
{
p2D = false;
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();
ps_accu += "\n";
}
void CPS_Plotter::start_frame2D(
const std::string& caller, const CAxis& _X, const CAxis& _Z, const CAxis& _Y,
const std::string& xlabel, const std::string& zlabel, const std::string& ylabel)
{
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 += 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();
ps_accu += "\n";
}
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 += "\n";
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) {
ret += "[\n";
if (A->logflag && (Tacks[0] < 1e-3 || Tacks[ntack - 1] > 1e3)) {
for (int i = 0; i < ntack; i++)
ret += str(format(" %9.6f {(10)(%i)sp()} %%{(%g)}\n")
% A->pc(Tacks[i])
% (int)(log10(Tacks[i]))
% (float)Tacks[i]);
} else {
for (int i = 0; i < ntack; i++)
ret += str(format(" %9.6f {(%g)}\n")
% 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;
}
string ps_coord(const CAxis* A, const char a)
{
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;
ret += "\n";
ret += "% " + string(1,a) + " axis:\n";
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);
ret += "{(" + label + ")}\n";
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";
}
string ps_verti()
{
return
" 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";
}
string ps_colorscale()
{
return "%TODO colorscale\n";
}
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