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 <iostream>
#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_coord(const CAxis* A);
string ps_axis(const CAxis* A);
string ps_horiz(const string& label);
string ps_verti(const string& label);
string ps_colorscale(const string& label);
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)
X = &_X;
Y = &_Y;
ps_snum = 0;
ps_Doc = "";
}
void CPS_Plotter::set_labels(const std::string& _xlabel, const std::string& _ylabel)
{
xlabel = _xlabel;
ylabel = _ylabel;
const std::string& _caller, const CAxis& _X, const CAxis& _Z, const CAxis& _Y)
X = &_X;
Z = &_Z;
Y = &_Y;
ps_snum = 0;
ps_Doc = "";
ps_accu += ps_coord(X);
ps_accu += ps_coord(Z);
ps_accu += ps_coord(Y);
ps_accu += "\n%% 2D image begin\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 += "%% 2D image end\n\n";
ps_accu += "/linsetTic {white 1 setline} def\n";
ps_accu += "/linsetTac {white 1.3 setline} def\n\n";
ps_accu += ps_axis(X) + ps_horiz(xlabel);
ps_accu += ps_axis(Z) + ps_verti(zlabel);
ps_accu += ps_axis(Y) + ps_colorscale(ylabel);
}
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";
}
const string& fname, const string& mode, const bool withDefs,
std::map<const string, string>& settings)
{
// 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 " + settings.at("ps_continuation") + " >> " + fname;
} else {
if (mode=="create") {
if (triv::file_exists(fname))
throw "File " + fname + " already exists. "
+ "Use command suffix '!' to overwrite";
} else if (mode=="overwrite") {
} else
throw "BUG: unexpected mode";
cmd = "cat ";
if (withDefs)
cmd += settings.at("ps_definitions") + " ";
cmd += settings.at(string("ps_setup") + (p2D ? "2" : "1") + "D") + " > " + 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 << "\n%% output created by " << caller << "\n\n";
if (!p2D) {
fs << ps_coord(X);
fs << ps_coord(Y);
fs << "\n";
fs << ps_axis(X) + ps_horiz(xlabel);
fs << ps_axis(Y) + ps_verti(ylabel);
fs << "\n";
}
fs << ps_footer(fname, ps_Doc);
fs.close();
}
//**************************************************************************************************
// static functions
//**************************************************************************************************
namespace {
//! Format ticks and tacks for postscript file.
{
int ticks_per_tack;
int ntacks4ticks;
A->calc_ticks(Tacks, ticks_per_tack, ntacks4ticks, ticklim);
string ret;
int ntack = Tacks.size();
ret += "[\n";
if (!ntack)
; // do nothing
else if (A->logflag && (Tacks.front() < 1e-3 || Tacks.back() > 1e3)) {
for (int i = 0; i < ntack; i++)
ret += str(format(" %g w%s {(10)(%i)sp()} %%{(%g)}\n")
% (float)Tacks[i]
% A->name
% (int)(log10(Tacks[i]))
% (float)Tacks[i]);
} else {
for (int i = 0; i < ntack; i++)
ret += str(format(" %g w%s {(%g)}\n")
% (float)Tacks[i]
% A->name
% (float)Tacks[i]);
ret += str(format("%g w%s %g w%s %i %i SetTicVec%s\n")
% (float)ticklim[0]
% A->name
% (float)ticklim[1]
% A->name
% ntacks4ticks
% ticks_per_tack
% (A->logflag ? "Log" : "Lin"));
return ret;
}
{
return str(format("%1i %g %g %cSetCoord\n")
% A->logflag % A->inf % A->sup % A->name);
throw "BUG: log incompatible with limits " + A->to_s();
string ps_horiz(const string& label)
" 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"
"{(" + label + ")} xCL\n\n";
string ps_verti(const string& label)
" 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"
"{(" + label + ")} yCL\n\n";
string ps_colorscale(const string& label)
" 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"
"{(" + label + ")} hxhig YCH\n\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;
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 "{ 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