diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex | 1541 |
1 files changed, 1185 insertions, 356 deletions
diff --git a/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex b/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex index 1c074e70bf7..ef27a7a2728 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex @@ -44,13 +44,18 @@ % \pgfplotslistnewempty\table % 3. A "file name" stored in % \csname\string<\namemacro>@@table@name\endcsname -% 4. foreach column, there is a list of row-values (a row-vector) in +% 4. A "scan line length" number stored in +% \csname\string<\namemacro>@@table@scanline\endcsname +% It contains the value of \pgfplotsscanlinelength which has +% been identified right after \pgfplotstableread. +% 5. foreach column, there is a list of row-values (a row-vector) in % the \pgfplotslist format named % \csname\string<\namemacro>@<column name>\endcsname % \newif\ifpgfplotstable@search@header +\newif\ifpgfplotstable@firstline@is@header \newcount\c@pgfplotstable@counta \newwrite\pgfplotstable@outfile \newif\ifpgfplotstabletypesetdebug @@ -65,6 +70,7 @@ % should always be false; use only in grouped internal macros \newif\ifpgfplots@table@options@areset \newif\ifpgfplots@tableread@to@listener +\newif\ifpgfplots@tableread@use@begingroup \input pgfplotstable.coltype.code.tex @@ -90,22 +96,32 @@ % /pgfplots/table/display columns/<col index>/.style={} % /pgfplots/table/create on use/<col name>/.style={create options} \pgfkeys{% - /pgfplots/table/header/.is if=pgfplotstable@search@header, + /pgfplots/table/header/.is choice, + /pgfplots/table/header/true/.code={\pgfplotstable@firstline@is@headerfalse\pgfplotstable@search@headertrue}, + /pgfplots/table/header/false/.code={\pgfplotstable@firstline@is@headerfalse\pgfplotstable@search@headerfalse}, + /pgfplots/table/header/has colnames/.code={\pgfplotstable@firstline@is@headertrue\pgfplotstable@search@headerfalse}, /pgfplots/table/header=true, /pgfplots/table/x index/.initial=0, /pgfplots/table/x/.initial=, + /pgfplots/table/x expr/.initial=, /pgfplots/table/y index/.initial=1, /pgfplots/table/y/.initial=, + /pgfplots/table/y expr/.initial=, /pgfplots/table/z index/.initial=2, /pgfplots/table/z/.initial=, + /pgfplots/table/z expr/.initial=, /pgfplots/table/meta index/.initial=, /pgfplots/table/meta/.initial=, + /pgfplots/table/meta expr/.initial=, /pgfplots/table/x error index/.initial=, /pgfplots/table/y error index/.initial=, /pgfplots/table/z error index/.initial=, /pgfplots/table/x error/.initial=, /pgfplots/table/y error/.initial=, /pgfplots/table/z error/.initial=, + /pgfplots/table/x error expr/.initial=, + /pgfplots/table/y error expr/.initial=, + /pgfplots/table/z error expr/.initial=, /pgfplots/table/read completely/.is if=pgfplots@addplotimpl@readcompletely, /pgfplots/table/read completely/.default=true, /pgfplots/table/disable rowcol styles/.is if=pgfplotstable@disable@rowcolstyles, @@ -152,12 +168,59 @@ \endgroup }% }, + % #1: colname + /pgfplots/table/unique/.code={% + \pgfkeys{/pgfplots/table/row predicate/.append code={% + \ifnum\pgfplotstablerow=0 + \ifnum\pgfplotstablecol=0 + % PREPARE ONCE! Assemble the boolean results into + % a list which is used for the complete table: + \expandafter\pgfplotstablegetcolumnfromstruct\expandafter{\expandafter\pgfplotstablecolname\expandafter}\expandafter\of\pgfplotstablename\to\pgfplotstable@unique@col + \pgfplotslistnewempty\pgfplotstable@unique@bitlist + \let\pgfplotstable@unique@LAST=\relax + \pgfplotslistforeachungrouped\pgfplotstable@unique@col\as\pgfplotstable@unique@cur{% + \def\pgfplotstable@unique@bit{1}% + \ifx\pgfplotstable@unique@LAST\relax + \else + \ifx\pgfplotstable@unique@LAST\pgfplotstable@unique@cur + \def\pgfplotstable@unique@bit{0}% + \fi + \fi + \expandafter\pgfplotslistpushback\pgfplotstable@unique@bit\to\pgfplotstable@unique@bitlist + \let\pgfplotstable@unique@LAST=\pgfplotstable@unique@cur + }% + \global\let\pgfplotstable@unique@bitlist@backup=\pgfplotstable@unique@bitlist + \else + \ifx\pgfplotstable@unique@bitlist@backup\relax + % this sanity checking is NOT fool proof: it + % fails if there are different occurances of + % unique in the same file + \pgfplotstable@error{Sorry, the row predicate /pgfplots/table/unique={#1} has been used in the wrong context: it needs to be invoked for the very first processed column, not column no \pgfplotstablecol. Please provide it as argument to \string\pgfplotstabletypeset[unique={#1}] and not inside of column-specific styles.}% + \fi + \fi + % acquire the assembled list here: we'll do a lot of + % popfronts with it. + \let\pgfplotstable@unique@bitlist=\pgfplotstable@unique@bitlist@backup + \fi + \pgfplotslistcheckempty\pgfplotstable@unique@bitlist + \ifpgfplotslistempty + % should not happen! + \pgfplotstableuserowfalse + \else + \pgfplotslistpopfront\pgfplotstable@unique@bitlist\to\pgfplots@loc@TMPa + \if\pgfplots@loc@TMPa0% + \pgfplotstableuserowfalse + \fi + \fi + }}% + },% /pgfplots/table/col sep/.is choice, /pgfplots/table/col sep/space/.code = {\def\pgfplotstableread@COLSEP@CASE{0}}, /pgfplots/table/col sep/comma/.code = {\def\pgfplotstableread@COLSEP@CASE{1}}, /pgfplots/table/col sep/semicolon/.code = {\def\pgfplotstableread@COLSEP@CASE{2}}, /pgfplots/table/col sep/colon/.code = {\def\pgfplotstableread@COLSEP@CASE{3}}, /pgfplots/table/col sep/braces/.code = {\def\pgfplotstableread@COLSEP@CASE{4}}, + /pgfplots/table/col sep/tab/.code = {\def\pgfplotstableread@COLSEP@CASE{5}}, /pgfplots/table/col sep=space, % columns={name1,name2} % or @@ -192,62 +255,113 @@ /pgfplots/table/multicolumn names/.default=c, /pgfplots/table/dec sep align/.code={% \pgfplots@assert@LaTeX@package@loaded{array}{dec sep align}% + \def\pgfplotstable@scisepalign@headeralign{#1}% \pgfkeysalso{% - /pgf/number format/assume math mode, - /pgf/number format/@dec sep mark={$&$}, - /pgfplots/table/assign column name/.code={% - \pgfkeyssetvalue{/pgfplots/table/column name}{\multicolumn{2}{#1}{##1}}% - },% - /pgfplots/table/column type={% - r<{\pgfplotstableresetcolortbloverhangright}% - @{}% - l<{\pgfplotstableresetcolortbloverhangleft}% - }, - /pgfplots/table/assign cell content/.code={% - \def\pgfmathresult{##1}% - \ifx\pgfmathresult\pgfutil@empty - \def\pgfmathresult{&}% - \else - \pgfmathprintnumberto{##1}\pgfmathresult% - % now make sure we have math mode for the single - % columns: - \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter$\pgfmathresult$}% - \fi - \pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult - }, + /pgf/number format/assume math mode, + /pgf/number format/@dec sep mark={$&$}, + /pgfplots/table/assign column name/.code={% + \pgfkeyssetvalue{/pgfplots/table/column name}{\multicolumn{2}{#1}{##1}}% + },% + /pgfplots/table/column type={% + r<{\pgfplotstableresetcolortbloverhangright}% + @{}% + l<{\pgfplotstableresetcolortbloverhangleft}% + }, + /pgfplots/table/assign cell content/.code={% + \def\pgfmathresult{##1}% + \let\continue=\pgfutil@empty + % allow special handling: + \pgfplots@invoke@pgfkeyscode{/pgfplots/table/dec sep align/process/.@cmd}{##1}% + \ifx\continue\pgfutil@empty + % nothing has changed. Processed as usual: + \ifx\pgfmathresult\pgfutil@empty + \def\pgfmathresult{&}% + \else + % -6.90000001e-01 -> \meaning\pgfmathresult = macro:->-0$&$.69 + \pgfmathprintnumberto{\pgfmathresult}\pgfmathresult% + % now make sure we have math mode for the single + % columns: + \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter$\pgfmathresult$}% + \fi + \fi + \pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult + }, }% }, /pgfplots/table/dec sep align/.default=c, - /pgfplots/table/sci sep align/.code={% - \pgfplots@assert@LaTeX@package@loaded{array}{sci sep align}% - \pgfkeysalso{% - /pgf/number format/assume math mode, - /pgf/number format/@sci exponent mark={$&$}, - /pgfplots/table/assign column name/.code={% - \pgfkeyssetvalue{/pgfplots/table/column name}{\multicolumn{2}{#1}{##1}}% - },% - /pgfplots/table/column type={% - r<{\pgfplotstableresetcolortbloverhangright}% - @{}% - l<{\pgfplotstableresetcolortbloverhangleft}% - }, - /pgfplots/table/assign cell content/.code={% - \def\pgfmathresult{##1}% + % + % A part of dec sep align which can be used to process special + % cases. + % + % #1: the unprocessed input argument. + % PRECONDITION: + % \pgfmathresult contains '#1', not more. + % \continue is empty. + % + % POSTCONDITION: + % If \continue is empty, `dec sep align' will continue just as + % if the 'process' key hadn't been invoked. + % It will, however, use the current value of \pgfmathresult. + % + % If \continue is NOT empty, for example \def\continue{0}, + % `dec sep align' assumes that \pgfmathresult contains the + % completely typeset cell, including any alignment material. + /pgfplots/table/dec sep align/process/.code=,% + /pgfplots/table/dec sep align/no unbounded/.style={% + % FIXME : this thing doesn't work as intended! It looks ugly! + /pgfplots/table/dec sep align/process/.code={% \ifx\pgfmathresult\pgfutil@empty - \def\pgfmathresult{&}% \else - \pgfmathprintnumberto{##1}\pgfmathresult% - \expandafter\pgfutil@in@\expandafter&\expandafter{\pgfmathresult}% - % now make sure we have math mode for the single - % columns: - \ifpgfutil@in@ - \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter$\pgfmathresult$}% + \pgfmathfloatparsenumber\pgfmathresult + \pgfmathfloatiffinite{\pgfmathresult}{% + % do nothing, just communicate the parsed + % \pgfmathresult + }{% + \begingroup + \t@pgfplots@toka=\expandafter{\pgfplotstable@scisepalign@headeralign}% + \t@pgfplots@tokb={\pgfkeyslet{/pgf/number format/@dec sep mark}\pgfutil@empty\pgfmathprintnumber}% + \t@pgfplots@tokc=\expandafter{\pgfmathresult}% + \xdef\pgfplotstable@glob@TMPc{% + \noexpand\multicolumn{2}{\the\t@pgfplots@toka}% + {\the\t@pgfplots@tokb{\the\t@pgfplots@tokc}}% + }% + \endgroup + \let\pgfmathresult=\pgfplotstable@glob@TMPc + \def\continue{0}% + }% + \fi + },% + },% + /pgfplots/table/sci sep align/.code={% + \pgfplots@assert@LaTeX@package@loaded{array}{sci sep align}% + \pgfkeysalso{% + /pgf/number format/assume math mode, + /pgf/number format/@sci exponent mark={$&$}, + /pgfplots/table/assign column name/.code={% + \pgfkeyssetvalue{/pgfplots/table/column name}{\multicolumn{2}{#1}{##1}}% + },% + /pgfplots/table/column type={% + r<{\pgfplotstableresetcolortbloverhangright}% + @{}% + l<{\pgfplotstableresetcolortbloverhangleft}% + }, + /pgfplots/table/assign cell content/.code={% + \def\pgfmathresult{##1}% + \ifx\pgfmathresult\pgfutil@empty + \def\pgfmathresult{&}% \else - \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter\pgfutilensuremath\expandafter{\pgfmathresult}&}% + \pgfmathprintnumberto{##1}\pgfmathresult% + \expandafter\pgfutil@in@\expandafter&\expandafter{\pgfmathresult}% + % now make sure we have math mode for the single + % columns: + \ifpgfutil@in@ + \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter$\pgfmathresult$}% + \else + \expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter\pgfutilensuremath\expandafter{\pgfmathresult}&}% + \fi \fi - \fi - \pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult - }, + \pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult + }, }% }, /pgfplots/table/sci sep align/.default=c, @@ -374,6 +488,28 @@ \fi } }, + /pgfplots/table/preproc/expr/.code={% + \ifpgfplots@usefpu + \pgfkeysalso{/pgf/fpu=true,/pgf/fpu/output format=sci}% + \fi + \expandafter\def\csname pgfplotstable@preproc@expr@thisrow@\pgfplotstablecolname\endcsname{\pgfkeysvalueof{/pgfplots/table/@cell content}}% + \def\thisrow##1{% + \pgfutil@ifundefined{pgfplotstable@preproc@expr@thisrow@##1}{% + --inaccessable--% + }{% + \csname pgfplotstable@preproc@expr@thisrow@##1\endcsname + }% + }% + \pgfkeysalso{/pgfplots/table/preproc cell content/.append code={% + \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult + \ifx\pgfmathresult\pgfutil@empty + \else + \pgfmathparse{#1}% + \pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult% + \fi + }% + }% + }, /pgfplots/table/multiply -1/.style={% /pgfplots/table/preproc cell content/.append code={% \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult @@ -437,12 +573,33 @@ \fi }% }, + /pgfplots/table/fonts by sign/.style 2 args={% + /pgfplots/table/postproc cell content/.append code={% + \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfplotsretval + \ifx\pgfplotsretval\pgfutil@empty + \else + \t@pgfplots@toka=\expandafter{\pgfplotsretval}% + \t@pgfplots@tokb={#1}% + \t@pgfplots@tokc={#2}% + \pgfmathfloatparsenumber{\pgfkeysvalueof{/pgfplots/table/@preprocessed cell content}}% + \pgfmathfloatifflags{\pgfmathresult}{-}{% + \edef\pgfmathresult{{\the\t@pgfplots@tokc{\the\t@pgfplots@toka}}}% + }{% + \edef\pgfmathresult{{\the\t@pgfplots@tokb{\the\t@pgfplots@toka}}}% + }% + \pgfkeyslet{/pgfplots/table/@cell content}{\pgfmathresult}% + \fi + }% + },% % /pgfplots/table/font/.initial=, - /pgfplots/table/.unknown/.code={% - \let\pgfplots@table@curkeyname=\pgfkeyscurrentname - \pgfqkeys{/pgf/number format}{\pgfplots@table@curkeyname=#1}% - },% + /pgfplots/table/.search also={/pgf/number format,/pgfplots/table/create col}, + %-------------------------------------------------- + % /pgfplots/table/.unknown/.code={% + % \let\pgfplots@table@curkeyname=\pgfkeyscurrentname + % \pgfqkeys{/pgf/number format}{\pgfplots@table@curkeyname=#1}% + % },% + %-------------------------------------------------- /pgfplots/table/create col/assign first/.style={ /pgfplots/table/create col/assign% }, @@ -487,15 +644,7 @@ /pgfplots/table/create col/expr accum={#1}{0}% },% /pgfplots/table/create col/copy column from table/.code 2 args={% - \pgfplotstable@isloadedtable{#1}{% - \pgfplotstablegetcolumnbyname{#2}\of#1\to\pgfmathaccumb - }{% - \begingroup - \pgfplotstableread{#1}\pgfplotstable@tmptbl - \pgfplotstablegetcolumnbyname{#2}\of\pgfplotstable@tmptbl\to\pgfmathaccumb - \pgfmath@smuggleone\pgfmathaccumb - \endgroup - }% + \pgfplotstablegetcolumn{#2}\of{#1}\to\pgfmathaccumb \pgfkeysalso{/pgfplots/table/create col/@from list struct=\pgfmathaccumb}% }, /pgfplots/table/create col/@from list struct/.code={% @@ -682,12 +831,8 @@ /pgfplots/table/create col/gradient semilogx/.style 2 args={% /pgfplots/table/columns={#1,#2}, /pgfplots/table/create col/assign first/.code={% - \pgfmathlog{\thisrow{#1}}% - \ifx\pgfmathresult\pgfutil@empty - \pgfmathfloatcreate{3}{0.0}{0}% - \else - \expandafter\pgfmathfloatqparsenumber\expandafter{\pgfmathresult}% - \fi + \pgfmathfloatparsenumber{\thisrow{#1}} + \pgfmathfloatln@{\pgfmathresult}% \let\pgfmathaccuma=\pgfmathresult \pgfmathfloatparsenumber{\thisrow{#2}}% \let\pgfmathaccumb=\pgfmathresult @@ -697,12 +842,8 @@ /pgfplots/table/create col/assign/.code={% \let\pgfmathcur@x=\pgfmathaccuma \let\pgfmathcur@y=\pgfmathaccumb - \pgfmathlog{\thisrow{#1}}% - \ifx\pgfmathresult\pgfutil@empty - \pgfmathfloatcreate{3}{0.0}{0}% - \else - \expandafter\pgfmathfloatqparsenumber\expandafter{\pgfmathresult}% - \fi + \pgfmathfloatparsenumber{\thisrow{#1}} + \pgfmathfloatln@{\pgfmathresult}% \let\pgfmathnext@x=\pgfmathresult \let\pgfmathaccuma=\pgfmathresult % @@ -727,12 +868,8 @@ /pgfplots/table/create col/assign first/.code={% \pgfmathfloatparsenumber{\thisrow{#1}}% \let\pgfmathaccuma=\pgfmathresult - \pgfmathlog{\thisrow{#2}}% - \ifx\pgfmathresult\pgfutil@empty - \pgfmathfloatcreate{3}{0.0}{0}% - \else - \expandafter\pgfmathfloatqparsenumber\expandafter{\pgfmathresult}% - \fi + \pgfmathfloatparsenumber{\thisrow{#2}} + \pgfmathfloatln@{\pgfmathresult}% \let\pgfmathaccumb=\pgfmathresult \def\pgfmathresult{}% leave first empty. \pgfkeyslet{/pgfplots/table/create col/next content}\pgfmathresult% @@ -740,12 +877,8 @@ /pgfplots/table/create col/assign/.code={% \let\pgfmathcur@x=\pgfmathaccuma \let\pgfmathcur@y=\pgfmathaccumb - \pgfmathlog{\thisrow{#2}}% - \ifx\pgfmathresult\pgfutil@empty - \pgfmathfloatcreate{3}{0.0}{0}% - \else - \expandafter\pgfmathfloatparsenumber\expandafter{\pgfmathresult}% - \fi + \pgfmathfloatparsenumber{\thisrow{#2}} + \pgfmathfloatln@{\pgfmathresult}% \let\pgfmathnext@y=\pgfmathresult \let\pgfmathaccumb=\pgfmathresult % @@ -784,8 +917,21 @@ /pgfplots/table/every first row/.code=, /pgfplots/table/every last row/.code=, }, + /pgfplots/table/colnames from/.initial=,% for \pgfplotstabletranspose + /pgfplots/table/input colnames to/.initial=colnames,% for \pgfplotstabletranspose +} +\pgfkeys{ + % #1: the argument which should have been assigned. + % #2: an error message. + /pgfplots/exception/non unique colname/.code 2 args={% + \ifx\pgfplotsexceptionmsg\relax + \pgfplots@error{#2}% + \else + \pgfplots@error{\pgfplotsexceptionmsg}% + \fi + \let#1=\pgfutil@empty + },% } - % 'function graph cut y'={<epsilon>}{<options>}{comma-separated-list of specs where to get yi} % % fills the column with x1,...,xN such that yi(xi) == epsilon where @@ -810,6 +956,8 @@ /pgfplots/table/create col/function graph cut/x/.initial=, /pgfplots/table/create col/function graph cut/y/.initial=, /pgfplots/table/create col/function graph cut/table/.initial=, + % foreach={\d in {1,2,3,4}}{{table\d}} + /pgfplots/table/create col/function graph cut/foreach/.initial=, } @@ -878,9 +1026,45 @@ % following methods can be used to query values: % \pgfplotstablereadgetcolindex{<index>}{<\macro>} % \pgfplotstablereadgetcolname{<name>}{<\macro>} +% \pgfplotstablereadvalueofcolname{<name>} +% \pgfplotstablereadvalueofcolindex{<index>} +% \thisrow{<name>} (equivalent to \pgfplotstablereadvalueofcolname) +% \getthisrow{<name>}{<\macro>} (equivalent to \pgfplotstablereadgetcolname) +% \thisrowno{<index>} (equivalent to \pgfplotstablereadvalueofcolindex) +% \getthisrowno{<index>}{<\macro>} +% \pgfplotstableforeachcolumn\as{<\iteratemacro>}{<loop body>} +% (the '\as' is required directly after +% \pgfplotstableforeachcolumn in this context) % Attention: 'to listener' is scoped by TeX groups, so any assignments % need to be done globally (or with aftergroup magic). +% +% More remarks about scoping: +% \pgfplotstableread to listener works as follows: +% \begingroup +% // load table +% while file has more lines: +% load line, read every column; +% invoke listener; +% repeat +% \endgroup +% +% In short: all invocations of listener have the same level of +% scoping: they are inside of one TeX group. But single listener +% invocations as such are not scoped. Make sure you don't +% accidentally overwrite one of the internals in listener. And: make +% sure you don't change temporary registers without scoping them! +% +% Note: this command also updates \pgfplotsscanlinelength. \def\pgfplotstableread{% + \pgfutil@ifnextchar*{% + \pgfplots@tableread@use@begingroupfalse + \pgfplotstableread@impl@star + }{% + \pgfplots@tableread@use@begingrouptrue + \pgfplotstableread@impl@star*% + }% +}% +\def\pgfplotstableread@impl@star*{% \pgfutil@ifnextchar[{% \pgfplotstableread@impl }{% @@ -893,7 +1077,7 @@ % Invokes #2 if '#1' is an already loaded table and #3 if not. \long\def\pgfplotstable@isloadedtable#1#2#3{% - \pgfutil@ifundefined{\string#1@@table@name}{#3}{#2}% + \pgfplotsutil@ifdefinedui@withsuffix{#1}{@@table@name}{#2}{#3}% }% % Defines \pgfmathresult to be the number of rows in table #1. @@ -928,47 +1112,49 @@ }% } -{ -\catcode`\^^I=12 -\gdef\pgfplotstablesave@impl@TAB{^^I} -} - \def\pgfplotstablesave@impl[#1]#2#3{% \pgfplotstabletypeset[% reset styles,% disable rowcol styles,% - begin table={}, end table={},% + begin table={},% + end table={},% typeset cell/.code={% \begingroup \t@pgfplots@toka={##1}% \ifcase\pgfplotstableread@OUTCOLSEP@CASE\relax - % SPACE: - \t@pgfplots@tokb=\expandafter{\pgfplotstablesave@impl@TAB}% + % col sep=SPACE: + \t@pgfplots@tokb=\expandafter{\pgfplotstableread@tab}% \pgfplots@ifempty{##1}{% \t@pgfplots@toka={{}}% }{}% \xdef\pgfplots@glob@TMPc{\the\t@pgfplots@toka\the\t@pgfplots@tokb}% \or - % comma: + % col sep=comma: \t@pgfplots@tokb={,}% \xdef\pgfplots@glob@TMPc{\the\t@pgfplots@toka\the\t@pgfplots@tokb}% \or - % semicolon: + % col sep=semicolon: \t@pgfplots@tokb={;}% \xdef\pgfplots@glob@TMPc{\the\t@pgfplots@toka\the\t@pgfplots@tokb}% \or - % colon: + % col sep=colon: \t@pgfplots@tokb={:}% \xdef\pgfplots@glob@TMPc{\the\t@pgfplots@toka\the\t@pgfplots@tokb}% \or - % braces: + % col sep=braces: \xdef\pgfplots@glob@TMPc{{\the\t@pgfplots@toka}}% + \or + % col sep=tab: + \xdef\pgfplots@glob@TMPc{\the\t@pgfplots@toka\pgfplotstableread@tab}% \fi \endgroup \pgfkeyslet{/pgfplots/table/@cell content}\pgfplots@glob@TMPc% },% - before row=,after row=,% - skip coltypes, typeset=false, string type,% + before row=,% + after row=,% + skip coltypes,% + typeset=false,% + string type,% TeX comment=,% columns=,% font=,% @@ -978,6 +1164,7 @@ /pgfplots/table/col sep/semicolon/.code = {\def\pgfplotstableread@OUTCOLSEP@CASE{2}},% /pgfplots/table/col sep/colon/.code = {\def\pgfplotstableread@OUTCOLSEP@CASE{3}},% /pgfplots/table/col sep/braces/.code = {\def\pgfplotstableread@OUTCOLSEP@CASE{4}},% + /pgfplots/table/col sep/tab/.code = {\def\pgfplotstableread@OUTCOLSEP@CASE{5}},% /pgfplots/table/col sep=space,% /pgfplots/table/in col sep/.is choice,% /pgfplots/table/in col sep/space/.code = {\def\pgfplotstableread@COLSEP@CASE{0}},% @@ -985,6 +1172,7 @@ /pgfplots/table/in col sep/semicolon/.code = {\def\pgfplotstableread@COLSEP@CASE{2}},% /pgfplots/table/in col sep/colon/.code = {\def\pgfplotstableread@COLSEP@CASE{3}},% /pgfplots/table/in col sep/braces/.code = {\def\pgfplotstableread@COLSEP@CASE{4}},% + /pgfplots/table/in col sep/tab/.code = {\def\pgfplotstableread@COLSEP@CASE{5}},% /pgfplots/table/in col sep=space,% % WARNING: you NEED a '%' before '#1': #1,% @@ -992,27 +1180,38 @@ ]{#2}% }% +% clears the table. +\def\pgfplotstableclear#1{% + \let#1=\relax + \expandafter\let\csname \string#1@@table@name\endcsname=\relax +}% + + % \pgfplotstablenew[<options>]{<numrows>}{<\name>} +% \pgfplotstablenew*[<options>]{<numrows>}{<\name>} % % Creates a new table from scratch. % % The new table will contain all columns listed in the 'columns' key -% which must be present in <options>. +% which must be present in <options>. The starred version +% \pgfplotstablenew* is not that strict: it will use the current value +% of the columns key (not matter where and when it has been set). % % Furthermore, there must be 'create on use' statements for every % column which shall be generated. Columns are generated % independently, in the order of appearance in 'columns'. % The table will contain exactly <numrows> rows. \def\pgfplotstablenew{% - \pgfutil@ifnextchar[{% - \pgfplotstablenew@impl - }{% - \pgfplotstablenew@impl[]% - }% -}% -\def\pgfplotstablenew@impl[#1]#2#3{% - \pgfutil@namedef{\string#3@@table@name}{newlycreatedtable}% \begingroup + \pgfutil@ifnextchar*{\pgfplotstablenew@star}{\pgfplotstablenew@nostar}} +\def\pgfplotstablenew@star*{\pgfutil@ifnextchar[{\pgfplotstablenew@impl}{\pgfplotstablenew@impl[]}}% +\def\pgfplotstablenew@nostar{% + % reset columns key: + \pgfkeyslet{/pgfplots/table/columns}{\pgfutil@empty}% + \pgfutil@ifnextchar[{\pgfplotstablenew@impl}{\pgfplotstablenew@impl[]}} + +\def\pgfplotstablenew@impl[#1]#2#3{% + \pgfplotsscanlinelengthinitzero % create a temporary column with the desired number of rows: \pgfutil@in@\pgfplotstablegetrowsof{#2}% \ifpgfutil@in@ @@ -1025,8 +1224,11 @@ \expandafter\pgfplots@assign@list\csname\string#3@@@@@@temporary@column@\endcsname{1,2,...,\pgfplotstable@loc@TMPa}% % % now, create all real columns: - \pgfkeyslet{/pgfplots/table/columns}{\pgfutil@empty}% - \pgfplotstableset{#1}% + \pgfplotstableset{#1,% + /pgf/fpu/handlers/empty number/.code 2 args={% + \pgfmathfloatcreate{0}{0.0}{0}% + }% + }% \pgfkeysgetvalue{/pgfplots/table/columns}{\pgfplotstable@colnames}% \ifx\pgfplotstable@colnames\pgfutil@empty \pgfplots@warning{\string\pgfplotstablenew[columns={},...]{#2}{\string#3} has been invoked - but empty tables are currently not really supported, sorry. You will have to live with an artifical column which contains temporary values.}% @@ -1050,9 +1252,10 @@ % unsupported! \pgfplotslistpopfront#3\to\pgfplotstable@loc@TMPa \fi - \pgfplotstable@copy@to@globalbuffers#3 + \pgfplotsscanlinelengthcleanup + \pgfplotstable@copy@to@globalbuffers#3{newlycreatedtable}% \endgroup - \pgfplotstable@copy@globalbuffers@to#3 + \pgfplotstable@copy@globalbuffers@to#3% }% % \pgfplotstablevertcat{<table1>}{<table2>} @@ -1089,6 +1292,180 @@ }% } +% \pgfplotstabletranspose{<\outtable>}{<intable>} +% \pgfplotstabletranspose[<colname>]{<\outtable>}{<intable>} +% Defines <\outtable> to be the transposed of <intable>. +% +% If <colname> is not empty, the respective column's entries will be used to +% make output column names. +% +% #1: a table macro name which will be overwritten (redefined) +% #2: either a file name or a table macro (loaded table). +\def\pgfplotstabletranspose{% + \begingroup + \pgfutil@ifnextchar*{% + \pgfplotstabletranspose@star% + }{% + \pgfkeyslet{/pgfplots/table/columns}\pgfutil@empty% clear! + \pgfplotstabletranspose@star*% + }% +} +\def\pgfplotstabletranspose@star*{\pgfutil@ifnextchar[{\pgfplotstabletranspose@opt}{\pgfplotstabletranspose@opt[]}}% +\def\pgfplotstabletranspose@opt[#1]#2#3{% + \pgfplotstable@isloadedtable{#3}{% + \pgfplotstabletranspose@[#1]{#2}{#3}% + }{% + \pgfplotstableread{#3}\pgfplotstable@tmptbl + \pgfplotstabletranspose@[#1]{#2}{\pgfplotstable@tmptbl}% + }% +}% + +% Iterates through every column of table '#1' and invokes the code +% '#3' for each column. The current column name will be available as +% '#2' and the current column index as |\pgfplotstablecol| (starting +% with 0). +% +% Example: +% \pgfplotstableforeachcolumn{\table}\as\colname{% +% The column name is `\colname'; its index \pgfplotstablecol.\par +% }% +% +% REMARK: this routine does NOT introduce TeX groups. +\long\def\pgfplotstableforeachcolumn#1\as#2#3{% + \def\pgfplotstablecol{0}% + \pgfplotslistforeachungrouped#1\as#2{% + #3\relax% + \pgfplotsutil@advancestringcounter\pgfplotstablecol + }% + \let\pgfplotstablecol=\relax +}% +% A variant of \pgfplotstableforeachcolumn which is used inside of +% \pgfplotstableread to listener. +% +% It is used as \pgfplotstableforeachcolumn\as\cur{<do something with \cur>} +\long\def\pgfplotstableforeachcolumn@listener\as#1#2{% + \def\pgfplotstablecol{0}% + \pgfplotslistforeachungrouped\pgfplotstable@colnames@glob\as#1{% + #2\relax% + \pgfplotsutil@advancestringcounter\pgfplotstablecol + }% + \let\pgfplotstablecol=\relax +}% + +% Reports every element t_{ij} for a fixed column j (in read-only +% mode). +% +% For every cell, the code '#4' will be executed where '#3' will +% contain the cell's value. During code '#4', the macro +% \pgfplotstablerow will contain the current row index. +% +% #1: either a column name or the string '[index]' followed by a +% number denoting a column index Access by column name is much faster.. +% #2: the table (macro or file name) +% #3: the macro in which the cell values shall be written +% #4: the code to execute. +% +% Example: +% \pgfplotstableforeachcolumnelement{colname}\of\table\as\cellelem{% +% I have now cell element `\cellelem' at row index +% `\pgfplotstablerow'. +% \par +% } +% +% REMARK: this routine does NOT introduce TeX groups. +\long\def\pgfplotstableforeachcolumnelement#1\of#2\as#3#4{% + \def\pgfplotstablerow{0}% + \pgfplotstablegetcolumn{#1}\of{#2}\to\pgfplotstableforeachcolumnelement@list + \pgfplotslistforeachungrouped\pgfplotstableforeachcolumnelement@list\as#3{% + % allow nesting by copying the old value of \pgfplotstablerow: + \expandafter\pgfplotstableforeachcolumnelement@\expandafter{\pgfplotstablerow}{#4}% + }% + \let\pgfplotstablerow=\relax +}% +% helper method to allow nesting. It copies \pgfplotstablerow. +% #1: the expanded value of \pgfplotstablerow. +\long\def\pgfplotstableforeachcolumnelement@#1#2{% + #2\relax + \def\pgfplotstablerow{#1}% restore to old value. + % advance. + \pgfplotsutil@advancestringcounter\pgfplotstablerow +}% + +% A routine which is similar to \pgfplotstableforeachcolumnelement, +% but this here checks for changes in \pgfplotsretval and writes them +% back into the respected cell. +% +% The runtime is quadratic in the number of rows. +\long\def\pgfplotstablemodifyeachcolumnelement#1\of#2\as#3#4{% + \def\pgfplotstablerow{0}% + % + % Step 0: get the REAL column name for '#1'. + % This needs modifications if '#1' is [index]<integer>. + % -> store the colname to \pgfplotstable@loc@TMPc: + \def\pgfplotstable@loc@TMPc{#1}% + \pgfplotstable@is@colname{\pgfplotstable@loc@TMPc}%% + \ifpgfplotstableread@foundcolnames + \else + \expandafter\pgfplotstablegetcolumnnamebyindex\pgfplotstable@loc@TMPc\of{#2}\to\pgfplotstable@loc@TMPc + \fi + % Step 0.1: prepare a command which re-assembles column '#1' + % (using the real column name). + % The re-assemblation command will be invoked at the end of each + % iteration. This complicated macro preparation allows nested + % calls to \pgfplotstablemodifyeachcolumnelement. + \t@pgfplots@toka={\expandafter\pgfplotslistpushback\expandafter{#3}\to}% + \edef\pgfplotstable@loc@TMPd{% + \the\t@pgfplots@toka{\expandafter\noexpand\csname\string#2@\pgfplotstable@loc@TMPc\endcsname}}% + % Step 1: copy the column data to \pgfplotstable@loc@TMPb + \expandafter\pgfplotstablegetcolumnbyname\pgfplotstable@loc@TMPc\of#2\to\pgfplotstable@loc@TMPb% + % + % clear the original column: + \expandafter\pgfplotslistnewempty\csname\string#2@\pgfplotstable@loc@TMPc\endcsname + % + % Call loop. The prepared re-assemble macro will be provided as macro argument + % to allow nested calls: + \expandafter\pgfplotstablemodifyeachcolumnelement@\expandafter{\pgfplotstable@loc@TMPd} + {\pgfplotstable@loc@TMPb}{#3}{#4}% + \let\pgfplotstablerow=\relax +}% +% #1: post-iteration code +% #2: the row list +% #3: the loop macro to assign +% #4: the loop body +\long\def\pgfplotstablemodifyeachcolumnelement@#1#2#3#4{% + \pgfplotslistforeachungrouped{#2}\as#3{% + % allow nesting by copying the old value of \pgfplotstablerow: + \expandafter\pgfplotstableforeachcolumnelement@\expandafter{\pgfplotstablerow}{#4}% + #1% + }% +} + +% Selects a single table element at row #1 and column #2 from table +% #3. +% +% #1: a row index. +% #2: a column name or the string '[index]' followed by a number +% denoting a column index. Access by column name is much faster. +% #3: the table (macro or file name). +% +% The cell value will be written into the macro \pgfplotsretval. +% +% REMARK: +% this routine is supposed to be very slow: it needs time O(N) where N +% is the number of rows. This may change in future versions. +% +% Example: +% \pgfplotstablegetelem{0}{[index]2}\of\table +% The elem is `\pgfplotsretval'. +\def\pgfplotstablegetelem#1#2\of#3{% + \begingroup + \pgfplotstablegetcolumn{#2}\of{#3}\to\pgfplotstable@loc@TMPa + \def\pgfplotsexceptionmsg{Sorry, row `#1' does not exist in table \pgfplotstablenameof{#3}}% + \pgfplotslistselect#1\of\pgfplotstable@loc@TMPa\to\pgfplotsretval + \pgfmath@smuggleone\pgfplotsretval + \endgroup +}% + \def\pgfplotstablegetcolumnlist#1\to#2{\let#2=#1} % Returns a column vector in form of \pgfplotslist @@ -1097,6 +1474,8 @@ % #1: the column name (not a macro) % #2: the table structure % #3: the output macro name. +% +% @throw `no such element' on error \def\pgfplotstablegetcolumnbyname#1\of#2\to#3{% \pgfutil@ifundefined{\string#2@#1}{% % Oh, there is no column '#1' in table '#2'! @@ -1109,6 +1488,7 @@ % *** \pgfplotstablereadgetptrtocolname *** % *** \pgfplotstablegetcolumnbyname *** % *** \pgfplotstableresolvecolname *** + % *** \pgfplotstablereadvalueofcolname *** \def\pgfplotstable@loc@TMPa{/pgfplots/table/create on use/#1}% \pgfkeysifdefined{\pgfplotstable@loc@TMPa/.@cmd}{% % aah - a 'create on use' style exists. Apply it! @@ -1123,14 +1503,12 @@ \pgfkeysgetvalue{\pgfplotstable@loc@TMPa}{\pgfplotstable@loc@TMPb}% \let\pgfplotstable@loc@TMPa=\pgfplotstable@loc@TMPb \pgfutil@ifundefined{\string#2@\pgfplotstable@loc@TMPa}{% - \pgfplots@error{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstablenameof{#2}'. The original request was for '#1', which does not exist either.}% - \pgfplotslistnewempty#3 + \pgfplotsthrow{no such element}{#3}{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstablenameof{#2}'. The original request was for '#1', which does not exist either.}\pgfeov% }{% \expandafter\let\expandafter#3\csname\string#2@\pgfplotstable@loc@TMPa\endcsname }% }{% - \pgfplots@error{Sorry, could not retrieve column '#1' from table '\pgfplotstablenameof{#2}'. Please check spelling (or introduce name aliases).}% - \pgfplotslistnewempty#3 + \pgfplotsthrow{no such element}{#3}{Sorry, could not retrieve column '#1' from table '\pgfplotstablenameof{#2}'. Please check spelling (or introduce name aliases).}\pgfeov% }% }% }{% @@ -1161,6 +1539,7 @@ % *** \pgfplotstablereadgetptrtocolname *** % *** \pgfplotstablegetcolumnbyname *** % *** \pgfplotstableresolvecolname *** + % *** \pgfplotstablereadvalueofcolname *** \def\pgfplotstable@loc@TMPa{/pgfplots/table/alias/#1}% \pgfkeysifdefined{\pgfplotstable@loc@TMPa}{% \pgfkeysgetvalue{\pgfplotstable@loc@TMPa}{\pgfplotstable@loc@TMPb}% @@ -1168,17 +1547,15 @@ \pgfutil@ifundefined{\string#2@\pgfplotstable@loc@TMPa}{% \def\pgfplotstable@loc@TMPb{/pgfplots/table/create on use/#1}% \pgfkeysifdefined{\pgfplotstable@loc@TMPb/.@cmd}{% - \pgfplots@error{Sorry, '\pgfplotstable@loc@TMPb' from table '\pgfplotstableread@filename' can't be evaluated in this context. Please prepare the table before using it here. You can do this using the 'read completely' key, see the manual for details.}% + \pgfplotstable@error{Sorry, '\pgfplotstable@loc@TMPb' from table '\pgfplotstableread@filename' can't be evaluated in this context. Please prepare the table before using it here. You can do this using the 'read completely' key, see the manual for details.}% }{% - \pgfplots@error{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstablenameof{#2}'. The original request was for '#1', which does not exist either.}% + \pgfplotsthrow{no such element}{#3}{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstablenameof{#2}'. The original request was for '#1', which does not exist either.}\pgfeov% }% - \let#3=\pgfutil@empty }{% \let#3=\pgfplotstable@loc@TMPa }% }{% - \pgfplots@error{Sorry, could not retrieve column '#1' from table '\pgfplotstablenameof{#2}'. Please check spelling (or introduce name aliases).}% - \let#3=\pgfutil@empty + \pgfplotsthrow{no such element}{#3}{Sorry, could not retrieve column '#1' from table '\pgfplotstablenameof{#2}'. Please check spelling (or introduce name aliases).}\pgfeov% }% }{% \def#3{#1}% @@ -1187,13 +1564,31 @@ % Invokes either \pgfplotstablegetcolumnbyindex or % \pgfplotstablegetcolumnbyname. +% +% #1: either a column name, alias or create on use specification, or +% [index]<integer> denoting a column index. +% #2: either a loaded table or a table macro. +% #3: a macro name which will be filled with the column, in the format +% accepted of \pgfplotslist... \def\pgfplotstablegetcolumn#1\of#2\to#3{% - \pgfplotstable@is@colname{#1}% + \begingroup + \pgfplotstable@isloadedtable{#2}{% + \pgfplotstablegetcolumnfromstruct{#1}\of{#2}\to{#3}% + }{% + \pgfplotstableread{#2}\pgfplotstable@tmptbl + \pgfplotstablegetcolumnfromstruct{#1}\of\pgfplotstable@tmptbl\to{#3}% + }% + \pgfmath@smuggleone#3% + \endgroup +}% +\def\pgfplotstablegetcolumnfromstruct#1\of#2\to#3{% + \def\pgfplotstable@loc@TMPc{#1}% + \pgfplotstable@is@colname{\pgfplotstable@loc@TMPc}%% \ifpgfplotstableread@foundcolnames \else - \pgfplotstablegetcolumnnamebyindex{#1}\of{#2}\to{#3} + \expandafter\pgfplotstablegetcolumnnamebyindex\pgfplotstable@loc@TMPc\of{#2}\to\pgfplotstable@loc@TMPc \fi - \pgfplotstablegetcolumnbyname{#1}\of#2\to{#3}% + \expandafter\pgfplotstablegetcolumnbyname\pgfplotstable@loc@TMPc\of#2\to{#3}% }% \def\pgfplotstablegetcolumnnamebyindex#1\of#2\to#3{% @@ -1208,6 +1603,7 @@ \let#2=#1% \pgfplotstablegetname#1\pgfplotstable@loc@TMPa \expandafter\let\csname\string#2@@table@name\endcsname=\pgfplotstable@loc@TMPa + \expandafter\edef\csname\string#2@@table@scanline\endcsname{\pgfplotstablescanlinelengthof{#1}}% \pgfplotslistforeachungrouped#1\as\pgfplotstable@loc@TMPa{% \def\pgfplotstable@loc@TMPb{% \expandafter\let\csname\string#2@\pgfplotstable@loc@TMPa\endcsname}% @@ -1225,6 +1621,15 @@ \csname\string#1@@table@name\endcsname } +% Returns the value of \pgfplotsscanlinelength for table '#1' into +% macro #2. +\def\pgfplotstablegetscanlinelength#1#2{% + \expandafter\let\expandafter#2\csname\string#1@@table@scanline\endcsname +}% + +% Expands to the scan line length of table '#1'. +\def\pgfplotstablescanlinelengthof#1{\csname\string#1@@table@scanline\endcsname}% + % Creates a new column named #1 and appends it to table #2. % % The column entries will be created using the command keys @@ -1275,9 +1680,10 @@ % % You will need to reconfigure the tables. % -% Inside of \pgfplotstabletypeset, the macros \pgfplotstablecol and -% \pgfplotstablerow will expand to the current column index and row -% index. +% Inside of \pgfplotstabletypeset, the macros +% \pgfplotstablecol,\pgfplotstablecolname and +% \pgfplotstablerow will expand to the current column index, column +% name and row index, respectively. \def\pgfplotstabletypeset{% \pgfutil@ifnextchar[{% \pgfplotstabletypeset@opt @@ -1309,12 +1715,12 @@ \pgfkeysgetvalue{/pgfplots/table/outfile}\pgfplotstable@outfilename \ifx\pgfplotstable@outfilename\pgfutil@empty \else - \openin1=\pgfplotstable@outfilename\relax - \ifeof1 + \openin\r@pgfplots@reada=\pgfplotstable@outfilename\relax + \ifeof\r@pgfplots@reada \else \pgfplotstabletypeset@includeoutfilestrue \fi - \closein1 + \closein\r@pgfplots@reada \fi \fi \fi @@ -1322,7 +1728,11 @@ \input \pgfplotstable@outfilename\relax \else \pgfplotstableread{#2}\pgfplotstabletypesetfile@opt@@ - \pgfplotstabletypeset\pgfplotstabletypesetfile@opt@@ + \ifx\pgfplotstabletypesetfile@opt@@\relax + % ERROR. + \else + \pgfplotstabletypeset\pgfplotstabletypesetfile@opt@@ + \fi \fi \pgfkeysgetvalue{/pgfplots/table/write to macro}\pgfplots@loc@TMPa \ifx\pgfplots@loc@TMPa\pgfutil@empty @@ -1377,68 +1787,125 @@ }% \def\pgfplotstableread@impl@#1#2#3{% + \ifpgfplots@tableread@use@begingroup \begingroup - \ifpgfplots@table@options@areset - \else - \pgfplotstableset{/pgfplots/table/every table={#2},#1}% \fi %\pgfplots@message{ATTEMPTING TO READ #2}% - \openin1=#2.tex - \ifeof1 - \openin1=#2\relax + \openin\r@pgfplots@reada=#2.tex + \ifeof\r@pgfplots@reada + \openin\r@pgfplots@reada=#2\relax \else \pgfplots@warning{% You requested to open table '#2', but there is also a '#2.tex'. TeX will automatically append the suffix '.tex', so I will now open '#2.tex'. Please make sure you don't accidentally load TeX files - this may produce unrecoverable errors.}% - \closein1 - \openin1=#2\relax + \closein\r@pgfplots@reada + \openin\r@pgfplots@reada=#2\relax \fi \pgfplots@logfileopen{#2}% - \def\pgfplotstableread@filename{#2}% - \let\pgfplotstableread@lineno=\c@pgf@counta - \let\pgfplotstableread@numcols=\c@pgf@countb - \let\pgfplotstableread@curcol=\c@pgf@countc - \let\pgfplotstableread@usablelineno=\c@pgf@countd - \pgfplotstableread@lineno=0 - \pgfplotstableread@usablelineno=0 - \pgfplotstableread@numcols=0 - \global\pgfplotslistnewempty\pgfplotstable@colnames@glob - \ifeof1 - \pgfplotstable@error{Could not read table file '#2'.}% - \global\pgfplotslistnewempty\pgfplotstable@colnames@glob + % + \edef\pgfplotstableread@oldendlinechar{\the\endlinechar}% + \endlinechar=-1 % do not append a white space after each line + % + \pgfplotstableread@impl@prepare{#1}{#2}{#3}% + \ifeof\r@pgfplots@reada + \pgfplotsthrow{no such table file}{\pgfplots@loc@TMPa}{#2}{Could not read table file '#2'.}\pgfeov% + \global\let\pgfplotstable@colnames@glob=\pgfplots@loc@TMPa \else - \ifpgfplots@tableread@to@listener - \let\pgfplotstable@listener=#3% - \let\pgfplotstableread@impl@nextrow@NEXT=\pgfplotstableread@impl@nextrow@NEXT@listener - \let\pgfplotstablereadgetcolindex=\pgfplotstablereadgetcolindex@ - \let\pgfplotstablereadgetcolname=\pgfplotstablereadgetcolname@ - \let\pgfplotstablereadgetptrtocolname=\pgfplotstablereadgetptrtocolname@ - \let\pgfplotstablereadgetptrtocolindex=\pgfplotstablereadgetptrtocolindex@ - \let\pgfplotstablereadevalptr=\pgfplotstablereadevalptr@ - \fi % \pgfplotstableread@loop@over@lines - \closein1 + % + \closein\r@pgfplots@reada % \pgfplotstableread@finish \fi + \endlinechar=\pgfplotstableread@oldendlinechar + \pgfplotsscanlinelengthcleanup + \pgfplotstable@copy@to@globalbuffers@simple{#2}% + \ifpgfplots@tableread@use@begingroup \endgroup + \fi \ifpgfplots@tableread@to@listener % there are no data structures in this case. + \let\pgfplotsscanlinelength=\pgfplotstable@glob@buf@scanline \else % Now, we can access the global variables! % copy them to #3. - \expandafter\def\csname\string#3@@table@name\endcsname{#2}% - \pgfplotstable@copy@globalbuffers@to#3 + \pgfplotstable@copy@globalbuffers@to#3% \fi } +% #1: any options to set (respect \ifpgfplots@table@options@areset ) +% #2: the file name +% #3: the output macro (or listener) +\def\pgfplotstableread@impl@prepare#1#2#3{% + \ifpgfplots@table@options@areset + \else + \pgfplotstableset{/pgfplots/table/every table={#2},#1}% + \fi + \def\pgfplotstableread@filename{#2}% + % + % local counter definitions: + \ifpgfplots@tableread@use@begingroup + \let\pgfplotstableread@lineno=\c@pgf@counta + \let\pgfplotstableread@numcols=\c@pgf@countb + \let\pgfplotstableread@curcol=\c@pgf@countc + \let\pgfplotstableread@usablelineno=\c@pgf@countd + \def\thepgfplotstableread@lineno{\the\pgfplotstableread@lineno}% + \def\thepgfplotstableread@usablelineno{\the\pgfplotstableread@usablelineno}% + \def\thepgfplotstableread@curcol{\the\pgfplotstableread@curcol}% + \def\thepgfplotstableread@numcols{\the\pgfplotstableread@numcols}% + \def\pgfplotstableread@countreset##1{##1=0 }% + \def\pgfplotstableread@countset##1##2{##1=##2 }% + \def\pgfplotstableread@countadvance##1{\advance##1 by1 }% + \else + % don't re-use integers! We have no protecting scopes! + \def\thepgfplotstableread@lineno{\pgfplotstableread@lineno}% + \def\thepgfplotstableread@usablelineno{\pgfplotstableread@usablelineno}% + \def\thepgfplotstableread@curcol{\pgfplotstableread@curcol}% + \def\thepgfplotstableread@numcols{\pgfplotstableread@numcols}% + \def\pgfplotstableread@countreset##1{\def##1{0}}% + \def\pgfplotstableread@countset##1##2{\def##1{##2}}% + \def\pgfplotstableread@countadvance##1{\pgfplotsutil@advancestringcounter{##1}}% + \fi + \pgfplotstableread@countreset\pgfplotstableread@lineno + \pgfplotstableread@countreset\pgfplotstableread@usablelineno + \pgfplotstableread@countreset\pgfplotstableread@numcols + \pgfplotstableread@countreset\pgfplotstableread@curcol + % + \pgfplotstableread@impl@prepare@DO + \def\pgfplotstableread@isgnuplotformat{0}% + \global\pgfplotslistnewempty\pgfplotstable@colnames@glob + \pgfplotsscanlinelengthinitzero + \ifpgfplots@tableread@to@listener + \def\pgfplotstablerow{\thepgfplotstableread@usablelineno}% + \def\pgfplotstablelineno{\thepgfplotstableread@lineno}% + \let\pgfplotstable@listener=#3% + \let\pgfplotstableread@impl@nextrow@NEXT=\pgfplotstableread@impl@nextrow@NEXT@listener + \let\pgfplotstablereadgetcolindex=\pgfplotstablereadgetcolindex@ + \let\pgfplotstablereadgetcolname=\pgfplotstablereadgetcolname@ + \let\pgfplotstablereadgetptrtocolname=\pgfplotstablereadgetptrtocolname@ + \let\pgfplotstablereadgetptrtocolindex=\pgfplotstablereadgetptrtocolindex@ + \let\pgfplotstablereadevalptr=\pgfplotstablereadevalptr@ + \let\pgfplotstablereadvalueofptr=\pgfplotstablereadvalueofptr@ + \let\pgfplotstableforeachcolumn=\pgfplotstableforeachcolumn@listener + \let\pgfplotstablereadvalueofcolname=\pgfplotstablereadvalueofcolname@ + \let\pgfplotstablereadvalueofcolindex=\pgfplotstablereadvalueofcolindex@ + \let\getthisrow=\pgfplotstablereadgetcolname + \let\thisrow=\pgfplotstablereadvalueofcolname + \let\thisrowno=\pgfplotstablereadvalueofcolindex + \let\getthisrowno=\pgfplotstablereadgetcolindex + \fi +}% + % Copies the table column list and the column vectors of #1 to global buffers. % @see \pgfplotstable@copy@globalbuffers@to % % Use these two methods to avoid scoping problems. -\def\pgfplotstable@copy@to@globalbuffers#1{% +% +% #1: the <\macro> name of the table which is to be copied to global buffers. +% #2: the table file name. +\def\pgfplotstable@copy@to@globalbuffers#1#2{% \global\let\pgfplotstable@colnames@glob=#1 \c@pgfplotstable@counta=0\relax% \pgfplotslistforeachungrouped\pgfplotstable@colnames@glob\as\pgfplotstable@loc@TMPa{% @@ -1448,11 +1915,29 @@ \expandafter\pgfplotstable@loc@TMPb\csname\string#1@\pgfplotstable@loc@TMPa\endcsname \advance\c@pgfplotstable@counta by1\relax }% + \pgfplotstable@copy@to@globalbuffers@simple{#2}% +}% +% A variant of \pgfplotstable@copy@to@globalbuffers which copies only +% the member variables of a loaded table (the name and scanline length) to +% global buffers. +% +% #1: the table's file name. +% +% @PRECONDITION: any other variables and cell data of the table are already stored +% in global buffers. +\def\pgfplotstable@copy@to@globalbuffers@simple#1{% + \gdef\pgfplotstable@glob@buf@name{#1}% + \global\let\pgfplotstable@glob@buf@scanline=\pgfplotsscanlinelength }% % copies the global column list and the global column vectors to #1 % (NOT the table file name). % @see \pgfplotstable@copy@to@globalbuffers +% +% @PRECONDITION the global buffers contain all members of a table. +% +% @POSTCONDITION The table '#1' is be initialised to these members. +% Furthermore, \pgfplotsscanlinelength is set. \def\pgfplotstable@copy@globalbuffers@to#1{% \let#1=\pgfplotstable@colnames@glob \c@pgfplotstable@counta=0\relax% @@ -1465,108 +1950,124 @@ \advance\c@pgfplotstable@counta by1\relax }% \global\let\pgfplotstable@colnames@glob=\pgfutil@empty + \expandafter\let\csname\string#1@@table@scanline\endcsname=\pgfplotstable@glob@buf@scanline + \expandafter\let\csname\string#1@@table@name\endcsname=\pgfplotstable@glob@buf@name + \let\pgfplotsscanlinelength=\pgfplotstable@glob@buf@scanline }% \def\pgfplotstableread@finish{% + \pgfplotsscanlinecomplete \ifpgfplots@tableread@to@listener \else \ifpgfplotstableread@foundcolnames \else \pgfplotstableread@create@column@names@with@numbers \fi - \pgfplotstableread@curcol=0\relax% + \pgfplotstableread@countreset\pgfplotstableread@curcol% \pgfutil@loop - \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols - \expandafter\pgfplotsapplistXflushbuffers\csname pgfp@numtable@glob@col@\the\pgfplotstableread@curcol\endcsname - \advance\pgfplotstableread@curcol by1 + \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols\relax + \expandafter\pgfplotsapplistXflushbuffers\csname pgfp@numtable@glob@col@\thepgfplotstableread@curcol\endcsname + \pgfplotstableread@countadvance\pgfplotstableread@curcol \pgfutil@repeat \fi } \def\pgfplotstableread@loop@over@lines{% - \ifeof1 + \ifeof\r@pgfplots@reada %\pgfplots@message{EOF}% \else - \read1 to\pgfplotstable@LINE - \ifeof1 - \else - \expandafter\pgfplotstableread@checkspecial@line\pgfplotstable@LINE\pgfplotstable@EOI - \ifpgfplotstableread@skipline + \read\r@pgfplots@reada to\pgfplotstable@LINE + \ifeof\r@pgfplots@reada \else - %-------------------------------------------------- - % \ifnum\pgfplotstableread@lineno=0 - % \let\pgfplotstable@firstline=\pgfplotstable@LINE - % \fi - %-------------------------------------------------- -%\pgfplots@message{READING LINE \the\pgfplotstableread@lineno: '\meaning\pgfplotstable@LINE'.}% - \pgfplotstableread@curline@contains@colnamesfalse - \ifnum\pgfplotstableread@numcols=0\relax - % STEP 0: initialise - % - count columns - % - find header data - \pgfplotstableread@curcol=0\relax - \pgfplotstableread@impl@DO\pgfplotstableread@impl@countcols@and@identifynames@NEXT\pgfplotstable@LINE - %\expandafter\pgfplotstableread@impl@countcols@and@identifynames@ITERATE\pgfplotstable@LINE\pgfplotstable@EOI - \pgfplotstableread@numcols=\pgfplotstableread@curcol - \pgfplotstableread@curcol=0\relax - % Create empty column lists: - \pgfplotstableread@create@column@lists - % - \ifnum\pgfplotstableread@usablelineno=0\relax - \ifnum\pgfplotstableread@lineno=2\relax - \ifnum\pgfplotstableread@numcols=3\relax - % The file started with - % #... - % #... - % X Y i - % -> thats a gnuplot file! - \pgfplotstableread@curline@contains@colnamesfalse - \fi - \fi - \fi - % Now, read the first line. - % It contains either - % - column names, - % - numerical data, - % - nothing (comments). - \ifpgfplotstableread@curline@contains@colnames - \pgfplotstableread@foundcolnamestrue - \pgfplotstableread@curcol=0\relax - \pgfplotstableread@impl@DO\pgfplotstableread@impl@collectcolnames@NEXT\pgfplotstable@LINE - %\expandafter\pgfplotstableread@impl@collectcolnames@ITERATE\pgfplotstable@LINE\pgfplotstable@EOI - \else - \pgfplotstableread@foundcolnamesfalse - \pgfplotstableread@curcol=0\relax - % Leave column name lists empty... - \pgfplotstableread@impl@DO\pgfplotstableread@impl@nextrow@NEXT\pgfplotstable@LINE - %\expandafter\pgfplotstableread@impl@nextrow@ITERATE\pgfplotstable@LINE\pgfplotstable@EOI - \fi -%\pgfplots@message{After reading first row: found '\the\pgfplotstableread@numcols' columns; column name list='\meaning\pgfplotstable@colnames@glob'}% + \pgfplotstableread@loop@processnextline + \fi + \expandafter\pgfplotstableread@loop@over@lines + \fi +} +% PRECONDITION: +% \pgfplotstable@LINE contains the current input line. +\def\pgfplotstableread@loop@processnextline{% + \expandafter\pgfplotstableread@checkspecial@line\pgfplotstable@LINE\pgfplotstable@EOI + \ifpgfplotstableread@skipline + \def\pgfplotstableread@gnuplotcheck{####x y type}% + \ifx\pgfplotstableread@gnuplotcheck\pgfplotstable@LINE + \def\pgfplotstableread@isgnuplotformat{1}% + \fi + \def\pgfplotstableread@gnuplotcheck{####x y z type}% + \ifx\pgfplotstableread@gnuplotcheck\pgfplotstable@LINE + \def\pgfplotstableread@isgnuplotformat{1}% + \fi + \else + %-------------------------------------------------- + % \ifnum\pgfplotstableread@lineno=0 + % \let\pgfplotstable@firstline=\pgfplotstable@LINE + % \fi + %-------------------------------------------------- +%\pgfplots@message{READING LINE \thepgfplotstableread@lineno: '\meaning\pgfplotstable@LINE'.}% + \pgfplotstableread@curline@contains@colnamesfalse + \ifnum\pgfplotstableread@numcols=0\relax + % STEP 0: initialise + % - count columns + % - find header data + \pgfplotstableread@countreset\pgfplotstableread@curcol + \ifpgfplotstable@firstline@is@header + \pgfplotstableread@curline@contains@colnamestrue + \fi + \pgfplotstableread@impl@DO\pgfplotstableread@impl@countcols@and@identifynames@NEXT\pgfplotstable@LINE + \pgfplotstableread@countset\pgfplotstableread@numcols{\pgfplotstableread@curcol}% + \pgfplotstableread@countreset\pgfplotstableread@curcol + % Create empty column lists: + \pgfplotstableread@create@column@lists + % + \ifnum\pgfplotstableread@usablelineno=0\relax + \if1\pgfplotstableread@isgnuplotformat% + % The file started with + % #... + % #x y type + % X Y i + % -> thats a gnuplot file! + \pgfplotstableread@curline@contains@colnamesfalse + \fi + \fi + % Now, read the first line. + % It contains either + % - column names, + % - numerical data, + % - nothing (comments). + \ifpgfplotstableread@curline@contains@colnames + \pgfplotstableread@foundcolnamestrue + \pgfplotstableread@countreset\pgfplotstableread@curcol + \pgfplotstableread@impl@DO\pgfplotstableread@impl@collectcolnames@NEXT\pgfplotstable@LINE \else - \pgfplotstableread@curcol=0\relax + \pgfplotsscanlinelengthincrease + \pgfplotstableread@foundcolnamesfalse + \pgfplotstableread@countreset\pgfplotstableread@curcol + % Leave column name lists empty... \pgfplotstableread@impl@DO\pgfplotstableread@impl@nextrow@NEXT\pgfplotstable@LINE - %\expandafter\pgfplotstableread@impl@nextrow@ITERATE\pgfplotstable@LINE\pgfplotstable@EOI \fi - \ifnum\pgfplotstableread@curcol=\pgfplotstableread@numcols +%\pgfplots@message{After reading first row: found '\thepgfplotstableread@numcols' columns; column name list='\meaning\pgfplotstable@colnames@glob'}% + \else + \pgfplotsscanlinelengthincrease + \pgfplotstableread@countreset\pgfplotstableread@curcol + \pgfplotstableread@impl@DO\pgfplotstableread@impl@nextrow@NEXT\pgfplotstable@LINE + \fi + \ifnum\pgfplotstableread@curcol=\pgfplotstableread@numcols\relax + \else + \pgfplotstable@error{input table '\pgfplotstableread@filename' has an unbalanced number of columns in row '\thepgfplotstableread@lineno' (expected '\thepgfplotstableread@numcols' cols; got '\thepgfplotstableread@curcol'). Maybe the input table is corrupted? If you need unbalanced data, consider using 'nan' in empty cells (perhaps combined with 'unbounded coords=jump')}% + \fi + \ifpgfplots@tableread@to@listener + \ifpgfplotstableread@curline@contains@colnames \else - \pgfplotstable@error{ERROR: the input table has an unexpected number of columns in row '\the\pgfplotstableread@lineno'. Expected: '\the\pgfplotstableread@numcols'; got '\the\pgfplotstableread@curcol. Maybe the input table is corrupted?}% - \fi - \ifpgfplots@tableread@to@listener - \ifpgfplotstableread@curline@contains@colnames - \else - % report row! - \pgfplotstable@listener - \fi + % report row! + \pgfplotstable@listener \fi - \advance\pgfplotstableread@usablelineno by1\relax \fi - \fi - \advance\pgfplotstableread@lineno by1\relax - \expandafter\pgfplotstableread@loop@over@lines + \pgfplotstableread@countadvance\pgfplotstableread@usablelineno \fi -} + \pgfplotstableread@countadvance\pgfplotstableread@lineno +}% -% WARNING: this routine is also use in pgfplots.code.tex ... +% WARNING: this routine is also used in pgfplots.code.tex ... \def\pgfplotstableread@checkspecial@line{% \pgfutil@ifnextchar##{% \pgfplotstableread@skiplinetrue @@ -1577,10 +2078,12 @@ }{% \pgfutil@ifnextchar\pgfplotstable@EOI{% \pgfplotstableread@skiplinetrue + \pgfplotsscanlinecomplete% the line is empty; same as \par! \pgfplotstableread@impl@gobble }{% \pgfutil@ifnextchar\par{% \pgfplotstableread@skiplinetrue + \pgfplotsscanlinecomplete \pgfplotstableread@impl@gobble }{% \pgfplotstableread@skiplinefalse @@ -1599,19 +2102,20 @@ \def\pgfplotstableread@create@column@lists{% \pgfutil@loop - \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols + \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols\relax \def\pgfplots@loc@TMPa{\pgfplotsapplistXnewempty[to global]}% - \expandafter\pgfplots@loc@TMPa\csname pgfp@numtable@glob@col@\the\pgfplotstableread@curcol\endcsname - \advance\pgfplotstableread@curcol by1\relax + \expandafter\pgfplots@loc@TMPa\csname pgfp@numtable@glob@col@\thepgfplotstableread@curcol\endcsname + \pgfplotstableread@countadvance\pgfplotstableread@curcol \pgfutil@repeat } \def\pgfplotstableread@create@column@names@with@numbers{% - \pgfplotstableread@curcol=0\relax + \pgfplotstableread@countreset\pgfplotstableread@curcol \pgfutil@loop - \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols - \expandafter\pgfplotslistpushbackglobal\the\pgfplotstableread@curcol\to\pgfplotstable@colnames@glob - \advance\pgfplotstableread@curcol by1\relax + \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols\relax + \edef\pgfplotstable@loc@TMPb{\thepgfplotstableread@curcol}% + \expandafter\pgfplotslistpushbackglobal\pgfplotstable@loc@TMPb\to\pgfplotstable@colnames@glob + \pgfplotstableread@countadvance\pgfplotstableread@curcol \pgfutil@repeat } @@ -1631,56 +2135,82 @@ % % #2: a macro containing a raw data line with <col sep> separated % entries. -\def\pgfplotstableread@impl@DO#1#2{% +\long\def\pgfplotstableread@impl@DO#1#2{% \let\pgfplotstableread@impl@ITERATE@NEXT@=#1\relax - \ifcase\pgfplotstableread@COLSEP@CASE\relax - % SPACE: - \expandafter\pgfplotstableread@impl@ITERATE#2\pgfplotstable@EOI - \or - % COMMA: - \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@COMMA - \expandafter\pgfplotstableread@impl@ITERATE#2,\pgfplotstable@EOI - \or - % SEMICOLON: - \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@SEMICOLON - \expandafter\pgfplotstableread@impl@ITERATE#2;\pgfplotstable@EOI - \or - % COLON: - \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@COLON - \expandafter\pgfplotstableread@impl@ITERATE#2:\pgfplotstable@EOI - \or - % BRACE: - \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@BRACE - \expandafter\pgfplotstableread@impl@ITERATE#2\pgfplotstable@EOI - \fi + \expandafter\pgfplotstableread@impl@DO@\expandafter{#2}% +} +{% + \catcode`\ =10 + \catcode`\;=12 + \catcode`\:=12 + \gdef\pgfplotstableread@impl@prepare@DO{% + \ifcase\pgfplotstableread@COLSEP@CASE\relax + % col sep=space: + \catcode`\ =10 + \long\def\pgfplotstableread@impl@DO@##1{\pgfplotstableread@impl@ITERATE##1 \pgfplotstable@EOI}% + \or + % col sep=comma: + \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@COMMA + \long\def\pgfplotstableread@impl@DO@##1{\pgfplotstableread@impl@ITERATE##1,\pgfplotstable@EOI}% + \or + % col sep=semicolon: + \catcode`\;=12 + \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@SEMICOLON + \long\def\pgfplotstableread@impl@DO@##1{\pgfplotstableread@impl@ITERATE##1;\pgfplotstable@EOI}% + \or + % col sep=colon: + \catcode`\:=12 + \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@COLON + \long\def\pgfplotstableread@impl@DO@##1{\pgfplotstableread@impl@ITERATE##1:\pgfplotstable@EOI}% + \or + % col sep=brace: + % allow multi line cells: + \endlinechar=\pgfplotstableread@oldendlinechar\relax + \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@BRACE + \long\def\pgfplotstableread@impl@DO@##1{\pgfplotstableread@impl@ITERATE##1\pgfplotstable@EOI}% + \or + % col sep=tab: + \catcode`\^^I=12 + \let\pgfplotstableread@impl@ITERATE@NEXT=\pgfplotstableread@impl@ITERATE@NEXT@TAB + \long\edef\pgfplotstableread@impl@DO@##1{\noexpand\pgfplotstableread@impl@ITERATE##1\pgfplotstableread@tab\noexpand\pgfplotstable@EOI}% + \fi + }% }% -\def\pgfplotstableread@impl@ITERATE{% +\long\def\pgfplotstableread@impl@ITERATE{% \pgfutil@ifnextchar\pgfplotstable@EOI{% \pgfplotstableread@impl@gobble }{% \pgfplotstableread@impl@ITERATE@NEXT }% }% -\def\pgfplotstableread@impl@ITERATE@NEXT#1 {% +\long\def\pgfplotstableread@impl@ITERATE@NEXT#1 {% \pgfplotstableread@impl@ITERATE@NEXT@{#1}% \pgfplotstableread@impl@ITERATE }% -\def\pgfplotstableread@impl@ITERATE@NEXT@COMMA#1,{% +\long\def\pgfplotstableread@impl@ITERATE@NEXT@COMMA#1,{% \pgfplotstableread@impl@ITERATE@NEXT@{#1}% \pgfplotstableread@impl@ITERATE }% -\def\pgfplotstableread@impl@ITERATE@NEXT@SEMICOLON#1;{% +\long\def\pgfplotstableread@impl@ITERATE@NEXT@SEMICOLON#1;{% \pgfplotstableread@impl@ITERATE@NEXT@{#1}% \pgfplotstableread@impl@ITERATE }% -\def\pgfplotstableread@impl@ITERATE@NEXT@COLON#1:{% +\long\def\pgfplotstableread@impl@ITERATE@NEXT@COLON#1:{% \pgfplotstableread@impl@ITERATE@NEXT@{#1}% \pgfplotstableread@impl@ITERATE }% -\def\pgfplotstableread@impl@ITERATE@NEXT@BRACE#1{% +\long\def\pgfplotstableread@impl@ITERATE@NEXT@BRACE#1{% \pgfplotstableread@impl@ITERATE@NEXT@{#1}% \pgfplotstableread@impl@ITERATE }% +\begingroup +\catcode`\^^I=12 +\gdef\pgfplotstableread@tab{^^I}% +\long\gdef\pgfplotstableread@impl@ITERATE@NEXT@TAB#1^^I{% the following white spaces are SPACES, not tabs: + \pgfplotstableread@impl@ITERATE@NEXT@{#1}% + \pgfplotstableread@impl@ITERATE +}% +\endgroup %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % these values are only usable for a read-listener, that means: @@ -1694,24 +2224,110 @@ % performs \let\content=<content of column no <index> > \def\pgfplotstablereadgetcolindex@#1#2{% \pgfutil@ifundefined{pgfplotstblread@colcontent@no#1}{% - \pgfplots@error{Sorry, the requested column number '#1' in table '\pgfplotstableread@filename' does not exist!? Please verify you used the correct index 0 <= i < N.}% - \let#2=\pgfutil@empty + \pgfplotsthrow{no such element}{#2}{Sorry, the requested column number '#1' in table '\pgfplotstableread@filename' does not exist!? Please verify you used the correct index 0 <= i < N.}\pgfeov% }{% \expandafter\let\expandafter#2\csname pgfplotstblread@colcontent@no#1\endcsname }% }% -% \pgfplotstablereadgetcolname{<index>}{<name>} +\pgfkeysdef{/pgfplots/table/@undefined column text}{#1__column_not_found.}% +\def\pgfplotstable@undefinedtext#1{\pgfkeysvalueof{/pgfplots/table/@undefined column text/.@cmd}#1\pgfeov}% + +% As \pgfplotstablereadgetcolindex, but +% \pgfplotstablereadvalueofcolindex{<index>} +% directly expands to the value stored in the desired column. +% +% Example: +% \pgfplotstablereadvalueofcolindex{3} -> expands to '42' if '42' is +% written in column no 3. +% +% Column indexing starts at 0. +% +% @ATTENTION: since such a command may occur within an \edef or an +% \csname, it can't perform sanity checking. Proving an invalid index +% expands to \pgfkeysvalueof{/pgfplots/table/@undefined column text}. +\def\pgfplotstablereadvalueofcolindex@#1{% + \pgfutil@ifundefined{pgfplotstblread@colcontent@no#1}{% + \pgfplotstable@undefinedtext{colindex#1}% + }{% + \csname pgfplotstblread@colcontent@no#1\endcsname + }% +} + +% \pgfplotstablereadgetcolname{<name>}{<\content>} % performs \let\content=<content of column named <name> > \def\pgfplotstablereadgetcolname@#1#2{% \pgfplotstablereadgetptrtocolname{#1}{\pgfplots@loc@TMPa}% \pgfplotstablereadevalptr\pgfplots@loc@TMPa{#2}% }% +% This here is the implementation of \pgfplotstablereadvalueofcolname +% (and \thisrow{<colname>}) for use inside of the 'read to listener' +% framework. +% +% Like \pgfplotstablereadgetcolname, but this one expands directly to +% the value of the desired column. +% +% #1: a column name or a column alias. +% +% @ATTENTION: since such a command may occur within an \edef or an +% \csname, it can't perform sanity checking. Proving an invalid index +% expands to \pgfkeysvalueof{/pgfplots/table/@undefined column text}. +\def\pgfplotstablereadvalueofcolname@#1{% + \pgfplotstable@thisrow@impl{#1}{pgfplotstblread@colindex@for@name}{\pgfplotstable@thisrow@impl@read}% +}% +\def\pgfplotstable@thisrow@impl@read#1{\csname pgfplotstblread@colcontent@no#1\endcsname}% + +% This implements \thisrow in different contexts. +% +% Usage: +% \def\thisrow#1{\pgfplotstable@thisrow@impl{#1}{macroprefix@}{\pgfplotstable@thisrow@impl@}} +% +% Then, \thisrow{existingcol} +% will expand to +% -> \pgfplotstable@thisrow@impl@{\csname macroprefix@existingcol\endcsname} +% -> \csname macroprefix@existingcol\endcsname +% +% Furthermore, if '#1' is no existing col and there exists /pgfplots/table/alias/#1, +% \thisrow{aliased} +% will expand to +% -> \pgfplotstable@thisrow@impl@{\csname macroprefix@\pgfkeysvalueof{/pgfplots/table/alias/aliased}\endcsname} +% -> \csname macroprefix@\pgfkeysvalueof{/pgfplots/table/alias/aliased}\endcsname +% +% #1: the argument for \thisrow{#1} +% #2: a macro prefix such that \csname #2<colname>\endcsname contains +% the value of the current row for (physical) column <colname> +% #3: the name of a one-argument-macro which will get \csname #2<colname>\endcsname +% as argument. This is the last step of \thisrow. It allows indirect +% access by translating colnames to col indices in '\pgfplotstableread to listener' +\def\pgfplotstable@thisrow@impl#1#2#3{% + \pgfutil@ifundefined{#2#1}% + {% + % WARNING : this code has been REPLICATED in + % *** \pgfplotstablereadgetptrtocolname *** + % *** \pgfplotstablegetcolumnbyname *** + % *** \pgfplotstableresolvecolname *** + % *** \pgfplotstablereadvalueofcolname *** + \pgfkeysifdefined{/pgfplots/table/alias/#1}{% + \pgfutil@ifundefined{#2\pgfkeysvalueof{/pgfplots/table/alias/#1}}{% + \pgfplotstable@undefinedtext{\pgfkeysvalueof{/pgfplots/table/alias/#1}}% + }{% + #3{\csname #2\pgfkeysvalueof{/pgfplots/table/alias/#1}\endcsname}% + }% + }{% + \pgfplotstable@undefinedtext{#1}% + }% + }% + {% + #3{\csname #2#1\endcsname}% + }% +}% +\def\pgfplotstable@thisrow@impl@#1{#1}% + % \pgfplotstablereadgetptrtocolname{<name>}{\ptr} % Creates some sort of "pointer" to the column named <name>. This % pointer can than be used every time a new line has been reported to -% the listener. IT works like this: +% the listener. It works like this: % % \let\ptr=\pgfutil@empty % \def\macro{% @@ -1725,6 +2341,11 @@ % \pgfplotstableread{<file>} to listener<\macro> % % -> will evaluate \macro foreach row. +% +% The advantage of such a prepared pointer over \thisrow{#1} or +% \getthisrow{#1} is simply efficiency and sanity checking: the checks +% are done at the time of pointer creation, dereferencing the pointer +% is fast. \def\pgfplotstablereadgetptrtocolname@#1#2{% % Implementation note: it is necessary to replicate code becuase % in this context, the table structure is NOT available. @@ -1737,13 +2358,14 @@ % *** \pgfplotstablereadgetptrtocolname *** % *** \pgfplotstablegetcolumnbyname *** % *** \pgfplotstableresolvecolname *** + % *** \pgfplotstablereadvalueofcolname *** % \def\pgfplotstable@loc@TMPa{/pgfplots/table/alias/#1}% \pgfkeysifdefined{\pgfplotstable@loc@TMPa}{% \pgfkeysgetvalue{\pgfplotstable@loc@TMPa}{\pgfplotstable@loc@TMPb}% \let\pgfplotstable@loc@TMPa=\pgfplotstable@loc@TMPb \pgfutil@ifundefined{pgfplotstblread@colindex@for@name\pgfplotstable@loc@TMPa}{% - \pgfplots@error{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstableread@filename'. The original request was for '#1', which does not exist either.}% + \pgfplotsthrow{no such element}{#2}{Sorry, could not retrieve aliased column '\pgfplotstable@loc@TMPa' from table '\pgfplotstableread@filename'. The original request was for '#1', which does not exist either.}\pgfeov% \def#2{0}% }{% \edef#2{\csname pgfplotstblread@colindex@for@name\pgfplotstable@loc@TMPa\endcsname}% @@ -1751,9 +2373,9 @@ }{% \def\pgfplotstable@loc@TMPa{/pgfplots/table/create on use/#1}% \pgfkeysifdefined{\pgfplotstable@loc@TMPa/.@cmd}{% - \pgfplots@error{Sorry, '\pgfplotstable@loc@TMPa' from table '\pgfplotstableread@filename' can't be evaluated in this context. Please prepare the table before using it here. You can do this using the 'read completely' key, see the manual for details.}% + \pgfplotstable@error{Sorry, '\pgfplotstable@loc@TMPa' from table '\pgfplotstableread@filename' can't be evaluated in this context. Please prepare the table before using it here. You can do this using the 'read completely' key, see the manual for details.}% }{% - \pgfplots@error{Sorry, could not retrieve column '#1' from table '\pgfplotstableread@filename'. Please check spelling (or introduce name aliases).}% + \pgfplotsthrow{no such element}{#2}{Sorry, could not retrieve column '#1' from table '\pgfplotstableread@filename'. Please check spelling (or introduce name aliases).}\pgfeov% }% \def#2{0}% }% @@ -1770,24 +2392,30 @@ % writes the current value of <\ptr> to <\content>. The pointer <\ptr> % must be initialised with \pgfplotstablereadgetptrtocolname \let\pgfplotstablereadevalptr@=\pgfplotstablereadgetcolindex@ + +% \pgfplotstablereadvalueofptr{<\ptr>} -> expands to the pointers value. +% +% The pointer \ptr must be initialised with +% \pgfplotstablereadgetptrtocolname. +\let\pgfplotstablereadvalueofptr@=\pgfplotstablereadvalueofcolindex@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \long\def\pgfplotstableread@impl@nextrow@NEXT@listener#1{% - \expandafter\def\csname pgfplotstblread@colcontent@no\the\pgfplotstableread@curcol\endcsname{#1}% - \advance\pgfplotstableread@curcol by1\relax + \expandafter\def\csname pgfplotstblread@colcontent@no\thepgfplotstableread@curcol\endcsname{#1}% + \pgfplotstableread@countadvance\pgfplotstableread@curcol } \long\def\pgfplotstableread@impl@nextrow@NEXT#1{% -%\pgfplots@message{Inserting '#1' at (\the\pgfplotstableread@lineno, \the\pgfplotstableread@curcol).}% - \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols +%\pgfplots@message{Inserting '#1' at (\thepgfplotstableread@lineno, \thepgfplotstableread@curcol).}% + \ifnum\pgfplotstableread@curcol<\pgfplotstableread@numcols\relax \pgfplotslist@assembleentry{#1}\into\t@pgfplots@tokc \def\pgfplotstableread@TMP{\expandafter\pgfplotsapplistXpushback\expandafter{\the\t@pgfplots@tokc}\to}% - \expandafter\pgfplotstableread@TMP\csname pgfp@numtable@glob@col@\the\pgfplotstableread@curcol\endcsname - \advance\pgfplotstableread@curcol by1\relax + \expandafter\pgfplotstableread@TMP\csname pgfp@numtable@glob@col@\thepgfplotstableread@curcol\endcsname + \pgfplotstableread@countadvance\pgfplotstableread@curcol \else \begingroup \t@pgfplots@tokc={#1}% - \pgfplots@error{Table '\pgfplotstableread@filename' has too much columns in line \the\pgfplotstableread@lineno: Ignoring '\the\t@pgfplots@tokc'. Please verify that every cell entry is separated correctly (use braces {<cell entry>} if necessary). This error is not critical}% + \pgfplotstable@error{Table '\pgfplotstableread@filename' has too much columns in line \thepgfplotstableread@lineno: Ignoring '\the\t@pgfplots@tokc'. Please verify that every cell entry is separated correctly (use braces {<cell entry>} if necessary). This error is not critical}% \endgroup \fi } @@ -1795,30 +2423,28 @@ \long\def\pgfplotstableread@impl@collectcolnames@NEXT#1{% -%\pgfplots@message{Got column name no \the\pgfplotstableread@curcol\ as '#1'}% +%\pgfplots@message{Got column name no \thepgfplotstableread@curcol\ as '#1'}% \pgfutil@ifundefined{pgfplotstableread@impl@COLNAME@#1}{% \def\pgfplotstable@loc@TMPa{#1}% - }{% generate unique column names + }{% generate unique column names warning: \pgfplots@warning{Table '\pgfplotstableread@filename' has non-unique column name '#1'. Only the first occurence can be accessed via column names.}% - \edef\pgfplotstable@loc@TMPa{#1--index\the\pgfplotstableread@curcol}% + \edef\pgfplotstable@loc@TMPa{#1--index\thepgfplotstableread@curcol}% }% \expandafter\def\csname pgfplotstableread@impl@COLNAME@#1\endcsname{foo}% remember this name. \expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplotstable@loc@TMPa}\to\pgfplotstable@colnames@glob \ifpgfplots@tableread@to@listener % create an associative container colindex -> colname % for use in a listener. - \def\pgfplots@loc@TMPb{% - \expandafter\def\csname pgfplotstblread@colindex@for@name#1\endcsname}% - \expandafter\pgfplots@loc@TMPb\expandafter{\the\pgfplotstableread@curcol}% + \expandafter\edef\csname pgfplotstblread@colindex@for@name#1\endcsname{\thepgfplotstableread@curcol}% \fi - \advance\pgfplotstableread@curcol by1\relax + \pgfplotstableread@countadvance\pgfplotstableread@curcol } \long\def\pgfplotstableread@impl@countcols@and@identifynames@NEXT#1{% - \advance\pgfplotstableread@curcol by1\relax + \pgfplotstableread@countadvance\pgfplotstableread@curcol \ifpgfplotstable@search@header \ifpgfplotstableread@curline@contains@colnames \else @@ -1888,7 +2514,7 @@ \pgfplotstableread@NEXT } -\def\pgfplotstable@error#1{\pgfplots@error{#1}}% +\def\pgfplotstable@error#1{\pgfplotsthrow{unsupported operation}{#1}\pgfeov}% \def\pgfplotstableset{% @@ -1898,7 +2524,7 @@ % Accepts a macro #1 which contains an argument denoting a column % name. % -% It checks whether #1 starts with '#', indicating that it is actually +% It checks whether #1 starts with '[index]', indicating that it is actually % a column INDEX. If that is the case, % \ifpgfplotstableread@foundcolnames is set to false and the index is % returned into #1. @@ -1924,19 +2550,21 @@ \def\pgfplotstable@loc@TMPa{#1}% \ifx\pgfplotstable@loc@TMPa\pgfplotstabletypeset@is@colname@index@@ \pgfplotstableread@foundcolnamesfalse - \def\pgfplotstable@loc@TMPa{#2}% + \edef\pgfplotstable@loc@TMPa{#2}% \else \pgfplotstableread@foundcolnamestrue \fi }% \def\pgfplotstabletypeset@is@colname@name#1\pgfplotstable@EOI{}% -\def\pgfplotstabletypeset@getfinalentry#1#2{% +\long\def\pgfplotstabletypeset@getfinalentry#1#2{% \begingroup \def\pgfplotstablepartno{0}% \pgfkeyssetvalue{/pgfplots/table/@cell content}{#1}% + \pgfkeyssetvalue{/pgfplots/table/@unprocessed cell content}{#1}% \pgfkeysvalueof{/pgfplots/table/preproc cell content/.@cmd}#1\pgfeov \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult% + \pgfkeyslet{/pgfplots/table/@preprocessed cell content}\pgfmathresult% % \pgfkeysgetvalue{/pgfplots/table/assign cell content/.@cmd}\pgfplotstable@assigncell \expandafter\pgfplotstable@assigncell\pgfmathresult\pgfeov @@ -1945,17 +2573,18 @@ \ifx\pgfplotstable@postproccellcontent\pgfplotstable@postproccellcontent@EMPTY \else % apply postprocessing to final cell content. + \def\pgfplotstabletypeset@rawinput{#1}% + % % This is complicated if there is an '&' in '@cell content', % so handle that specially! % % FIXME also support more than one '&' ? - \def\pgfplotstabletypeset@rawinput{#1}% \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult% \expandafter\pgfutil@in@\expandafter&\expandafter{\pgfmathresult}% \ifpgfutil@in@ \expandafter\pgfplotstabletypeset@postproc@separately\pgfmathresult\pgfplotstable@EOI \else - \pgfplotstable@postproccellcontent#1\pgfeov + \expandafter\pgfplotstable@postproccellcontent\pgfplotstabletypeset@rawinput\pgfeov \fi \fi \pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult% @@ -1965,7 +2594,7 @@ }% % This routine invokes 'postproc cell content' for columns which -% contain the column separate '&'. +% contain the column separator '&'. % % #1 is the formatted number, the result of 'dec sep align % #3 is the (unformatted) input number. @@ -2033,6 +2662,8 @@ % \pgfplotslistnewempty#2 % }{}% %-------------------------------------------------- + \def\pgfplotstablename{#2}% + \def\pgfplotstablecolname{\pgfplotstable@colname}% \def\pgfplotstablecol{\the\c@pgfplotstable@colindex}% \def\pgfplotstablerow{\the\c@pgfplotstable@rowindex}% \def\pgfplotstablecols{\the\c@pgfplotstable@numcols}% @@ -2054,9 +2685,9 @@ \ifx\pgfplotstable@outfilename\pgfutil@empty \else \pgfplots@logfileopen{\pgfplotstable@outfilename}% - \openin1=\pgfplotstable@outfilename\relax - \ifeof1 \else\pgfplotstabletypeset@includeoutfilestrue \fi - \closein1 + \openin\r@pgfplots@reada=\pgfplotstable@outfilename\relax + \ifeof\r@pgfplots@reada \else\pgfplotstabletypeset@includeoutfilestrue \fi + \closein\r@pgfplots@reada \fi \fi \fi @@ -2116,6 +2747,7 @@ \def\pgfplotstable@firstnumrows{-1}% \c@pgfplotstable@numrows=-1\relax \c@pgfplotstable@colindex=0\relax + % FOREACH COLUMN: \pgfplotslistforeach\pgfplotstable@colnames\as\pgfplotstable@colname{% \c@pgfplotstable@rowindex=0\relax \pgfplotstable@is@colname\pgfplotstable@colname @@ -2153,6 +2785,8 @@ \ifnum\c@pgfplotstable@colindex=\c@pgfplotstable@numcols \t@pgfplots@toka=\expandafter{\the\t@pgfplots@toka,every last column}% \fi + % temporarily restore it: we may need it in row predicates: + \global\advance\c@pgfplotstable@colindex by-1\relax \ifpgfplotstable@disable@rowcolstyles % ok, then don't check for 'columns/<name>' and % 'display columns/<index>': @@ -2177,13 +2811,9 @@ \let\pgfplotstable@colname@out=\pgfplotstable@colname \fi \expandafter\pgfplotstabletypeset@assign@final@colname\expandafter{\pgfplotstable@colname@out}\pgfplotstable@colname@out - {\globaldefs=1 - \expandafter\pgfplotslistpushback\pgfplotstable@colname@out\to\pgfplotstabletypeset@final@colnames - }% + \expandafter\pgfplotslistpushbackglobal\pgfplotstable@colname@out\to\pgfplotstabletypeset@final@colnames \pgfkeysgetvalue{/pgfplots/table/column type}{\pgfplotstable@coltype}% - {\globaldefs=1 - \expandafter\pgfplotslistpushback\pgfplotstable@coltype\to\pgfplotstabletypeset@final@coltypes - }% + \expandafter\pgfplotslistpushbackglobal\pgfplotstable@coltype\to\pgfplotstabletypeset@final@coltypes % \pgfplotslistnewempty\pgfplotstable@col@processed \c@pgfplotstable@counta=0 @@ -2194,7 +2824,8 @@ \ifpgfplotstableuserow \ifnum\pgfplotstable@firstnumrows=-1\relax \else - \ifnum\c@pgfplotstable@counta=\pgfplotstable@firstnumrows + \ifnum\c@pgfplotstable@counta<\pgfplotstable@firstnumrows\relax + \else \t@pgfplots@toka=\expandafter{\pgfplotstable@entry}% \t@pgfplots@tokb=\expandafter{\pgfplotstable@colname@out}% \pgfplots@warning{Unbalanced cell with content '\the\t@pgfplots@toka' of column '\the\t@pgfplots@tokb' has been skipped: row count \the\c@pgfplotstable@counta+1 > \pgfplotstable@firstnumrows (which is the number of rows in the first column)}% @@ -2215,9 +2846,8 @@ % balance columns: \pgfplotstable@insertemptycells@forbalance \fi - {\globaldefs=1 - \expandafter\pgfplotslistpushback\expandafter{\pgfplotstable@col@processed}\to\pgfplotstabletypeset@final@cols - }% + \expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplotstable@col@processed}\to\pgfplotstabletypeset@final@cols + \global\advance\c@pgfplotstable@colindex by1\relax }% % % Ok, I have now everything which will come into the final table. @@ -2287,6 +2917,7 @@ \t@pgfplots@tokb=\expandafter{\pgfplotstable@curline}% \edef\pgfplotstable@curline{\the\t@pgfplots@tokb\the\t@pgfplots@toka}% % + \def\pgfplotstablecolname{\pgfplotstable@colname@out}% \pgfplotslistforeachungrouped\pgfplotstabletypeset@final@colnames\as\pgfplotstable@colname@out{% % \advance\c@pgfplotstable@colindex by1\relax @@ -2328,6 +2959,7 @@ \else \pgfplots@loop@CONTINUEfalse \fi + \def\pgfplotstablecolname{\pgfplotstable@error{Sorry, you can't evaluate \string\pgfplotstablecolname\space in this context.}}% \pgfutil@loop \ifpgfplots@loop@CONTINUE \pgfplotsarrayselect\c@pgfplotstable@colindex\of\pgfplotstabletypeset@final@cols@array\to\pgfplotstable@col@processed @@ -2421,8 +3053,8 @@ \immediate\closeout\pgfplotstable@outfile \fi %\message{I have now \meaning\pgfplotstable@result.}% - \def\pgfplotstablecol{\pgfplots@error{Sorry, you can't access the \string\pgfplotstablecol\ in this context. It is ONLY valid during the preparation routines (please check the 'display columns/<index>' style in the manual).}}% - \def\pgfplotstablerow{\pgfplots@error{Sorry, you can't access the \string\pgfplotstablerow\ in this context. It is ONLY valid during the preparation routines (please check the 'every row no <index>' style).}}% + \def\pgfplotstablecol{\pgfplotstable@error{Sorry, you can't access the \string\pgfplotstablecol\ in this context. It is ONLY valid during the preparation routines (please check the 'display columns/<index>' style in the manual).}}% + \def\pgfplotstablerow{\pgfplotstable@error{Sorry, you can't access the \string\pgfplotstablerow\ in this context. It is ONLY valid during the preparation routines (please check the 'every row no <index>' style).}}% \ifpgfplotstabletypesetresult \pgfplotstable@result \fi @@ -2444,7 +3076,11 @@ \def\pgfplotstablecreatecol@opt[#1]#2#3{% \begingroup - \pgfplotstableset{columns=,#1}% + \pgfplotstableset{columns=,#1,% + /pgf/fpu/handlers/empty number/.code 2 args={% + \pgfmathfloatcreate{0}{0.0}{0}% + }% + }% \pgfkeysgetvalue{/pgfplots/table/columns}{\pgfplotstable@colnames}% \ifx\pgfplotstable@colnames\pgfutil@empty \pgfplotstablegetcolumnlist#3\to\pgfplotstable@colnames @@ -2478,9 +3114,9 @@ \def\pgfplotstablerow{\the\c@pgfplotstable@rowindex}% \def\pgfplotstablerows{\the\c@pgfplotstable@numrows}% % - \def\prevrow##1{\csname pgfplotstablecreate@prev@##1\endcsname}% - \def\thisrow##1{\csname pgfplotstablecreate@cur@##1\endcsname}% - \def\nextrow##1{\csname pgfplotstablecreate@next@##1\endcsname}% + \def\prevrow##1{\pgfplotstable@thisrow@impl{##1}{pgfplotstablecreate@prev@}{\pgfplotstable@thisrow@impl@}}% + \def\thisrow##1{\pgfplotstable@thisrow@impl{##1}{pgfplotstablecreate@cur@}{\pgfplotstable@thisrow@impl@}}% + \def\nextrow##1{\pgfplotstable@thisrow@impl{##1}{pgfplotstablecreate@next@}{\pgfplotstable@thisrow@impl@}}% \def\getprevrow##1##2{\expandafter\let\expandafter##2\csname pgfplotstablecreate@prev@##1\endcsname}% \def\getthisrow##1##2{\expandafter\let\expandafter##2\csname pgfplotstablecreate@cur@##1\endcsname}% \def\getnextrow##1##2{\expandafter\let\expandafter##2\csname pgfplotstablecreate@next@##1\endcsname}% @@ -2591,10 +3227,14 @@ % \pgfqkeys{/pgfplots/table/create col/function graph cut}{#2}% \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/table}\pgfplotstable@fgc@table + \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/x}\pgfplotstable@fgc@x + \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/y}\pgfplotstable@fgc@y \ifx\pgfplotstable@fgc@table\pgfutil@empty + % no table here, ok. \else % ok, we need to query (or load) a table! - \pgfplotstable@isloadedtable{\pgfplotstable@fgc@table}{% + \expandafter\pgfplotstable@isloadedtable\expandafter{\pgfplotstable@fgc@table}{% + \expandafter\let\expandafter\pgfplotstable@fgc@table\pgfplotstable@fgc@table }{% \expandafter\pgfplotstableread\expandafter{\pgfplotstable@fgc@table}{\pgfplotstable@fgc@table}% }% @@ -2607,6 +3247,17 @@ \fi \let\pgfplotstable@fgc@eps=\pgfmathresult \pgfplots@assign@list\pgfmathaccumb{#3}% + \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/foreach}\pgfplotstable@fgc@foreach@ + \ifx\pgfplotstable@fgc@foreach@\pgfutil@empty + \else + \edef\pgfplotstable@fgc@foreach@process@append{x={\pgfplotstable@fgc@x},y={\pgfplotstable@fgc@y}}% + % we have something like + % foreach={\d in {1,2,3,4}}{table\d} + % -> process it! + % This will modify \pgfmathaccumb + \expandafter\pgfplotstable@fgc@foreach@process\pgfplotstable@fgc@foreach@\pgfplots@EOI + \pgfkeyssetvalue{/pgfplots/table/create col/function graph cut/foreach}{}% + \fi % \pgfkeysdef{/pgfplots/table/create col/assign}{% %\message{working on next cell ...}% @@ -2615,6 +3266,8 @@ \pgfkeyslet{/pgfplots/table/create col/next content}\pgfutil@empty% \else \pgfplotslistpopfront\pgfmathaccumb\to\pgfmathresult +%\message{working on next cell: \meaning\pgfmathresult ...}% + \global\let\pgfplotstable@fgc@foreach=\pgfutil@empty \begingroup % set local keys: \def\pgfplots@loc@TMPa{\pgfqkeys{/pgfplots/table/create col/function graph cut}}% @@ -2623,45 +3276,90 @@ \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/table}\pgfplotstable@fgc@table \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/x}\pgfplotstable@fgc@x \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/y}\pgfplotstable@fgc@y - \ifx\pgfplotstable@fgc@table\pgfutil@empty - \else - % ok, we need to query (or load) a table! - \pgfplotstable@isloadedtable{\pgfplotstable@fgc@table}{% - }{% - \expandafter\pgfplotstableread\expandafter{\pgfplotstable@fgc@table}{\pgfplotstable@fgc@table}% - }% - \fi - \expandafter\pgfplotstablegetcolumnbyname\expandafter{\pgfplotstable@fgc@x}\of\pgfplotstable@fgc@table\to\pgfplotstable@fgc@x@col - \expandafter\pgfplotstablegetcolumnbyname\expandafter{\pgfplotstable@fgc@y}\of\pgfplotstable@fgc@table\to\pgfplotstable@fgc@y@col - % - % search for epsilon in the y values: - \expandafter\pgfplotstable@fgc@findintervalwitheps\expandafter{\csname pgfplotstable@fgc@#4@col\endcsname}{\csname pgfplotstable@fgc@#4mode\endcsname}% - \ifx\pgfplotstable@fgc@second\pgfutil@empty - \let\pgfmathresult=\pgfutil@empty - \else - % - % acquire the associated x values: - \expandafter\pgfplotstable@fgc@getassociated\expandafter{\csname pgfplotstable@fgc@#5@col\endcsname}{\csname pgfplotstable@fgc@#5mode\endcsname}% - % - % Interpolate: - \pgfmathparse{ - \pgfplotstable@fgc@abscissafirst + - (\pgfplotstable@fgc@eps - \pgfplotstable@fgc@first) / (\pgfplotstable@fgc@second-\pgfplotstable@fgc@first) - * (\pgfplotstable@fgc@abscissasecond - \pgfplotstable@fgc@abscissafirst) }% - \if\pgfplotstable@fgc@xmode1 - \pgfmathfloatexp@{\pgfmathresult}% + \pgfkeysgetvalue{/pgfplots/table/create col/function graph cut/foreach}\pgfplotstable@fgc@foreach@ + \ifx\pgfplotstable@fgc@foreach@\pgfutil@empty + \ifx\pgfplotstable@fgc@table\pgfutil@empty + \else + % ok, we need to query (or load) a table! + \expandafter\pgfplotstable@isloadedtable\expandafter{\pgfplotstable@fgc@table}{% + \expandafter\let\expandafter\pgfplotstable@fgc@table\pgfplotstable@fgc@table + }{% + \expandafter\pgfplotstableread\expandafter{\pgfplotstable@fgc@table}{\pgfplotstable@fgc@table}% + }% \fi - \pgflibraryfpuifactive{\pgfmathfloattosci{\pgfmathresult}}{}% + \expandafter\pgfplotstablegetcolumnbyname\expandafter{\pgfplotstable@fgc@x}\of\pgfplotstable@fgc@table\to\pgfplotstable@fgc@x@col + \expandafter\pgfplotstablegetcolumnbyname\expandafter{\pgfplotstable@fgc@y}\of\pgfplotstable@fgc@table\to\pgfplotstable@fgc@y@col + % + % search for epsilon in the y values: + \expandafter\pgfplotstable@fgc@findintervalwitheps\expandafter{\csname pgfplotstable@fgc@#4@col\endcsname}{\csname pgfplotstable@fgc@#4mode\endcsname}% + \ifx\pgfplotstable@fgc@second\pgfutil@empty + \let\pgfmathresult=\pgfutil@empty + \else + % + % acquire the associated x values: + \expandafter\pgfplotstable@fgc@getassociated\expandafter{\csname pgfplotstable@fgc@#5@col\endcsname}{\csname pgfplotstable@fgc@#5mode\endcsname}% + % + % Interpolate: + \pgfmathparse{ + \pgfplotstable@fgc@abscissafirst + + (\pgfplotstable@fgc@eps - \pgfplotstable@fgc@first) / (\pgfplotstable@fgc@second-\pgfplotstable@fgc@first) + * (\pgfplotstable@fgc@abscissasecond - \pgfplotstable@fgc@abscissafirst) }% + \if\pgfplotstable@fgc@xmode1 + \pgfmathfloatexp@{\pgfmathresult}% + \fi + \pgflibraryfpuifactive{\pgfmathfloattosci{\pgfmathresult}}{}% %\message{FGC: found \pgfplotstable@fgc@eps\space in no \pgfplotstable@fgc@index; \pgfplotstable@fgc@first:\pgfplotstable@fgc@second; lastwasless=\pgfplotstable@fgc@lastwasless; abscissa interval = \pgfplotstable@fgc@abscissafirst:\pgfplotstable@fgc@abscissasecond; result = \pgfmathresult}% + \fi + \else + \global\let\pgfplotstable@fgc@foreach=\pgfplotstable@fgc@foreach@ + \edef\pgfmathresult{x={\pgfplotstable@fgc@x},y={\pgfplotstable@fgc@y}}% \fi % \pgfmath@smuggleone\pgfmathresult \endgroup - \pgfkeyslet{/pgfplots/table/create col/next content}\pgfmathresult% + \ifx\pgfplotstable@fgc@foreach\pgfutil@empty + \pgfkeyslet{/pgfplots/table/create col/next content}\pgfmathresult% + \else + % we have something like + % foreach={\d in {1,2,3,4}}{table\d} + % -> process it! + % This will modify \pgfmathaccumb + \let\pgfplotstable@fgc@foreach@process@append=\pgfmathresult + \expandafter\pgfplotstable@fgc@foreach@process\pgfplotstable@fgc@foreach\pgfplots@EOI + \fi \fi }% }% +\def\pgfplotstable@fgc@foreach@process{% + \pgfutil@ifnextchar\bgroup + {\pgfplotstable@fgc@foreach@process@a}{% + \pgfplotstable@fgc@foreach@process@error}% +}% +\def\pgfplotstable@fgc@foreach@process@a#1{% + \pgfutil@ifnextchar\bgroup + {\pgfplotstable@fgc@foreach@process@b{#1}}{% + \pgfplotstable@fgc@foreach@process@error}% +}% +\def\pgfplotstable@fgc@foreach@process@error#1\pgfplots@EOI{% + \def\pgfplots@loc@TMPa{#1}% + \pgfplots@command@to@string\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \pgfplotsthrow{invalid argument}{\pgfplots@loc@TMPa}{Sorry, I expected two arguments for /pgfplots/table/create col/function graph cut/foreach, but I found 'foreach=\pgfplots@loc@TMPb'. Perhaps the braces are not as expected?}\pgfeov% +}% +\def\pgfplotstable@fgc@foreach@process@b#1#2#3\pgfplots@EOI{% + \global\pgfplotslistnewempty\pgfplots@glob@TMPa + \begingroup + \foreach #1 {% + \edef\pgfplots@loc@TMPa{#2}% + \expandafter\pgfplotslistpushfrontglobal\pgfplots@loc@TMPa\to\pgfplots@glob@TMPa + }% + \endgroup + \pgfplotslistforeachungrouped\pgfplots@glob@TMPa\as\pgfplots@loc@TMPa{% + \edef\pgfplots@loc@TMPa{table={\pgfplots@loc@TMPa},\pgfplotstable@fgc@foreach@process@append}% + \expandafter\pgfplotslistpushfront\pgfplots@loc@TMPa\to\pgfmathaccumb + }% +}% + % #1 : the coordinate list to query % #2 : the mode % @@ -2745,4 +3443,135 @@ \global\def\pgfplotstable@fgc@lastwasless{#2}% }% + + +\def\pgfplotstabletranspose@[#1]#2#3{% + %\begingroup is already in \pgfplotstabletranspose + \def\pgfplotstable@loc@TMPa{#1}% + \ifx\pgfplotstable@loc@TMPa\pgfutil@empty + \else + \pgfplotstableset{#1}% + \fi + % + \pgfkeysgetvalue{/pgfplots/table/colnames from}\pgfplotstabletranspose@outcolnames + \pgfkeysgetvalue{/pgfplots/table/input colnames to}\pgfplotstabletranspose@incolnames + \pgfkeysgetvalue{/pgfplots/table/columns}\pgfplotstable@colnames + % + \ifx\pgfplotstable@colnames\pgfutil@empty + \pgfplotstableforeachcolumn{#3}\as\pgfplots@colname{% + \ifnum\pgfplotstablecol=0 + \let\pgfplotstable@colnames=\pgfplots@colname + \else + \t@pgfplots@toka=\expandafter{\pgfplots@colname}% + \t@pgfplots@tokb=\expandafter{\pgfplotstable@colnames}% + \edef\pgfplotstable@colnames{\the\t@pgfplots@tokb,\the\t@pgfplots@toka}% + \fi + }% + \fi + % + % sanity checking: + \ifx\pgfplotstabletranspose@outcolnames\pgfutil@empty + \else + \def\pgfplotstable@loc@TMPa{\expandafter\pgfutil@in@\expandafter{\pgfplotstabletranspose@outcolnames}}% + \expandafter\pgfplotstable@loc@TMPa\expandafter{\pgfplotstable@colnames}% + \ifpgfutil@in@ + \else + % insert the 'colnames from' column into 'columns': + \pgfplots@warning{table transposition: the 'colnames from=\pgfplotstabletranspose@outcolnames' is not part of 'columns'. Adding it.}% + \t@pgfplots@toka=\expandafter{\pgfplotstabletranspose@outcolnames}% + \t@pgfplots@tokb=\expandafter{\pgfplotstable@colnames}% + \edef\pgfplotstable@colnames{\the\t@pgfplots@tokb,\the\t@pgfplots@toka}% + \fi + \fi + % + \global\pgfplotslistnewempty\pgfplotstable@colnames@glob + % this thing counts output columns: + \let\c@pgfplotstable@numoutcols=\c@pgf@countd + \c@pgfplotstable@numoutcols=0 + \let\c@pgfplotstable@rowindex=\c@pgf@counta + \c@pgfplotstable@rowindex=0 + % + \ifx\pgfplotstabletranspose@incolnames\pgfutil@empty + \else + \expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplotstabletranspose@incolnames}\to\pgfplotstable@colnames@glob + \def\pgfplots@loc@TMPa{\pgfplotsapplistXnewempty[to global]}% + \expandafter\pgfplots@loc@TMPa\csname pgfp@numtable@glob@col@0\endcsname + \advance\c@pgfplotstable@numoutcols by1 + \fi + \def\pgfplotstable@isfirstcol{1}% + \expandafter\pgfplotsutilforeachcommasep\expandafter{\pgfplotstable@colnames}\as\pgfplots@colname{% + \c@pgfplotstable@rowindex=0 + \ifx\pgfplotstabletranspose@incolnames\pgfutil@empty + \else + \def\pgfplotstabletranspose@useit{1}% + \ifx\pgfplotstabletranspose@outcolnames\pgfutil@empty + \else + \ifx\pgfplotstabletranspose@outcolnames\pgfplots@colname + \def\pgfplotstabletranspose@useit{0}% + \fi + \fi + \if1\pgfplotstabletranspose@useit + \expandafter\pgfplotslist@assembleentry\expandafter{\pgfplots@colname}\into\t@pgfplots@tokc + \def\pgfplotstableread@TMP{\expandafter\pgfplotsapplistXpushback\expandafter{\the\t@pgfplots@tokc}\to}% + \expandafter\pgfplotstableread@TMP\csname pgfp@numtable@glob@col@\the\c@pgfplotstable@rowindex\endcsname + \advance\c@pgfplotstable@rowindex by1 + \fi + \fi + % + \pgfplotstableforeachcolumnelement\pgfplots@colname\of#3\as\pgfplots@cell{% + \if1\pgfplotstable@isfirstcol + % prepare a new column for the output: + \def\pgfplots@loc@TMPa{\pgfplotsapplistXnewempty[to global]}% + \expandafter\pgfplots@loc@TMPa\csname pgfp@numtable@glob@col@\the\c@pgfplotstable@rowindex\endcsname + % + \ifx\pgfplotstabletranspose@outcolnames\pgfutil@empty + \edef\pgfplotstable@loc@TMPa{\pgfplotstablerow}% + \expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplotstable@loc@TMPa}\to\pgfplotstable@colnames@glob + \fi + \advance\c@pgfplotstable@numoutcols by1 + \fi + \def\pgfplotstabletranspose@useit{1}% + \ifx\pgfplotstabletranspose@outcolnames\pgfutil@empty + \else + \ifx\pgfplotstabletranspose@outcolnames\pgfplots@colname + \pgfutil@ifundefined{pgfplotstabletranspose@@\pgfplots@cell}{% + }{% + \let\pgfplots@loc@TMPa=\pgfplots@cell + \pgfplotsthrow{non unique colname}{\pgfplots@loc@TMPa}{Sorry, 'colnames from=\pgfplotstabletranspose@outcolnames' doesn't yield unique column names (`\pgfplots@cell' comes twice)}\pgfeov% + \ifx\pgfplots@loc@TMPa\pgfutil@empty + \edef\pgfplots@cell{row no \pgfplotstablerow}% + \fi + }% + \expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplots@cell}\to\pgfplotstable@colnames@glob + \expandafter\def\csname pgfplotstabletranspose@@\pgfplots@cell\endcsname{1}% + \def\pgfplotstabletranspose@useit{0}% + \fi + \fi + \if1\pgfplotstabletranspose@useit + % append everything to the output column with index + % \pgfplotstablerow + \expandafter\pgfplotslist@assembleentry\expandafter{\pgfplots@cell}\into\t@pgfplots@tokc + \def\pgfplotstableread@TMP{\expandafter\pgfplotsapplistXpushback\expandafter{\the\t@pgfplots@tokc}\to}% + \expandafter\pgfplotstableread@TMP\csname pgfp@numtable@glob@col@\the\c@pgfplotstable@rowindex\endcsname + \advance\c@pgfplotstable@rowindex by1 + \fi + }% + \def\pgfplotstable@isfirstcol{0}% + }% + % + % flush the buffers of the applistX things: + \c@pgfplotstable@rowindex=0 + \pgfutil@loop + \ifnum\c@pgfplotstable@rowindex<\c@pgfplotstable@numoutcols + \expandafter\pgfplotsapplistXflushbuffers\csname pgfp@numtable@glob@col@\the\c@pgfplotstable@rowindex\endcsname + \advance\c@pgfplotstable@rowindex by1 + \pgfutil@repeat + % finalize the global buffers: + \def\pgfplotsscanlinelength{-1}% + \edef\pgfplots@loc@TMPa{\pgfplotstablenameof{#3}_transposed}% + \expandafter\pgfplotstable@copy@to@globalbuffers@simple\expandafter{\pgfplots@loc@TMPa}% + \endgroup + \pgfplotstable@copy@globalbuffers@to{#2}% +}% + \endinput |