[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{pstricks-add}
\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
\addbefore at par{dotstyle=o,PSxfunc=,PSyfunc=}
\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}{}}%


\pst at addfams{pst-GetCoor}
%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
\addbefore at par{dotstyle=o}
\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{%
  \addto at pscode{
    \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}

\readdata[ignoreLines=0]{\dataC}{datafile.dat}
\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}
\pstScalePoints(1,1){5 add}{2 div}
\listplot[plotstyle=ErrorLine,plotNo=1,plotNoMax=2]{\dataC}
\pstScalePoints(1,1){}{}
\GetOneCoor[PSyfunc=2 div,PSxfunc=10 add]{\dataC}{2}{3}
\end{psgraph}
\end{figure}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}


More information about the PSTricks mailing list