# [pstricks] TeX loop structures versus Postscript Loop Structures and Plotting

Buddy Ledger buddyledger at gmail.com
Fri May 1 18:49:12 CEST 2009

Hello all,

I have been working on developing a few plotting routines for writing a
thesis.  I started out using high level TeX objects only, i.e. repeated
\psdot or \psline calls using a TeX loop (adapted from The Latex
Graphics Companion "GetCoordinates" example on page 329).  However, as I
started to learn a bit about pstricks I started to re-write some of the
postscript routines as well.

Now for my question (or rather a request for opinion).  Is it worth it
to create new plotstyles or just string together high level objects?  I
will likely be plotting over 100 graphs and diagrams.

The features I was looking for and at least partially implimented were:

1. X and Y ErrorBars (implimented below in \GetOneCoor and new plotstyle
ErrorLine)

2. Plot Linear Regression (in the process of modifying LSM plotstyle to
present equations, 95% conf. intervals and r^2 values, partially
implimented)

3. Plot (x, y1 y2 dup mul exch dup mul sqrt) square root of sum of
squares [application: two orthogonal vibration amplitude channels]
(implimented below in \GetTwoCoors)

4. Postscript modifying functions (implimented in \GetOneCoor below or
use \psScalePoints)

5. LineToXaxis should respect \psScalePoints.  i.e.
\psScalePoints(1,1){}{10 add} then the line should be drawn to (x,10)
not (x,0) this allows for spatial velocity plots.  I want to do scaled
velocity plots on a spatial diagram.

5. Generalized iterative non-linear regression using prototype function
and AlgtoPS (I'll probably be leaving this one alone, but I'd love to do it)

So what ar the implications of:
%%%%%Pseudo Code%%%%%%
Start TeX  Loop (i =1 to n){
\psline(xi-1,yi-1)(xi,yi)
\psdot(xi,yi)}
End TeX Loop

Versus

Tex Command{
Start PS Loop
Dot
Line}
End PS Loop
%%%%%%%%%%%%%%%%%

What is the effect on processing speed, overflow issues, final document
load times, final document size.  Thanks very much for any advice.

Buddy Ledger

\documentclass[]{article}

\usepackage{pst-all}
\usepackage{pst-func}
\usepackage{filecontents}

\begin{filecontents*}{datafile.dat}
1.10 1.00 1.00
2.00 2.20 2.20
3.05 3.00 3.00
4.30 6.10 6.10
5.40 9.20 9.20
6.50 12.6 12.6
\end{filecontents*}

\makeatletter

\def\pserrorLine{\pst at object{pserrorLine}}
\def\pserrorLine at i(#1)#2#3{\begingroup
\use at par \pst at getcoor{#1}\pst at tempA
\def\ps at xErr{#2}\def\ps at yErr{#3}
\if\ps at yErr 0\relax \else
\psline(! /yDot \pst at tempA\space exch pop \pst at number\psyunit\space div def
/xDot \pst at tempA\space pop \pst at number\psxunit\space div def
xDot yDot yDot \ps at yErr\space mul add )
(! /yDot \pst at tempA\space exch pop \pst at number\psyunit\space div def
/xDot \pst at tempA\space pop \pst at number\psxunit\space div def
xDot yDot yDot \ps at yErr\space mul sub )
\fi
\if\ps at xErr 0\relax \else
\psline(! /yDot \pst at tempA\space exch pop \pst at number\psyunit\space div def
/xDot \pst at tempA\space pop \pst at number\psxunit\space div def
xDot xDot \ps at xErr\space mul add yDot )
(! /yDot \pst at tempA\space exch pop \pst at number\psyunit\space div def
/xDot \pst at tempA\space pop \pst at number\psxunit\space div def
xDot xDot \ps at xErr\space mul sub yDot )
\fi
\endgroup}

\def\psXaxesLine{\pst at object{psXaxesLine}}
\def\psXaxesLine at i(#1)#2{\begingroup
\use at par \pst at getcoor{#1}\pst at tempA
\def\ps at Yfunc{#2}
\psline{->}(!\pst at tempA\space pop \pst at number\psxunit\space div
0\space \ps at Yfunc)
(!\pst at tempA\space pop \pst at number\psxunit\space div
\pst at tempA\space exch pop \pst at number\psyunit\space div)
\endgroup}

\newcounter{loopcount}

\def\GetOneCoor{\pst at object{GetOneCoor}}
\def\GetOneCoor at i#1#2#3{%
%default options
\use at par
\setcounter{loopcount}{0}
\xdef\plotxvalold{}
\xdef\plotyvalold{}
\def\numplot{#2}
\def\numplotmax{#3}
\expandafter\GetOneCoor at ii#1}
\def\GetOneCoor at ii#1{\GetOneCoor at iii#1}
\def\GetOneCoor at iii D #1 {%
\stepcounter{loopcount}
\ifnum\theloopcount=1 \def\plotxval{#1 }\fi
\ifnum\theloopcount=\numplot \def\plotyval{#1 }\fi
\ifnum\theloopcount=\numplotmax
%%%%%%%%
\ifx\plotyvalold\@empty \relax \else
\psset{linejoin=1}
\psline{-}(!\plotxvalold\space \gtc at PSxfunc\space
\plotyvalold\space \gtc at PSyfunc\space)%
(!\plotxval\space \gtc at PSxfunc\space
\plotyval\space \gtc at PSyfunc\space)
\fi%
\xdef\plotxvalold{\plotxval}
\xdef\plotyvalold{\plotyval}
%%%%%%%%%%%%%%%%%%%
\psdot(!\plotxval\space \gtc at PSxfunc\space \plotyval\space
\gtc at PSyfunc)%
\pserrorLine(!\plotxval\space \gtc at PSxfunc\space \plotyval\space
\gtc at PSyfunc){\gtc at relxerr}{\gtc at relyerr}%
%\psXaxesLine(!\plotxval\space \gtc at PSxfunc\space \plotyval\space
\gtc at PSyfunc){\gtc at PSyfunc}%input offset value
%\uput{0}[0](!\plotxval\space \gtc at PSxfunc\space \plotyval\space
\gtc at PSyfunc){% Data Labels Preliminary
%\psPrintCoor(!\plotxval\space \gtc at PSxfunc\space \plotyval\space
\gtc at PSyfunc){\gtc at relxerr}{\gtc at relyerr}}%
\setcounter{loopcount}{0}%
\fi%
\@ifnextchar D{\GetOneCoor at iii}{}}%

%Keys for psPrintCoor
\define at key[psset]{pst-GetCoor}{PSfont}[Times-Roman]{\def\gtc at PSfont{/#1 }}
\define at key[psset]{pst-GetCoor}{valuewidth}[10]{\pst at getint{#1}\gtc at valuewidth
}
\define at key[psset]{pst-GetCoor}{fontscale}[10]{\pst at checknum{#1}\gtc at fontscale
}
\define at key[psset]{pst-GetCoor}{decimals}[-1]{\pst at getint{#1}\gtc at decimals }
\define at key[psset]{pst-GetCoor}{xShift}[0]{\def\gtc at xShift{#1}}
\define at key[psset]{pst-GetCoor}{yShift}[0]{\def\gtc at yShift{#1}}
\psset[pst-GetCoor]{xShift=0,yShift=0}
\psset[pst-GetCoor]{PSfont=Times-Roman,fontscale=10,valuewidth=10,decimals=-1}

\define at key[psset]{pst-GetCoor}{PSxfunc}{\def\gtc at PSxfunc{#1}}
\define at key[psset]{pst-GetCoor}{PSyfunc}{\xdef\gtc at PSyfunc{#1}}
\define at key[psset]{pst-GetCoor}{PSfunc}{\def\gtc at PSfunc{#1}}
\define at key[psset]{pst-GetCoor}{relxerr}{\def\gtc at relxerr{#1}}
\define at key[psset]{pst-GetCoor}{relyerr}{\def\gtc at relyerr{#1}}
\define at boolkey[psset]{pst-GetCoor}[Pst@]{xyPlotLabels}[true]{}%
\define at boolkey[psset]{pst-GetCoor}[Pst@]{science}[true]{%
\ifPst at science\def\gtc at Scin{true }\else\def\gtc at Scin{false }\fi}
\psset[pst-GetCoor]{science=false} %,xyPlotLabels=true}
\psset[pst-GetCoor]{PSfunc=dup mul exch dup mul add
sqrt,relxerr=0,relyerr=0,xyPlotLabels=false}
\psset{dotstyle=square*,arrows=|-|} %Setup errorbar & dot style
\psset{PSxfunc=,PSyfunc=}

%\GetTwoCoor[relxerr=0.1,relyerr=0.1,PSfunc=sqrt]{<data
macro>}{<firstplot row>}{<secondplot row>}{<max plot row>}
%The post script function has to be written to operate on the first two
stack objects \plotyvalA & \plotyvalB and
%should return one argument which will be the y plot value.
\def\GetTwoCoor{\pst at object{GetTwoCoor}}
\def\GetTwoCoor at i#1#2#3#4{%
%default options
\use at par
\setcounter{loopcount}{0}
\def\numplotA{#2}
\def\numplotB{#3}
\def\numplotmax{#4}
\expandafter\GetTwoCoor at ii#1}
\def\GetTwoCoor at ii#1{\GetTwoCoor at iii#1}
\def\GetTwoCoor at iii D #1 {%
\stepcounter{loopcount}
\ifnum\theloopcount=1 \def\plotxval{#1 }\fi
\ifnum\theloopcount=\numplotA \def\plotyvalA{#1 }\fi
\ifnum\theloopcount=\numplotB \def\plotyvalB{#1 }\fi
\ifnum\theloopcount=\numplotmax
\psdot(!\plotxval \plotyvalA \plotyvalB \gtc at PSfunc)
\pserrorLine(!\plotxval \plotyvalA \plotyvalB
\gtc at PSfunc){\gtc at relxerr}{\gtc at relyerr}
\uput{0}[0](!\plotxval \plotyvalA \plotyvalB \gtc at PSfunc){% Data
Labels Preliminary
\psPrintCoor(!\plotxval \plotyvalA \plotyvalB
\gtc at PSfunc){\gtc at relxerr}{\gtc at relyerr}}
\setcounter{loopcount}{0}
\fi%
\@ifnextchar D{\GetTwoCoor at iii}{}}

%%%%%%%%%%%%%%

\define at key[psset]{pstricks-add}{EqPos}[{}]{\def\psk at EqPos{#1}}
\psset{EqPos=}
%\define at key[psset]{pstricks-add}{xEnd}[{}]{\def\psk at xEnd{#1}}
% LSM Least Square Method 2006-03-13 (hv)
\def\psLSM at ii{\addto at pscode{false \tx at NArray \psLSM at iii}}
\def\psLSM at iii{%
/xiSquare 0 def                % xi*xi
/xi 0 def                    % xi
/fi 0 def                    % f(xi)
/xifi 0 def                    % xi*f(xi)
exch dup dup /xEnd ED /xStart ED exch
n {                         % number of data pairs
/Yval ED /Xval ED                 % save x y values
/xi xi Xval add def                % sum xi
/xiSquare xiSquare Xval dup mul add def    % sum xi*xi
/xifi xifi Xval Yval mul add def        % sum xi*yi, same as xi*f(xi)
/fi fi Yval add def                % sum yi, same as f(xi)
Xval xStart lt { /xStart Xval def } if    % find the lowest xi
Xval xEnd gt { /xEnd Xval def } if        % find the largest xi
} repeat
/u xiSquare fi mul xi xifi mul sub n xiSquare mul xi dup mul sub div def
/v n xifi mul xi fi mul sub n xiSquare mul xi dup mul sub div def
%CUT
newpath
(\psk at xStart) length 0 gt             % special start value?
{ \psk at xStart\space \pst at number\psxunit mul dup /xStart exch def }
{ xStart } ifelse
dup v mul u add                 % xStart f(xStart)
moveto                     % goto first point x1 y(x1)
(\psk at xEnd) length 0 gt             % special end value?
{ \psk at xEnd\space \pst at number\psxunit mul dup /xEnd exch def}
{ xEnd } ifelse
dup v mul u add                 % xEnd f(xEnd)
lineto                    % line to second point x2 y(x2)
%
\psk at decimals\space -1 gt
{v 10 \psk at decimals exp dup 3 1 roll mul round exch div } if
%\psk at decimals\space 0 eq {cvi} if
/v exch def
\psk at decimals\space -1 gt
{u 10 \psk at decimals exp dup 3 1 roll mul round exch div } if
%\psk at decimals\space 0 eq {cvi} if
/u exch def
%
\Pst at Debug\space 0 gt {             % print the equation
%/Helvetica findfont 12 scalefont setfont
\psk at PSfont findfont \psk at fontscale scalefont setfont
(\psk at EqPos) length 0 gt
{\psk at EqPos\space \pst at number\psxunit mul exch \pst at number\psxunit mul
exch}
{xEnd xStart add 2 div 5 add xEnd v mul u add xStart v mul u add add 2
div} ifelse moveto (y =)show             % print y=
v 0 ne {v 30 string cvs show ( x) show
u 0 gt {( + ) show} if } if        % v x+
u 0 ne {u \pst at number\psyunit div 30 string cvs show} if } if
%\psk at decimals 20 string cvs show
%\gtc at decimals 20 string cvs show
}%
%
\def\beginplot at LSM{\begin at SpecialObj}
\def\endplot at LSM{%
\psLSM at ii\psk at fillstyle\ifpsshadow\pst at closedshadow\fi%
\pst at stroke
\end at SpecialObj%
}
%
%%%%%%%%%%%%%%
\def\pttounit#1{\pst at number{#1}}
%New PlotStyle ErrorLine
%%%%%%%%%%%
\def\beginplot at ErrorLine{\begin at OpenObj}
\def\endplot at ErrorLine{\psErrorLine at ii}

\def\psErrorLine at ii{%
\pst at cp     % current point
\psline at iii % arc and lineto type
\tx at myLine    % .pro function
}%
\end at OpenObj%
}
%
\def\tx at myLine{myLine }
\pst at def{myLine}<{
/copypt { dup 3 2 roll dup 4 1 roll exch } def %copy point
NArray n 0 eq not
{ n { \gtc at relyerr\space 0 eq not
{copypt copypt dup \gtc at relyerr\space mul add ArrowA
dup \gtc at relyerr\space mul sub
Lineto
copypt dup \gtc at relyerr\space mul sub ArrowB L} if
\gtc at relxerr\space 0 eq not
{copypt copypt exch dup \gtc at relxerr\space mul add exch ArrowA
exch dup \gtc at relxerr\space mul sub exch
Lineto
copypt exch dup \gtc at relxerr\space mul sub exch ArrowB L pop pop }
{ pop pop } ifelse } repeat
} if
}>
\makeatother

\begin{document}
\pagestyle{empty}
\pagenumbering{arabic}

\psset{xAxisLabel=y, %Setup for psgraph env
yAxisLabel=V,
xAxisLabelPos=,
yAxisLabelPos=}
\begin{figure}
\centering
\begin{psgraph}%
[arrows=->,Dx=1,Dy=1,xsubticks=0,ysubticks=0]%
(0,0)(15,15){5in}{!}
%\GetOneCoor[dotstyle=x,relxerr=0,relyerr=0,xyPlotLabels]{\dataC}{2}{2}
\psset{relxerr=0.0,relyerr=0.1}
\listplot[linestyle=dashed,plotstyle=LSM,xEnd=3.5,PstDebug=1,fontscale=12,decimals=3,EqPos=3
1,plotNo=1,plotNoMax=2]{\dataC}
\listplot[linestyle=dashed,plotstyle=LSM,xStart=2.5,PstDebug=1,fontscale=12,decimals=3,EqPos=6
8,plotNo=1,plotNoMax=2]{\dataC}
\listplot[arrows=|-|,plotstyle=ErrorLine,plotNo=1,plotNoMax=2]{\dataC}