% Copyright 2019 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.

\ProvidesFileRCS{pgfmoduledatavisualization.code.tex}

\usepgfmodule{oo,shapes}%
\usepgflibrary{fpu}%


% This module defines the basic framework for data visualization.

% In order to visualize data, you first need data. The format for this
% data is not specified, indeed, different formats are possible. A
% data point is created each time the command \pgfdatapoint is
% used. The "parameters" of the data point are just the current values
% of the keys or macros in the current scope.
%
% A set of data points created using the \pgfdata command.
% When a data point is created, a number of signals are emitted, see
% the description of \pgfdatapoint. To actually visualize something,
% objects should be created that listen to these signals and that
% handle them.
%
% The following class manages a data visualization

\pgfooclass{data visualization}
{%
  % Class data visualization
  %
  % This class is used to "manage" a data visualization. It provides
  % methods for hooking into the data visualization process and its
  % constructor initializes the signals that are issued during a data
  % visualization.
  %
  % When a data visualization object is created, a whole bunch of
  % signal objects. You should then create objects that connect to
  % these signals. They will be emitted when datapoints come
  % available.
  %
  % It is permissible to have several data visualization objects
  % active at the same time.
  %
  % To use a data visualization object, you should (possibly
  % repeatedly) call the method add data() or the macro \pgfdata. You should also
  % create transformation, mapping and visualization objects. Then,
  % you should, first, call the method survey, which will "survey" the
  % data, allowing the mapping and bounding objects to compute the
  % correct ranges. You may then create further objects based on this
  % data. Then, you should call the "visualize" method, which will
  % invoke the visualization signals for the data points.


  % These attribute store code that should be executed at certain
  % points. The order is the following:
  %
  %  1. "before survey" code
  %  2. "begin survey" phase signal
  %  3. "at start survey" code
  %  4. data points are processed
  %  5. "at end survey" code
  %  6. "end survey" phase signal
  %  7. "after survey" code
  %
  % The first seven points will be repeated until the method "do
  % another survey" is no longer called during a survey.
  %
  %  8. "before visualization" code
  %  9. "begin visualization" phase signal
  % 10. "at start visualization" code
  % 11. data points are processed once more
  % 12. "at end visualization" code
  % 13. "end visualization" phase signal
  % 14. "after visualization" code
  \attribute before survey;%
  \attribute at start survey;%
  \attribute at end survey;%
  \attribute after survey;%
  \attribute before visualization;%
  \attribute at start visualization;%
  \attribute at end visualization;%
  \attribute after visualization;%

  %
  % Survey counts and handling
  %

  \attribute survey count=1;%
  % Each time a survey is done before the visualization is done, this
  % count is incremented. Normally, there is only one survey, but
  % objects may request another survey or even more surveys to be
  % done, giving them a chance to setup further internal values. By
  % accessing this count (via the get survey count method), you can
  % find out which survey is currently being done.

  \attribute number of surveys=1;%
  % By increasing this count, you can request additional surveys to be
  % done.


  % Stores the to-be-visualized data
  \attribute data;%


  % Stores the signal objects
  \attribute prepare datapoint signal;%
  \attribute map datapoint signal;%
  \attribute transform datapoint signal;%
  \attribute visualize datapoint signal;%
  \attribute finish datapoint signal;%
  \attribute survey datapoint signal;%
  \attribute phase signal;%
  \attribute path signal;%
  \attribute direction signal;%
  \attribute style signal;%


  % Constructor
  %
  % Inits the signals
  \method data visualization() {
    \pgfoonew{prepare datapoint signal}=new signal()%
    \pgfoonew{map datapoint signal}=new signal()%
    \pgfoonew{transform datapoint signal}=new signal()%
    \pgfoonew{visualize datapoint signal}=new signal()%
    \pgfoonew{finish datapoint signal}=new signal()%
    \pgfoonew{survey datapoint signal}=new signal()%
    \pgfoonew{phase signal}=new signal()%
    \pgfoonew{path signal}=new signal()%
    \pgfoonew{direction signal}=new signal()%
    \pgfoonew{style signal}=new signal()%
    %
    % Store this object in a key
    %
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeyslet{/pgf/data visualization/obj}\pgf@dv@me
  }%

  % The phase signal will emit the following constants:
  \def\pgfdvbeforesurvey{1}%
  \def\pgfdvbeginsurvey{2}%
  \def\pgfdvendsurvey{3}%
  \def\pgfdvaftersurvey{4}%
  \def\pgfdvbeforevisualization{5}%
  \def\pgfdvbeginvisualization{6}%
  \def\pgfdvendvisualization{7}%
  \def\pgfdvaftervisualization{8}%

  % The path signale will meit the following constants:
  \def\pgfdvpathmovetotoken{5}%
  \def\pgfdvpathlinetotoken{6}%
  \def\pgfdvdirectionfromtoken{7}%
  \def\pgfdvdirectiontotoken{8}%
  \def\pgfdvdirectionattoken{9}%

  % Method
  %
  % Connect the object #1's slot "#2" to the signal named "#3"
  \method connect(#1,#2,#3) {
    \pgfoovalueof{#3}.connect(#1,#2)
  }%

  % Method
  %
  % Add data that is to be visualized. The code #1 should call the
  % \pgfdatapoint macro for each data point it creates.
  \method add data(#1) {
    \pgf@dv@stripped@add#1\pgf@stop
  }%
  \def\pgf@dv@stripped@add#1\pgf@stop{%
    \pgfooappend{data}{#1}%
  }%


  % Setters
  \method before survey(#1) {
    \pgfooappend{before survey}{#1}
  }%
  \method at start survey(#1) {
    \pgfooappend{at start survey}{#1}
  }%
  \method before visualization(#1) {
    \pgfooappend{before visualization}{#1}
  }%
  \method at start visualization(#1) {
    \pgfooappend{at start visualization}{#1}
  }%

  % Method
  \method at end survey(#1) {
    \pgfooprefix{at end survey}{#1}
  }%
  \method after survey(#1) {
    \pgfooprefix{after survey}{#1}
  }%
  \method at end visualization(#1) {
    \pgfooprefix{at end visualization}{#1}
  }%
  \method after visualization(#1) {
    \pgfooprefix{after visualization}{#1}
  }%


  % Method
  %
  % Copy the signals to macros. This is just for efficiency (ha!)
  \method prepare signal macros() {
    \pgfooget{prepare datapoint signal}\pgf@signalpreparedatapoint
    \pgfooget{map datapoint signal}\pgf@signalmapdatapoint
    \pgfooget{transform datapoint signal}\pgf@signaltransformdatapoint
    \pgfooget{visualize datapoint signal}\pgf@signalvisualizedatapoint
    \pgfooget{finish datapoint signal}\pgf@signalfinishdatapoint
    \pgfooget{survey datapoint signal}\pgf@signalsurveydatapoint
    \pgfooget{phase signal}\pgf@signalphase
    \pgfooget{path signal}\pgf@signalpath
    \pgfooget{direction signal}\pgf@signaldirection
    \pgfooget{style signal}\pgf@signalstyle
  }%


  % Survey method
  %
  % Call this method to "survey" the data. This should be done before
  % the "visualize" method is called.
  \method survey() {
    % Survey phase.
    \let\pgfdatapoint=\pgfdatapoint@surveyphase%
    \pgfoothis.prepare signal macros()
    \pgfooset{survey count}{1}
    \pgfutil@loop
      \pgf@signalphase.emit(\pgfdvbeforesurvey)
      \pgfoovalueof{before survey}%
      \pgf@signalphase.emit(\pgfdvbeginsurvey)
      \pgfoovalueof{at start survey}
      \pgfoovalueof{data}%
      \pgfoovalueof{at end survey}
      \pgf@signalphase.emit(\pgfdvendsurvey)%
      \pgfoovalueof{after survey}
      \pgf@signalphase.emit(\pgfdvaftersurvey)
      \c@pgf@counta=\pgfoovalueof{survey count}\relax
      \c@pgf@countb=\pgfoovalueof{number of surveys}\relax
    \ifnum\c@pgf@counta<\c@pgf@countb
      \advance\c@pgf@counta by1\relax
      \pgfooeset{survey count}{\the\c@pgf@counta}
    \pgfutil@repeat
  }%

  % Getter
  \method get survey count(#1) {
    \pgfooget{survey count}{#1}
  }%

  % Request another survey to be done
  \method do an additional survey() {
    \c@pgf@counta=\pgfoovalueof{number of surveys}\relax
    \advance\c@pgf@counta by1\relax
    \pgfooeset{number of surveys}{\the\c@pgf@counta}
  }%

  % Visualize method
  %
  % This method will cause the actual visualization.
  \method visualize() {
    % Visualization phase.
    \let\pgfdatapoint=\pgfdatapoint@visualizationphase%
    \pgfoothis.prepare signal macros()
    \pgf@signalphase.emit(\pgfdvbeforevisualization)%
    \pgfoovalueof{before visualization}
    \pgf@signalphase.emit(\pgfdvbeginvisualization)%
    \pgfoovalueof{at start visualization}
    \pgfoovalueof{data}%
    \pgfoovalueof{at end visualization}
    \pgf@signalphase.emit(\pgfdvendvisualization)%
    \pgfoovalueof{after visualization}
    \pgf@signalphase.emit(\pgfdvaftervisualization)%
  }%
}%


%
% The data point keys
%
% Unlike other keys, the subkeys of /data point/ can simply be set
% directly. If the key has not been initialized, it will automatically
% be.
\pgfkeys{/data point/.unknown/.code={%
    \pgfkeyssetvalue{/data point/\pgfkeyscurrentname}{#1}
  },
}%




% Create and handle a data point
%
% Description:
%
% This command is called by the survey and the visualize methods
% whenever a complete data point has been produced. Depending on the
% current circumstances, different signals will be emitted.
%
% The data that is represented by the data point is not given as a
% parameter. Rather, it is stored in macros and keys, that is, the
% data point is conceptually given by the settings of all the keys and
% macros in the local scope.
%
% There are two phases to data processing: In the survey phase data
% points are produced and handled in order to find out things like
% their number or the minimum and maximum values of attributes, so
% that axes and picture sizes can be prepared correctly. In the
% visualization phase, data point are actually shown.
%
% During the survey phase, for each data point the signal
% "surveydatapoint" is emitted.
%
% During the visualization phase, more signals are emitted. A prepare
% signal is emitted first, giving all objects a
% chance to "prepare" for the data point. Note that it is permissible
% for an object to manipulate the data point here (and also
% in later on).
%
% Next, the command \pgfdvmapdatapointtocanvas is called. Mainly,
% the effect of this command is to setup the keys /data point/canvas x
% and /data point/canvas y, see the description of this command for
% more details.
%
% The next step consists of signaling "visualize data point". Objects
% listening to this will cause some form of visualization of the
% data point to occur.
%
% Before the visualization is started, it is checked whether the key
% /data point/name is set (to a non-empty value). If so,
% a coordinate is created with the given canvas x and y values and
% this key's value as name.
%
% Finally, finish data point allows objects to do any final processing
% of the data point.

\def\pgfdatapoint@surveyphase{%
  \pgf@signalpreparedatapoint.emit()%
  \pgf@signalmapdatapoint.emit()%
  \pgf@signalsurveydatapoint.emit()%
}%

\def\pgfdatapoint@visualizationphase{%
  \pgf@signalpreparedatapoint.emit()%
  \pgfdvmapdatapointtocanvas%
  \pgfkeysifdefined{/data point/name}
  {%
    \pgfcoordinate{\pgfkeysvalueof{/data point/name}}{\pgfpointdvdatapoint}%
  }{}%
  \pgf@signalvisualizedatapoint.emit()%
  \pgf@signalfinishdatapoint.emit()%
}%



% Compute a position of a data point
%
% Description:
%
% This command uses a special signal to compute the position where a
% data point should be visualized on the canvas. In detail, the
% following happens:
%
% A local scope is created and the
% transformation matrix is reset. Then, two signals are emitted: First,
% "map data points" and then "transform data point". The first
% lets listening objects "map" the object by setting up
% attributes of the data point. The second asks objects
% listening to this signal to transform  the current transformation
% matrix. After the signals, we compute where
% the origin lies inside this transformed coordinate system. Then the
% two keys /data point/canvas x and /data point/canvas y are set to
% the values of this position. The local scope ends (but the settings
% of the keys persist by a bit of magic), thus restoring the
% transformation matrix to its original value.

\def\pgfdvmapdatapointtocanvas{%
  {%
    \pgfpointdvlocaldatapoint
    % Smuggle outside group
    \expandafter%
  }%
  \edef\pgf@marshal{%
    \noexpand\pgfkeyssetvalue{/data point/canvas x}{\the\pgf@x}
    \noexpand\pgfkeyssetvalue{/data point/canvas y}{\the\pgf@y}
  }%
  \pgf@marshal%
}%

% Help functions for locating a canvas data point
%
% Description:
%
% The first function returns the data point computed by a
% canvasposition... call.

\def\pgfpointdvdatapoint{%
  \pgfqpoint{\pgfkeysvalueof{/data point/canvas x}}{\pgfkeysvalueof{/data point/canvas y}}%
}%

\def\pgfpointdvlocaldatapoint{%
  {%
    % only returns the data point in \pgf@x and \pgf@y, does not set
    % canvas x and canvas y
    \pgf@signalmapdatapoint.emit()%
    \pgftransformreset%
    \pgf@signaltransformdatapoint.emit()%
    \pgfpointtransformed{\pgfpointorigin}%
  }%
}%



%
% Special path constructions commands
%
%
% The following commands are used to construct paths based on
% datapoints.
%
% Normally, all these methods need to do is to compute the current
% canvas position of the current data point and then do a moveto,
% lineto or some other operation to this position.
%
% However, when the coordinate system is weird, like with polar
% coordinates or spherical or log-polar coordinate or whatever, a
% straight line "along an attribute" is no longer a straight line.
% In this case, two actions can be taken:
%
% 1. The problem can be ignored, resulting in a wrong line.
% 2. Some clever algorithm kicks in an replaces the straight line by
%    the correct replacement.
%
% As always, when a computer tries to be clever, things can go
% wrong... Nevertheless, some support for the second method is
% given. This works as follows: Objects can register to the data
% visualization path signal. This signal is emitted every time the
% lineto or moveto commands are executed. If an object reacts to such
% a command and handles it, it should set
% \pgfdvhandledtrue.

\newif\ifpgfdvhandled

\def\pgfdv@generic#1#2#3{%
  {%
    \pgfdvhandledfalse%
    \pgf@signalmapdatapoint.emit()%
    #1.emit(#2)%
    \ifpgfdvhandled%
    \else%
      \pgf@process{%
        \pgftransformreset%
        \pgf@signaltransformdatapoint.emit()%
        \pgfpointtransformed{\pgfpointorigin}%
      }%
      #3{}%
    \fi%
  }%
}%


% Handle a moveto
%
% This command has no parameters since the target of the moveto is
% given by the canvas position of the current local data point.
\def\pgfpathdvmoveto{%
  \pgfdv@generic{\pgf@signalpath}{\pgfdvpathmovetotoken}{\pgfpathmoveto}
}%


% Handle a lineto
%
% This command has no parameters since the target of the moveto is
% given by the canvas position of the current local data point.
\def\pgfpathdvlineto{%
  \pgfdv@generic{\pgf@signalpath}{\pgfdvpathlinetotoken}{\pgfpathlineto}
}%



% Compute a normalized vector at the current point pointing along a
% line from #1 to #2.
%
% #1 = code for setting the attributes of the first point
% #2 = code for setting the attributes of the second point
%
% The current point should be a point on a line from #1 to
% #2. Both points as well as the current point are
% localized on the canvas and a vector pointing from the first point
% to the second one is returned. However, for instance in polar
% coordinates the vector may actually "point along" the angle axis.
%
% Internally, this command first sets up the first data point and then
% emits a "direction" signal with the \pgfdvpathdirectionfromtoken set and
% then sets up the second point and emits the corresponding
% ...totoken. Finally, the \pgfdvpathdirectionattoken is emitted.
%

\def\pgfpointdvdirection#1#2{%
  {
    {
      #1
      \pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectionfromtoken}{\xdef\pgf@dv@from{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}
    }
    {
      #2
      \pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectiontotoken}{\xdef\pgf@dv@to{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}
    }
    {\pgfdv@generic{\pgf@signaldirection}{\pgfdvdirectionattoken}{%
        \pgf@process{
          \pgfpointnormalised{%
            \pgfpointdiff{\pgf@dv@from}{\pgf@dv@to}
          }
        }}}
  }
}%





%
%
% Data parsing and formatting
%
%



% Run the rendering pipeline on a dataset and/or save the dataset.
%
% #1 = options with path /pgf/data/
% #2 = optionally data given inline in curly braces.
%
% Description:
%
% This command is used to define a data set. For a single data
% visualization, multiple data sets can be defined, they will
% accumulate. Data can be in different formats, as specified by the
% "format" key, and you can define new formats.
%
% The settings of the following keys are important:
%
% /pgf/data visualization/obj
%   contains a handle to the dv-object
%
% /pgf/data/format
%   stores the format (see below)
%
% /pgf/data/read from file
%   determines where the data is.
%
% /pgf/data/store in group
%   when nonempty, the data is stored here instead of being fed to the
%   rendering pipeline
%
% /pgf/data/use group
%   when nonempty, data that has previously been stored here using
%   |define group| is read from here and all other keys are ignored
%
% If "read from file" is empty, the data is stored in the argument that
% follows. Otherwise, the data is read from the specified source file.
% This data is stored in an internal variable, which is local to the
% current group.
%
% After the group, the key "/pgf/data/continue code" will be
% executed.
%
% When the data is actually used later on (during a survey or a
% visualization), independently of what source is used, a format
% handler is started for each data set. This works as follows: first,
% the handler's startup code is executed. Then for each line of the
% data file/the data given inline, the line handler function is
% called. Finally, the data format end handler is called.
%
% The format handler's job is to call \pgfdatapoint each time a
% complete data point has been produced.
%
% Example:
%
% \pgfoonew \dv=new data visualization()
% \pgfoonew \obj=new attribute mapper(...)
% ...
%
% \pgfkeys{/pgf/data/.cd,
%          column 1=dax/low,
%          column 2=dax/high,
%          column 3=dax/entry,
%          column 4=dax/exit}
%
% \pgfdata[format=space separated columns]
% {
%   % today
%   2000 2300 2100 2200
%   2000 2350 2200 2500
%   2200 2300 2250 2260
%   1800 2260 2260 1900
%   2000 2300 2100 2200
% }
%
% \pgfdata[format=comma separated columns]
% {
%   % yesterday
%   2000, 2350, 2200, 2250
%   2200, 2300, 2250, 2260
% }
%
% \pgfdata[read from file=data.csv,format=comma separated columns]
%
% \dv.survey()
% \dv.visualize()

\def\pgfdata{\pgfutil@ifnextchar[{\pgf@datagroup@data@opt}{\pgf@datagroup@data@opt[]}}%}%
\def\pgf@datagroup@data@opt[#1]{%
  % Ok, add one data thing...
  \begingroup%
    \pgfkeys{/pgf/data/.cd,/pgf/every data/.try,#1}%
    \pgfkeysgetvalue{/pgf/data/continue code}\pgf@dv@cont@code%
    \global\let\pgf@dv@cont@code\pgf@dv@cont@code%
    \pgfkeysgetvalue{/pgf/data/use group}\pgf@dv@use@group%
    \ifx\pgf@dv@use@group\pgfutil@empty%
      \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data(\pgf@do@data{#1})}%
      \expandafter\pgf@datagroup@data@opt@cont%
    \else%
      \expandafter\ifx\csname pgf@dv@group@@\pgf@dv@use@group\endcsname\relax%
        \pgferror{Undefined data group '\pgf@dv@use@group'}%
      \else%
        {%
          \pgfkeys{/pgf/data/define group/.code=}% no redefinitions during use
          \csname pgf@dv@group@@\pgf@dv@use@group\endcsname%
        }%
      \fi%
  \endgroup%
  \expandafter\pgf@dv@cont@code%
      \fi%
}%
\def\pgf@datagroup@data@opt@cont{%
  \pgfkeysgetvalue{/pgf/data/format}\pgf@dv@format%
  \expandafter\let\expandafter\pgf@dv@format@catcodes\csname pgfdv@format@\pgf@dv@format @catcodes\endcsname%
  \ifx\pgf@dv@format@catcodes\relax
    \pgferror{Unknown data format '\pgf@dv@format'}%
  \else%
    \pgfkeysgetvalue{/pgf/data/read from file}\pgf@dv@source%
    \ifx\pgf@dv@source\pgfutil@empty%
      \let\pgf@next\pgf@datagroup@grab@inline%
    \else%
      \let\pgf@next\pgf@datagroup@grab@external%
    \fi%
    \pgf@next%
}%

\def\pgf@datagroup@grab@inline{%
  \pgfutil@ifnextchar\bgroup{%
    \begingroup%
    \catcode`\^^M=\active%
    \pgf@dv@format@catcodes%
    \pgf@datagroup@grab@@inline}%
  {\pgferror{Opening brace expected}}%
}%
\def\pgf@datagroup@grab@external{%
    \fi%
  \endgroup%
  \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data({{{\pgf@datagroup@do@external}}})}%
  \pgf@dv@cont@code%
}%

\def\pgf@dv@do@adddata#1{%
  \pgfkeysgetvalue{/pgf/data/store in group}\pgf@dv@temp%
  \ifx\pgf@dv@temp\pgfutil@empty%
    #1%
  \else%
    \expandafter\pgfutil@g@addto@macro\csname pgf@dv@group@@\pgf@dv@temp\endcsname{#1}%
  \fi%
}%

{\catcode`\^=7 \catcode`\^^M=13
  \gdef\pgf@datagroup@grab@@inline#1{%
    \endgroup%
    \pgf@dv@do@adddata{\pgfkeysvalueof{/pgf/data visualization/obj}.add data({{{\pgf@datagroup@do@inline#1^^M\pgf@@eol}}})}%
    \fi%
  \endgroup%
  \pgf@dv@cont@code%
  }%
}%
\def\pgf@@eol{\pgf@eol}%

\def\pgf@do@data#1#2{%
  \begingroup%
    \pgfkeys{/pgf/data/.cd,/pgf/every data/.try,#1}%
    \pgfkeysgetvalue{/pgf/data/format}\pgf@dv@format%
    \expandafter\let\expandafter\pgf@dv@format@line\csname pgfdv@format@\pgf@dv@format @line\endcsname%
    \expandafter\let\expandafter\pgf@dv@format@emptyline\csname pgfdv@format@\pgf@dv@format @empty\endcsname%
    \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@startup\endcsname%
    #2%
    \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@end\endcsname%
  \endgroup%
}%


%
% Read external file
%

\def\pgf@datagroup@do@external{%
  \csname pgfdv@format@\pgfkeysvalueof{/pgf/data/format}@catcodes\endcsname%
  \immediate\openin\r@pgf@reada=\pgfkeysvalueof{/pgf/data/read from file} %
  \ifeof\r@pgf@reada\relax
     \pgferror{Data file '\pgfkeysvalueof{/pgf/data/read from file}' not found}%
  \else
    \pgf@datagroup@readline%
  \fi
  \immediate\closein\r@pgf@reada%
}%

\def\pgf@partext{\par}%
\def\pgf@datagroup@readline{%
  \immediate\read\r@pgf@reada to \pgf@temp%
  \ifx\pgf@temp\pgf@partext%
    \pgf@dv@format@emptyline%
  \else%
    \ifx\pgf@temp\pgfutil@empty%
      \pgf@dv@format@emptyline%
    \else%
      \expandafter\pgf@dv@format@line\pgf@temp\pgfeol%
    \fi%
  \fi%
  \ifeof\r@pgf@reada\else\expandafter\pgf@datagroup@readline\fi%
}%


%
% Read inline data
%

\def\pgf@datagroup@do@inline{%
  \pgf@dv@handle@line%
}%

{\catcode`\^=7 \catcode`\^^M=13
\gdef\pgf@dv@handle@line{%
  \pgfutil@ifnextchar^^M{\pgf@dv@format@emptyline\expandafter\pgf@dv@handle@line\pgfutil@gobble}%
  {\pgfutil@ifnextchar\pgf@@eol{\pgfutil@gobble}{\pgf@dv@handle@nonemptyline}}%
}%
\gdef\pgf@dv@handle@nonemptyline#1^^M{%
  \pgf@dv@format@line#1\pgfeol%
  \pgf@dv@handle@line%
}%
}%

\pgfkeys{
  /pgf/data/data visualization obj/.initial=\undefined,
  /pgf/data/format/.initial=table,% the default format
  /pgf/data/read from file/.initial=,
  /pgf/data/inline/.style={read from file=},
  /pgf/data/continue code/.initial=,
  /pgf/data/store in group/.initial=,
  /pgf/data/new group/.code={\expandafter\global\expandafter\let\csname pgf@dv@group@@#1\endcsname\pgfutil@empty},
  /pgf/data/use group/.initial=,
}%






% Define a data format
%
% #1 = format name
% #2 = catcode code
% #3 = startup code
% #4 = line arguments
% #5 = line code
% #6 = empty line code
% #7 = end code
%
% Description:
%
% This command defines a new data format for data visualization. When
% a data set is visualized and the format is set to #1, this handler
% is used to parse the data.
%
% In detail, the \pgfdata command will select a source. Before this
% source is read, #2 will be executed to setup the
% catcodes. Additionally, each time the data is parsed, #3 will be
% called. Then, for each nonempty line of the source, the
% command #5 is executed, where the line will be matched against the
% argument pattern given in #4. For empty lines, #6 will be executed
% instead. At the end of the source, #7 will be executed.

\def\pgfdeclaredataformat#1#2#3#4#5#6#7{%
  \expandafter\def\csname pgfdv@format@#1@catcodes\endcsname{#2}%
  \expandafter\def\csname pgfdv@format@#1@startup\endcsname{#3}%
  \expandafter\def\csname pgfdv@format@#1@line\endcsname#4\pgfeol{#5}%
  \expandafter\def\csname pgfdv@format@#1@empty\endcsname{#6}%
  \expandafter\def\csname pgfdv@format@#1@end\endcsname{#7}%
}%



%
% Predefined standard formats
%

% TeX code format
%
% Description:
%
% The lines of the data set are assumed to contain executable TeX
% code that will call \pgfdatapoint.
%
% Example:
%
% \pgfdatavisualizationrender[format=TeX code]
% \dataset{
%   \pgfkeyssetvalue{/data point/x}{5}
%   \pgfkeyssetvalue{/data point/y}{5}
%   \pgfdatapoint
%   \pgfkeyssetvalue{/data point/x}{6}
%   \pgfkeyssetvalue{/data point/y}{6}
%   \pgfdatapoint
% }

\pgfdeclaredataformat{TeX code}{}{}{#1}{#1 }{}{}%



% Key-value lines format
%
% Description:
%
% The lines of the data set are passed to \pgfkeys with the path set
% to /data point.
%
% Example:
%
% \data[format=named] {
%   x=5, y=6, hi=9
%   x=7, y=6, lo=10
% }

\pgfdeclaredataformat{named}{}{}{#1}{\pgf@dv@parse@named#1,\pgf@stop}{}{}%
\def\pgf@dv@parse@named{%
  \pgfutil@ifnextchar\pgf@stop{\pgfdatapoint\pgfutil@gobble}{\pgf@dv@parse@named@}
}%
\def\pgf@dv@parse@named@#1=#2,#3\pgf@stop{%
  \foreach \pgf@dv@temp in {#2} {%
    \def\pgf@dv@tempb{/data point/#1=}%
    \expandafter\expandafter\expandafter\pgfkeys%
    \expandafter\expandafter\expandafter{\expandafter\pgf@dv@tempb\pgf@dv@temp}%
    \pgf@dv@parse@named#3\pgf@stop%
  }
}%





% Table format
%
% Description:
%
% A table consists of a head line, which contains the attribute names
% of the values that will be found in the following lines. Each line
% (except for the headline) contains one data point.
%
% Inside each line the data points are separated by a separator like a
% comma or a space or a colon. The separator can be configured using
% the key /pgf/data/separator (leave the separator empty or set it to
% \space for a space as separator). The default separator is a comma.
%
% Some tables will miss the headline. In this case, using the
% /pgf/data/headline key you can provide a headline yourself.
%
% Example:
%
% \data[format=table] {
%    x  y
%   10  5
%   11  6
%    6  7
%  }
%
% \data[format=table,separator={,}] {
%    x, y
%   10, 5
%   11, 6
%    6, 7
% }
%
% \data[format=table,headline=x y] {
%   10 5
%   11 6
%    6 7
% }

\pgfdeclaredataformat{table}
{} % no catcodes
{
  \pgfkeysgetvalue{/pgf/data/headline}\pgf@dv@headline
  \pgfkeysgetvalue{/pgf/data/separator}\pgf@dv@separator
  \ifx\pgf@dv@separator\pgfutil@empty
    \let\pgf@dv@separator\space
  \fi
  \ifx\pgf@dv@separator\pgf@dv@spacetext
    \let\pgf@dv@separator\space
  \fi
  \expandafter\def\expandafter\pgf@dv@till@separator%
  \expandafter##\expandafter1\pgf@dv@separator{\pgf@dv@table@handle{##1}}
  \expandafter\def\expandafter\pgf@dv@till@separator@head%
  \expandafter##\expandafter1\pgf@dv@separator{\pgf@dv@head@handle{##1}}
  \ifx\pgf@dv@headline\pgfutil@empty
    % Ok, read headline from file
    \pgfdv@firstlinetrue
  \else
    % Headline already set
    \pgfdv@firstlinefalse
    \expandafter\pgf@dv@parse@headline\expandafter{\pgf@dv@headline}
  \fi
}
{#1} % special line pattern, so read everything
{
  \ifpgfdv@firstline
    \pgfdv@firstlinefalse
    \pgf@dv@parse@headline{#1}
  \else
    {
      \c@pgf@counta=0\relax% keep track of attribute number
      \def\pgf@marshal{\pgf@dv@parse@table#1}
      \expandafter\expandafter\expandafter\pgf@marshal%
      \expandafter\pgf@dv@separator\expandafter\pgfeol\pgf@dv@separator
      \pgfdatapoint
    }
  \fi
}
{}% ignore empty lines
{}% no special end code

\newif\ifpgfdv@firstline

\pgfkeys{
  /pgf/data/separator/.initial={,},
  /pgf/data/headline/.initial=
}%
\def\pgf@dv@spacetext{\space}%

\def\pgf@dv@parse@table{%
  \pgfutil@ifnextchar"% Special, but ignored right now...
  {\pgferror{csv with quotes not yet implemented}}
  {\pgf@dv@till@separator}
}%
\def\pgf@dv@table@handle#1{%
  \def\pgf@temp{#1}%
  \ifx\pgf@temp\pgfeoltext%
    % Bingo! Stop
    \let\pgf@next=\relax%
  \else%
    \advance\c@pgf@counta by1\relax%
    \pgfkeysgetvalue{/pgf/data/table/attribute \the\c@pgf@counta}\pgf@dv@target
    \ifx\pgf@dv@target\relax%
      \edef\pgf@dv@target{attribute \the\c@pgf@counta}
      \pgfkeyslet{/pgf/data/table/attribute \the\c@pgf@counta}\pgf@dv@target
    \fi
    \pgfkeyssetvalue{/data point/\pgf@dv@target}{#1}
    \let\pgf@next=\pgf@dv@parse@table%
  \fi%
  \pgf@next%
}%



\def\pgf@dv@parse@headline#1{
  \c@pgf@counta=0\relax% keep track of attribute number
  \def\pgf@marshal{\pgf@dv@doparse@headline#1}
  \expandafter\expandafter\expandafter\pgf@marshal%
  \expandafter\pgf@dv@separator\expandafter\pgfeol\pgf@dv@separator
}%

\def\pgf@dv@doparse@headline{%
  \pgfutil@ifnextchar"% Special, but ignored right now...
  {\pgferror{csv with quotes not yet implemented}}
  {\pgf@dv@till@separator@head}
}%
\def\pgf@dv@head@handle#1{%
  \def\pgf@temp{#1}%
  \ifx\pgf@temp\pgfeoltext%
    % Bingo! Stop
    \let\pgf@next=\relax%
  \else%
    \advance\c@pgf@counta by1\relax%
    \pgfkeyssetvalue{/pgf/data/table/attribute \the\c@pgf@counta}{#1}
    \let\pgf@next=\pgf@dv@doparse@headline%
  \fi%
  \pgf@next%
}%

\def\pgfeoltext{\pgfeol}%


%
%
% Micro math kernel for dv
%
%

% The idea behind the following methods is to "abstract away" which
% math engine is used. In the future, something fancy build on luatex
% might be used, so it would we should not rely directly on the
% fpu library code.
%
% The system works as follows: First, you "enter" a number into the
% engine. When you do so, it is converted into some internal
% representation that cannot be accessed any more and is called a
% "math variable" henceforth. All commands of the
% math system only work on math variables.
%
% In order to "exit" a value stored in a math variable from the
% engine, some other macros can be used.
%
% Operations like addition or multiplication take two math variables
% and store the result in another math variable.



% Store a value in a math variable of the math engine
%
% #1 = a math variable (a macro name) that is to store the value
% #2 = an expression describing a number
%
%
% Description:
%
% The #2 should be an expression that evaluates to a number. However,
% due to the way the pgf math engine(s) work, currently, there are
% several restrictions/the syntax is not as simple as one might
% hope. Fortunately, the syntax is hopefully compatible with
% easier-to-use future systems.
%
% The syntax is as follows: #2 may be
%
% 1. a simple high-precision number. This number is currently directly
%    passed to \pgfmathfloatparsenumber, so typical permissible values
%    are "100" or "10000000000000" or "nan" or "-5.673543345345e9000"
%
% 2. a mathematical expression, which *must* be surrounded by
%    parentheses. From a "mathematical" point of view these
%    parentheses are superfluous, but the they are used to help pgf
%    distinguish expressions from high-precision numbers. (If, in the
%    future, expressions may contain high precision numbers, the
%    parentheses will simply be ignored.)
%
%    The expression is evaluated using \pgfmathparse, which means that
%    TeX-precision is used. This means, for instance, that numbers
%    larger than about 16500 will create error messages.
%
%    The advantage is that you may say write things like "(5+6)" or
%    "(pi/2)".
%
% 3. In case #2 starts with an exclamation mark (indicating an
%    "escape"), everything following the mark is simply evaluated by
%    TeX. The effect of evaluating #2 should be that the math
%    variable "\pgfdvmathvalue" is set to some value. This value will
%    then be transferred to #1.
%
% 4. In case #2 is the result of calling \pgfdvmathexitbyserializing, the
%    "serialized" value is restored. The idea is that the serialized
%    will turn its internal representation of a number into something
%    that can be stored as a text somewhere.
%
%    Currently, "@" at the beginning of #2 is used to indicate that
%    what follows is a serialized version of a math variable.
%
% In order to determine which of the above cases is to be used for a
% variable, the first symbol #2 is checked, *after* the first symbol
% of #2 has been expanded once (using \expandafter once).
%
% Example:
%
% \pgfdvmathenter{\mymacro}{20000000000000}
% \pgfdvmathenter{\mymacro}{(5+pi)}
% \pgfdvmathenter{\mymacro}{!\pgfdvmathadd{\pgfdvmathvalue}{\a}{\b}}
%
% \pgfdvmathenter{\foo}{5}
% \pgfdvmathexitbyserializing{\somevalue}{\foo}
% \pgfdvmathenter{\mymacro}{\somevalue}

\def\pgfdvmathenter#1#2{%
  \expandafter\pgfdvmathenter@check\expandafter#1#2\pgfdvmath@end%
}%
\def\pgfdvmathenter@check#1{%
  \pgfutil@ifnextchar @{\pgfdvmath@internal#1}{%
    \pgfutil@ifnextchar ({\pgfdvmath@expression#1}{%)
      \pgfutil@ifnextchar !{\pgfdvmath@execute#1}{\pgfdvmath@normal#1}}}%
}%

\def\pgfdvmath@internal#1@#2\pgfdvmath@end{%
  \def#1{#2}%
}%
\def\pgfdvmath@expression#1(#2)#3\pgfdvmath@end{%
  \pgfmathparse{#2}%
  \pgfmathfloatparsenumber{\pgfmathresult}%
  \let#1=\pgfmathresult%
}%
\def\pgfdvmath@execute#1!#2\pgfdvmath@end{%
  #2%
  \let#1=\pgfdvmathvalue%
}%
\def\pgfdvmath@normal#1#2\pgfdvmath@end{%
  \pgfmathfloatparsenumber{#2}%
  \let#1=\pgfmathresult%
}%



% Print a math variable in the math engine using \pgfmathprintnumber
%
% #1 = math variable
%
% Description:
%
% See the description of \pgfmathprintnumber
%
% Example:
%
% \pgfdvmathenter{\mymacro}{20000000000000}
% \pgfdvmathexitbyprinting{\mymacro}

\def\pgfdvmathexitbyprinting#1{%
  \pgfmathprintnumber{#1}%
}%



% Exit a math variable as a number in a scientific and portable number
% format in a macro
%
% #1 = macro in which to store the value
% #2 = math variable
%
% Description:
%
% You can exit a number using this operation. You can then directly
% reenter the number using \pgfdvmathenter
%
% Example:
%
% \pgfdvmathenter{\mynumber}{20000000000000}
% \pgfdvmathexitbyscientificformat{\mymacro}{\mynumber}

\def\pgfdvmathexitbyscientificformat#1#2{%
  \edef#1{\pgfmathfloatvalueof#2}%
}%



% Exit a math variable as a "serialized" (= string-based)
% version.
%
% #1 = macro in which to store the value
% #2 = math variable
%
% Description:
%
% The serialized version can be reentered using
% \pgfmathenter and is similar to \pgfdvmathexitbyscientificformat,
% but exiting and entering are (a bit) faster.
%
% Example:
%
% \pgfdvmathenter{\mynumber}{20000000000000}
% \pgfdvmathexitbyserializing{\mymacro}{\mynumber}

\def\pgfdvmathexitbyserializing#1#2{%
  \edef#1{@#2}%
}%





% Operations on two numbers
%
% #1 = macro that should store the result of applying the
%      corresponding operation to the following:
% #2 = entered number
% #3 = entered number
%
% Description:
%
% Sets #1 to the result of applying an operation to #2 and #3
%
% Example:
%
% \pgfdvmathenter{\a}{2000}
% \pgfdvmathenter{\b}{5+6}
% \pgfdvmathadd{\c}{\a}{\b}

\def\pgfdvmathadd#1#2#3{%
  \pgfmathfloatadd{#2}{#3}%
  \let#1=\pgfmathresult%
}%
\def\pgfdvmathsub#1#2#3{%
  \pgfmathfloatsubtract{#2}{#3}%
  \let#1=\pgfmathresult%
}%
\def\pgfdvmathmul#1#2#3{%
  \pgfmathfloatmultiply{#2}{#3}%
  \let#1=\pgfmathresult%
}%
\def\pgfdvmathdiv#1#2#3{%
  \pgfmathfloatdivide{#2}{#3}%
  \let#1=\pgfmathresult%
}%

% Multiply by small number
%
% #1 = macro that should store the result of applying the
%      corresponding operation to the following:
% #2 = entered number
% #3 = fixed point number like 2 or 0.5, but not 10000000000
%
% Description:
%
% Sets #1 to the result of applying an operation to #2 and #3
%
% Example:
%
% \pgfdvmathenter{\a}{2000}
% \pgfdvmathadd{\b}{\a}{0.2}
% % \b now stores 400

\def\pgfdvmathmulfixed#1#2#3{%
  \pgfmathfloatmultiplyfixed{#2}{#3}%
  \let#1=\pgfmathresult%
}%



% Log, ln and exponent functions
%
% #1 = a math variable
% #2 = a math variable
%
% Description
%
% \pgfdvmathln will compute #1 = ln(#2)
% \pgfdvmathlog will compute #1 = log_{10}(#2)
% \pgfdvmathexp will compute #1 = exp(#2)
% \pgfdvmathpowten will compute #1 = 10^{#2}

\def\pgfdvmathln#1#2{%
  \pgfmathfloatln{#2}%
  \let#1=\pgfmathresult%
}%

\def\pgfdvmathlog#1#2{%
  \pgfmathfloatln{#2}%
  \pgfmathfloatmultiply{\pgfmathresult}{\pgfdvmathalwaysloge}%
  \let#1=\pgfmathresult%
}%

\def\pgfdvmathexp#1#2{%
  \pgfmathfloatexp{#2}%
  \let#1=\pgfmathresult%
}%

\def\pgfdvmathpowten#1#2{%
  \pgfmathfloattofixed{#2}%
  \let\pgf@dv@temp=\pgfmathresult%
  \pgfmathround{\pgf@dv@temp}%
  \let\pgf@dv@temp@round=\pgfmathresult%
  \pgf@x=\pgf@dv@temp@round pt%
  \pgf@x=-\pgf@x%
  \advance\pgf@x by\pgf@dv@temp pt\relax%
  \ifdim\pgf@x>0.0002pt%
    \pgfmathfloatmultiply{#2}{\pgfdvmathalwayslnten}%
    \pgfmathfloatexp{\pgfmathresult}%
  \else
    \ifdim\pgf@x<-0.0002pt%
      \pgfmathfloatmultiply{#2}{\pgfdvmathalwayslnten}%
      \pgfmathfloatexp{\pgfmathresult}%
    \else
      \pgf@x=\pgf@dv@temp@round sp%
      \c@pgf@counta=\pgf@x%
      \pgfmathfloatcreate{1}{1.0}{\the\c@pgf@counta}%
    \fi
  \fi
  \let#1=\pgfmathresult%
}%


% Floor functions
%
% #1 = a math variable
% #2 = a math variable
%
% Description
%
% Sets #1 to the largest integer less or equal to #2

\def\pgfdvmathfloor#1#2{%
  \pgfmathifisint{#2}{%
    \let#1=#2%
  }{%
    \pgfmathfloatgetflags#2\c@pgf@counta%
    \ifcase\c@pgf@counta
      \let#1=\pgfdvmathalwayszero%
    \or
      \pgfmathfloatfloor{#2}%
      \let#1=\pgfmathresult%
    \or
      \pgfmathfloatsubtract{\pgfdvmathalwaysone}{#2}%
      \pgfmathfloatfloor{\pgfmathresult}%
      \pgfmathfloatsubtract{\pgfdvmathalwayszero}{\pgfmathresult}%
      \let#1=\pgfmathresult%
    \or\let#1=#2%
    \or\let#1=#2%
    \or\let#1=#2%
    \fi%
  }%
}%


% Advanced unary operations
%
% #1 = macro that should store the result of applying the
%      operation to an entered number
% #2 = the operation (as a string like "ln")
% #3 = entered number
%
% Description:
%
% Sets #1 to the result of applying #2 to #3
%
% Example:
%
% \pgfdvmathenter{\a}{2000}
% \pgfdvmathunaryop{\b}{ln}{\a}

\def\pgfdvmathunaryop#1#2#3{%
  \csname pgfmathfloat#2\endcsname{#3}%
  \let#1=\pgfmathresult%
}%


% Advanced binary operations
%
% #1 = macro that should store the result of applying the
%      operation to two entered number
% #2 = the operation (as a string like "veclen")
% #3 = first argument (an entered number)
% #4 = second argument (an entered number)
%
% Description:
%
% Sets #1 to the result of applying #2 to #3
%
% Example:
%
% \pgfdvmathenter{\a}{3}
% \pgfdvmathenter{\b}{4}
% \pgfdvmathbinop{\c}{veclen}{\a}{\b}

\def\pgfdvmathbinop#1#2#3#4{%
  \csname pgfmathfloat#2\endcsname{#3}{#4}%
  \let#1=\pgfmathresult%
}%



% Comparing values
%
% #1 = first math variable
% #2 = second math variable
% #3 = code to-be-executed if #1 < #2
% #4 = code to-be-executed if #1 >= #2
%
%
% Example:
%
% \pgfdvmathenter{\a}{3}
% \pgfdvmathenter{\b}{4}
% \pgfdvmathifless{\a}{\b}{yes}{should not happen}

\def\pgfdvmathifless#1#2#3#4{%
  \pgfmathfloatlessthan{#1}{#2}%
  \ifpgfmathfloatcomparison#3\else#4\fi%
}%




%
%
% Standard objects for data visualization
%
%


%
% Transformers
%

\pgfooclass{linear transformer}
{%
  % Class linear transformer
  %
  % This class is a transformer class. It reacts to the transform
  % datapoint signal. When this signal is raised, it will shift the
  % coordinate system as follows: If the current value of /data
  % point/this.attribute  is 0, then the system is shifted to the
  % current value of this.origin. If the current value is 1, the
  % system is shifted to this.origin + this.unit vector. For other
  % values of /data point/this.attribuate, the shift is interpolated
  % between these two values.


  \attribute attribute;%
  % The attribute (/data point/this.attribute) by which
  % the unit vector is multiplied. If it is empty (which is
  % different from 0), no transformation is done at all.

  \attribute origin = \pgfpointorigin;%
  % The shift in case the /data point/this.attribute is 0.

  \attribute unit vector;%
  % The coordinate system is additionally shifted by this amount
  % times the current value of /data point/this.attribute.


  % Constructor
  %
  % #1 = attribute that is being transformed. Example: x
  % #2 = a vector corresponding to one unit of #1.
  %      Example: \pgfpoint{1cm}{0cm}
  \method linear transformer(#1,#2) {
    \pgfooset{attribute}{#1}
    \pgf@process{#2}
    \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
    \pgfoolet{unit vector}\pgf@temp%
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,transform,transform datapoint signal)
  }%

  % Setter
  \method set origin(#1) {
    \pgf@process{#1}
    \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
    \pgfoolet{origin}\pgf@temp%
  }%

  % Slot
  %
  % This slot should be connected to the transform datapoint
  % signal. When this signal is emitted, the coordinate system will be
  % shifted according to the current value of the attribute.
  \method transform() {
    \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}\pgf@dv@val%
    \ifx\pgf@dv@val\pgfutil@empty%
    \else%
      \ifx\pgf@dv@val\relax%
      \else%
        \pgfdvmathenter{\pgf@dv@math@var}{\pgf@dv@val}%
        \pgfdvmathexitbyscientificformat{\pgf@dv@val}{\pgf@dv@math@var}%
        \pgftransformshift{\pgfoovalueof{origin}}%
        \pgfmathfloatgetexponent\pgf@dv@math@var\c@pgf@counta%
        \ifnum\c@pgf@counta<-3\relax%
        \else%
          \pgftransformshift{\pgfpointscale{\pgf@dv@val}{\pgfoovalueof{unit vector}}}%
        \fi%
      \fi%
    \fi%
  }%
}%


%
% Numerical mapping of attributes to other attributes
%

\pgfooclass{interval mapper}
{%
  % Class interval mapper
  %
  % This interval mapper reacts to the map datapoint signal. Its purpose is to
  % map one attribute to another attribute. For the first attribute,
  % an intervals is specified.
  %
  % In addition to the in interval [a,b] there is also an outinterval
  % [c,d]. Values in the range [a,b] are linearly mapped to the
  % range [c,d] and the result is stored in the second attribute.
  %
  % For instance, if the first range is [10,20] and the second range
  % is [0,100], then 10 is mapped to 0, 11 is mapped to 10, 20 is
  % mapped to 100 and 30 is mapped to 200.
  %
  % It is permissible to specify an additional non-linear
  % transformation function f. In this case, for an input value x the
  % position of f(x) inside the interval [f(a),f(b)] is determined and
  % this position is linearly mapped to [c,d].
  %
  % For example, if f(x) = log_10 (x) and the first range [a,b] =
  % [10,1000] and the second range is [1,2], then 10 is mapped to 1,
  % 100 is mapped to 1.5 (since f(100) = 3 lies in the middle
  % between f(10) = 2 and f(1000) = 4) and 100000 is mapped to 3.


  \attribute in;%
  % The name of the input attribute. If the value of this attribute
  % is empty or undefined, no mapping is done.
  %
  % The in attribute may have a subkey called .../const. If this key
  % has a value different from \relax, it will always be used instead
  % of the in attribute itself. This can be useful to temporarily
  % set a constant value to a key inside a mapping chain.
  %
  % If the subkey /is min or max is set to "min" or "max", the mapping
  % will always be done to the respective out min or out max values.

  \attribute out;%
  % The name of the output attribute.

  \attribute trans;%
  % Stores (more or less) the transformation function.

  \attribute out min;%
  % Start of the second range (the value of c).

  \attribute out min;%
  % End of the second range (the value of d).

  \attribute trans in min;%
  % Transformed value of the start of the first range (the value
  % f(a)).

  \attribute scale;%
  % The scaling factor, that is, the value of (f(b)-f(a))/(d-c).


  % Constructor
  %
  % #1 = input attribute. Example: velocity.
  % #2 = output attribute. Example: x
  % #3 = optional transformation function. The input value for this
  %      function is stored in entered number \pgfvalue.
  %      The output of the function should be stored in the
  %      same entered number.
  %
  % The intervals are set using setter methods later on.
  %
  \method interval mapper(#1,#2,#3) {
    \pgfooset{in}{#1}
    \pgfooset{out}{#2}
    \def\pgf@temp{#3}%
    \ifx\pgf@temp\pgfutil@empty%
    \else%
      \pgfooset{trans}{%
        #3%
      }%
    \fi%
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,map,map datapoint signal)
  }%

  % Method
  %
  % #1 = in interval minimum
  % #2 = in interval maximum
  % #3 = out interval minimum
  % #4 = out interval maximum
  %
  % This method will (re)compute the correct mappings for the interval
  % mapper.
  \method set interval values(#1,#2,#3,#4) {
    {%
      \pgfdvmathenter{\pgf@in@interval@min}{#1}
      \pgfdvmathenter{\pgf@in@interval@max}{#2}
      \pgfdvmathenter{\pgf@out@interval@min}{#3}
      \pgfdvmathenter{\pgf@out@interval@max}{#4}
      % Let's start with the output, it's easier...
      \pgfoolet{out min}{\pgf@out@interval@min}
      \pgfoolet{out max}{\pgf@out@interval@max}
      \pgfdvmathifless{\pgf@in@interval@min}{\pgf@in@interval@max}{%
        \pgfdvmathsub{\pgf@out@diff}{\pgf@out@interval@max}{\pgf@out@interval@min}
        \let\pgfvalue=\pgf@in@interval@min
        \pgfoovalueof{trans}
        \let\pgf@in@interval@min@transformed=\pgfvalue
        \pgfoolet{trans in min}{\pgf@in@interval@min@transformed}%
        \let\pgfvalue=\pgf@in@interval@max
        \pgfoovalueof{trans}
        \let\pgf@in@interval@max@transformed=\pgfvalue
        \pgfdvmathsub{\pgf@diff@in@transformed}{\pgf@in@interval@max@transformed}{\pgf@in@interval@min@transformed}
        %
        % Precompute the scaling
        %
        \pgfdvmathdiv{\pgf@scale}{\pgf@out@diff}{\pgf@diff@in@transformed}%
        \pgfoolet{scale}{\pgf@scale}%
      }{%
        \pgfoolet{scale}\pgf@dv@no@scale%
      }%
    }%
  }%
  \def\pgf@dv@no@scale{noscale}%

  % Slot
  \method map() {
    \pgfooget{scale}\pgf@dv@scale
    \ifx\pgf@dv@scale\pgfutil@empty%
      % not yet setup
    \else%
      \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/is min or max}\pgf@dv@is%
      \ifx\pgf@dv@is\pgf@min@text%
        \pgf@dv@set@out@min%
      \else%
        \ifx\pgf@dv@is\pgf@max@text%
          \pgf@dv@set@out@max%
        \else%
          \ifx\pgf@dv@scale\pgf@dv@no@scale%
            \pgf@dv@mapper@goto@mid%
          \else%
            \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/const}\pgf@dv@external@value%
            \ifx\pgf@dv@external@value\relax%
              \pgfkeysgetvalue{/data point/\pgfoovalueof{in}}\pgf@dv@external@value%
            \fi%
            \ifx\pgf@dv@external@value\pgfutil@empty%
              \pgf@dv@mapper@pos@check%
            \else%
              \ifx\pgf@dv@external@value\relax%
                \pgf@dv@mapper@pos@check%
              \else%
                \pgfdvmathenter{\pgfvalue}{\pgf@dv@external@value}%
                \pgf@dv@mapper@trans
              \fi%
            \fi%
          \fi%
        \fi%
      \fi%
    \fi%
  }%

  \def\pgf@dv@set@out@min{%
    \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@min@text%
    \pgfooget{out min}{\pgf@minmax@temp}%
    \pgf@dv@set@out@now%
  }%
  \def\pgf@dv@set@out@max{%
    \pgfkeyslet{/data point/\pgfoovalueof{out}/is min or max}\pgf@max@text%
    \pgfooget{out max}{\pgf@minmax@temp}%
    \pgf@dv@set@out@now%
  }%
  \def\pgf@dv@set@out@now{%
    \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset%
    \ifx\pgf@dv@external@offset\relax\else%
      \ifx\pgf@dv@external@offset\pgfutil@empty\else%
        \pgfdvmathenter{\pgfvalue}{\pgf@minmax@temp}%
        \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}%
        \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@offset}
        \pgfdvmathexitbyserializing{\pgf@minmax@temp}{\pgfvalue}%
      \fi
    \fi
    \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@minmax@temp%
  }%

  \def\pgf@dv@mapper@trans{
    \pgfooget{trans in min}{\pgf@dv@trans@in@min}%
    \pgfooget{scale}{\pgf@dv@scale}%
    \pgfooget{out min}{\pgf@dv@out@min}%
    \pgfoovalueof{trans}%
    \pgfdvmathsub{\pgfvalue}{\pgfvalue}{\pgf@dv@trans@in@min}%
    \pgfdvmathmul{\pgfvalue}{\pgfvalue}{\pgf@dv@scale}%
    \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@out@min}%
    \pgfkeysgetvalue{/data point/\pgfoovalueof{out}/offset}\pgf@dv@external@offset%
    \ifx\pgf@dv@external@offset\relax\else%
      \ifx\pgf@dv@external@offset\pgfutil@empty\else%
        \pgfdvmathenter{\pgf@dv@offset}{\pgf@dv@external@offset}%
        \pgfdvmathadd{\pgfvalue}{\pgfvalue}{\pgf@dv@offset}
      \fi
    \fi
    \pgfdvmathexitbyserializing{\pgf@temp}{\pgfvalue}%
    \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
  }%

  \def\pgf@dv@mapper@pos@check{%
    \pgfkeysgetvalue{/data point/\pgfoovalueof{in}/out pos}\pgf@dv@pos@value%
    \ifx\pgf@dv@pos@value\relax\else\if\pgf@dv@pos@value\pgfutil@empty\else%
      \pgfmathsetmacro{\pgf@dv@pos@num}{\pgf@dv@pos@value}%
      \pgfmathsetmacro{\pgf@dv@pos@num@prime}{1-\pgf@dv@pos@num}%
      % Ok, compute transformed min position:
      \pgfooget{out min}{\pgf@out@interval@min}
      \pgfooget{out max}{\pgf@out@interval@max}
      \pgfdvmathmulfixed{\pgf@out@interval@min}{\pgf@out@interval@min}{\pgf@dv@pos@num@prime}
      \pgfdvmathmulfixed{\pgf@out@interval@max}{\pgf@out@interval@max}{\pgf@dv@pos@num}
      \pgfdvmathadd{\pgf@out@val}{\pgf@out@interval@min}{\pgf@out@interval@max}%
      \pgfdvmathexitbyserializing{\pgf@temp}{\pgf@out@val}%
      \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
    \fi\fi%
  }%

  \def\pgf@dv@mapper@goto@mid{%
    % Ok, compute transformed min position:
    \pgfooget{out min}{\pgf@out@interval@min}
    \pgfooget{out max}{\pgf@out@interval@max}
    \pgfdvmathmulfixed{\pgf@out@interval@min}{\pgf@out@interval@min}{.5}
    \pgfdvmathmulfixed{\pgf@out@interval@max}{\pgf@out@interval@max}{.5}
    \pgfdvmathadd{\pgf@out@val}{\pgf@out@interval@min}{\pgf@out@interval@max}%
    \pgfdvmathexitbyserializing{\pgf@temp}{\pgf@out@val}%
    \pgfkeyslet{/data point/\pgfoovalueof{out}}\pgf@temp%
  }%
}%





%\newif\ifpgf@dvclip
\newif\ifpgf@dvignore

\pgfooclass{scaling mapper}
{%
  % Class scaling mapper
  %
  % A scaling mapper is (mainly) used to scale an attribute in such a way
  % that it can be rendered easily on a page. The idea is that you
  % specify some attribute and a desired target interval size (like
  % [0,5]). The scaling mapper will then survey the data and will setup a
  % interval mapper in such a way that the minimum value present in the data is
  % mapped to 0 and the maximum to 5. However, it is also possible to,
  % say, only have the maximum value mapped to 5 and have 0 be mapped
  % to 0. Other, more complicated specifications are also possible.
  %
  % The scaling mapper internally creates several objects: First, a surveyor
  % for determining the minimum and maximum values of the attribute
  % and a interval mapper for then mapping the values to the scaled
  % values. Additionally, interval objects are needed.

  \attribute in;%
  % The to-be-scaled attribute;

  \attribute out;%
  % The attribute storing the scaled value.

  \attribute in range obj;%
  % This interval keep track of the range of the in attribute

  \attribute scaling spec;%
  % A specification of how the scaling should be performed.
  %
  % The format is the following:
  %
  % #1 at #2 and #3 at #4
  %
  % Here, #2 and #4 must be numbers. #1 and #3 can either be numbers
  % or #1 can be the text "min" and #3 can be the text "max".
  %
  % The effect of such a specification is the following: The value #1
  % is mapped to #2, the value #3 is mapped to #4 and values between
  % #1 and #3 (or outside this range) are mapped linearly to a value
  % between (or outside) #2 and #4. In case #1 is set to "min", the
  % smallest observed value of the in-attribute is mapped to #3 and
  % similarly for a value of "max" for #3.
  %
  % Additionally, as for a interval mapper, a function f might be specified
  % that deforms the linear mapping. In case f is specified,
  % f(#1) is mapped to #2 and f(#3) is mapped to #4.

  \attribute spec maps min;%
  % When the scaling spec maps "min" to some value, rather than some
  % specific value to that value, then spec maps min will be set to
  % \pgfutil@firstoftwo, otherwise to \pgfutil@secondoftwo

  \attribute spec maps max;%
  % Like spec maps min

  \attribute function;%
  % Stores the function

  \attribute interval mapper;%
  % Stores the interval mapper object

  \attribute range surveyor;%
  % Stores the range surveyor object


  % Constructor
  %
  % #1 = in attribute
  % #2 = out attribute
  % #3 = scaling specification
  % #4 = optional function
  %
  \method scaling mapper(#1,#2,#3,#4) {
    %
    % Save the parameters in attributes
    %
    \pgfooset{in}{#1}
    \pgfooset{out}{#2}
    \pgfooset{scaling spec}{#3}
    \pgfooset{function}{#4}
    %
    % Now setup the objects for the before survey phase
    %
    %
    % First, the in range interval
    \pgfoonew \pgf@dv@in@range@obj=new interval(,)
    \pgfoolet{in range obj}\pgf@dv@in@range@obj
    % Second, the in range surveyor. We do not need to store this
    % object, it will "do its work in the background"
    \pgfoonew \pgf@dv@range@obj=new range surveyor(#1,\pgf@dv@in@range@obj)
    \pgf@dv@range@obj.default connects()
    \pgfoolet{range surveyor}\pgf@dv@range@obj
    %
    %
    % The interval mapper:
    %
    \pgfoonew{interval mapper}=new interval mapper(#1,#2,#4)
    \pgfoovalueof{interval mapper}.default connects()
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Getter
  %
  % Returns an interval object that stores the range of the in
  % attribute.
  \method get in range interval() {
    \pgfooget{in range obj}\pgfdvinrangeinterval
  }%


  % Getter
  %
  % Returns the out attribute.
  %
  \method get out() {
    \pgfooget{out}\pgfdvout
  }%

  % Getter
  %
  % Returns the function attribute.
  %
  \method get function(#1) {
    \pgfooget{function}#1
  }%

  % Method
  %
  % #1 = a included in value
  %
  % This method only affects the survey. The value #1 is recorded as
  % if it were encountered for the in attribute at some point.
  %
  \method include in value(#1) {
    \pgfoovalueof{range surveyor}.include attribute value({#1})
  }%


  % Method
  %
  % #1 = value for the attribute
  %
  % Sets the attribute to the (evaluated) given value (evaluation
  % using \pgfmathparse). When the value  is evaluated, the values of
  % \pgfdvmin and \pgfdvmax will be set to the minimum and maximum
  % values of the in interval. (See \pgfdvmathenter with the "!"-notation).
  %
  % In case #1 is set to the special value "min", it evaluates to
  % \pgfdvmin, when set to "max" it evaluates to \pgfdvmax.
  %
  \method set in to(#1) {%
    \edef\pgf@temp{#1}%
    \ifx\pgf@temp\pgf@min@text%
      \pgf@dv@lib@set@mm%
      \let\pgf@dv@value\pgfdvmin%
      \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@min@text}{}%
    \else%
      \ifx\pgf@temp\pgf@max@text%
        \pgf@dv@lib@set@mm%
        \let\pgf@dv@value\pgfdvmax%
        \pgfoovalueof{spec maps min}{\pgfkeyslet{/data point/\pgfoovalueof{in}/is min or max}\pgf@max@text}{}%
      \else%
        \pgfdvmathenter{\pgf@dv@value}{\pgf@temp}%
      \fi%
    \fi%
    \pgfdvmathexitbyserializing{\pgf@dv@serial}{\pgf@dv@value}%
    \pgfkeyslet{/data point/\pgfoovalueof{in}}\pgf@dv@serial%
  }%
  \def\pgf@dv@lib@set@mm{
    \pgfooget{in range obj}\pgfdvinrangeinterval
    \pgfdvinrangeinterval.get min and max()%
  }%


  % Slot
  \method phase(#1) {
    \ifx#1\pgfdvendsurvey
      % Ok, we setup the interval mapper.
      %
      % We start by computing the interval borders:
      \pgfoovalueof{in range obj}.get min and max()
      \ifx\pgfdvmin\pgfutil@empty% undefined, since no data points
      \else%
        \pgfooget{scaling spec}\pgf@temp%
        \expandafter\pgf@lib@dv@parse@scaling\pgf@temp\pgf@stop%
        \pgfoovalueof{interval mapper}.set interval values(%
          \pgf@lib@dv@min,\pgf@lib@dv@max,%
          \pgf@lib@dv@min@at,\pgf@lib@dv@max@at)
      \fi
    \fi
  }%


  % Internal helper
  \def\pgf@lib@dv@parse@scaling#1 at#2and #3 at#4\pgf@stop{%
    \def\pgf@lib@dv@min{#1}%
    \pgfdvmathenter{\pgf@lib@dv@min@at@mv}{#2}
    \def\pgf@lib@dv@max{#3}%
    \pgfdvmathenter{\pgf@lib@dv@max@at@mv}{#4}
    \ifx\pgf@lib@dv@min\pgf@min@text%
      \let\pgf@lib@dv@min@mv\pgfdvmin
      \pgfoolet{spec maps min}\pgfutil@firstoftwo%
    \else
      \pgfdvmathenter{\pgf@lib@dv@min@mv}{\pgf@lib@dv@min}
      \pgfoolet{spec maps min}\pgfutil@secondoftwo%
    \fi
    \ifx\pgf@lib@dv@max\pgf@max@text%
      \let\pgf@lib@dv@max@mv\pgfdvmax
      \pgfoolet{spec maps max}\pgfutil@firstoftwo%
    \else
      \pgfdvmathenter{\pgf@lib@dv@max@mv}{\pgf@lib@dv@max}
      \pgfoolet{spec maps max}\pgfutil@secondoftwo%
    \fi
    \pgfdvmathexitbyserializing{\pgf@lib@dv@min}{\pgf@lib@dv@min@mv}
    \pgfdvmathexitbyserializing{\pgf@lib@dv@min@at}{\pgf@lib@dv@min@at@mv}
    \pgfdvmathexitbyserializing{\pgf@lib@dv@max}{\pgf@lib@dv@max@mv}
    \pgfdvmathexitbyserializing{\pgf@lib@dv@max@at}{\pgf@lib@dv@max@at@mv}
  }%
  \def\pgf@min@text{min}%
  \def\pgf@max@text{max}%
}%





%
% Surveyors
%

\pgfooclass{range surveyor}
{%
  % Class range surveyor
  %
  % A range surveyor is used only in the survey phase. Its job is to
  % determine the minimum and maximum values of an attribute that are
  % "seen" during the survey phase. Based on this value, the size of,
  % say, an axis can be determined later on.
  %
  % You can also set the key "sub attributes" of the attribute. In
  % this case, this key should contain -- as the name suggests -- a
  % list of subkeys that should also be taken into account for the
  % computation of the minimum and maximum value. Inside the "sub
  % attributes" key, each subkey should be surrounded by a call of
  % \pgfdvsub. For instance, if there are two sub attributes "/data
  % point/velocity/min" and "/data point/velocity/max" for a key
  % "/data point/velocity", then "/data point/velocity/sub attributes"
  % should be set to "\pgfdvsub{/min}\pgfdvsub{/max}".

  \attribute attribute;%
  % The to-be-surveyed attribute

  \attribute interval obj;%
  % The interval object that protocols the minimum and maximum
  % values.


  % Constructor
  %
  % #1 = the attribute
  % #2 = handle to the interval object
  %
  \method range surveyor(#1,#2) {
    \pgfooset{attribute}{#1}
    \pgfoolet{interval obj}#2
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,survey,survey datapoint signal)
  }%

  % Method
  %
  % #1 = a value
  %
  % Adjust the interval as if during the survey this value were
  % encountered
  \method include attribute value(#1) {
    \pgf@dv@assign@val@stripped#1\pgf@stop%
    \pgfoovalueof{interval obj}.adjust(\pgf@dv@range@surv)
  }%
  \def\pgf@dv@assign@val@stripped#1\pgf@stop{%
    \def\pgf@dv@val{#1}
  }%

  % Slot
  %
  % This slot should be connected to the survey datapoint signal. For
  % each datapoint, this method will call the adjust method of the
  % interval.
  %
  \method survey() {
    \let\pgfdvsub\pgf@dv@range@surv@sub
    \pgfdvsub{}%
    \pgfkeysvalueof{/data point/\pgfoovalueof{attribute}/sub attributes}
  }%

  \def\pgf@dv@range@surv@sub#1{
    \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}#1}\pgf@dv@val%
    \ifx\pgf@dv@val\relax%
    \else%
      \edef\pgf@dv@val{\pgf@dv@val}%
      \ifx\pgf@dv@val\pgfutil@empty%
      \else%
        \pgfoovalueof{interval obj}.adjust(\pgf@dv@range@surv)%
      \fi%
    \fi%
  }%

  \def\pgf@dv@range@surv{%
    \pgfdvmathenter{\pgf@dv@value}{\pgf@dv@val}%
    % Now, protocol value
    \ifx\pgfdvmin\pgfutil@empty%
      \let\pgfdvmin\pgf@dv@value%
    \else%
      \pgfdvmathifless{\pgf@dv@value}{\pgfdvmin}{\let\pgfdvmin\pgf@dv@value}{}%
    \fi%
    \ifx\pgfdvmax\pgfutil@empty%
      \let\pgfdvmax\pgf@dv@value%
    \else%
      \pgfdvmathifless{\pgfdvmax}{\pgf@dv@value}{\let\pgfdvmax\pgf@dv@value}{}%
    \fi%
  }%
}%



%
% Visualizers
%

\usepgflibrary{plothandlers}%



\pgfooclass{plot handler visualizer}
{%
  % Class plot handler visualizer
  %
  % This visualizer uses one or more plot handlers to visualize data points.
  % As the data points are processed, the canvas positions of the data
  % points are recorded. At the end of a group of data points, the
  % recorded stream of canvas position is visualized (rendered)
  % using plot handlers. For instance, when the lineto plot handler
  % is used, the data points are connected by straight lines, when the
  % curveto plot handler is used, they are connected by smooth curves
  % and so on.
  %
  % Since plot lines are not drawn immediately, but only at the end,
  % when everything has been collected, multiple plot handlers can
  % coexist peacefully at the same time.
  %
  % You can specify a "filter", which will cause only those data
  % points to be visualized by the visualizer that pass the test. The
  % filter should set \pgfdvfilterpassedfalse for to-be-filtered data
  % point.
  %
  % You can specify "projection code" that changes the canvas x and
  % canvas y positions. This projection code allows you to draw, say,
  % projected points instead of the actual data point.
  %
  % The keys /data point/<name>/execute at begin and /data
  % point/<name>/execute at end, where <name> is the name of
  % the visualizer, should store code that is to be executed directly
  % before and after the stream of coordinates is created. Typically,
  % these keys will store commands to use the path created by the plot
  % handler.

  \attribute handlers;%
  % The to-be-used handlers

  \attribute name;%
  % The attribute

  \attribute filter=\pgfdvnamedvisualizerfilter;%
  % Filter code

  \attribute positions;%
  % An internal protocol of the positions on the stream

  \attribute cache;%
  % An internal cache. Positions are first inserted into this
  % cache. Every 100 steps this cache is moved to positions. The idea
  % behind this is that it will avoid the quadratic time increase that
  % is normally caused when a protocol is build in TeX.

  \attribute projection code;%
  % This code is empty by default. However, you can set it for
  % instance to the following
  %
  % \pgfkeyssetvalue{/data point/y=0}\pgfdvmapdatapointtocanvas
  %
  % in order to visualize the data point with its y-coordinate
  % replaced by 0.

  % Constructor
  %
  % #1 = A name
  % #2 = A comma-separated list of handlers like
  %      "\pgfplothandlerlineto,\pgfplothandlercurveto"
  %
  \method plot handler visualizer(#1,#2) {
    \pgfooset{name}{#1}
    \pgfooset{handlers}{#2}
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,protocol,visualize datapoint signal)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Setter
  \method set filter(#1) {
    \pgfooset{filter}{#1}
  }%

  % Setter
  \method set projection code(#1) {
    \pgfooset{projection code}{#1}
  }%

  % Slot
  \method protocol() {
    \pgfdvfilterpassedtrue
    \pgfoovalueof{filter}
    \ifpgfdvfilterpassed%
      \pgf@dv@line@cache@it
    \fi%
  }%

  \def\pgf@dv@line@cache@it{
    % Cache it
    \pgfooget{cache}\pgf@dv@cache
    \pgfkeysgetvalue{/data point/outlier}\pgf@temp%
    \ifx\pgf@temp\pgfutil@empty
      {%
        \pgfoovalueof{projection code}
        \xdef\pgf@dv@add{\noexpand\pgf@dv@ph{\pgfkeysvalueof{/data
              point/canvas x}}{\pgfkeysvalueof{/data point/canvas y}}}%
      }
    \else%
      % An outlier!
      \gdef\pgf@dv@add{\pgf@dv@outliner}%
    \fi%
    \expandafter\expandafter\expandafter\def%
    \expandafter\expandafter\expandafter\pgf@dv@cache%
    \expandafter\expandafter\expandafter{\expandafter\pgf@dv@cache\pgf@dv@add}%
    % Possibly flush cache
    \global\advance\pgf@lib@dv@cache@count by1\relax%
    \ifnum\pgf@lib@dv@cache@count=100\relax%
      \global\pgf@lib@dv@cache@count=0\relax%
      % Append cache to positions
      \pgfooget{positions}\pgf@dv@temp
      \expandafter\expandafter\expandafter\def%
      \expandafter\expandafter\expandafter\pgf@dv@temp%
      \expandafter\expandafter\expandafter{\expandafter\pgf@dv@temp\pgf@dv@cache}%
      \pgfoolet{positions}\pgf@dv@temp
      \let\pgf@dv@cache\pgfutil@empty
    \fi
    \pgfoolet{cache}\pgf@dv@cache
  }%

  % Slot
  \method phase(#1) {%
    \ifx#1\pgfdvendvisualization%
      \pgfoothis.render()%
    \fi%
  }%

  % Internal method
  \method render() {
    \pgfscope
      \pgfooget{handlers}\tikz@dv@temp@list
      \foreach\tikz@dv@temp in\tikz@dv@temp@list{
        \ifx\tikz@dv@temp\pgfutil@empty
        \else
          \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at begin}
          \tikz@dv@temp
          \pgfdvnewstreamtrue
          \pgfoovalueof{positions}
          \pgfoovalueof{cache}
          \ifpgfdvnewstream\else\pgfplotstreamend\fi
          \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at end}
        \fi
      }
    \endpgfscope
    \pgfoolet{positions}\pgfutil@empty
    \pgfoolet{cache}\pgfutil@empty
  }%

  \def\pgf@dv@ph#1#2{\ifpgfdvnewstream\pgfplotstreamstart\pgfdvnewstreamfalse\fi\pgfplotstreampoint{\pgfqpoint{#1}{#2}}}%
  \def\pgf@dv@outliner{\ifpgfdvnewstream\else\pgfplotstreamend\pgfdvnewstreamtrue\fi}%
}%

\newif\ifpgfdvnewstream
\newcount\pgf@lib@dv@cache@count

\pgfkeys{%
  /data point/outlier/.initial=,
  /data point/outlier/.default=true,
}%


% A possible filter for unnamed visualizers
%
% #1 = Text to be compared with key /data point/set
%
% Description:
%
% In a data visualization with multiple visualizers, data points
% typically "belong" only to a single visualizer. It is, thus,
% necessary to filter data points according to the current
% visualizer. This current visualizer is assumed to be stored in /data
% point/visualizer.
%
% When objects allow you to set a filter, you can use this filter to
% test against /data point/set being equal to #1.

\def\pgfdvvisualizerfilter#1{%
  \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
  \def\pgf@temp{#1}%
  \ifx\pgf@temp\pgf@dv@visualizer%
  \else
    \pgfdvfilterpassedfalse
  \fi%
}%



% A filter for named visualizer
%
% Description:
%
% This filter works like \pgfdvvisualizerfilter, only it assumes the
% the object defines a "name" attribute. In this case, the value of
% /data point/set is tested against this attribute.

\def\pgfdvnamedvisualizerfilter{%
  \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
  \pgfooget{name}\pgf@temp%
  \ifx\pgf@temp\pgf@dv@visualizer%
  \else
    \pgfdvfilterpassedfalse
  \fi%
}%



\pgfooclass{rectangle visualizer}
{%
  % Class rectangle visualizer
  %
  % This visualizer visualizes a datapoint as a rectangle. It needs
  % a name, so that /data point/<name>/attribute 1 and /data
  % point/<name>/attribute 2 store two attributes names a1 to a2. Then,
  % provided the current value of /data point/set equals name, for
  % each data point a rectangle between (a1/min,a2/min) and
  % (a1/max,a2/max) is created.


  \attribute name;%
  % The name

  \attribute a1;%
  \attribute a2;%
  % The attributes, filled from /data point/<name>/attribute 1 and 2


  % Constructor
  %
  % #1 = first attribute
  % #2 = second attribute
  %
  \method rectangle visualizer(#1) {
    \pgfooset{name}{#1}
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,visualize,visualize datapoint signal)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Slot
  \method phase(#1) {%
    \ifx#1\pgfdvbeginsurvey%
      \pgfooeset{a1}{/data point/\pgfkeysvalueof{/data point/\pgfoovalueof{name}/attribute 1}}
      \pgfooeset{a2}{/data point/\pgfkeysvalueof{/data point/\pgfoovalueof{name}/attribute 2}}
      \pgfkeyssetvalue{\pgfoovalueof{a1}/sub attributes}{\pgfdvsub{/min}\pgfdvsub{/max}}
      \pgfkeyssetvalue{\pgfoovalueof{a2}/sub attributes}{\pgfdvsub{/min}\pgfdvsub{/max}}
    \fi%
  }%

  % Slot
  \method visualize() {
    {
      \pgfkeysgetvalue{/data point/set}\pgf@dv@visualizer%
      \pgfooget{name}\pgf@temp%
      \ifx\pgf@temp\pgf@dv@visualizer%
        \pgf@dv@rect@do
      \fi
    }
  }%

  \def\pgf@dv@rect@do{
      \pgfkeysgetvalue{\pgfoovalueof{a1}/min}\pgf@dv@amin
      \ifx\pgf@dv@amin\relax\else\ifx\pgf@dv@amin\pgfutil@empty\else
      \pgfkeysgetvalue{\pgfoovalueof{a1}/max}\pgf@dv@amax
      \ifx\pgf@dv@amax\relax\else\ifx\pgf@dv@amax\pgfutil@empty\else
      \pgfkeysgetvalue{\pgfoovalueof{a2}/min}\pgf@dv@bmin
      \ifx\pgf@dv@bmin\relax\else\ifx\pgf@dv@bmin\pgfutil@empty\else
      \pgfkeysgetvalue{\pgfoovalueof{a2}/max}\pgf@dv@bmax
      \ifx\pgf@dv@bmax\relax\else\ifx\pgf@dv@bmax\pgfutil@empty\else
      \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at begin}
        \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amin}
        \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmin}
        \pgfpathdvmoveto
        \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmax}
        \pgfpathdvlineto
        \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amax}
        \pgfpathdvlineto
        \pgfkeyssetvalue{\pgfoovalueof{a2}}{\pgf@dv@bmin}
        \pgfpathdvlineto
        \pgfkeyssetvalue{\pgfoovalueof{a1}}{\pgf@dv@amin}
        \pgfpathdvlineto
        \pgfpathclose
      \pgfkeysvalueof{/data point/\pgfoovalueof{name}/execute at end}
      \fi\fi
      \fi\fi
      \fi\fi
      \fi\fi
  }%
}%

\newcount\pgf@lib@dv@cache@count



%
% Label positioning classes
%

\pgfooclass{label visualizer}
{%
  % Class label visualizer
  %
  % The job of this class is to visualize a label of a curve or some
  % other object.
  %
  % The idea is as follows: This class monitors a certain
  % attribute. When this attribute reaches a certain value for the
  % first time, the following happens: A normalized vector of the line
  % connecting the current canvas position to the canvas position of
  % the previous data point is computed and stored in pgf@x/pgf@y. The
  % coordinate system is shifted so that the current data point is at
  % the origin. Then, some drawing code is executed.

  \attribute attribute;%
  % The monitored attribute

  \attribute filter;%
  % Filter code, see plot handler visualizer doc.

  \attribute threshold;%
  % When the attribute exceeds this threshold, the drawing code is
  % executed

  \attribute before canvas position=;%
  % Stores canvas position of the data point before the interesting one

  \attribute canvas position=;%
  % Stores canvas position of the data point

  \attribute code;%
  % To-be-executed code when the label should be drawn


  % Constructor
  %
  % #1 = attribute
  % #2 = a macro, storing the threshold
  % #3 = code
  % #4 = filter code
  %
  \method label visualizer(#1,#2,#3,#4) {
    \pgfooset{attribute}{#1}
    \expandafter\pgfdvmathenter\expandafter{\expandafter\pgf@temp\expandafter}\expandafter{#2}
    \pgfoolet{threshold}\pgf@temp
    \pgfooset{code}{#3}
    \pgfooset{filter}{#4}
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,test,visualize datapoint signal)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Slot
  \method test() {
    \pgfdvfilterpassedtrue
    \pgfoovalueof{filter}
    \ifpgfdvfilterpassed%
      \pgfooget{attribute}\pgf@dv@attribute
      \ifx\pgf@dv@attribute\pgfutil@empty%
      % nothing to do (anymore)
      \else%
        \pgf@dv@label@vis@record
      \fi%
    \fi%
  }%

  \def\pgf@dv@label@vis@record{
    % Record current position
    \edef\pgf@dv@pos{%
      \noexpand\pgfqpoint%
      {\pgfkeysvalueof{/data point/canvas x}}%
      {\pgfkeysvalueof{/data point/canvas y}}}%
    \pgfooget{canvas position}\pgf@dv@temp%
    \pgfoolet{before canvas position}\pgf@dv@temp%
    \pgfoolet{canvas position}\pgf@dv@pos%
    % Now check threshold
    \pgfooget{threshold}\pgf@dv@thres%
    \ifx\pgf@dv@thres\pgfutil@empty%
    \else%
      % Hmm, have to check, whether the value is, indeed, correct
      \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}\pgf@dv@val
      \ifx\pgf@dv@val\relax%
      \else\ifx\pgf@dv@val\pgfutil@empty%
      \else%
        \pgfdvmathenter{\pgf@dv@value}{\pgf@dv@val}%
        \pgfooget{threshold}{\pgf@dv@thres}
        % Now, protocol value
        \pgfdvmathifless{\pgf@dv@value}{\pgf@dv@thres}{}{%
          \pgfoolet{attribute}\pgfutil@empty% Stop!
        }%
      \fi\fi%
    \fi%
  }%

  % Slot
  \method phase(#1) {%
    \ifx#1\pgfdvendvisualization%
      \scope
        \pgfcoordinate{label visualizer coordinate}{\pgfoovalueof{canvas position}}
        \pgfcoordinate{label visualizer coordinate'}{\pgfoovalueof{before canvas position}}
        \pgfoovalueof{code}
      \endscope
    \fi%
  }%
}%



%
% Style sheets
%
\pgfooclass{style attribute}
{%
  % Class style attribute
  %
  % Instances of this class are used to select a style based on the
  % current value of an attribute.
  %
  % Instances of this class monitor an attribute. Whenever the "style"
  % signal is raised, the object investigates the current value of the
  % attribute. It then looks up /pgf/data visualization/style
  % sheets/<name of style sheet>/<value of the attribute> and executes
  % this key, provided it is defined. If it not defined, the key
  % /pgf/data visualization/style sheets/<name of style sheet>/default
  % style is executed with the value as a parameter.

  \attribute attribute;%
  % The name of the attribute

  \attribute style sheet name;%
  % The styling function

  % Constructor
  %
  % #1 = attribute (including, if present, /data point/)
  % #2 = style sheet name
  %
  \method style attribute(#1,#2) {
    \pgfooset{attribute}{#1}
    \pgfooset{style sheet name}{#2}
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,invoke style,style signal)
  }%

  % Slots
  \method invoke style() {
    \pgfooget{attribute}\pgf@dv@temp
    \pgfkeysgetvalue{\pgf@dv@temp}\pgf@dv@temp@val
    \ifx\pgf@dv@temp@val\pgfutil@empty%do nothing
    \else\ifx\pgf@dv@temp@val\relax%do nothing
    \else%
      \pgfkeysifdefined{\pgf@dv@temp/\pgf@dv@temp@val}{\pgfkeysgetvalue{\pgf@dv@temp/\pgf@dv@temp@val}\pgf@dv@temp@val}{}% redirect
      \edef\pgf@temp{/pgf/data visualization/style sheets/\pgfoovalueof{style sheet name}}
      \pgfkeysifassignable{\pgf@temp/\pgf@dv@temp@val}{%
        \pgfkeysalso{\pgf@temp/\pgf@dv@temp@val}}{%
        \pgfkeysalso{\pgf@temp/default style/.expand once=\pgf@dv@temp@val}
      }
    \fi\fi%
  }%
}%


% Declares a new style sheet
%
% #1 = name of style sheet
% #2 = settings
%
% Description:
%
% This is a shortcut for doing a /.cd to /pgf/data visualization/style sheets/#1

\def\pgfdvdeclarestylesheet#1#2{
  \pgfkeys{/pgf/data visualization/style sheets/#1/.cd,#2}
}%









%
% Legend container class
%

\pgfooclass{legend}
{%
  % Class legend
  %
  % This class is used to collect entries into a legend. The idea is
  % that, say, for each line of a picture you would like to have an
  % entry in a legend. Then you prepare these entries and send
  % them to a legend container object. It will collect the entries
  % and, at the end, arrange them in rows and columns by
  % separating them using \pgfdvnextcell and \pgfdvendrow.
  %
  % By surrounding the resulting arrangement by a call to \pgfmatrix or
  % a call to \halign you can then create a legend.
  %
  % To specify how the entries should be arranged, a size
  % specification and two directions are needed.
  %
  % For the size specification you specify either the ideal number of
  % columns and the maximum number of rows or you specify the ideal
  % number of rows and the maximum number of columns. In the first
  % case, the class first tries to create as many columns as specified
  % by the "ideal" parameter. If there are less entries than this
  % parameter, you obviously get less columns, namely as many as there
  % are entries, each column containing only one entry. If there are
  % more entries that the ideal number of columns, you get multiple
  % columns, each containing as many entries to make sure that the
  % ideal number is met. However, if a column would get more than the
  % specified maximum number of elements per column, you get more
  % columns that the ideal number -- to ensure that no column contains
  % more than the desired number. The case is symmetric, but with the
  % roles of columns and rows exchanged.
  %
  % Here is an example: You specify that you want 2 columns, ideally,
  % each having a maximum of 4 entries. Here is what you would get:
  %
  % Number of entries & Number of resulting columns ... & ... and rows
  % 1                 & 1                               & 1
  % 2                 & 2                               & 1
  % 3                 & 2                               & 2
  % 4                 & 2                               & 2
  % 5                 & 2                               & 3
  % 6                 & 2                               & 3
  % 7                 & 2                               & 4
  % 8                 & 2                               & 4
  % 9                 & 3                               & 4
  % 10                & 3                               & 4
  % 11                & 3                               & 4
  % 12                & 3                               & 4
  % 13                & 4                               & 4
  %
  %
  % Once the number of columns and rows has been computed, the next
  % step is to "fill" the table. For this, eight strategies may be
  % specified: right then down, right then up, left then down, left
  % then up, up then right, up then left, down then right, down then
  % left. A strategy like "right then up" means the following: Each
  % new entry should placed right of the previous entry in the
  % arrangement. However, once the maximum number of elements in a row
  % has been reached, the a new row should be started that is placed
  % above ("up") then just-assembled row.
  %
  %
  %
  %
  % Example:
  %
  % You create an object \legend and then call
  %
  % \pgfoofnew \legend=new legend(columns,2,3,down then right)
  % \legend.add entry(first)
  % \legend.add entry(second)
  % \legend.add entry(third)
  % \legend.add entry(fourth)
  % \legend.add entry(fifth)
  % \legend.add entry(sixth)
  % \legend.add entry(seventh)
  % \legend.get arrangement(\arrangement)
  %
  % Then \arrangment will expand to
  %
  %   first  \pgfdvnextcell   fourth  \pgfdvnextcell  seventh  \pgfdvendrow
  %   second \pgfdvnextcell   fifth   \pgfdvnextcell  third    \pgfdvendrow
  %   third  \pgfdvendrow   sixth   \pgfdvnextcell           \pgfdvendrow
  %
  % By saying \let\pgfdvendrow=\\ and \let\pgfdvnextcell=&, you
  % can use \arrangment inside a table.


  \attribute entries;%
  % Collects the entries

  \attribute columns or rows;%
  % Specifies whether columns or rows are specified

  \attribute ideal;%
  % The ideal number of columns/rows

  \attribute max;%
  % The maximum number of entries per column/row

  \attribute strategy;%
  % Specifies how the matrix should be filled

  \attribute number of entries=0;%
  % Counts the number of entries that have been stored


  % Constructor
  %
  % #1 = "columns" or "rows" -> specifies whether the ideal number and
  %      the max entries number refer to columns or the row
  % #2 = the ideal number of #1's
  % #3 = the maximum number of entries in a #1
  % #4 = one of the eight strategies
  %
  \method legend(#1,#2,#3,#4) {
    \pgfooset{columns or rows}{#1}
    \pgfooset{ideal}{#2}
    \pgfooset{max}{#3}
    \pgfooset{strategy}{#4}
  }%

  % Method
  \method default connects() {
  }%

  % Method
  \method add entry(#1) {
    \pgfooappend{entries}{{#1}}
    \c@pgf@counta=\pgfoovalueof{number of entries}\relax%
    \advance\c@pgf@counta by1\relax%
    \pgfooeset{number of entries}{\the\c@pgf@counta}
  }%

  % Method
  \method get arrangement(#1) {
    {
      %
      % Step 1: Compute the desired number of rows or columns
      %
      %
      % Compute the ideal number of entries per row/column (called
      % "target" in the following) and entries per colum/row (called
      % "per target" in the following)
      %
      % if (number of entries > ideal)
      \ifnum\pgfoovalueof{number of entries}>\pgfoovalueof{ideal}\relax%
      % {
        % if (ideal * max > number of entries)
        \c@pgf@counta=\pgfoovalueof{ideal}\relax%
        \multiply\c@pgf@counta by\pgfoovalueof{max}\relax%
        \ifnum\c@pgf@counta>\pgfoovalueof{number of entries}\relax
        % {
        %   target = ideal;
        %   per target = ceil (number of entries / ideal);
          \c@pgf@counta=\pgfoovalueof{ideal}\relax%
          \c@pgf@countb=\pgfoovalueof{number of entries}\relax
          \advance\c@pgf@countb by-1\relax
          \divide\c@pgf@countb by\c@pgf@counta\relax%
          \advance\c@pgf@countb by1\relax%
        % }
        % else
        % {
        %   target = ceil(number of entries / max);
        %   per target = max;
        \else
          \c@pgf@countb=\pgfoovalueof{max}\relax%
          \c@pgf@counta=\pgfoovalueof{number of entries}\relax
          \advance\c@pgf@counta by-1\relax
          \divide\c@pgf@counta by\c@pgf@countb\relax%
          \advance\c@pgf@counta by1\relax%
        \fi
        % }
      % }
      % else
      % {
      %   target = number of entries;
      %   per target = 1;
      % }
      \else
        \c@pgf@counta=\pgfoovalueof{number of entries}\relax%
        \c@pgf@countb=1\relax%
      \fi%
      %
      % Ensure that counta = rows, countb = columns
      %
      \pgfooget{columns or rows}\pgf@temp
      \ifx\pgf@temp\pgf@dv@columnstext%
        \c@pgf@countc=\c@pgf@counta\relax
        \c@pgf@counta=\c@pgf@countb\relax
        \c@pgf@countb=\c@pgf@countc\relax
      \fi
      %\edef\temp{rows: \the\c@pgf@counta, columns: \the\c@pgf@countb}\temp
      %
      % Now arrange the matrix
      %
      \csname pgf@dv@legend@init@\pgfoovalueof{strategy}\endcsname
      \expandafter\let\expandafter\pgf@dv@updater\csname pgf@dv@legend@update@\pgfoovalueof{strategy}\endcsname
      \pgfooget{entries}\pgf@temp
      \expandafter\pgf@dv@legend@arrange\pgf@temp\pgf@stop
      %
      % Now assemble the matrix
      %
      \edef\pgf@dv@row@list{1,...,\the\c@pgf@counta}
      \edef\pgf@dv@column@list{1,...,\the\c@pgf@countb}
      \global\let\pgf@dv@matrix\pgfutil@empty
      \foreach \pgf@dv@row in \pgf@dv@row@list
      {
        \global\let\pgf@dv@matrix@row\pgf@dv@first@mark
        \foreach \pgf@dv@column in \pgf@dv@column@list
        {
          \expandafter\let\expandafter\pgf@temp\csname pgf@dv@legend@entry@\pgf@dv@row @\pgf@dv@column\endcsname
          \ifx\pgf@temp\relax
            \let\pgf@temp\pgfutil@empty
          \fi
          \ifx\pgf@dv@matrix@row\pgf@dv@first@mark
            \global\let\pgf@dv@matrix@row\pgf@temp
          \else
            \expandafter\pgfutil@g@addto@macro\expandafter\pgf@dv@matrix@row\expandafter{\expandafter\pgfdvnextcell\pgf@temp}
          \fi
        }
        \pgfutil@g@addto@macro\pgf@dv@matrix@row{\pgfdvendrow}
        \expandafter\pgfutil@g@addto@macro\expandafter\pgf@dv@matrix\expandafter{\pgf@dv@matrix@row}
      }
      \global\let\pgf@dv@matrix@row\relax
    }
    \let#1\pgf@dv@matrix
    \global\let\pgf@dv@matrix\relax
  }%

  \def\pgf@dv@first@mark{\pgf@dv@first@mark}%

  \def\pgf@dv@legend@arrange{%
    \pgfutil@ifnextchar\pgf@stop{\pgfutil@gobble}{\pgf@dv@legend@handle@entry}
  }%

  \def\pgf@dv@legend@handle@entry#1{
    \expandafter\def\csname pgf@dv@legend@entry@\the\c@pgf@countc @\the\c@pgf@countd\endcsname{#1}%
    \pgf@dv@updater%
    \pgf@dv@legend@arrange%
  }%

  \expandafter\def\csname pgf@dv@legend@init@down then right\endcsname{%
    \c@pgf@countc=1\relax%
    \c@pgf@countd=1\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@down then right\endcsname{%
    \advance\c@pgf@countc by1\relax
    \ifnum\c@pgf@countc>\c@pgf@counta\relax%
      \c@pgf@countc=1\relax%
      \advance\c@pgf@countd by1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@right then down\endcsname{%
    \c@pgf@countc=1\relax%
    \c@pgf@countd=1\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@right then down\endcsname{%
    \advance\c@pgf@countd by1\relax
    \ifnum\c@pgf@countd>\c@pgf@countb\relax%
      \c@pgf@countd=1\relax%
      \advance\c@pgf@countc by1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@up then right\endcsname{%
    \c@pgf@countc=\c@pgf@counta\relax%
    \c@pgf@countd=1\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@up then right\endcsname{%
    \advance\c@pgf@countc by-1\relax
    \ifnum\c@pgf@countc=0\relax%
      \c@pgf@countc=\c@pgf@counta\relax%
      \advance\c@pgf@countd by1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@right then up\endcsname{%
    \c@pgf@countc=\c@pgf@counta\relax%
    \c@pgf@countd=1\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@right then up\endcsname{%
    \advance\c@pgf@countd by1\relax
    \ifnum\c@pgf@countd>\c@pgf@countb\relax%
      \c@pgf@countd=1\relax%
      \advance\c@pgf@countc by-1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@left then up\endcsname{%
    \c@pgf@countc=\c@pgf@counta\relax%
    \c@pgf@countd=\c@pgf@countb\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@left then up\endcsname{%
    \advance\c@pgf@countd by-1\relax
    \ifnum\c@pgf@countd=0\relax%
      \c@pgf@countd=\c@pgf@countb\relax%
      \advance\c@pgf@countc by-1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@up then left\endcsname{%
    \c@pgf@countc=\c@pgf@counta\relax%
    \c@pgf@countd=\c@pgf@countb\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@up then left\endcsname{%
    \advance\c@pgf@countc by-1\relax
    \ifnum\c@pgf@countc=0\relax%
      \c@pgf@countc=\c@pgf@counta\relax%
      \advance\c@pgf@countd by-1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@left then down\endcsname{%
    \c@pgf@countc=1\relax%
    \c@pgf@countd=\c@pgf@countb\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@left then down\endcsname{%
    \advance\c@pgf@countd by-1\relax
    \ifnum\c@pgf@countd=0\relax%
      \c@pgf@countd=\c@pgf@countb\relax%
      \advance\c@pgf@countc by1\relax%
    \fi%
  }%

  \expandafter\def\csname pgf@dv@legend@init@down then left\endcsname{%
    \c@pgf@countc=1\relax%
    \c@pgf@countd=\c@pgf@countb\relax%
  }%

  \expandafter\def\csname pgf@dv@legend@update@down then left\endcsname{%
    \advance\c@pgf@countc by1\relax
    \ifnum\c@pgf@countc>\c@pgf@countb\relax%
      \c@pgf@countc=1\relax%
      \advance\c@pgf@countd by-1\relax%
    \fi%
  }%

  \def\pgf@dv@columnstext{columns}%
}%



%
% Help classes
%

\pgfooclass{interval}
{%
  % Class interval
  %
  % Instances of this class store intervals. When either the min or
  % the max value is empty, this corresponds to "not yet set", (not to
  % "infinity).

  \attribute min;%
  % The minimum value of the interval

  \attribute max;%
  % The maximum value of the interval

  % Constructor
  %
  % #1 = initial minimum value
  % #2 = initial maximum value
  %
  \method interval(#1,#2) {
    \pgfooset{min}{#1}
    \pgfooset{max}{#2}
  }%

  % Method
  \method default connects() {
  }%

  % Sets the minimum/maximum to a new value
  \method set min(#1) {
    \pgfooset{min}{#1}
  }%
  \method set max(#1) {
    \pgfooset{max}{#1}
  }%
  \method let min(#1) {
    \pgfoolet{min}{#1}
  }%
  \method let max(#1) {
    \pgfoolet{max}{#1}
  }%

  % Getter
  %
  % Returns the current values of the minimum and maximum in the
  % macros \pgfdvmin and \pgfdvmax.
  \method get min and max() {
    \pgfooget{min}\pgfdvmin
    \pgfooget{max}\pgfdvmax
  }%

  % Adjusts the minimum and maximum values
  %
  % #1 = some code. When this code is executed, the values of
  %      \pgfdvmin and \pgfdvmax will be set to the current values of
  %      the minimum/maximum. The code may change these values. The
  %      changed values will then be stored.
  %
  % This method does nothing that cannot be achieved also by calling
  % set/get methods, but it is easier to use and faster.
  \method adjust(#1) {
    {%
      \pgfooget{min}\pgfdvmin
      \pgfooget{max}\pgfdvmax
      #1%
      \pgfoolet{min}\pgfdvmin
      \pgfoolet{max}\pgfdvmax
    }%
  }%
}%



\pgfooclass{count}
{%
  % Class count
  %
  % This class can be used to count the number of data points that are
  % present or that have a certain property. By default, for every
  % data point a counter is incremented and the value of this counter
  % is stored in an attribute. You can also specify an increment for
  % the counter. You can specify that certain data points should
  % not have an effect on the counter.


  \attribute attribute;%
  % The attribute that will be set to the current value of the counter

  \attribute val=0;%
  % The current value of the counter

  \attribute max=0;%
  % The current value of the counter

  \attribute step=1;%
  % The stepping by which the counter is incremented for each
  % datapoint

  \attribute start val=0;%
  % The start value of the counter

  \attribute filter=;%
  % This attribute stores some code that is executed for each
  % data point. If the data point sets the TeX-if ifpgfdvfilterpassed to
  % true, then the counter is not incremented.


  % Constructor
  %
  % #1 = The attribute in which the counter value is stored
  %
  \method count(#1) {
    \pgfooset{attribute}{#1}
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,apply,prepare datapoint signal)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Getter
  \method get max(#1) {
    \pgfooget{max}{#1}
  }%

  % Setter
  \method set value(#1) {
    \pgfooset{val}{#1}
    \pgfkeyssetvalue{/data point/\pgfoovalueof{attribute}}{#1}%
  }%

  % Setter
  \method set start value(#1) {
    \pgfooset{start val}{#1}
    \pgfooset{max}{#1}
  }%

  % Setter
  \method set filter(#1) {
    \pgfooset{filter}{#1}
  }%

  % Setter
  \method set step(#1) {
    \pgfooset{step}{#1}
  }%

  % Slot
  \method apply() {
    \pgfdvfilterpassedtrue%
    \pgfoovalueof{filter}%
    \ifpgfdvfilterpassed%
      \pgfmathparse{\pgfoovalueof{val}+\pgfoovalueof{step}}%
      \pgfoolet{val}\pgfmathresult%
      \pgfkeyslet{/data point/\pgfoovalueof{attribute}}\pgfmathresult%
      \ifdim\pgfmathresult pt>\pgfoovalueof{max}pt\relax%
        \pgfoolet{max}\pgfmathresult%
      \fi%
      \pgfooget{max}\pgfmathresult%
      \pgfkeyslet{/data point/\pgfoovalueof{attribute}/max}\pgfmathresult%
    \fi%
  }%

  % Slot
  \method phase(#1) {
    \ifx#1\pgfdvbeginsurvey
      \pgfooeset{val}{\pgfoovalueof{start val}}
    \else \ifx#1\pgfdvbeginvisualization
      \pgfooeset{val}{\pgfoovalueof{start val}}
    \fi\fi
  }%
}%

\newif\ifpgfdvfilterpassed




\pgfooclass{accumulator}
{%
  % Class accumulator
  %
  % This class is used to keep track of the sum of the values of some
  % attribute. When this object is connected to some attribute, the
  % subkey attribute/sum will always contain the sum of all values in
  % all previous data points with respect to this
  % attribute. Furthermore, the subkey attribute/prev key will hold
  % the previous sum, which is sometimes also useful to have access
  % to.

  \attribute attribute;%
  % The attribute to-be-accumulated

  \attribute sum;%
  % The initial value of the sum

  % Constructor
  %
  % #1 = to-be-accumulated attribute
  \method accumulator(#1) {
    \pgfooset{attribute}{#1}
    \pgfoothis.reset()
  }%

  % Method
  \method default connects() {
    \pgfoothis.get handle(\pgf@dv@me)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,apply,prepare datapoint signal)
    \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,phase,phase signal)
  }%

  % Slot
  \method apply() {%
    % Save old sum
    \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}/sum}\pgf@temp%
    \pgfkeyslet{/data point/\pgfoovalueof{attribute}/prev sum}\pgf@temp%
    % Add new attribute...
    \pgfkeysgetvalue{/data point/\pgfoovalueof{attribute}}{\pgf@temp@b}%
    \pgfdvmathenter{\pgf@dv@new@val}{\pgf@temp@b}%
    % ... to sum
    \pgfooget{sum}\pgf@dv@sum%
    \pgfdvmathadd{\pgf@dv@sum}{\pgf@dv@new@val}{\pgf@dv@sum}%
    \pgfoolet{sum}\pgf@dv@sum
    % Record in attribute
    \pgfdvmathexitbyscientificformat{\pgf@dv@serial@sum}{\pgf@dv@sum}
    \pgfkeyslet{/data point/\pgfoovalueof{attribute}/sum}\pgf@dv@serial@sum
  }%

  % Method
  %
  % Use this method to reset the sum at any point.
  %
  \method reset() {
    \pgfdvmathenter{\pgf@dv@temp}{0}
    \pgfoolet{sum}{\pgf@dv@temp}
    \pgfdvmathexitbyserializing{\pgf@dv@zero}{\pgf@dv@temp}
    \pgfkeyslet{/data point/\pgfoovalueof{attribute}/prev sum}{\pgf@dv@zero}
    \pgfkeyslet{/data point/\pgfoovalueof{attribute}/sum}{\pgf@dv@zero}
  }%

  % Slot
  \method phase(#1) {
    \ifx#1\pgfdvbeginsurvey
      \pgfoothis.reset()
    \else \ifx#1\pgfdvbeginvisualization
      \pgfoothis.reset()
    \fi\fi
  }%
}%







%
%
% Help keys and, attributes
%
%

\pgfkeys{% do not even think of changing the values of the following:
  /data point/always true/.initial=true,
  /data point/always false/.initial=false,
  /data point/always 0/.initial=0,
  /data point/always 1/.initial=1,
  /data point/always empty/.initial=,
  /data point/always pgfusepath stroke/.initial=\pgfusepath{stroke},
}%

\pgfdvmathenter{\pgfdvmathalwaysloge}{0.434294481903252}%
\pgfdvmathenter{\pgfdvmathalwayslnten}{2.302585092994046}%
\pgfdvmathenter{\pgfdvmathalwayszero}{0}%
\pgfdvmathenter{\pgfdvmathalwaysone}{1}%


\endinput
