%%%==============================================================================
%% Copyright 2025-present by Alceu Frigeri
%%
%% This work may be distributed and/or modified under the conditions of
%%
%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
%%   version 1.3c (or later), and/or
%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
%%   version 3 (or later)
%%
%% This work has the LPPL maintenance status *maintained*.
%%
%% The Current Maintainer of this work is Alceu Frigeri
%%
%% This is version {1.0} {2025/04/19}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/tikzfxgraph
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2022/06/01]

\ProvidesExplPackage
   {tikzfxgraph}
   {2025/04/19}
   {1.0}
   {tikzfxgraph Plotting functions in a simplified way.}

%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% Idea being: { <pck-name> / pkg info } for each and all.
%%%
%%%%%%%
\keys_define:nn { tikzfxgraph / pkg info}
 {
    name        .code:n = {tikzfxgraph} ,
    prefix      .code:n = {tikzfxgraph} ,
    date        .code:n = {2025/04/19},
    version     .code:n = {1.0} ,
    description .code:n = {tikzfxgraph Plotting functions in a simplified way.}
 }
\cs_if_exist:NF \PkgInfo
 {
   \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} }
   \NewDocumentCommand \PkgDescription {m}
     { \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par }
 }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%


\msg_new:nnnn {tikzfxgraph} { no explicit domain}
 {
   (ID:#1)~You~ didn't~ explicitily~ define~ a~ range/domain~ for~ the~ x~ axis.
 }
 {
   You~ didn't~ explicitily~ define~ a~ range/domain~ for~ the~ x~ axis.
   ~Error~ Code~ ID:<#1>.
 }

\msg_new:nnnn {tikzfxgraph} { ticks min max}
 {
   (ID:#1)~Missing~ min~ and~ max~ values.~Got~#2
 }
 {
   You~ need~ to~ supply~ both~ min~ and~ max~ values.
   ~Error~ Code~ ID:<#1>.
 }

\msg_new:nnnn {tikzfxgraph} { ticks N delta}
 {
   (ID:#1)~Missing~ N~ or~ delta.~ ticks~ not~ generated.
 }
 {
   You~ need~ to~ supply~ at~ least~ N~ or~ delta.~ ticks~ not~ generated.
   ~Error~ Code~ ID:<#1>.
 }


\msg_new:nnnn {tikzfxgraph} { log min max}
 {
   (ID:#1)~For~ a~ log~ axis~ both~ min~ max~ values~ must~ be~ positive.~Got~#2
 }
 {
   For~ a~ log~ axis~ both~ min~ max~ values~ must~ be~ positive.
   ~Error~ Code~ ID:<#1>.
 }

\msg_new:nnnn {tikzfxgraph} { x domain}
 {
   (ID:#1)~X~ min/max~ weren't~ explicitly~ defined.~ This~ might~ be~ an~ error.
 }
 {
   X~ min/max~ weren't~ explicitly~ defined.~ This~ might~ be~ an~ error.
   ~Error~ Code~ ID:<#1>.
 }

\msg_new:nnnn {tikzfxgraph} {fxset already defined}
 {
   (ID:#1)~fxset~ #2~ already~ defined.
 }
 {
   The~ fxset~ #2~ is~ already~ defined.
   ~Error~ Code~ ID:<#1>.
 }

\msg_new:nnnn {tikzfxgraph} {fxset undefined}
 {
   (ID:#1)~invalid/undefined~ fxset~ #2.
 }
 {
   The~ fxset~ #1~ doesn't~ exist,~ isn't~ defined.
   ~Error~ Code~ ID:<#1>.
 }



\pgfplotscreateplotcyclelist{fxgraph~ color~ list}
 {
   red!80!black,
   green!80!black,
   blue!80!black,
   black,
   brown!70!black,
   teal!80!black,
   orange!80!black,
   violet!80!black,
   cyan!80!black,
   magenta!80!black,
   yellow!75!black,
   black!60!white
 }
\pgfplotscreateplotcyclelist{fxgraph~ line~ list}
 {
   solid,
   solid,
   solid,
   dashed,
   dashed,
   dashed,
   dashdotdotted,
   dashdotdotted,
   dashdotdotted
 }

\pgfkeys{
   pgfplots,
   linear~ axis/.style =
     {
       grid=both,
       tick~ align=outside,
       width=0.8\textwidth,
       height=0.35\textwidth,
       axis~ line~ style={color=black!85!white,very~ thick},
       axis~ x~ line=bottom,
       axis~ y~ line=left,
       cycle~ multiindex*~ list =
         {
           fxgraph~ color~ list\nextlist fxgraph~ line~ list
         } ,
       legend~ style =
         {
           font=\footnotesize,
           legend~ pos = outer~ north~ east,
           draw = none ,
           inner~ xsep=0pt,
           inner~ ysep=0pt,
           anchor = west ,
         } ,
     } ,
   semilog~ x~ axis/.style =
     {
       linear~ axis,
       log~ identify~ minor~ tick~ positions=true,
%        log~ basis~ x = 10,
     } ,
   semilog~ y~ axis/.style =
     {
       linear~ axis,
       log~ identify~ minor~ tick~ positions=true,
%        log~ basis~ y = 10,
     } ,
   loglog~ axis/.style =
     {
       linear~ axis,
       log~ identify~ minor~ tick~ positions=true,
%        log~ basis~ x = 10,
%        log~ basis~ y = 10,
     }
 }



\int_new:N \l__tikzfxgraph_tmpi_int
\seq_new:N \l__tikzfxgraph_tick_tmpi_seq
\fp_new:N  \l__tikzfxgraph_tmpi_fp
\fp_new:N  \l__tikzfxgraph_delta_tmpi_fp
\tl_new:N  \l__tikzfxgraph_nill_tl
\tl_new:N  \l__tikzfxgraph_tmpi_tl

\cs_generate_variant:Nn \fp_set:Nn {Ne}
\cs_generate_variant:Nn \fp_add:Nn {Ne}
\cs_generate_variant:Nn \seq_put_right:Nn {Ne}


\tl_new:N \l__tikzfxgraph_axis_kind_key_tl
\tl_new:N \l__tikzfxgraph_axis_style_key_tl
\tl_new:N \l__tikzfxgraph_Xaxis_type_key_tl
\tl_new:N \l__tikzfxgraph_Yaxis_type_key_tl

\tl_new:N \l__tikzfxgraph_Xticks_key_tl
\tl_new:N \l__tikzfxgraph_Xmin_key_tl
\tl_new:N \l__tikzfxgraph_Xmax_key_tl
\tl_new:N \l__tikzfxgraph_Xunits_key_tl

\tl_new:N \l__tikzfxgraph_Yticks_key_tl
\tl_new:N \l__tikzfxgraph_Ymin_key_tl
\tl_new:N \l__tikzfxgraph_Ymax_key_tl
\tl_new:N \l__tikzfxgraph_Yunits_key_tl

\tl_new:N \l__tikzfxgraph_functions_tl

\tl_new:N \l__tikzfxgraph_fxstyles_key_tl

\clist_new:N \l__tikzfxgraph_fxset_key_clist


\keys_define:nn  {tikzfxgraph / axis kind}
 {
   linear .usage:n = general ,
   linear .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_axis_kind_key_tl {axis}
       \tl_set:Nn \l__tikzfxgraph_axis_basestyle_key_tl {linear~ axis}
       \tl_set:Nn \l__tikzfxgraph_Xaxis_type_key_tl {linear}
       \tl_set:Nn \l__tikzfxgraph_Yaxis_type_key_tl {linear}
     } ,
   linear .value_forbidden:n = true ,

   loglog .usage:n = general ,
   loglog .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_axis_kind_key_tl {loglogaxis}
       \tl_set:Nn \l__tikzfxgraph_axis_basestyle_key_tl {loglog~ axis}
       \tl_set:Nn \l__tikzfxgraph_Xaxis_type_key_tl {log}
       \tl_set:Nn \l__tikzfxgraph_Yaxis_type_key_tl {log}
     } ,
   loglog .value_forbidden:n = true ,

   semilog~ x .usage:n = general ,
   semilog~ x .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_axis_kind_key_tl {semilogxaxis}
       \tl_set:Nn \l__tikzfxgraph_axis_basestyle_key_tl {semilog~ x~ axis}
       \tl_set:Nn \l__tikzfxgraph_Xaxis_type_key_tl {log}
       \tl_set:Nn \l__tikzfxgraph_Yaxis_type_key_tl {linear}
     } ,
   semilog~ x .value_forbidden:n = true ,

   semilog~ y .usage:n = general ,
   semilog~ y .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_axis_kind_key_tl {semilogyaxis}
       \tl_set:Nn \l__tikzfxgraph_axis_basestyle_key_tl {semilog~ y~ axis}
       \tl_set:Nn \l__tikzfxgraph_Xaxis_type_key_tl {linear}
       \tl_set:Nn \l__tikzfxgraph_Yaxis_type_key_tl {log}
     } ,
   semilog~ y .value_forbidden:n = true ,
 }

\cs_new_protected:Npn \__tikzfxgraph_axiskind_init:n #1
 {
   \keys_set:nn {tikzfxgraph / axis kind} {#1}
 }


\keys_define:nn   {tikzfxgraph / axis ticks}
 {
   x~ ticks .usage:n = general ,
   x~ ticks .code:n =
     {
       \__tikzfxgraph_ticks_set:NVn \l__tikzfxgraph_Xticks_key_tl \l__tikzfxgraph_Xaxis_type_key_tl {#1}

       \tl_set:NV \l__tikzfxgraph_Xmin_key_tl \l__tikzfxgraph_min_key_tl
       \tl_set:NV \l__tikzfxgraph_Xmax_key_tl \l__tikzfxgraph_max_key_tl
       \tl_set:NV \l__tikzfxgraph_Xunits_key_tl \l__tikzfxgraph_units_key_tl
     } ,
   x~ ticks .value_required:n = true ,

   y~ ticks .usage:n = general ,
   y~ ticks .code:n =
     {
       \__tikzfxgraph_ticks_set:NVn \l__tikzfxgraph_Yticks_key_tl \l__tikzfxgraph_Yaxis_type_key_tl {#1}

       \tl_set:NV \l__tikzfxgraph_Ymin_key_tl \l__tikzfxgraph_min_key_tl
       \tl_set:NV \l__tikzfxgraph_Ymax_key_tl \l__tikzfxgraph_max_key_tl
       \tl_set:NV \l__tikzfxgraph_Yunits_key_tl \l__tikzfxgraph_units_key_tl
     } ,
   y~ ticks .value_required:n = true ,
 }

\cs_new_protected:Npn \__tikzfxgraph_axisticks_init:
 {
   \tl_clear:N \l__tikzfxgraph_Xticks_key_tl
   \tl_clear:N \l__tikzfxgraph_Xmin_key_tl
   \tl_clear:N \l__tikzfxgraph_Xmax_key_tl
   \tl_clear:N \l__tikzfxgraph_Xunits_key_tl
   \tl_clear:N \l__tikzfxgraph_Yticks_key_tl
   \tl_clear:N \l__tikzfxgraph_Ymin_key_tl
   \tl_clear:N \l__tikzfxgraph_Ymax_key_tl
   \tl_clear:N \l__tikzfxgraph_Yunits_key_tl
 }



\keys_define:nn {}
 {
   tikzfxgraph / graph desc .inherit:n =
     {
       tikzfxgraph / axis kind ,
       tikzfxgraph / axis ticks ,
     }
 }

\keys_define:nn {tikzfxgraph / graph desc}
 {
   sans~ tikz picture .usage:n = general ,
   sans~ tikz picture .bool_set:N = \l__tikzfxgraph_sanstikz_key_bool ,

   without~ tikz picture .usage:n = general ,
   without~ tikz picture .bool_set:N = \l__tikzfxgraph_sanstikz_key_bool ,

   function .usage:n = general ,
   function .code:n =
     {
       \__tikzfxgraph_fxset_append:nn {default _ set}{#1}
     } ,
   function .value_required:n = true ,

   fx~ set .usage:n = general ,
   fx~ set .clist_set:N = \l__tikzfxgraph_fxset_key_clist ,
   fx~ set .value_required:n = true ,

   unknown .code:n =
     {
       \__tikzfxgraph_fxstyles_setkey:NVn
         \l__tikzfxgraph_axis_style_key_tl
         \l_keys_key_str
         {#1}
     } ,
 }

\cs_new_protected:Npn \__tikzfxgraph_graphdesc_init:
 {
       \__tikzfxgraph_fxset_clear:n {default _ set}
       \clist_clear:N \l__tikzfxgraph_fxset_key_clist
       \bool_set_false:N \l__tikzfxgraph_sanstikz_key_bool
       \tl_clear:N \l__tikzfxgraph_axis_style_key_tl

   \__tikzfxgraph_axisticks_init:
   \__tikzfxgraph_axiskind_init:n {linear}
 }


\keys_define:nn {}
 {
   tikzfxgraph / keys desc .inherit:n =
     {
       tikzfxgraph / axis kind ,
       tikzfxgraph / axis ticks ,
     }
 }

\keys_define:nn {tikzfxgraph / keys desc}
 {
   unknown .code:n =
     {
       \__tikzfxgraph_fxstyles_setkey:NVn
         \l__tikzfxgraph_axis_style_key_tl
         \l_keys_key_str
         {#1}
     } ,
 }


\cs_new_protected:Npn \__tikzfxgraph_keysdesc_init:
 {
   \tl_clear:N \l__tikzfxgraph_axis_style_key_tl

   \__tikzfxgraph_axisticks_init:
   \__tikzfxgraph_axiskind_init:n {linear}
 }


\keys_define:nn {tikzfxgraph / ticks}
 {
   min .usage:n = general ,
   min .tl_set:N = \l__tikzfxgraph_min_key_tl ,
   min .value_required:n  = true ,

   max .usage:n = general ,
   max .tl_set:N = \l__tikzfxgraph_max_key_tl ,
   max .value_required:n  = true ,

   delta .usage:n = general ,
   delta .tl_set:N = \l__tikzfxgraph_delta_key_tl ,
   delta .value_required:n  = true ,

   N .usage:n = general ,
   N .tl_set:N = \l__tikzfxgraph_N_key_tl ,
   N .value_required:n  = true ,

   units .usage:n = general ,
   units .tl_set:N = \l__tikzfxgraph_units_key_tl ,
   units .value_required:n  = true ,

   phi .usage:n = general ,
   phi .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_min_key_tl {-3.14159265}
       \tl_set:Nn \l__tikzfxgraph_max_key_tl { 3.14159265}
       \tl_set:Nn \l__tikzfxgraph_N_key_tl   { 8 }
       \tl_set:Nn \l__tikzfxgraph_units_key_tl   { rad }
     } ,
   phi .value_forbidden:n  = true ,

   db .usage:n = general ,
   db .code:n =
     {
       \tl_set:Nn \l__tikzfxgraph_min_key_tl {-20}
       \tl_set:Nn \l__tikzfxgraph_max_key_tl { 80}
       \tl_set:Nn \l__tikzfxgraph_N_key_tl   { 5 }
       \tl_set:Nn \l__tikzfxgraph_units_key_tl   { db }
     } ,
   db .value_forbidden:n  = true ,
 }

\cs_new_protected:Npn \__tikzfxgraph_ticks_init:
 {
   \tl_clear:N \l__tikzfxgraph_min_key_tl
   \tl_clear:N \l__tikzfxgraph_max_key_tl
   \tl_clear:N \l__tikzfxgraph_delta_key_tl
   \tl_clear:N \l__tikzfxgraph_N_key_tl
   \tl_clear:N \l__tikzfxgraph_units_key_tl
 }


\keys_define:nn {tikzfxgraph / fx set}
 {
   fx .usage:n = general ,
   fx .tl_set:N = \l__tikzfxgraph_fx_key_tl ,
   fx .value_required:n  = true ,

   id .usage:n = general ,
   id .tl_set:N = \l__tikzfxgraph_fxid_key_tl ,
   id .value_required:n  = true ,

   legend .usage:n = general ,
   legend .tl_set:N = \l__tikzfxgraph_fxlegend_key_tl ,
   legend .value_required:n  = true ,

   unknown .code:n =
     {
       \__tikzfxgraph_fxstyles_setkey:NVn
         \l__tikzfxgraph_fxstyles_key_tl
         \l_keys_key_str
         {#1}
     } ,
 }


\cs_new_protected:Npn \__tikzfxgraph_fxset_init:
 {
   \tl_clear:N \l__tikzfxgraph_fxstyles_key_tl
   \tl_clear:N \l__tikzfxgraph_fx_key_tl
   \tl_clear:N \l__tikzfxgraph_fxid_key_tl
   \tl_clear:N \l__tikzfxgraph_fxlegend_key_tl
 }


\prg_generate_conditional_variant:Nnn \fp_compare:nNn {eNn} {p , T , F , TF}


\cs_new_protected:Npn  \__tikzfxgraph_fxstyles_setkey:Nnn #1#2#3
 {
   \tl_if_blank:VF #1
     {
       \tl_put_right:Nn #1 ,
     }
    \tl_if_blank:nTF {#3}
     {
       \tl_put_right:Nn #1 {#2}
     }
     {
       \tl_put_right:Nn #1 {#2={#3}}
     }
 }

\cs_generate_variant:Nn  \__tikzfxgraph_fxstyles_setkey:Nnn {NVn}


\cs_new_protected:Npn \__tikzfxgraph_ticks_set:Nnn #1#2#3
 {
   \__tikzfxgraph_ticks_init:

   \keys_set:nn {tikzfxgraph / ticks}
     {#3}
   \bool_lazy_or:nnTF
     {\tl_if_blank_p:V \l__tikzfxgraph_min_key_tl} {\tl_if_blank_p:V \l__tikzfxgraph_max_key_tl}
     {
       \msg_error:nnne {tikzfxgraph} {ticks min max}{ticks-01}
         {min:<\l__tikzfxgraph_min_key_tl> ~-~ max:<\l__tikzfxgraph_max_key_tl>}
     }
     {
       \tl_if_blank:VTF \l__tikzfxgraph_N_key_tl
         {
           \tl_if_blank:VTF \l__tikzfxgraph_delta_key_tl
             {
               \msg_warning:nnn {tikzfxgraph} {ticks N delta}{ticks-02}
               \tl_clear:N #1
             }
             {
                 \int_zero:N \l__tikzfxgraph_tmpi_int
                 \seq_clear:N \l__tikzfxgraph_tick_tmpi_seq
               \str_if_eq:nnTF {#2}{linear}
                 {
                   \fp_set:Ne \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_min_key_tl}
                   \fp_set:Ne \l__tikzfxgraph_delta_tmpi_fp { \l__tikzfxgraph_delta_key_tl }
                   \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_use:N \l__tikzfxgraph_tmpi_fp}
                   \fp_while_do:nNnn
                     {\l__tikzfxgraph_tmpi_fp} < {\l__tikzfxgraph_max_key_tl}
                     {
                       \fp_add:Nn  \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_delta_tmpi_fp}
                       \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_use:N \l__tikzfxgraph_tmpi_fp}
                     }
                   \tl_set:Ne #1 {\seq_use:Nn \l__tikzfxgraph_tick_tmpi_seq {~,~}}
                 }
                 { %log
                   \bool_lazy_and:nnTF
                     { \fp_compare_p:eNn {\l__tikzfxgraph_max_key_tl} > {0} } { \fp_compare_p:eNn {\l__tikzfxgraph_min_key_tl} > {0} }
                     {
                     \fp_set:Ne \l__tikzfxgraph_tmpi_fp {ln(\l__tikzfxgraph_min_key_tl)}
                     \fp_set:Ne \l__tikzfxgraph_tmpii_fp {ln(\l__tikzfxgraph_max_key_tl)}
                     \fp_set:Ne \l__tikzfxgraph_delta_tmpi_fp { ln(\l__tikzfxgraph_delta_key_tl) }
                       \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_eval:n {exp(\l__tikzfxgraph_tmpi_fp)}}
                       \fp_while_do:nNnn
                         {\l__tikzfxgraph_tmpi_fp} < {\l__tikzfxgraph_tmpii_fp}
                         {
                           \fp_add:Nn  \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_delta_tmpi_fp}
                           \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_eval:n {exp(\l__tikzfxgraph_tmpi_fp)}}
                         }
                       \tl_set:Ne #1 {\seq_use:Nn \l__tikzfxgraph_tick_tmpi_seq {~,~}}
                     }
                     {
                       \msg_error:nnne {tikzfxgraph}{log min max}{ticks-03}
                         {min:<\l__tikzfxgraph_min_key_tl> ~-~ max:<\l__tikzfxgraph_max_key_tl>} % both must be positive
                     }
                 }
             }
         }
         {
             \int_zero:N \l__tikzfxgraph_tmpi_int
             \seq_clear:N \l__tikzfxgraph_tick_tmpi_seq
           \str_if_eq:nnTF {#2}{linear}
             {
               \fp_set:Ne \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_min_key_tl}
               \fp_set:Ne \l__tikzfxgraph_delta_tmpi_fp { (\l__tikzfxgraph_max_key_tl - \l__tikzfxgraph_min_key_tl) / \l__tikzfxgraph_N_key_tl}
               \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_use:N \l__tikzfxgraph_tmpi_fp}
               \int_while_do:nNnn
                 {\l__tikzfxgraph_tmpi_int} < {\l__tikzfxgraph_N_key_tl}
                 {
                   \fp_add:Nn  \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_delta_tmpi_fp}
                   \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_use:N \l__tikzfxgraph_tmpi_fp}
                   \int_incr:N \l__tikzfxgraph_tmpi_int
                 }
               \tl_set:Ne #1 {\seq_use:Nn \l__tikzfxgraph_tick_tmpi_seq {~,~}}
             }
             { %log
               \bool_lazy_and:nnTF
                 { \fp_compare_p:eNn {\l__tikzfxgraph_max_key_tl} > {0} } { \fp_compare_p:eNn {\l__tikzfxgraph_min_key_tl} > {0} }
                 {
                 \fp_set:Ne \l__tikzfxgraph_tmpi_fp {ln(\l__tikzfxgraph_min_key_tl)}
                 \fp_set:Ne \l__tikzfxgraph_delta_tmpi_fp { (ln(\l__tikzfxgraph_max_key_tl) - ln(\l__tikzfxgraph_min_key_tl)) / \l__tikzfxgraph_N_key_tl}
                   \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_eval:n {exp(\l__tikzfxgraph_tmpi_fp)}}
                   \int_while_do:nNnn
                     {\l__tikzfxgraph_tmpi_int} < {\l__tikzfxgraph_N_key_tl}
                     {
                       \fp_add:Nn  \l__tikzfxgraph_tmpi_fp {\l__tikzfxgraph_delta_tmpi_fp}
                       \seq_put_right:Ne \l__tikzfxgraph_tick_tmpi_seq {\fp_eval:n {exp(\l__tikzfxgraph_tmpi_fp)}}
                       \int_incr:N \l__tikzfxgraph_tmpi_int
                     }
                   \tl_set:Ne #1 {\seq_use:Nn \l__tikzfxgraph_tick_tmpi_seq {~,~}}
                 }
                 {
                   \msg_error:nnn {tikzfxgraph}{log min max}{ticks-04}
                     {min:<\l__tikzfxgraph_min_key_tl> ~-~ max:<\l__tikzfxgraph_max_key_tl>} % both must be positive
                 }
             }
         }
     }
 }
\cs_generate_variant:Nn \__tikzfxgraph_ticks_set:Nnn { NVn }


\cs_new_protected:Npn \__tikzfxgraph_fxset_addplot:nn #1#2
 {
   \__tikzfxgraph_fxset_init:

   \keys_set:nn {tikzfxgraph / fx set}
     {#2}

   \tl_set:Nn \l_tmpa_tl {samples=2000}
   \tl_if_blank:VF \l__tikzfxgraph_fxid_key_tl
     {
       \tl_put_right:Ne \l_tmpa_tl {,id=\l__tikzfxgraph_fxid_key_tl}
     }
   \tl_put_right:ce {l__tikzfxgraph_fxset_ #1 _tl}
     {
       \exp_not:N\addplot+ gnuplot
         [ \l_tmpa_tl , \l__tikzfxgraph_fxstyles_key_tl ]
         {\l__tikzfxgraph_fx_key_tl};
     }
   \tl_if_blank:VF \l__tikzfxgraph_fxlegend_key_tl
     {
       \tl_put_right:ce {l__tikzfxgraph_fxset_ #1 _tl}
         {
           \exp_not:N\addlegendentry {\l__tikzfxgraph_fxlegend_key_tl}
         }
     }
 }

\cs_new_protected:Npn \__tikzfxgraph_fxset_new:n #1
 {
   \tl_if_exist:cTF {l__tikzfxgraph_fxset_ #1 _tl}
     {
       \msg_error:nnnn {tikzfxgraph}{fxset already defined}{fxset-01}{#1}
     }
     {
       \tl_new:c {l__tikzfxgraph_fxset_ #1 _tl}
     }
 }


\__tikzfxgraph_fxset_new:n {default _ set}

\cs_new_protected:Npn \__tikzfxgraph_fxset_clear:n #1
 {
   \tl_if_exist:cTF {l__tikzfxgraph_fxset_ #1 _tl}
     {
       \tl_clear:c {l__tikzfxgraph_fxset_ #1 _tl}
     }
     {
       \msg_error:nnnn {tikzfxgraph}{fxset undefined}{fxset-02}{#1}
     }
 }



\cs_new_protected:Npn \__tikzfxgraph_fxset_append:nn #1#2
 {
   \tl_if_exist:cTF {l__tikzfxgraph_fxset_ #1 _tl}
     {
       \__tikzfxgraph_fxset_addplot:nn {#1}{#2}
     }
     {
       \msg_error:nnnn {tikzfxgraph}{fxset undefined}{fxset-03}{#1}
     }
  }

\NewDocumentCommand{\fxsetnew}{m}
 { \__tikzfxgraph_fxset_new:n {#1} }


\NewDocumentCommand{\fxsetappend}{mm}
 { \__tikzfxgraph_fxset_append:nn {#1}{#2} }


\NewDocumentCommand{\fxsetnewstyle}{mm}
 {
   \__tikzfxgraph_keysdesc_init:

   \keys_set:nn {tikzfxgraph / keys desc}
     {#2}
   \__tikzfxgraph_set_keys:N \l__tikzfxgraph_stylekeys_set_tl
   \use:e
     {
       \exp_not:N\pgfkeys{pgfplots,
         #1/.style =
           { \l__tikzfxgraph_stylekeys_set_tl }
       }
     }
%    \tl_show:n {key~ being~ defined:<#1>}
%     \pgfkeys{pgfplots,#1/.show~ code}
 }


\cs_new_protected:Npn \__tikzfxgraph_axisdraw:nnnn #1#2#3#4
 {
   \bool_if:NTF \l__tikzfxgraph_sanstikz_key_bool
     {
       \tl_set:Nn \l_tmpa_tl
         {
           \begin{#1}[#2]
             #3
             #4
           \end{#1}
         }
     }
     {
       \tl_set:Nn \l_tmpa_tl
         {
           \begin{tikzpicture}
             \begin{#1}[#2]
               #3
               #4
             \end{#1}
           \end{tikzpicture}
         }
     }
%    \tl_show:N \l_tmpa_tl
   \l_tmpa_tl
 }

\cs_generate_variant:Nn \__tikzfxgraph_axisdraw:nnnn {VVVn}

\cs_new_protected:Npn \__tikzfxgraph_set_keys:Nnnn #1#2#3#4
 {
   \tl_if_blank:nTF {#2}
     { \tl_clear:N #1 }
     { \tl_set:Nn #1 {#2} }
   \tl_if_blank:nF {#3}
     { \tl_put_right:Nn #1 {xtick={#3},} }
   \tl_if_blank:nF {#4}
     { \tl_put_right:Nn #1 {ytick={#4}} }
 }

\cs_generate_variant:Nn \__tikzfxgraph_set_keys:Nnnn {NVVV}

\tl_new:N \l__tikzfxgraph_stylekeys_set_tl

\cs_new_protected:Npn \__tikzfxgraph_set_keys:N #1
 {
   \tl_clear:N \l_tmpa_tl
   \tl_if_blank:VF \l__tikzfxgraph_axis_style_key_tl
     {
       \tl_set:NV \l_tmpa_tl \l__tikzfxgraph_axis_style_key_tl
       \tl_put_right:Nn \l_tmpa_tl {,}
     }

   \bool_lazy_or:nnTF {\tl_if_blank_p:V \l__tikzfxgraph_Xmin_key_tl } {\tl_if_blank_p:V \l__tikzfxgraph_Xmax_key_tl}
     {
       \msg_warning:nnn {tikzfxgraph}{x domain}{keys-01}
     }
     {
       \tl_put_right:Ne \l_tmpa_tl
         {
           xmin=\l__tikzfxgraph_Xmin_key_tl,
           xmax=\l__tikzfxgraph_Xmax_key_tl,
           domain=\l__tikzfxgraph_Xmin_key_tl : \l__tikzfxgraph_Xmax_key_tl,
         }
     }
   \tl_if_blank:VF \l__tikzfxgraph_Xunits_key_tl
     {
       \tl_put_right:Ne \l_tmpa_tl
         { x~ unit=\l__tikzfxgraph_Xunits_key_tl, }
     }
   \bool_lazy_or:nnF {\tl_if_blank_p:V \l__tikzfxgraph_Ymin_key_tl} {\tl_if_blank_p:V \l__tikzfxgraph_Ymax_key_tl}
     {
       \tl_put_right:Ne \l_tmpa_tl
         {
           ymin=\l__tikzfxgraph_Ymin_key_tl,
           ymax=\l__tikzfxgraph_Ymax_key_tl,
         }
     }
   \tl_if_blank:VF \l__tikzfxgraph_Yunits_key_tl
     {
       \tl_put_right:Ne \l_tmpa_tl
         { y~ unit=\l__tikzfxgraph_Yunits_key_tl, }
     }

   \__tikzfxgraph_set_keys:NVVV
     #1
     \l_tmpa_tl
     \l__tikzfxgraph_Xticks_key_tl
     \l__tikzfxgraph_Yticks_key_tl

 }


\NewDocumentCommand{\fxgraphdraw}{m}
 {
   \begin{fxgraph}{#1}
   \end{fxgraph}
 }

\NewDocumentEnvironment{fxgraph}{m +b}
 {
   \__tikzfxgraph_graphdesc_init:

   \keys_set:nn {tikzfxgraph / graph desc}
     {#1}

   \__tikzfxgraph_set_keys:N \l__tikzfxgraph_stylekeys_set_tl

   \clist_map_inline:Nn \l__tikzfxgraph_fxset_key_clist
     {
       \tl_if_exist:cTF {l__tikzfxgraph_fxset_ ##1 _tl}
         {
           \tl_put_right:Nv
             \l__tikzfxgraph_fxset_default_set_tl
             { l__tikzfxgraph_fxset_ ##1 _tl }
         }
         {
         \msg_error:nnnn {tikzfxgraph} {fxset undefined}{set-02}{##1}
         }
     }

     \tl_set:NV \l_tmpa_tl \l__tikzfxgraph_axis_basestyle_key_tl
     \tl_put_right:Nn \l_tmpa_tl {,}
     \tl_put_right:NV \l_tmpa_tl \l__tikzfxgraph_stylekeys_set_tl

%  \tl_show:N \l__tikzfxgraph_stylekeys_set_tl
%  \tl_show:N \l_tmpa_tl


   \__tikzfxgraph_axisdraw:VVVn
     \l__tikzfxgraph_axis_kind_key_tl
     \l_tmpa_tl
     \l__tikzfxgraph_fxset_default_set_tl
     {#2}
 }
 {}