%%
%% Package: spectralsequences.sty version 1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
%% Date: 2017-06-18
%% License: Latex Project Public License
%%
%% File: sseqdrawing.code.tex
%%
%%    Defines the macros that draw the features of the spectral sequence (at least, those that aren't drawn by tikz).
%%    Everything here has to be super optimized, because like 90% of the execution time is in these functions.
%%    In particular, tikz is a horrible performance hole that must be avoided at all costs. For example, the code
%%    the code to produce the axis ticks used to use the tikz \node command, and in the file example_KF3n.tex drawing
%%    the axes ticks was taking about 1/3 of the compile time (a little under 1s out of a 3.2)
%%



%%%
%%% Draw axes and clip
%%%
\def\sseq@handlexaxis{
    \ifsseq@drawxaxis
        \bgroup
        \ifsseq@borderxaxis\else
            \let\sseq@ymin\sseq@yaxisorigin % Warning: this is a stupid, lazy hack.
        \fi
        \sseq@drawxaxis
        \ifsseq@drawxaxisticks
            \sseq@drawxticks
        \fi
        \egroup
    \fi
}
\def\sseq@handleyaxis{
    \ifsseq@drawyaxis
        \bgroup
        \ifsseq@borderyaxis\else
            \let\sseq@xmin\sseq@xaxisorigin % Warning: this is a stupid, lazy hack.
        \fi
        \sseq@drawyaxis
        \ifsseq@drawyaxisticks
            \sseq@drawyticks
        \fi
        \egroup
    \fi
}
\def\sseq@drawxaxis{
    \bgroup
    \pgftransformreset
    \sseq@globaldetonetransform
    %
    \bgroup
    \pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformyshift{-\sseq@xaxisgap}
    \sseq@globalscaletransform
    \pgfpathmoveto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
    \egroup
    \bgroup
    \pgftransformxshift{-\sseq@yaxisgap}
    %\pgftransformxshift{-\sseq@ylabelgap}
    \pgftransformxshift{-\sseq@xaxis@start@extend}
    \pgftransformyshift{-\sseq@xaxisgap}
    \sseq@globalscaletransform
    \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
    \egroup
    \egroup
    \pgfusepath{stroke}
}
\def\sseq@drawyaxis{
    \bgroup
    \pgftransformreset
    \sseq@globaldetonetransform
    \bgroup
    \pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformxshift{-\sseq@yaxisgap}
    \sseq@globalscaletransform
    \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
    \egroup
    \bgroup
    \pgftransformyshift{-\sseq@xaxisgap}
    %\pgftransformyshift{-\sseq@xlabelgap}
    \pgftransformyshift{-\sseq@yaxis@start@extend}
    \pgftransformxshift{-\sseq@yaxisgap}
    \sseq@globalscaletransform
    \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
    \egroup
    \egroup
    \pgfusepath{stroke}%
}
\def\sseq@drawxticks{
    \sseq@tempy=\sseq@ymin\relax
    \sseq@tempx=\sseq@xmax\relax
    \advance\sseq@tempx\@ne\relax
    \edef\sseq@temp{\the\sseq@tempx}%
    \sseq@tempx=\sseq@xmin\relax
    \loop
        \bgroup
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
        \pgftransformresetnontranslations
        \sseq@globaldetonetransform
        \pgftransformyshift{-\sseq@xlabelgap}\pgftransformyshift{-\sseq@xaxisgap}
        \pgftransformresetnontranslations
        \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
        \sseq@xtickstyle
        \tikz@options
        \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}}
        \egroup
        \advance\sseq@tempx\sseq@xtickstep\relax
    \ifnum\sseq@tempx<\sseq@temp\repeat
}
\def\sseq@drawyticks{
    \sseq@tempx=\sseq@xmin\relax
    \sseq@tempy=\sseq@ymax\relax
    \advance\sseq@tempy\@ne\relax
    \edef\sseq@tempmax{\the\sseq@tempy}
    \sseq@tempy=\sseq@ymin\relax
    \loop
        \bgroup
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
        \pgftransformresetnontranslations
        \sseq@globaldetonetransform
        \pgftransformxshift{-\sseq@ylabelgap}\pgftransformxshift{-\sseq@yaxisgap}
        \pgftransformresetnontranslations
        \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
        \sseq@ytickstyle
        \tikz@options
        \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempy}$}}
        \egroup
        \advance\sseq@tempy\sseq@ytickstep\relax
    \ifnum\sseq@tempy<\sseq@tempmax\repeat
}
\def\sseq@setupclip{
    %\clip(\sseq@xmin-0.4,\sseq@ymin-0.4) rectangle (\sseq@xmax+0.5,\sseq@ymax+0.5);%
    \ifsseq@clip
        \ifx\sseq@customclip\pgfutil@empty
            \bgroup
            \pgftransformreset
            \sseq@globaldetonetransform
            \ifsseq@borderyaxis
                \def\xmin{\pgftransformxshift{-\sseq@yaxisgap}\pgftransformxshift{\sseq@yclip@axisgap}}
            \else
                \def\xmin{\pgftransformxshift{-\sseq@xaxis@start@extend}\pgftransformxshift{-\sseq@clip@padding@left}}
            \fi
            \ifsseq@borderxaxis
                \def\ymin{\pgftransformyshift{-\sseq@xaxisgap}\pgftransformyshift{\sseq@xclip@axisgap}}
            \else
                \def\ymin{\pgftransformyshift{-\sseq@yaxis@start@extend}\pgftransformyshift{-\sseq@clip@padding@bottom}}
            \fi
            \def\xmax{\pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformxshift{\sseq@clip@padding@right}}
            \def\ymax{\pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformyshift{\sseq@clip@padding@top}}
            \bgroup
            \xmin\ymin\sseq@globalscaletransform
            \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
            \egroup
            \bgroup
            \xmin\ymax\sseq@globalscaletransform
            \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
            \egroup
            \bgroup
            \xmax\ymax\sseq@globalscaletransform
            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
            \egroup
            \bgroup
            \xmax\ymin\sseq@globalscaletransform
            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
            \egroup
            \egroup
            \pgfpathclose
            \pgfgetpath\sseq@theclippath % This stores the clipping so I can find intersections later
            \pgfusepath{discard}% This has to be after the egroup or else the clipping gets screwed up
            \bgroup
                %\sseq@globalscaletransform
                \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
                \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
                \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
                \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
                \pgfpathclose
            \egroup
            \pgfgetpath\sseq@therangepath % Only for deciding whether to draw "tricky edges"
            \pgfusepath{discard}
        \else
            \def\sseq@temp{\path[name path=temp]}
            \@xptwo\sseq@temp\@xp\@gobble\sseq@customclip
            \pgfgetpath\sseq@theclippath
            \let\sseq@theclippath\tikz@intersect@path@name@temp
        \fi
    \else
        \let\sseq@theclippath\relax
    \fi
}
\def\sseq@useclip{\ifx\sseq@theclippath\relax\else\pgfsetpath\sseq@theclippath\pgfusepath{clip}\fi}
\def\sseq@grid@chess{
 \bgroup
 \pgfscope
 \sseq@useclip
 \pgflowlevelsynccm
 \pgfsetlinewidth{1cm}
 \pgfsetdash{{1cm}{1cm}}{1cm}
 \pgfsetcolor{lightgray}
 \pgfpathgrid[stepx=2cm,stepy=2cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\sseq@xmax cm+0.499cm}{\sseq@ymax cm+0.499cm}}
 \pgfusepath{stroke}
 \endpgfscope
 \egroup
}
\def\sseq@grid@crossword{
 \bgroup
 \pgfscope
 \pgfsetlinewidth{\the\sseq@gridstrokethickness}
 \sseq@useclip
 \pgftransformxshift{-0.5cm}
 \pgftransformyshift{-0.5cm}
 \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.99cm}{\ymax cm+0.99cm}}
 \pgfusepath{stroke}
 \endpgfscope
 \egroup
}
\def\sseq@grid@go{
 \bgroup
 \pgfscope
 \sseq@useclip
 \pgfsetlinewidth{\the\sseq@gridstrokethickness}
 \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.5cm}{\ymax cm+0.5cm}}
 \pgfusepath{stroke}
 \endpgfscope
 \egroup
}
\def\sseq@grid@none{}
\def\sseq@grid@dots{
 \bgroup
 \pgfscope
 \pgfgettransform\sseq@savetransform
 \pgftransformreset
 \sseq@globalscaletransform
 \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v}
 \pgfsettransform\sseq@savetransform
 \sseq@useclip
 \pgftransformxshift{-1.5cm}
 \pgftransformyshift{-0.5cm}
 \pgfsetdash{{1pt}{\sseq@a*1cm-1pt}}{0.5cm+.5pt}
 \pgfsetlinewidth{1pt}
 \sseq@tempy=\sseq@ymin\relax
 \advance\sseq@tempy\m@ne
 \loop
 \advance\sseq@tempy\@ne
 \pgfpathmoveto{\pgfpoint{\sseq@xmin cm+0.5cm/\sseq@a}{\the\sseq@tempy cm}}
 \pgfpathlineto{\pgfpoint{\sseq@xmax cm+1.01cm }{\the\sseq@tempy cm}}
 \ifnum\sseq@tempy<\sseq@ymax\repeat
 %\pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\xmax cm-0.5cm}{\ymax cm-0.5cm}}
 \pgfusepath{stroke}
 \endpgfscope
 \egroup
}
%%%
%%% Draw Classes
%%%
%%% Class offsets
\sseqnewclasspattern{standard}{
    (0,0);
    (-0.13,0)(0.13,0);
    (-0.2,0)(0,0)(0.2,0);
    (-0.13,-0.13)(0.13,-0.13)(-0.13,0.13)(0.13,0.13);
    (-0.16,-0.16)(0.16,-0.16)(-0.16,0.16)(0.16,0.16)(0,0);
    (-0.13,-0.2)(-0.13,0)(-0.13,0.2)(0.13,-0.2)(0.13,0)(0.13,0.2);
}
\sseqnewclasspattern{linear}{
    (0,0);
    (-0.13,0)(0.13,0);
    (-0.2,0)(0,0)(0.2,0);
    (-0.3,0)(-0.1,0)(0.1,0)(0.3,0);
    (-0.4,0)(-0.2,0)(0,0)(0.2,0)(0.4,0);
    (-0.5,0)(-0.3,0)(-0.1,0)(0.1,0)(0.3,0)(0.5,0);
}
\def\sseq@offset#1#2{
    \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{0\csname sseq@\sseq@classpattern xoffset#1/#2\endcsname cm}{0\csname sseq@\sseq@classpattern yoffset#1/#2\endcsname cm}}}
}
\def\sseq@class@getparts#1(#2,#3,#4)[#5].{
    \sseq@seterrorannotation@drawing{#1}{#2}{#3}{#4}{#5}
    \def\sseq@thisclassname{class.(#2,#3,#4)}
    \def\sseq@thisnodename{sseq{#2,#3,#4}}
    \def\sseq@thispos{(#2,#3)}
    \def\sseq@thisposnum{#4}
    \def\sseq@thisclassnum{#5}
}

\def\sseqtooltip#1#2{%
    \edef\temp{\detokenize\@xpthree{#2}}%
    \edef\temp{\@xp\sseqtooltip@replaceslashes\@xp{\temp}}%
    \sseq@eval{\@nx\pdftooltip{\unexpanded{#1}}{\temp}}%
}
\bgroup\lccode`\!=`\\\lowercase{\egroup
\def\sseqtooltip@replaceslashes#1{\sseqtooltip@replaceslashes@#1!\sseq@nil}
\def\sseqtooltip@replaceslashes@#1!#2{%
    #1%
    \ifx\sseq@nil#2\@xp\@gobble\else
        \@nx\@nx\@nx\textbackslash
        \@xp\sseqtooltip@replaceslashes@
    \fi#2%
}
}

% #1 -- the name of the node object
\def\sseq@class@drawnode#1{%
    \begingroup
    \sseq@class@getparts#1.
    \sseq@tempx=\sseq@obj{\sseq@thisclassname.x}\relax
    \sseq@tempy=\sseq@obj{\sseq@thisclassname.y}\relax
    \sseq@needstikzfalse
    \sseq@options@firstpassmode
        \sseq@thesseqstyle
        \sseq@theclassstyle
        \ifnum\sseq@obj{#1.page}=\sseq@infinitycount
            \sseq@thepermanentcyclestyle
        \else
            \sseq@thetransientcyclestyle
            \ifsseq@thispage
                \sseq@thethispagecyclestyle
            \fi
        \fi
        \the\sseq@scope@toks
        \sseq@obj{#1.needstikz}
%
    \sseq@outofrangetrue
    \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax
        \sseq@outofrangefalse
        \pgfscope
        \let\tikz@options\pgfutil@empty
        \let\tikz@alias=\pgfutil@empty
        \def\pgfkeysdefaultpath{/sseqpages/class/}
        \sseq@options@secondpassmode
            \sseq@thesseqstyle
            \sseq@theclassstyle
            \ifnum\sseq@obj{#1.page}=\sseq@infinitycount
                \sseq@thepermanentcyclestyle
            \else
                \sseq@thetransientcyclestyle
                \ifsseq@thispage
                    \sseq@thethispagecyclestyle
                \fi
            \fi
            \the\sseq@scope@toks
            \sseq@obj{#1.options}%
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
        \iftikz@fullytransformed\pgfgettransform{\savetransform}\fi
        \pgftransformresetnontranslations
        \sseq@globalrotatetransform
        \sseq@classplacementtransform
        \sseq@obj@ifdef{#1.offset}{\sseq@obj{#1.offset}}{%
            \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}}%
        }%
        \iftikz@fullytransformed\pgfsettransform{\savetransform}\else\pgftransformresetnontranslations\ifsseq@rotatelabels\sseq@globalrotatetransform\fi\fi
        \tikz@options
        \ifsseq@needstikz
            \let\sseq@mode\tikz@mode
            \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj{#1.nodetext.options}}}%
            \sseq@eval{%
                \@nx\node[/utils/exec={\let\@nx\tikz@mode\@nx\sseq@mode},
                    /handlers/first char syntax/the character "/.initial=\@nx\sseq@handlequote
                ] (\sseq@thisnodename) {\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}}
                [every text node part/.code={}]
                \@nx\sseq@obj{#1.labelnodes};
            }%
        \else
            \tikz@node@textfont
            \edef\sseq@classnodetextoptions{\@xptwo\@nx\sseq@obj{#1.nodetext.options}}
            \edef\sseq@classnodetext{\@xptwo\@nx\sseq@obj{#1.nodetext}}
            \sseq@setnodetext
            \let\tikz@fig@name\sseq@thisnodename
            \pgfmultipartnode{\tikz@shape}{\tikz@anchor}{\tikz@fig@name}{\sseq@drawnode}%
            \tikz@alias
            \sseq@obj{#1.labelnodes}
        \fi
        \sseq@obj@ifdef{#1.tooltip}{
            \pgfpointanchor{\sseq@thisnodename}{west}
            \pgf@xa=\pgf@x
            \pgfpointanchor{\sseq@thisnodename}{south}
            \pgf@ya=\pgf@y
%
            \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{west}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{east}}}}
            \pgf@xb=\pgf@x
            \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{south}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{north}}}}
            \pgf@yb=\pgf@y
%
            \setbox\tikz@tempbox=\hbox{
                \pgfinterruptpicture
                \sseqtooltip{\rule{\pgf@xb}{0pt}\rule{0pt}{\pgf@yb}}{\sseq@obj{#1.tooltip}}
                \endpgfinterruptpicture
            }
            {%
                \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
                \pgfapproximatenonlineartransformation%
                \pgfqboxsynced{\tikz@tempbox}%
            }%
        }{}
        \endpgfscope
    \fi\fi\fi\fi
    \ifsseq@outofrange
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}%
        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
        \pgftransformresetnontranslations
        \sseq@globalrotatetransform
        \sseq@classplacementtransform
        \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}}
        \pgfcoordinate{\sseq@thisnodename}{\pgfpointorigin}%
    \fi
    \endgroup
}
\def\sseq@setnodetext{%
    \setbox\pgfnodeparttextbox=\hbox{%
        \pgfscope%
        \tikzset{every text node part/.try}%
        \sseq@classnodetextoptions
        \ifx\tikz@textopacity\pgfutil@empty%
        \else%
         \pgfsetfillopacity{\tikz@textopacity}%
          \pgfsetstrokeopacity{\tikz@textopacity}%
        \fi%
        \pgfinterruptpicture
      \ifx\tikz@text@width\pgfutil@empty%
        \tikz@textfont%
      \else%
        \begingroup%
        	\pgfmathsetlength{\pgf@x}{\tikz@text@width}%
          \pgfutil@minipage[t]{\pgf@x}\leavevmode\hbox{}%
            \tikz@textfont%
            \tikz@text@action%
      \fi%
        \ifx\tikz@textcolor\pgfutil@empty%
        \else%
          \pgfutil@colorlet{.}{\tikz@textcolor}%
        \fi%
        \pgfsetcolor{.}%
          \tikz@atbegin@node%
          \sseq@classnodetext%
          \tikz@atend@node%
           \ifx\tikz@text@width\pgfutil@empty%
           \else%
              \pgfutil@endminipage%
            \endgroup%
          \fi%
          \endpgfinterruptpicture
      \endpgfscope%
    }%
    \ifx\tikz@text@width\pgfutil@empty%
    \else%
      \pgfmathsetlength{\pgf@x}{\tikz@text@width}%
      \wd\pgfnodeparttextbox=\pgf@x%
    \fi%
    \ifx\tikz@text@height\pgfutil@empty%
    \else%
      \pgfmathsetlength{\pgf@x}{\tikz@text@height}%
      \ht\pgfnodeparttextbox=\pgf@x%
    \fi%
    \ifx\tikz@text@depth\pgfutil@empty%
    \else%
      \pgfmathsetlength{\pgf@x}{\tikz@text@depth}%
      \dp\pgfnodeparttextbox=\pgf@x%
    \fi%
}
\def\sseq@drawnode{%
  \pgfutil@tempdima=\pgflinewidth%
  {%
    \tikz@mode%
    %\iftikz@mode@clip \sseq@error@internal{Clip shouldn't happen here, but this error should be caught earlier}{}\fi %
    \iftikz@mode@draw%
        \iftikz@mode@double%
        % Change line width
            \begingroup%
            \pgfsys@beginscope%
            \tikz@double@setup%
        \fi%
    \fi%
    %
    % Step 10: Do stroke/fill as needed
    %
    \sseq@eval{\noexpand\pgfusepath{%
        \iftikz@mode@fill fill,\fi%
        \iftikz@mode@draw draw,\fi%
    }}%
    %
    % Step 11: Double stroke, if necessary
    %
    \iftikz@mode@draw%
        \iftikz@mode@double%
            \pgfsys@endscope%
            \endgroup%
        \fi%
    \fi
  }%
  \global\pgflinewidth=\pgfutil@tempdima%
}

%%%
%%% Drawing edges
%%%
\def\sseq@ifinrange(#1){\sseq@ifinrange@#1,\sseq@nil}
\def\sseq@ifinrange@#1,#2,#3\sseq@nil{%
    \sseq@tempx=#1\relax\sseq@tempy=#2\relax
    \sseq@outofrangetrue
    \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax
    \sseq@outofrangefalse
    \fi\fi\fi\fi
    \ifsseq@outofrange
        \@xp\pgfutil@secondoftwo
    \else
        \@xp\pgfutil@firstoftwo
    \fi
}

\def\sseq@fullcoord@to@partialcoord(#1){\sseq@fullcoord@to@partialcoord@#1,\@nil}
\def\sseq@fullcoord@to@partialcoord@#1,#2,#3\@nil{{#1cm}{#2cm}}
% #1 -- source (full)
% #2 -- target (full)
% #3 -- which type of edge (either "structline" or "differential")
% #4 -- options
\def\sseq@drawedge(#1)(#2)#3#4{%
    \begingroup\pgfscope
    \def\sseq@edgetype{#3}
    \let\sseq@edgesourceanchor\pgfutil@empty
    \let\sseq@edgetargetanchor\pgfutil@empty
%
    \sseq@needstikzfalse
    \def\pgfkeysdefaultpath{/sseqpages/#3/}%
    \sseq@options@bothpassmode
    \sseq@thesseqstyle
    \sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks
    #4%
    \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}%
    % First calculate actual start and end of the edge
    \let\tempaf\pgfutil@empty
    \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
        \def\tempa{\pgfpointanchor{sseq{#1}}{center}}% if so, start by taking the center of that coordinate
    \else
        \edef\tempa{\@nx\pgfpointanchor{sseq{#1}}{\sseq@edgesourceanchor}} % If it has an anchor, use that
        \let\tempaf\tempa
    \fi
    \ifx\sseq@edgetargetanchor\pgfutil@empty % check that the target doesn't have a specified anchor
        \def\tempb{\pgfpointshapeborder{sseq{#2}}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate
    \else
        \edef\tempb{\@nx\pgfpointanchor{sseq{#2}}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that
    \fi
    \let\tempbf\tempb
    \ifx\tempaf\pgfutil@empty%
        \def\tempaf{\pgfpointshapeborder{sseq{#1}}{\tempb}}%
    \fi
%
    \tikz@options
    \tikz@mode
    \def\temparrowstartspec{}%
    \def\temparrowendspec{}%
    \pgfcoordinate{tempa}{\tempaf}%
    \pgfcoordinate{tempb}{\tempbf}%
    \pgftransformreset
    \sseq@ifinrange(#1){\sseq@ifinrange(#2){\sseq@outofrangefalse}{\sseq@outofrangetrue}}{\sseq@outofrangetrue}%
    \ifsseq@outofrange
        \sseq@handleoffpageedge{#1}{#2}{#3}%
    \fi
    \ifsseq@drawedge
        % TODO: should some sort of transformation manipulation be here? Maybe allow user to specify preference?
        % Don't draw dots on very short segments
        \pgfpointdiff{\tempbf}{\tempaf}
        \pgfmathveclen{\pgf@x}{\pgf@y}%
        \@xp\pgfmathint\@xp{\pgfmathresult}%
        \ifnum\pgfmathresult<10\relax%%17? % TODO: Fix this predicate
            \tikzset{every text node part/.append code={\pgfsetcolor{white}}}% I wonder why this is here...
            \ifx\temparrowstartspec\pgfutil@empty
            \else
                \def\temparrowstartspec{\pgfsetarrowsstart{}}%
            \fi
            \ifx\temparrowendspec\pgfutil@empty
            \else
                \def\temparrowendspec{\pgfsetarrowsend{}}%
            \fi
        \fi
        \ifsseq@needstikz
            \draw[/sseqpages,
                /utils/exec={\sseq@thesseqstyle\sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks
                             \temparrowstartspec\temparrowendspec #4}%
            ]  (tempa) to (tempb);%
        \else
            \temparrowstartspec
            \temparrowendspec
            \pgfpathmoveto{\pgfpointanchor{tempa}{center}}%
            \pgfpathlineto{\pgfpointanchor{tempb}{center}}%
            \sseq@eval{\noexpand\pgfusepath{%
                \iftikz@mode@fill fill,\fi
                \iftikz@mode@draw draw,\fi
            }}%
        \fi
    \fi
    \sseq@breakpoint
    \endpgfscope\endgroup
}

% TODO: this macro is super expensive. Make it faster (avoid
\def\sseq@handleoffpageedge#1#2#3{
    \pgfpathmoveto{\tempaf}%
    \pgfpathlineto{\tempbf}%
    \pgfgetpath\thispath
    \pgfusepath{discard}%
    \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}%
    \ifcase\pgfintersectionsolutions\relax
        % No intersections, but one or both endpoints may be out of range but still in clipping region due to scaling. Add ellipses as appropriate.
        \sseq@ifinrange(#1){% If the first endpoint is in range, the second must be out of range b/c sseq@outofrange is true.
            %\edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
        }{%
            \sseq@ifinrange(#2){%
                \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}
            }{\sseq@drawedge@handletrickyedge}% uh-oh, both ends are out of range
        }%
    \or
        \sseq@ifinrange(#1){% If the startpoint is in range, the intersection must be the end.
            \def\tempbf{\pgfpointintersectionsolution{1}}
            \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
            \pgfcoordinate{tempb}{\tempbf}
        }{%
            \sseq@ifinrange(#2){% If the startpoint is out of range and the endpoint is in range, the intersection must be the start
                \def\tempaf{\pgfpointintersectionsolution{1}}%
                \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}%
                \pgfcoordinate{tempa}{\tempaf}%
            }{\sseq@drawedge@handletrickyedge}% Uh-oh, both ends are out of range.
        }
    \or% an orphan
        \ifsseq@draworphanedges
            \sseq@drawedge@handleorphan
        \else
            \sseq@drawedgefalse % Don't draw "orphaned edges"
        \fi
    \else
        \sseq@error{clip-not-convex}%
        \sseq@breakfifi
    \fi
}

\def\sseq@drawedge@handletrickyedge{%
    \ifsseq@draworphanedges
        \pgfintersectionofpaths{\pgfsetpath\sseq@therangepath}{\pgfsetpath\thispath}%
        \ifnum\pgfintersectionsolutions=\z@
            \sseq@drawedgefalse % don't draw orphan edges that never intersect actual range
        \else% Now we have to make a line through tempa and tempb long enough so that it intersects the original clip area twice.
            \pgfmathanglebetweenpoints{\pgfpointanchor{tempa}{center}}{\pgfpointanchor{tempb}{center}}%
            \edef\tempangle{\pgfmathresult}
            \pgfpathmoveto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{100cm}}}% a really long line
            \pgfpathlineto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{-100cm}}}%
            \pgfgetpath\thispath
            \pgfusepath{discard}
            \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}
            \sseq@drawedge@handleorphan
        \fi
    \else
        \sseq@drawedgefalse
    \fi
}


\def\sseq@drawedge@handleorphan{%
    \def\tempaf{\pgfpointintersectionsolution{1}}%
    \def\tempbf{\pgfpointintersectionsolution{2}}%
    \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@\sseq@edgetype @spec\endcsname}}%
    \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@\sseq@edgetype @spec\endcsname}}%
    \pgfcoordinate{tempa}{\tempaf}%
    \pgfcoordinate{tempb}{\tempbf}%
}


%
% #1 -- first coordinate
% #2 -- second coordinate
% #3 -- uid
\def\sseq@circleclass@draw#1#2#3{
    \begingroup
        \pgfmathanglebetweenpoints{\pgfpointanchor{sseq{#2}}{center}}{\pgfpointanchor{sseq{#3}}{center}}
        \let\tempangle\pgfmathresult
        \let\tikz@lib@fit@scan@handle\sseq@fit@tikz@lib@fit@scan@handle % install fit modifications.
        \let\tikz@calc@anchor\sseq@fit@tikz@calc@anchor
        \sseq@tempiftrue
        \node[
            rotate fit=\tempangle,
            /utils/exec={\sseq@thesseqstyle\sseq@thecircleclassstyle\the\sseq@scope@toks\sseq@savedoptioncode
                \sseq@obj{#1.options}
                \sseq@obj{#1.fitnodes}
                \@xp\pgfkeysalso\@xp{\romannumeral0\sseq@obj{#1.tikzprimoptions}}
            }
        ] {};
    \endgroup
}
% Modifies tikz commands \tikz@lib@fit@scan@handle from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 and
% \tikz@calc@anchor from \pgf\frontendlayer\tikz\tikz.code.tex line 5164
% make it so that fit silently ignores nodes that are not defined.
% This is copied with modification from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81
\def\sseq@fit@tikz@lib@fit@scan@handle#1{%
  \ifsseq@tempif % this has been set in the following macro to be true if there is a node with the given name. If it's not true, ignore this.
      \iftikz@shapeborder%
        % Ok, fit all four external anchors, if they exist
        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{west}}%
        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{east}}%
        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{north}}%
        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{south}}%
      \else%
        \tikz@lib@fit@adjust{#1}%
      \fi%
  \fi
  \sseq@tempiftrue
  \tikz@lib@fit@scan%
}

% This is copied with modification from \pgf\frontendlayer\tikz\tikz.code.tex line 5164
\def\sseq@fit@tikz@calc@anchor#1.#2\tikz@stop{%
  \pgfutil@ifundefined{pgf@sh@ns@#1}{\sseq@tempiffalse}{%If the node doesn't exist, don't throw an error but record that we should skip it
    \pgfpointanchor{\tikz@pp@name{#1}}{#2}%
  }%s
}


%% New shapes and arrows
%% These use lots of keys with spaces so it's convenient to turn off ExplSyntax.

% Stolen from: https://tex.stackexchange.com/a/24621
\pgfqkeys{/pgf}{
    ellipse ratio/.code={\pgfkeyssetvalue{/pgf/ellipse ratio}{#1}},
    ellipse ratio/.initial=1
}
\pgfdeclareshape{newellipse}
{
  \inheritsavedanchors[from=ellipse]
  \inheritanchorborder[from=ellipse]
  \savedanchor\radius{%
    %
    % Caculate ``height radius''
    %
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y by\pgf@yb%
    %
    % Caculate ``width radius''
    %
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x by\pgf@xb%
    %
    % Adjust
    %
    \pgfkeysgetvalue{/pgf/ellipse ratio}{\ratioscale}
    \pgfmathsetmacro\widthfactor{sqrt(\ratioscale^2+1)/\ratioscale}
    \pgfmathsetmacro\heightfactor{sqrt(\ratioscale^2+1)}
    \pgf@x=\widthfactor\pgf@x%
    \pgf@y=\heightfactor\pgf@y%
    %
    % Adjust height, if necessary
    %
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@y<.5\pgf@yc%
      \pgf@y=.5\pgf@yc%
    \fi%
    %
    % Adjust width, if necessary
    %
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
    \ifdim\pgf@x<.5\pgf@xc%
      \pgf@x=.5\pgf@xc%
    \fi%
    %
    % Add outer sep
    %
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@x by\pgf@xb%
    \advance\pgf@y by\pgf@yb%
  }

  \inheritanchor[from=ellipse]{center}
  \inheritanchor[from=ellipse]{mid}
  \inheritanchor[from=ellipse]{base}
  \inheritanchor[from=ellipse]{north}
  \inheritanchor[from=ellipse]{south}
  \inheritanchor[from=ellipse]{west}
  \inheritanchor[from=ellipse]{mid west}
  \inheritanchor[from=ellipse]{base west}
  \inheritanchor[from=ellipse]{north west}
  \inheritanchor[from=ellipse]{south west}
  \inheritanchor[from=ellipse]{east}
  \inheritanchor[from=ellipse]{mid east}
  \inheritanchor[from=ellipse]{base east}
  \inheritanchor[from=ellipse]{north east}
  \inheritanchor[from=ellipse]{south east}

  \inheritbackgroundpath[from=ellipse]
}

%%
%%
%% n concentric circles
%%

\tikzset{circlen/.code={\def\circlen@n{#1}\pgfkeysalso{shape=circlen@shape}}}
\pgfdeclareshape{circlen@shape}
{
  \savedanchor\centerpoint{%
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
  }

  \saveddimen\radius{%
    %
    % Caculate ``height radius''
    %
    \pgf@ya=.5\ht\pgfnodeparttextbox%
    \advance\pgf@ya by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@ya by\pgf@yb%
    %
    % Caculate ``width radius''
    %
    \pgf@xa=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@xa by\pgf@xb%
    %
    % Calculate length of radius vector:
    %
    \pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
    \ifdim\pgf@x>\pgf@y%
        \c@pgf@counta=\pgf@x%
        \ifnum\c@pgf@counta=\z@%
        \else%
          \divide\c@pgf@counta by 255\relax%
          \pgf@xa=16\pgf@xa\relax%
          \divide\pgf@xa by\c@pgf@counta%
          \pgf@xa=16\pgf@xa\relax%
        \fi%
      \else%
        \c@pgf@counta=\pgf@y%
        \ifnum\c@pgf@counta=\z@%
        \else%
          \divide\c@pgf@counta by 255\relax%
          \pgf@ya=16\pgf@ya\relax%
          \divide\pgf@ya by\c@pgf@counta%
          \pgf@xa=16\pgf@ya\relax%
        \fi%
    \fi%
    \pgf@x=\pgf@xa%
    %
    % If necessary, adjust radius so that the size requirements are
    % met:
    %
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@x<.5\pgf@xb%
        \pgf@x=.5\pgf@xb%
    \fi%
    \ifdim\pgf@x<.5\pgf@yb%
        \pgf@x=.5\pgf@yb%
    \fi%
    %
    % Now, add larger of outer sepearations.
    %
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@xb<\pgf@yb%
      \advance\pgf@x by\pgf@yb%
    \else%
      \advance\pgf@x by\pgf@xb%
    \fi%
    \pgf@xb=2pt
    \multiply\pgf@xb\circlen@n
    \advance\pgf@x\pgf@xb
    \advance\pgf@x-2pt\relax
  }

  %
  % Anchors
  %
  \anchor{center}{\centerpoint}
  \anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{base}{\centerpoint\pgf@y=0pt}
  \anchor{north}{\centerpoint\advance\pgf@y by\radius}
  \anchor{south}{\centerpoint\advance\pgf@y by-\radius}
  \anchor{west}{\centerpoint\advance\pgf@x by-\radius}
  \anchor{east}{\centerpoint\advance\pgf@x by\radius}
  \anchor{mid west}{\centerpoint\advance\pgf@x by-\radius\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{mid east}{\centerpoint\advance\pgf@x by\radius\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{base west}{\centerpoint\advance\pgf@x by-\radius\pgf@y=0pt}
  \anchor{base east}{\centerpoint\advance\pgf@x by\radius\pgf@y=0pt}
  \anchor{north west}{
    \centerpoint
    \pgf@xa=\radius
    \advance\pgf@x by-0.707107\pgf@xa
    \advance\pgf@y by0.707107\pgf@xa
  }
  \anchor{south west}{
    \centerpoint
    \pgf@xa=\radius
    \advance\pgf@x by-0.707107\pgf@xa
    \advance\pgf@y by-0.707107\pgf@xa
  }
  \anchor{north east}{
    \centerpoint
    \pgf@xa=\radius
    \advance\pgf@x by0.707107\pgf@xa
    \advance\pgf@y by0.707107\pgf@xa
  }
  \anchor{south east}{
    \centerpoint
    \pgf@xa=\radius
    \advance\pgf@x by0.707107\pgf@xa
    \advance\pgf@y by-0.707107\pgf@xa
  }
  \anchorborder{
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \edef\pgf@marshal{%
      \noexpand\pgfpointborderellipse
      {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}
      {\noexpand\pgfqpoint{\radius}{\radius}}%
    }%
    \pgf@marshal%
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \centerpoint%
    \advance\pgf@x by\pgf@xa%
    \advance\pgf@y by\pgf@ya%
  }

  %
  % Background path
  %
  \behindbackgroundpath{
    \pgfutil@tempdima=\radius%
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@xb<\pgf@yb%
      \advance\pgfutil@tempdima by-\pgf@yb%
    \else%
      \advance\pgfutil@tempdima by-\pgf@xb%
    \fi%
    \sseq@tempcount=\@ne
    \loop
    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}%
    \advance\pgfutil@tempdima-2pt\relax
    \advance\sseq@tempcount\@ne
    \ifnum\sseq@tempcount<\circlen@n \repeat
    \tikz@mode
    \sseq@eval{\noexpand\pgfusepath{
        \iftikz@mode@draw draw,\fi
    }}
  }
  \backgroundpath{%
    \pgfutil@tempdima=\radius%
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@xb<\pgf@yb%
      \advance\pgfutil@tempdima by-\pgf@yb%
    \else%
      \advance\pgfutil@tempdima by-\pgf@xb%
    \fi%
    \advance\pgfutil@tempdima2pt\relax
    \pgfutil@tempdimb=-2pt\relax
    \multiply\pgfutil@tempdimb\circlen@n
    \advance\pgfutil@tempdima\pgfutil@tempdimb\relax
    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}
  }
}



% For out of bounds edges:

\pgfdeclarearrow{
    name = ...,
    parameters = { \the\pgfarrowlength\the\pgflinewidth},
    setup code = {
        % The different end values:
        \pgfarrowssetlineend{-\pgfarrowlength}
        \pgfarrowssetbackend{-0.6\pgfarrowlength}
        % The hull
        \pgfarrowshullpoint{-\pgfarrowlength}{0pt}
        \pgfarrowshullpoint{\pgfarrowlength}{0pt}
        % Saves: Only the length:
        \pgfarrowssavethe\pgfarrowlength
        \pgfarrowssavethe\pgflinewidth
    },
    drawing code = {
        \pgfpathcircle{\pgfpoint{-0.7\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
        \pgfpathcircle{\pgfpoint{-0.4\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
        \pgfpathcircle{\pgfpoint{-0.1\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
        \pgfpathclose
        \pgfusepathqfill
    },
    defaults = { length = 0.3cm }
} 