% \iffalse %<*driver> \documentclass{l3doc} \OnlyDescription \begin{document} \DocInput{gradbars.dtx} \end{document} % % \fi % \title{\textsf{gradbars}: documented source} % \author{SuFan (Tape5try)} % \date{v1.1.0 / 2026/10/25} % \maketitle % \input{docs/source-guide.tex} % \StopEventually{} % \section{\texttt{gradbars-accessible.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Opt-in color roles; existing defaults unchanged. %\ProvidesPackage{gradbars-accessible}[2026/10/25 v1.1.0 Accessible color roles] %% Okabe--Ito Color Universal Design palette; see docs/accessibility.md. %\definecolor{gradbarsCudBlue}{HTML}{0072B2} %\definecolor{gradbarsCudOrange}{HTML}{E69F00} %\definecolor{gradbarsCudTeal}{HTML}{009E73} %\definecolor{gradbarsCudSky}{HTML}{56B4E9} %\definecolor{gradbarsCudVermillion}{HTML}{D55E00} %\definecolor{gradbarsCudPurple}{HTML}{CC79A7} %\definecolor{gradbarsCudYellow}{HTML}{F0E442} %\pgfkeys{/gradbars, % .accessible heat roles/.code={\pgfkeysifdefined{/gradbars/heat low color/.@cmd} % {\pgfkeysalso{/gradbars/heat low color=white,/gradbars/heat high color=gradbarsCudBlue}}{}}, % theme/accessible/.style={fill=solid,left color=gradbarsCudBlue,right color=gradbarsCudBlue, % track color=black!6,text color=auto,negative color=gradbarsCudVermillion}, % palette/accessible/.style={theme=accessible, % stack colors={gradbarsCudBlue,gradbarsCudOrange,gradbarsCudTeal,gradbarsCudPurple,gradbarsCudSky,gradbarsCudVermillion,gradbarsCudYellow}, % stack patterns={none,diagonal,dots,crosshatch,none,diagonal,dots}, % threshold colors={gradbarsCudVermillion,black!15,gradbarsCudBlue}, % compare color=gradbarsCudOrange,spark high color=gradbarsCudBlue,spark low color=gradbarsCudVermillion, % spark win color=gradbarsCudBlue,spark loss color=gradbarsCudVermillion,spark zero color=black, % heat center color=white,.accessible heat roles}, % heat palette/accessible-sequential/.style={heat palette=sequential, % heat low color=white,heat high color=gradbarsCudBlue,heat text color=auto}, % heat palette/accessible-diverging/.style={heat palette=diverging, % heat low color=gradbarsCudVermillion,heat high color=gradbarsCudBlue, % heat center color=white,heat text color=auto}} %\endinput % \end{macrocode} % \section{\texttt{gradbars-api.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Stable version-1 public extension entry points. %\ProvidesPackage{gradbars-api}[2026/10/25 v1.1.0 gradbars public interfaces] %\ExplSyntaxOn %\prop_new:N\g__gradbars_library_files_prop %\prop_new:N\g__gradbars_library_dependencies_prop %\prop_new:N\g__gradbars_library_state_prop %\seq_new:N\g__gradbars_library_stack_seq %\tl_new:N\l__gradbars_library_file_tl %\tl_new:N\l__gradbars_library_dependencies_tl %\bool_new:N\g__gradbars_loader_valid_bool %\prop_new:N\g__gradbars_type_names_prop %\prop_new:N\g__gradbars_formatter_names_prop %\tl_new:N\l__gradbars_public_value_tl %\seq_new:N\l__gradbars_module_version_seq %\tl_new:N\g__gradbars_release_version_tl %\tl_set:Nx\l_tmpa_tl{\use:c{ver@gradbars.sty}} %\regex_extract_once:nVNTF{v([0-9]+\.[0-9]+\.[0-9]+)}\l_tmpa_tl\l__gradbars_module_version_seq % {\tl_gset:Nx\g__gradbars_release_version_tl{\seq_item:Nn\l__gradbars_module_version_seq{2}}} % {\PackageError{gradbars}{Load~the~gradbars~entry~package}{Do~not~load~internal~modules~directly.}} %\cs_generate_variant:Nn\clist_map_inline:nn{Vn} %\cs_new_protected:Npn\__gradbars_public_error:n #1 % {\PackageError{gradbars}{#1}{Check~the~public~interface~and~library~requirements.}} %\cs_new_protected:Npn\__gradbars_check_module:n #1 % {\tl_set:Nx\l_tmpa_tl{\use:c{ver@#1.sty}} % \regex_extract_once:nVNTF{v([0-9]+\.[0-9]+\.[0-9]+)}\l_tmpa_tl\l__gradbars_module_version_seq % {\str_if_eq:eeF{\seq_item:Nn\l__gradbars_module_version_seq{2}}{\g__gradbars_release_version_tl} % {\bool_gset_false:N\g__gradbars_loader_valid_bool % \__gradbars_public_error:n{Mixed~module~versions:~#1~requires~v\g__gradbars_release_version_tl}}} % {\bool_gset_false:N\g__gradbars_loader_valid_bool % \__gradbars_public_error:n{Missing~module~version:~#1}}} %\prg_new_protected_conditional:Npnn\__gradbars_name_valid:n #1{TF} % {\regex_match:nnTF{\A[a-z][a-z0-9-]*\Z}{#1}{\prg_return_true:}{\prg_return_false:}} % %\NewExpandableDocumentCommand\gradbarsversion{}{\tl_use:N\g__gradbars_release_version_tl} %\seq_new:N\l__gradbars_required_version_seq %\seq_new:N\l__gradbars_current_version_seq %\int_new:N\l__gradbars_version_order_int %\NewDocumentCommand\gradbarsrequireversion{m} % {\regex_match:nnTF{\A(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\Z}{#1} % {\seq_set_split:Nnn\l__gradbars_required_version_seq{.}{#1} % \exp_args:NNnV\seq_set_split:Nnn\l__gradbars_current_version_seq{.}\g__gradbars_release_version_tl % \int_zero:N\l__gradbars_version_order_int % \int_step_inline:nn{3} % {\int_compare:nNnT{\l__gradbars_version_order_int}={0} % {\int_compare:nNnT{\seq_item:Nn\l__gradbars_current_version_seq{##1}}> % {\seq_item:Nn\l__gradbars_required_version_seq{##1}}{\int_set:Nn\l__gradbars_version_order_int{1}} % \int_compare:nNnT{\seq_item:Nn\l__gradbars_current_version_seq{##1}}< % {\seq_item:Nn\l__gradbars_required_version_seq{##1}}{\int_set:Nn\l__gradbars_version_order_int{-1}}}} % \int_compare:nNnT{\l__gradbars_version_order_int}<{0} % {\__gradbars_public_error:n{Library~requires~gradbars~#1~or~newer;~installed~\gradbarsversion}}} % {\__gradbars_public_error:n{Invalid~required~version:~#1}}} % %\NewDocumentCommand\gradbarsdeclarelibrary{m m m} % {\__gradbars_name_valid:nTF{#1} % {\prop_if_in:NnTF\g__gradbars_library_files_prop{#1} % {\__gradbars_public_error:n{Library~already~registered:~#1}} % {\prop_gput:Nnn\g__gradbars_library_files_prop{#1}{#3} % \prop_gput:Nnn\g__gradbars_library_dependencies_prop{#1}{#2}}} % {\__gradbars_public_error:n{Invalid~library~name:~#1}}} %\cs_new_protected:Npn\__gradbars_load_library:n #1 % {\prop_get:NnNTF\g__gradbars_library_files_prop{#1}\l__gradbars_library_file_tl % {\str_case_e:nnF{\prop_item:Nn\g__gradbars_library_state_prop{#1}} % {{loaded}{}{loading}{\bool_gset_false:N\g__gradbars_loader_valid_bool % \__gradbars_public_error:n{Circular~library~dependency:~\seq_use:Nn\g__gradbars_library_stack_seq{~->~}~->~#1}}} % {\prop_gput:Nnn\g__gradbars_library_state_prop{#1}{loading} % \seq_gput_right:Nn\g__gradbars_library_stack_seq{#1} % \prop_get:NnN\g__gradbars_library_dependencies_prop{#1}\l__gradbars_library_dependencies_tl % \clist_map_inline:Vn\l__gradbars_library_dependencies_tl % {\bool_if:NT\g__gradbars_loader_valid_bool{\__gradbars_load_library:n{##1}}} % \bool_if:NT\g__gradbars_loader_valid_bool % {\prop_get:NnN\g__gradbars_library_files_prop{#1}\l__gradbars_library_file_tl % \file_if_exist:VTF\l__gradbars_library_file_tl % {\regex_replace_once:nnN{\.sty\Z}{}\l__gradbars_library_file_tl % \exp_args:NV\RequirePackage\l__gradbars_library_file_tl % \regex_match:nVT{\Agradbars-lib-}\l__gradbars_library_file_tl % {\exp_args:NV\__gradbars_check_module:n\l__gradbars_library_file_tl} % \bool_if:NT\g__gradbars_loader_valid_bool % {\prop_gput:Nnn\g__gradbars_library_state_prop{#1}{loaded}}} % {\bool_gset_false:N\g__gradbars_loader_valid_bool % \__gradbars_public_error:n{Library~file~not~found:~\l__gradbars_library_file_tl}}} % \seq_gpop_right:NN\g__gradbars_library_stack_seq\l_tmpa_tl % \bool_if:NF\g__gradbars_loader_valid_bool{\prop_gremove:Nn\g__gradbars_library_state_prop{#1}}}} % {\bool_gset_false:N\g__gradbars_loader_valid_bool\__gradbars_public_error:n{Unknown~library:~#1}}} %\NewDocumentCommand\usegradbarslibrary{m} % {\bool_gset_true:N\g__gradbars_loader_valid_bool % \clist_map_inline:nn{#1}{\bool_if:NT\g__gradbars_loader_valid_bool{\__gradbars_load_library:n{##1}}}} %\NewDocumentCommand\gradbarsiflibraryloaded{m m m} % {\str_if_eq:eeTF{\prop_item:Nn\g__gradbars_library_state_prop{#1}}{loaded}{#2}{#3}} %\NewDocumentCommand\gradbarsset{m}{\gradbarssetup{#1}} %\cs_new_protected:Npn\gradbarsCheckFormatter #1 % {\prop_if_in:NnF\g__gradbars_formatter_names_prop{#1}{\__gradbars_public_error:n{Unknown~formatter:~#1}}} %\pgfkeys{/gradbars/formatter/.code={\gradbarsCheckFormatter{#1}\def\gradbars@formatter{#1}}} %\prop_gput:Nnn\g__gradbars_formatter_names_prop{builtin}{builtin} %\prop_gput:Nnn\g__gradbars_formatter_names_prop{siunitx}{builtin} %\cs_new_protected:Npn\__gradbars_format_builtin:nnn #1#2#3 % {\str_if_eq:nnTF{#3}{scientific} % {\pgfmathprintnumber[sci,sci~zerofill,precision=#2]{#1}} % {\str_if_eq:nnTF{#3}{grouped} % {\pgfmathprintnumber[fixed,fixed~zerofill,precision=#2,1000~sep={\mathord{,}}]{#1}} % {\pgfmathprintnumber[fixed,fixed~zerofill,precision=#2,1000~sep={\,}]{#1}}}} %\NewDocumentCommand\gradbarsformatnumber{O{} m} % {\group_begin:\pgfkeys{/gradbars,formatter=builtin,precision=1,number~format=fixed,#1} % \gradbars@validtrue\gradbarsCheckNumber{#2}{formatter~value} % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl % {\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \ifgradbars@valid % \str_if_eq:eeTF{\gradbars@formatter}{builtin} % {\use:x{\exp_not:N\__gradbars_format_builtin:nnn{\fp_eval:n{#2}}{\gradbars@precision}{\gradbars@numberformat}}} % {\str_if_eq:eeTF{\gradbars@formatter}{siunitx} % {\gradbarsValidateFormatter\gradbarsSIOptions\num{#2}} % {\__gradbars_public_error:n{Number~helper~supports~builtin~or~siunitx}}} % \fi\group_end:} %\NewDocumentCommand\gradbarsdeclareformatter{m +m} % {\__gradbars_name_valid:nTF{#1} % {\prop_if_in:NnTF\g__gradbars_formatter_names_prop{#1} % {\__gradbars_public_error:n{Formatter~already~registered:~#1}} % {\cs_gset_protected:cpn{__gradbars_formatter_#1:nnn}##1##2##3{#2} % \prop_gput:Nnn\g__gradbars_formatter_names_prop{#1}{custom}}} % {\__gradbars_public_error:n{Invalid~formatter~name:~#1}}} %\cs_new_eq:NN\__gradbars_single_label_before_api:\gradbarsSingleLabel %\cs_set_protected:Npn\gradbarsSingleLabel % {\str_if_eq:eeTF{\prop_item:Ne\g__gradbars_formatter_names_prop{\gradbars@formatter}}{custom} % {\tl_if_empty:oTF{\gradbars@text} % {\ifgradbars@missing\gradbars@missingtext\else % \bool_if:NTF\l__gradbars_decimal_active_bool % {\__gradbars_public_error:n{Custom~formatters~do~not~support~decimal~alignment}} % {\use:x{\exp_not:c{__gradbars_formatter_\gradbars@formatter :nnn} % {\gradbars@number}{\gradbars@precision}{\gradbars@numberformat}}\gradbarsNumericSuffix}\fi} % {\gradbars@text}} % {\__gradbars_single_label_before_api:}} %\NewDocumentCommand\gradbarsdeclaretype{m +m} % {\__gradbars_name_valid:nTF{#1} % {\prop_if_in:NnTF\g__gradbars_type_names_prop{#1} % {\__gradbars_public_error:n{Graphic~type~already~registered:~#1}} % {\cs_gset_protected:cpn{__gradbars_type_#1:n}##1{#2} % \prop_gput:Nnn\g__gradbars_type_names_prop{#1}{custom}}} % {\__gradbars_public_error:n{Invalid~graphic~type~name:~#1}}} %\gradbarsdeclaretype{bar}{\gradbar{#1}} %\gradbarsdeclaretype{heat}{\gradheat{#1}} %\NewDocumentCommand\gradgraphic{O{} m m} % {\group_begin:\gradbarssetup{#1} % \prop_if_in:NnTF\g__gradbars_type_names_prop{#2} % {\tl_set:Nn\l__gradbars_public_value_tl{#3}\tl_trim_spaces:N\l__gradbars_public_value_tl % \str_if_eq:VnTF\l__gradbars_public_value_tl{NA} % {\use:c{__gradbars_type_#2:n}{NA}} % {\gradbars@validtrue\gradbarsCheckNumber{#3}{graphic~value} % \ifgradbars@valid % \use:x{\exp_not:c{__gradbars_type_#2:n}{\fp_eval:n{#3}}}\fi}} % {\__gradbars_public_error:n{Unknown~graphic~type:~#2}} % \group_end:} %\cs_new_protected:Npn\__gradbars_unloaded:n #1 % {\__gradbars_public_error:n{Library~#1~not~loaded;~use~usegradbarslibrary~in~the~preamble}} %\ProvideDocumentCommand\gradstack{O{} m}{\__gradbars_unloaded:n{stack}} %\ProvideDocumentCommand\gradspark{O{} m}{\__gradbars_unloaded:n{spark}} %\ProvideDocumentCommand\gradheat{O{} m}{\__gradbars_unloaded:n{heat}} %\ProvideDocumentCommand\gradbarscolumn{s m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarshead{m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarsloadcsv{O{} m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarcsv{O{} m m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarscsvcell{m m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarscsvstyle{m m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentCommand\gradbarscsvtable{O{} m m m}{\__gradbars_unloaded:n{csv}} %\ProvideDocumentEnvironment{gradtable}{O{} +b}{\__gradbars_unloaded:n{table}}{} %\ProvideDocumentCommand\gradcolumn{O{} m m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradrow{m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradsummary{O{} m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradgroup{m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradheader{+m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradspan{m m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradtablestyle{m m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\gradtableschema{m +m}{\__gradbars_unloaded:n{table}} %\ProvideDocumentCommand\graduseschema{m}{\__gradbars_unloaded:n{table}} %\cs_new_protected:Npn\__gradbars_tblr_unloaded: % {\__gradbars_public_error:n{Load~the~tabularray~gradbars~library~with~UseTblrLibrary}} %\ProvideDocumentCommand\gradtblrsetup{m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradtblrcell{O{} m m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradbarTblr{O{} m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradheatTblr{O{} m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradnumberTblr{O{} m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradcompareTblr{O{} m}{\__gradbars_tblr_unloaded:} %\ProvideDocumentCommand\gradcorrelation{O{} m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradablation{O{} m m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradmetric{O{} m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradcorrelationcolumn{O{} m m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradablationcolumn{O{} m m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradmetriccolumn{O{} m m}{\__gradbars_unloaded:n{reports}} %\ProvideDocumentCommand\gradboxplot{O{} m}{\__gradbars_unloaded:n{distribution}} %\ProvideDocumentCommand\gradboxsummary{O{} m}{\__gradbars_unloaded:n{distribution}} %\ProvideDocumentCommand\gradcomputesummary{m +m}{\__gradbars_unloaded:n{distribution}} %\ProvideDocumentCommand\gradsummarytext{O{} m}{\__gradbars_unloaded:n{distribution}} %\ProvideDocumentCommand\gradheatlegend{O{}}{\__gradbars_unloaded:n{legend}} %\ProvideDocumentCommand\gradreferencelegend{O{} m}{\__gradbars_unloaded:n{legend}} %\ProvideDocumentCommand\gradlegenddefine{m m}{\__gradbars_unloaded:n{legend}} %\ProvideDocumentCommand\gradlegenduse{O{} m}{\__gradbars_unloaded:n{legend}} %\ProvideDocumentCommand\gradtblrtagging{m}{\__gradbars_tblr_unloaded:} %\@onlypreamble\usegradbarslibrary %\@onlypreamble\gradbarsdeclarelibrary %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-backend.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Versioned public scalar backend contract. %\ProvidesPackage{gradbars-backend}[2026/10/25 v1.1.0 Public backend contract] %\ExplSyntaxOn %\cs_generate_variant:Nn\clist_if_in:nnTF{Vn} %\cs_generate_variant:Nn\clist_if_in:nnF{Vn} %\prop_new:N\g__gradbars_backends_prop %\prop_new:N\l__gradbars_backend_record_prop %\clist_const:Nn\c__gradbars_backend_features_clist % {bar,heat,missing,signed,gradient,print,labels,units,clip,decorations,embedded,tagging,artifact} %\clist_const:Nn\c__gradbars_backend_kinds_clist % {bar,heat,stack,spark,compare,dumbbell,range,bullet,boxplot,heat-legend,reference-legend,category-legend} %\tl_new:N\l__gradbars_backend_tl %\tl_new:N\l__gradbars_backend_fallback_tl %\tl_new:N\l__gradbars_backend_native_tl %\clist_new:N\l__gradbars_backend_caps_clist %\clist_new:N\l__gradbars_backend_required_clist %\clist_new:N\l__gradbars_backend_missing_clist %\tl_new:N\l__gradbars_backend_kind_tl %\bool_new:N\l__gradbars_backend_active_bool %\bool_new:N\l__gradbars_backend_default_bool %\bool_new:N\l__gradbars_backend_valid_bool %\tl_set:Nn\l__gradbars_backend_tl{tikz} %\tl_set:Nn\l__gradbars_backend_fallback_tl{error} %\prop_gput:Nnn\g__gradbars_backends_prop{tikz} % {bar,heat,stack,spark,compare,dumbbell,range,bullet,boxplot,heat-legend,reference-legend,category-legend,missing,signed,gradient,print,labels,units,clip,decorations,embedded,tagging,artifact} %\pgfkeys{/gradbars, % backend/.code={\prop_if_in:NnTF\g__gradbars_backends_prop{#1} % {\tl_set:Nn\l__gradbars_backend_tl{#1}} % {\__gradbars_public_error:n{Unknown~backend:~#1}}}, % backend~fallback/.is~choice, % backend~fallback/error/.code={\tl_set:Nn\l__gradbars_backend_fallback_tl{error}}, % backend~fallback/tikz/.code={\tl_set:Nn\l__gradbars_backend_fallback_tl{tikz}}} %\NewExpandableDocumentCommand\gradbarsbackendversion{}{1} %\NewDocumentCommand\gradbarsdeclarebackend{m m +m} % {\bool_set_true:N\l__gradbars_backend_valid_bool % \__gradbars_name_valid:nTF{#1}{} % {\bool_set_false:N\l__gradbars_backend_valid_bool % \__gradbars_public_error:n{Invalid~backend~name:~#1}} % \prop_if_in:NnT\g__gradbars_backends_prop{#1} % {\bool_set_false:N\l__gradbars_backend_valid_bool % \__gradbars_public_error:n{Backend~already~registered:~#1}} % \clist_set:Nn\l__gradbars_backend_caps_clist{#2} % \clist_remove_duplicates:N\l__gradbars_backend_caps_clist % \clist_map_inline:Nn\l__gradbars_backend_caps_clist % {\clist_if_in:NnF\c__gradbars_backend_features_clist{##1} % {\bool_set_false:N\l__gradbars_backend_valid_bool % \__gradbars_public_error:n{Unknown~backend~capability:~##1}}} % \clist_if_in:NnF\l__gradbars_backend_caps_clist{bar} % {\clist_if_in:NnF\l__gradbars_backend_caps_clist{heat} % {\bool_set_false:N\l__gradbars_backend_valid_bool % \__gradbars_public_error:n{Backend~must~support~bar~or~heat}}} % \bool_if:NT\l__gradbars_backend_valid_bool % {\prop_gput:NnV\g__gradbars_backends_prop{#1}\l__gradbars_backend_caps_clist % \cs_gset_protected:cpn{__gradbars_backend_#1:n}##1{#3}}} %\NewDocumentCommand\gradbarsifbackendcapable{m m m m} % {\prop_get:NnNTF\g__gradbars_backends_prop{#1}\l_tmpa_tl % {\clist_if_in:VnTF\l_tmpa_tl{#2}{#3}{#4}}{#4}} %\msg_new:nnn{gradbars}{backend-field}{Backend~record~field~unavailable:~#1.} %\NewExpandableDocumentCommand\gradbarsbackendvalue{m} % {\bool_if:NTF\l__gradbars_backend_active_bool % {\prop_if_in:NnTF\l__gradbars_backend_record_prop{#1} % {\prop_item:Nn\l__gradbars_backend_record_prop{#1}} % {\msg_expandable_error:nnn{gradbars}{backend-field}{#1}}} % {\msg_expandable_error:nnn{gradbars}{backend-field}{#1}}} %\NewDocumentCommand\gradbarsbackendlabel{} % {\bool_if:NTF\l__gradbars_backend_active_bool % {{\gradbars@font\gradbarsSingleLabel}} % {\__gradbars_public_error:n{Backend~label~requires~an~active~callback}}} %\NewDocumentCommand\gradbarsbackenddefault{} % {\bool_if:NTF\l__gradbars_backend_active_bool % {\bool_if:NTF\l__gradbars_backend_default_bool % {\__gradbars_public_error:n{Backend~default~may~be~drawn~only~once}} % {\bool_set_true:N\l__gradbars_backend_default_bool % \tl_use:N\l__gradbars_backend_native_tl}} % {\__gradbars_public_error:n{Backend~default~requires~an~active~callback}}} %\cs_new_protected:Npn\__gradbars_backend_record:n #1 % {\prop_clear:N\l__gradbars_backend_record_prop % \prop_put:Nnn\l__gradbars_backend_record_prop{version}{1} % \prop_put:Nnn\l__gradbars_backend_record_prop{kind}{#1} % \clist_map_inline:nn{min,max,shape,baseline,precision,numberformat,format,better,overflow,label,labelalign,accessibility, % left,right,negativecolor,track,textcolor,text,rounded,pattern,patterncolor,overflowmark,change,changecolor,markershape,markerfill,markersize,target,targetcolor,band,bandcolor,bandopacity, % references,errorminus,errorplus,errorcolor,thresholds,thresholdcolors,unit,unitcode,unittext,missingtext,gap,labelwidth, % baselineshift,heatpalette,heatcenter,heatcentercolor,heatlow,heathigh,heatmissing} % {\cs_if_exist:cT{gradbars@##1} % {\prop_put:Nnx\l__gradbars_backend_record_prop{##1}{\exp_not:v{gradbars@##1}}}} % \prop_put:Nnx\l__gradbars_backend_record_prop{raw-value}{\exp_not:o{\gradbars@value}} % \prop_put:Nnx\l__gradbars_backend_record_prop{width}{\dim_eval:n{\gradbars@width}} % \prop_put:Nnx\l__gradbars_backend_record_prop{height}{\dim_eval:n{\gradbars@height}} % \prop_put:Nnn\l__gradbars_backend_record_prop{missing}{false} % \prop_put:Nnn\l__gradbars_backend_record_prop{print}{false} % \prop_put:Nnn\l__gradbars_backend_record_prop{gradient}{false} % \prop_put:Nnn\l__gradbars_backend_record_prop{tagging}{false} % \prop_put:Nnn\l__gradbars_backend_record_prop{embedded}{false} % \ifpgfpicture\prop_put:Nnn\l__gradbars_backend_record_prop{embedded}{true}\fi % \cs_if_exist:NT\tag_if_active:T{\tag_if_active:T{\prop_put:Nnn\l__gradbars_backend_record_prop{tagging}{true}}} % \ifgradbars@print\prop_put:Nnn\l__gradbars_backend_record_prop{print}{true}\fi % \ifgradbars@gradient\prop_put:Nnn\l__gradbars_backend_record_prop{gradient}{true}\fi % \ifgradbars@missing % \prop_put:Nnn\l__gradbars_backend_record_prop{missing}{true} % \prop_put:Nnn\l__gradbars_backend_record_prop{value}{NA} % \prop_put:Nnn\l__gradbars_backend_record_prop{display-value}{NA} % \prop_put:Nnn\l__gradbars_backend_record_prop{position}{NA} % \else % \prop_put:Nnx\l__gradbars_backend_record_prop{value}{\fp_eval:n{\gradbars@value}} % \prop_put:Nnx\l__gradbars_backend_record_prop{display-value}{\gradbars@number} % \prop_put:Nnx\l__gradbars_backend_record_prop{position} % {\fp_eval:n{max(0,min(1,(\gradbars@value-\gradbars@min)/(\gradbars@max-\gradbars@min)))}} % \fi % \prop_put:Nnx\l__gradbars_backend_record_prop{zero} % {\fp_eval:n{max(0,min(1,-\gradbars@min/(\gradbars@max-\gradbars@min)))}} % \str_if_eq:nnTF{#1}{bar} % {\gradbarsBuildAlt % \clist_map_inline:nn{start,stop,end} % {\prop_put:Nnx\l__gradbars_backend_record_prop{##1}{\use:c{gradbars@##1}}}} % {\convertcolorspec{named}{gradbarsHeatCell}{rgb}\gradbars@rgb % \prop_put:Nno\l__gradbars_backend_record_prop{heat-rgb}{\gradbars@rgb}} % \tl_if_empty:oF{\gradbars@alt}{\tl_set:No\l__gradbars_alt_tl{\gradbars@alt}} % \prop_put:NnV\l__gradbars_backend_record_prop{alt}\l__gradbars_alt_tl % \prop_put:Nnx\l__gradbars_backend_record_prop{percentbase}{\gradbarsPercentBase}} %\cs_new_protected:Npn\__gradbars_backend_requirements:n #1 % {\clist_set:Nn\l__gradbars_backend_required_clist{#1} % \ifgradbars@missing\clist_put_right:Nn\l__gradbars_backend_required_clist{missing}\fi % \fp_compare:nNnT{\gradbars@min}<{0}{\clist_put_right:Nn\l__gradbars_backend_required_clist{signed}} % \str_if_eq:nnT{#1}{bar} % {\ifgradbars@gradient\clist_put_right:Nn\l__gradbars_backend_required_clist{gradient}\fi} % \ifgradbars@print\clist_put_right:Nn\l__gradbars_backend_required_clist{print}\fi % \str_if_eq:eeF{\gradbars@label}{none}{\clist_put_right:Nn\l__gradbars_backend_required_clist{labels}} % \tl_if_empty:oF{\gradbars@unit}{\clist_put_right:Nn\l__gradbars_backend_required_clist{units}} % \tl_if_empty:oF{\gradbars@unitcode}{\clist_put_right:Nn\l__gradbars_backend_required_clist{units}} % \ifgradbars@missing\else % \fp_compare:nT{\gradbars@value<\gradbars@min || \gradbars@value>\gradbars@max} % {\clist_put_right:Nn\l__gradbars_backend_required_clist{clip}}\fi % \dim_compare:nNnT{\gradbars@rounded}>{0pt}{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}} % \str_if_eq:nnT{#1}{bar} % { % \str_if_eq:eeF{\gradbars@pattern}{none}{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}} % \str_if_eq:eeF{\gradbars@shape}{bar}{\str_if_eq:nnT{#1}{bar}{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}}} % \clist_map_inline:nn{target,band,references,errorminus,errorplus,thresholds} % {\tl_set:Nv\l_tmpb_tl{gradbars@##1} % \tl_if_empty:NF\l_tmpb_tl{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}}} % \ifgradbars@outline\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}\fi % \str_if_eq:eeF{\gradbars@overflowmark}{none}{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}} % \str_if_eq:eeF{\gradbars@change}{none}{\clist_put_right:Nn\l__gradbars_backend_required_clist{decorations}} % } % \ifpgfpicture\clist_put_right:Nn\l__gradbars_backend_required_clist{embedded}\fi % \cs_if_exist:NT\tag_if_active:T % {\tag_if_active:T % {\str_case_e:nn{\gradbars@accessibility} % {{auto}{\clist_put_right:Nn\l__gradbars_backend_required_clist{tagging}} % {artifact}{\clist_put_right:Nn\l__gradbars_backend_required_clist{artifact}}}}}} %\cs_new_protected:Npn\__gradbars_backend_draw:nn #1#2 % {\str_if_eq:VnTF\l__gradbars_backend_tl{tikz}{#2} % {\group_begin: % \bool_if:NTF\l__gradbars_backend_active_bool % {\__gradbars_public_error:n{Recursive~backend~callback}} % {\clist_set:Nn\l__gradbars_backend_required_clist{#1} % \str_case:nn{#1}{{bar}{\__gradbars_backend_requirements:n{bar}}{heat}{\__gradbars_backend_requirements:n{heat}}} % \prop_get:NVN\g__gradbars_backends_prop\l__gradbars_backend_tl\l_tmpa_tl % \bool_set_true:N\l__gradbars_backend_valid_bool % \clist_clear:N\l__gradbars_backend_missing_clist % \clist_map_inline:Nn\l__gradbars_backend_required_clist % {\clist_if_in:VnF\l_tmpa_tl{##1}{\bool_set_false:N\l__gradbars_backend_valid_bool\clist_put_right:Nn\l__gradbars_backend_missing_clist{##1}}} % \clist_remove_duplicates:N\l__gradbars_backend_missing_clist % \bool_if:NTF\l__gradbars_backend_valid_bool % {\__gradbars_backend_record:n{#1} % \tl_set:Nn\l__gradbars_backend_native_tl{#2} % \bool_set_true:N\l__gradbars_backend_active_bool % \bool_set_false:N\l__gradbars_backend_default_bool % \use:c{__gradbars_backend_\l__gradbars_backend_tl :n}{#1}} % {\str_if_eq:VnTF\l__gradbars_backend_fallback_tl{tikz}{#2} % {\__gradbars_public_error:n{Backend~\l__gradbars_backend_tl~lacks~required~capabilities~for~#1:~\clist_use:Nn\l__gradbars_backend_missing_clist{,~}}}}} % \group_end:}} %\cs_new_protected:Npn\__gradbars_backend_core: % {\tl_set:Nn\l__gradbars_backend_kind_tl{bar} % \ifgradbars@stack\tl_set:Nn\l__gradbars_backend_kind_tl{stack}\fi % \ifgradbars@spark\tl_set:Nn\l__gradbars_backend_kind_tl{spark}\fi % \ifgradbars@compare\tl_set:Nn\l__gradbars_backend_kind_tl{compare} % \str_if_eq:eeT{\gradbars@shape}{dumbbell}{\tl_set:Nn\l__gradbars_backend_kind_tl{dumbbell}}\fi % \ifgradbars@rangemode\tl_set:Nn\l__gradbars_backend_kind_tl{range}\fi % \ifgradbars@bullet\tl_set:Nn\l__gradbars_backend_kind_tl{bullet}\fi % \exp_args:NV\__gradbars_backend_draw:nn\l__gradbars_backend_kind_tl{\__gradbars_render_tikz:}} %\@onlypreamble\gradbarsdeclarebackend %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-core.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-core}[2026/10/25 v1.1.0 gradbars core] %\RequirePackage{tikz} %\RequirePackage{xparse} %\RequirePackage{expl3} %\usetikzlibrary{shadings,patterns} %\ExplSyntaxOn %\cs_generate_variant:Nn\prop_put:Nnn{Nxn,Nxx,NVx} %\ExplSyntaxOff %\definecolor{gradbarsBlue}{HTML}{2563EB} %\definecolor{gradbarsBlueLight}{HTML}{93C5FD} %\definecolor{gradbarsTeal}{HTML}{0F766E} %\definecolor{gradbarsTealLight}{HTML}{5EEAD4} %\definecolor{gradbarsViolet}{HTML}{7C3AED} %\definecolor{gradbarsVioletLight}{HTML}{C4B5FD} %\definecolor{gradbarsWarmOrange}{HTML}{EA580C} %\definecolor{gradbarsWarmOrangeLight}{HTML}{FDBA74} %\definecolor{gradbarsForest}{HTML}{166534} %\definecolor{gradbarsForestLight}{HTML}{86EFAC} %\definecolor{gradbarsInk}{HTML}{243247} %\definecolor{gradbarsTrack}{HTML}{EDF2F7} %% Public built-in palette. %\definecolor{lightgreen}{RGB}{144,238,144} %\definecolor{lightyellow}{RGB}{255,255,224} %\definecolor{lightblue}{RGB}{173,216,230} %\definecolor{lightred}{RGB}{255,160,122} %\definecolor{rose}{RGB}{255,102,204} %\definecolor{skyblue}{RGB}{135,206,235} %\definecolor{gold}{RGB}{255,215,0} %\definecolor{lavender}{RGB}{230,230,250} %\definecolor{peach}{RGB}{255,218,185} %\newif\ifgradbars@valid %\newif\ifgradbars@gradient %\def\gradbars@width{24mm} %\def\gradbars@height{1.5ex} %\def\gradbars@max{100} %\def\gradbars@min{0} %\def\gradbars@scalegroup{} %\def\gradbars@percentbase{} %\def\gradbars@rounded{0pt} %\def\gradbars@target{} %\def\gradbars@targetcolor{gradbarsInk} %\def\gradbars@negativecolor{lightred} %\def\gradbars@negativeleft{} %\def\gradbars@negativeright{} %\newif\ifgradbars@negativegradient %\gradbars@negativegradientfalse %\def\gradbars@thresholds{} %\def\gradbars@thresholdcolors{lightred,gold,lightgreen} %\def\gradbars@errorminus{} %\def\gradbars@errorplus{} %\def\gradbars@errorcolor{gradbarsInk} %\newif\ifgradbars@error %\newsavebox\gradbars@labelbox %\def\gradbars@precision{1} %\def\gradbars@unit{} %\def\gradbars@text{} %\def\gradbars@alt{} %\def\gradbars@accessibility{auto} %\newif\ifgradbars@capturealt %\def\gradbars@label{outside} %\def\gradbars@baseline{auto} %\def\gradbars@baselineshift{0pt} %\def\gradbars@format{value} %\def\gradbars@overflow{clip} %\def\gradbars@gap{.6em} %\def\gradbars@labelwidth{4.5em} %\def\gradbars@labelalign{graphic} %\def\gradbars@font{\relax} %\newif\ifgradbars@missing %\newif\ifgradbars@stack %\newcount\gradbars@styledepth %\def\gradbars@missingtext{--} %\def\gradbars@numberformat{fixed} %\def\gradbars@band{} %\def\gradbars@bandcolor{gold} %\def\gradbars@bandopacity{0.3} %\def\gradbars@stackcolors{gradbarsBlue,gradbarsTeal,gold} %\RequirePackage{gradbars-keys} %\pgfkeys{/gradbars,theme=blue} %\DeclareDocumentCommand\gradbarssetup{m}{\pgfkeys{/gradbars,#1}} %% Style definitions follow ordinary TeX grouping, like setup. %\DeclareDocumentCommand\gradbarsstyle{m m}{% % \expandafter\def\csname gradbars@style@#1\endcsname{#2}} %\def\gradbarsUseStyle#1{% % \ifcsname gradbars@style@#1\endcsname % \ifnum\gradbars@styledepth<32 % \advance\gradbars@styledepth by 1 % \expandafter\let\expandafter\gradbars@styleoptions\csname gradbars@style@#1\endcsname % \expandafter\pgfkeysalso\expandafter{\gradbars@styleoptions}% % \advance\gradbars@styledepth by -1 % \else\PackageError{gradbars}{Style nesting exceeds 32 levels}{Check for recursive styles.}\fi % \else\PackageError{gradbars}{Unknown style: #1}{Define it with gradbarsstyle first.}\fi %} % %% Validate before drawing; floating point arithmetic also supports large counts. %\ExplSyntaxOn % % %\cs_new_protected:Npn \gradbarsFail #1 % {\gradbars@validfalse \PackageError{gradbars}{#1}{Check~the~gradbars~options~and~data.}} %\cs_new_protected:Npn \gradbarsRange #1#2 % { % \fp_compare:nT {#2 < \gradbars@min || #2 > \gradbars@max} % { % \str_if_eq:eeTF {\gradbars@overflow}{error} % {\gradbarsFail{#1~exceeds~range}} % {\PackageWarning{gradbars}{#1~exceeds~range;~bar~clipped,~label~unchanged}} % } % } %\cs_new:Npn \gradbarsPosition #1 % {\fp_eval:n {(max(\gradbars@min,min(\gradbars@max,#1))-\gradbars@min)/ % (\gradbars@max-\gradbars@min)}} %\clist_new:N \l__gradbars_thresholds_clist %\clist_new:N \l__gradbars_colors_clist %\cs_new_protected:Npn \gradbarsValidate % { % \gradbars@missingfalse % \tl_set:Nx \l_tmpa_tl {\gradbars@value} % \tl_trim_spaces:N \l_tmpa_tl % \tl_if_empty:NT \l_tmpa_tl {\gradbars@missingtrue} % \str_if_eq:VnT \l_tmpa_tl {NA} {\gradbars@missingtrue} % \ifgradbars@missing \def\gradbars@value{0}\fi % \gradbarsCheckNumber{\gradbars@value}{value} % \gradbarsCheckNumber{\gradbars@min}{min} % \gradbarsCheckNumber{\gradbars@max}{max} % \tl_set:Nx \l_tmpa_tl {\gradbars@precision} % \regex_match:nVTF {\A [0-6] \Z} \l_tmpa_tl { } % {\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \ifgradbars@valid % \fp_compare:nNnF {\gradbars@max} > {\gradbars@min} % {\gradbarsFail{Max~must~be~greater~than~min}} % \fp_compare:nNnT {\gradbars@min} = {0} % {\fp_compare:nNnT {\gradbars@value} < {0} % {\gradbarsFail{Negative~values~require~a~negative~min}}} % \str_if_eq:eeT {\gradbars@format}{percent} % {\fp_compare:nNnF {\gradbars@min} = {0} % {\gradbarsFail{Percent~format~requires~min=0}}\gradbarsValidatePercentBase} % \fi % \tl_if_empty:oF {\gradbars@target} % {\gradbarsCheckNumber{\gradbars@target}{target}} % \gradbars@errorfalse % \tl_if_empty:oF {\gradbars@errorminus}{\gradbars@errortrue} % \tl_if_empty:oF {\gradbars@errorplus}{\gradbars@errortrue} % \ifgradbars@error % \tl_if_empty:oT {\gradbars@errorminus}{\def\gradbars@errorminus{0}} % \tl_if_empty:oT {\gradbars@errorplus}{\def\gradbars@errorplus{0}} % \gradbarsCheckNumber{\gradbars@errorminus}{error~minus} % \gradbarsCheckNumber{\gradbars@errorplus}{error~plus} % \fi % \clist_set:Nx \l__gradbars_thresholds_clist {\gradbars@thresholds} % \clist_set:Nx \l__gradbars_colors_clist {\gradbars@thresholdcolors} % \clist_if_empty:NF \l__gradbars_thresholds_clist % { % \int_compare:nNnF {\clist_count:N \l__gradbars_thresholds_clist} = {2} % {\gradbarsFail{Thresholds~must~contain~two~values}} % \int_compare:nNnF {\clist_count:N \l__gradbars_colors_clist} = {3} % {\gradbarsFail{Threshold~colors~must~contain~three~colors}} % \clist_map_inline:Nn \l__gradbars_thresholds_clist % {\gradbarsCheckNumber{##1}{threshold}} % } % \ifgradbars@valid % \ifgradbars@missing\else\gradbarsRange{Value}{\gradbars@value}\fi % \tl_if_empty:oF {\gradbars@target} % { % \fp_compare:nT {\gradbars@target < \gradbars@min || \gradbars@target > \gradbars@max} % {\gradbarsFail{Target~must~lie~within~range}} % \cs_set:Npx \gradbars@targetpos {\gradbarsPosition{\gradbars@target}} % } % \ifgradbars@error % \fp_compare:nT {\gradbars@errorminus<0 || \gradbars@errorplus<0} % {\gradbarsFail{Error~magnitudes~must~be~nonnegative}} % \ifgradbars@missing\else % \gradbarsRange{Error~lower~endpoint}{\gradbars@value-\gradbars@errorminus} % \gradbarsRange{Error~upper~endpoint}{\gradbars@value+\gradbars@errorplus} % \cs_set:Npx \gradbars@errorlo % {\gradbarsPosition{\gradbars@value-\gradbars@errorminus}} % \cs_set:Npx \gradbars@errorhi % {\gradbarsPosition{\gradbars@value+\gradbars@errorplus}} % \fi % \fi % \cs_set:Npx \gradbars@zero {\gradbarsPosition{0}} % \cs_set:Npx \gradbars@end {\gradbarsPosition{\gradbars@value}} % \cs_set:Npx \gradbars@start {\fp_eval:n {min(\gradbars@zero,\gradbars@end)}} % \cs_set:Npx \gradbars@stop {\fp_eval:n {max(\gradbars@zero,\gradbars@end)}} % \fp_compare:nNnT {\gradbars@value} < {0} % {\ifgradbars@negativegradient % \gradbars@gradienttrue % \ifx\gradbars@negativeleft\@empty % \let\gradbars@left\gradbars@negativecolor % \else % \let\gradbars@left\gradbars@negativeleft % \fi % \ifx\gradbars@negativeright\@empty % \let\gradbars@right\gradbars@negativecolor % \else % \let\gradbars@right\gradbars@negativeright % \fi % \else % \gradbars@gradientfalse \let\gradbars@left\gradbars@negativecolor % \fi} % \clist_if_empty:NF \l__gradbars_thresholds_clist % { % \fp_compare:nNnF {\clist_item:Nn \l__gradbars_thresholds_clist {1}} % < {\clist_item:Nn \l__gradbars_thresholds_clist {2}} % {\gradbarsFail{Thresholds~must~be~strictly~increasing}} % \int_set:Nn \l_tmpa_int {1} % \fp_compare:nNnF {\gradbars@value} % < {\clist_item:Nn \l__gradbars_thresholds_clist {1}} % {\int_set:Nn \l_tmpa_int {2}} % \fp_compare:nNnF {\gradbars@value} % < {\clist_item:Nn \l__gradbars_thresholds_clist {2}} % {\int_set:Nn \l_tmpa_int {3}} % \cs_set:Npx \gradbars@left % {\clist_item:Nn \l__gradbars_colors_clist % {\str_if_eq:eeTF {\gradbars@better}{lower}{4-\l_tmpa_int}{\l_tmpa_int}}} % \gradbars@gradientfalse % } % \str_if_eq:eeTF {\gradbars@format}{percent} % {\cs_set:Npx \gradbars@number % {\fp_eval:n {100*\gradbars@value/\gradbarsPercentBase}}} % {\cs_set:Npx \gradbars@number % {\fp_eval:n {\gradbars@value}}} % \fi % } %\clist_new:N \l__gradbars_band_clist %\clist_new:N \l__gradbars_stack_clist %\clist_new:N \l__gradbars_stackcolors_clist %\fp_new:N \l__gradbars_sum_fp %\fp_new:N \l__gradbars_before_fp %\cs_new_protected:Npn \gradbarsValidateExtras % { % \clist_set:Nx \l__gradbars_band_clist {\gradbars@band} % \clist_if_empty:NF \l__gradbars_band_clist % { % \tl_set:Nx \l_tmpa_tl {\gradbars@band} % \regex_match:nVT {\A\s*,|,\s*,|,\s*\Z} \l_tmpa_tl % {\gradbarsFail{Band~must~contain~two~endpoints}} % \int_compare:nNnF {\clist_count:N \l__gradbars_band_clist} = {2} % {\gradbarsFail{Band~must~contain~two~endpoints}} % \clist_map_inline:Nn \l__gradbars_band_clist % {\gradbarsCheckNumber{##1}{band~endpoint}} % \gradbarsCheckNumber{\gradbars@bandopacity}{band~opacity} % \ifgradbars@valid % \cs_set:Npx \gradbars@bandlo {\clist_item:Nn \l__gradbars_band_clist {1}} % \cs_set:Npx \gradbars@bandhi {\clist_item:Nn \l__gradbars_band_clist {2}} % \fp_compare:nF {\gradbars@min <= \gradbars@bandlo < \gradbars@bandhi <= \gradbars@max} % {\gradbarsFail{Band~must~be~increasing~and~within~range}} % \fp_compare:nF {0 <= \gradbars@bandopacity <= 1} % {\gradbarsFail{Band~opacity~must~be~between~zero~and~one}} % \fi % } % \ifgradbars@stack % \ifgradbars@valid % \gradbarsRange{Positive~stack~total}{\gradbars@positive} % \gradbarsRange{Negative~stack~total}{\gradbars@negative} % \fp_compare:nNnT {\gradbars@negative} < {0} % {\fp_compare:nNnT {\gradbars@min} = {0} % {\gradbarsFail{Negative~stack~requires~a~negative~min}}} % \cs_set:Npx \gradbars@start {\gradbarsPosition{\gradbars@negative}} % \cs_set:Npx \gradbars@stop {\gradbarsPosition{\gradbars@positive}} % \fi % \tl_if_empty:oF {\gradbars@thresholds} % {\gradbarsFail{Stacked~bars~do~not~support~thresholds}} % \ifgradbars@error \gradbarsFail{Stacked~bars~do~not~support~error~whiskers}\fi % \clist_set:Nx \l__gradbars_stackcolors_clist {\gradbars@stackcolors} % \clist_if_empty:NT \l__gradbars_stackcolors_clist % {\gradbarsFail{Stack~colors~must~not~be~empty}} % \fi % } %\ExplSyntaxOn % % %\ExplSyntaxOff % %\RequirePackage{gradbars-model} %\RequirePackage{gradbars-render-tikz} %\ExplSyntaxOff %\DeclareDocumentCommand\gradbar{O{} m}{% % \leavevmode\begingroup % \gradbarsCaptureTikzAlt % \gradbars@capturealttrue % \pgfkeys{/gradbars,#1}% % \gradbars@capturealtfalse % % Resolve font-relative dimensions in the surrounding text font. % \ifpgfpicture % \pgfinterruptpicture % \font@name % \edef\gradbars@resolved{% % \noexpand\endpgfinterruptpicture % \def\noexpand\gradbars@width{\the\dimexpr\gradbars@width\relax}% % \def\noexpand\gradbars@height{\the\dimexpr\gradbars@height\relax}% % \def\noexpand\gradbars@rounded{\the\dimexpr\gradbars@rounded\relax}% % \def\noexpand\gradbars@gap{\the\dimexpr\gradbars@gap\relax}% % \def\noexpand\gradbars@labelwidth{\the\dimexpr\gradbars@labelwidth\relax}% % }% % \gradbars@resolved % \fi % \def\gradbars@value{#2}% % \gradbars@render % \endgroup %} % % %% v0.0.2: labels, legends and collected table columns. %\def\gradbars@stacknames{} %\def\gradbars@segmentlabels{none} %\def\gradbars@segmentfont{\scriptsize} %\def\gradbars@segmenttextcolor{auto} %\def\gradbars@labeloverflow{auto} %\newif\ifgradbars@legend %\newif\ifgradbars@inside %\newif\ifgradbars@fit %\newsavebox\gradbars@segmentbox %\pgfkeys{/gradbars, % stack names/.store in=\gradbars@stacknames, % legend/.is if=gradbars@legend,legend/.default=true, % segment font/.store in=\gradbars@segmentfont, % segment text color/.store in=\gradbars@segmenttextcolor, % segment labels/.is choice, % segment labels/none/.code=\def\gradbars@segmentlabels{none}, % segment labels/value/.code=\def\gradbars@segmentlabels{value}, % segment labels/percent/.code=\def\gradbars@segmentlabels{percent}, % segment labels/name/.code=\def\gradbars@segmentlabels{name}, % segment labels/name value/.code=\def\gradbars@segmentlabels{name value}, % segment labels/name percent/.code=\def\gradbars@segmentlabels{name percent}, % label overflow/.is choice, % label overflow/auto/.code=\def\gradbars@labeloverflow{auto}, % label overflow/allow/.code=\def\gradbars@labeloverflow{allow} %} %\def\gradbarsMeasure#1#2#3{% % \sbox#1{\pgfinterruptpicture\font@name #2#3\endpgfinterruptpicture}} % %\ExplSyntaxOn %\clist_new:N \l__gradbars_names_clist %\seq_new:N \l__gradbars_occupied_seq %\dim_new:N \l__gradbars_top_dim %\dim_new:N \l__gradbars_labelbottom_dim %\dim_new:N \l__gradbars_labelleft_dim %\dim_new:N \l__gradbars_labelright_dim %\dim_new:N \l__gradbars_leaderx_dim %\dim_new:N \l__gradbars_leaderleft_dim %\dim_new:N \l__gradbars_leaderright_dim %\fp_new:N \l__gradbars_luminance_fp %\int_new:N \l__gradbars_index_int % %\let\gradbarsValidatePrevious\gradbarsValidateExtras %\cs_set_protected:Npn \gradbarsValidateExtras % { % \gradbarsValidatePrevious % \clist_set:No \l__gradbars_names_clist {\gradbars@stacknames} % \ifgradbars@stack % \clist_if_empty:NF \l__gradbars_names_clist % {\int_compare:nNnF {\clist_count:N \l__gradbars_names_clist} % = {\clist_count:N \l__gradbars_stack_clist} % {\gradbarsFail{Stack~names~must~match~the~segment~count}}} % \bool_set_false:N \l_tmpa_bool % \ifgradbars@legend \bool_set_true:N \l_tmpa_bool \fi % \str_case_e:nn {\gradbars@segmentlabels} % {{name}{\bool_set_true:N \l_tmpa_bool} % {name~value}{\bool_set_true:N \l_tmpa_bool} % {name~percent}{\bool_set_true:N \l_tmpa_bool}} % \bool_if:NT \l_tmpa_bool % {\clist_if_empty:NT \l__gradbars_names_clist % {\gradbarsFail{Stack~names~are~required~for~names~or~legend}}} % \ifgradbars@legend % \ifdim\gradbars@width>14pt\relax\else % \gradbarsFail{Legend~width~must~exceed~14pt}\fi % \fi % \else % \ifgradbars@legend \gradbarsFail{Automatic~legend~requires~gradstack}\fi % \fi % } %\cs_new_protected:Npn \gradbarsResetLabels % {\seq_clear:N \l__gradbars_occupied_seq % \dim_set:Nn \l__gradbars_top_dim {\gradbars@height+4pt}} %\cs_new_protected:Npn \gradbarsCheckOverlap #1#2#3 % { % \dim_compare:nNnT {\l__gradbars_labelleft_dim} < {#2+3pt} % {\dim_compare:nNnT {\l__gradbars_labelright_dim} > {#1-3pt} % {\dim_set:Nn \l__gradbars_labelbottom_dim % {\dim_max:nn {\l__gradbars_labelbottom_dim}{#3+3pt}}}} % } %\cs_new_protected:Npn \gradbarsLeaderBounds #1#2#3 % { % \dim_set:Nn \l__gradbars_leaderleft_dim % {\dim_min:nn {\l__gradbars_leaderleft_dim}{#1-4pt}} % \dim_set:Nn \l__gradbars_leaderright_dim % {\dim_max:nn {\l__gradbars_leaderright_dim}{#2+4pt}} % } %\cs_new_protected:Npn \gradbarsPlaceSegment % { % \pgfmathsetlengthmacro\gradbars@segmentmid{.5*(\gradbars@segmentlo+\gradbars@segmenthi)} % \gradbars@fittrue % \ifgradbars@outline\gradbars@fitfalse\fi % \ifdim\dimexpr\wd\gradbars@segmentbox+4pt\relax>\dimexpr\gradbars@segmenthi-\gradbars@segmentlo\relax % \gradbars@fitfalse\fi % \ifdim\dimexpr\ht\gradbars@segmentbox+\dp\gradbars@segmentbox+2pt\relax>\gradbars@height\relax % \gradbars@fitfalse\fi % \ifx\gradbars@target\@empty\else % \pgfmathsetlengthmacro\gradbars@distance{abs(\gradbars@xtarget-\gradbars@segmentmid)} % \ifdim\gradbars@distance<\dimexpr.5\wd\gradbars@segmentbox+2pt\relax % \gradbars@fitfalse\fi % \fi % \ifgradbars@fit % \let\gradbars@labelcolor\gradbars@segmenttextcolor % \str_if_eq:eeT {\gradbars@segmenttextcolor}{auto}{\gradbarsContrast{\gradbars@segmentcolor}} % \gradbarsMeasure\gradbars@segmentbox\gradbars@segmentfont{\color{\gradbars@labelcolor}\gradbars@segmentcontent} % \node[inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % [gradbars~label~background] % at (\gradbars@segmentmid,.5*\gradbars@height){\usebox\gradbars@segmentbox}; % \else % \pgfmathsetlengthmacro\gradbars@labelx % {max(.5*\wd\gradbars@segmentbox,min(\gradbars@segmentmid,\gradbars@width-.5*\wd\gradbars@segmentbox))} % \dim_set:Nn \l__gradbars_labelleft_dim {\gradbars@labelx-.5\wd\gradbars@segmentbox} % \dim_set:Nn \l__gradbars_labelright_dim {\gradbars@labelx+.5\wd\gradbars@segmentbox} % \dim_set:Nn \l__gradbars_labelbottom_dim {\gradbars@height+4pt} % \seq_map_inline:Nn \l__gradbars_occupied_seq {\gradbarsCheckOverlap ##1} % % Route elevated leaders around earlier label boxes, not through text. % \dim_set:Nn \l__gradbars_leaderx_dim {\gradbars@segmentmid} % \dim_compare:nNnT {\l__gradbars_labelbottom_dim} > {\gradbars@height+4pt} % { % \dim_set:Nn \l__gradbars_leaderleft_dim {\gradbars@segmentmid} % \dim_set:Nn \l__gradbars_leaderright_dim {\gradbars@segmentmid} % \seq_map_inline:Nn \l__gradbars_occupied_seq {\gradbarsLeaderBounds ##1} % \dim_compare:nNnTF % {\gradbars@segmentmid-\l__gradbars_leaderleft_dim} < % {\l__gradbars_leaderright_dim-\gradbars@segmentmid} % {\dim_set_eq:NN \l__gradbars_leaderx_dim \l__gradbars_leaderleft_dim} % {\dim_set_eq:NN \l__gradbars_leaderx_dim \l__gradbars_leaderright_dim} % } % \seq_put_right:Nx \l__gradbars_occupied_seq % {{\dim_use:N \l__gradbars_labelleft_dim}{\dim_use:N \l__gradbars_labelright_dim} % {\dim_eval:n {\l__gradbars_labelbottom_dim+\ht\gradbars@segmentbox+\dp\gradbars@segmentbox}}} % \dim_set:Nn \l__gradbars_top_dim {\dim_max:nn {\l__gradbars_top_dim} % {\l__gradbars_labelbottom_dim+\ht\gradbars@segmentbox+\dp\gradbars@segmentbox+3pt}} % \draw[gradbarsInk!55,line~width=.3pt] % (\gradbars@segmentmid,\gradbars@height)-- % (\gradbars@segmentmid,\dim_eval:n {\gradbars@height+1pt})-- % (\dim_use:N \l__gradbars_leaderx_dim,\dim_eval:n {\gradbars@height+1pt})-- % (\dim_use:N \l__gradbars_leaderx_dim,\dim_eval:n {\l__gradbars_labelbottom_dim-2pt})-- % (\gradbars@labelx,\dim_eval:n {\l__gradbars_labelbottom_dim-2pt}); % \let\gradbars@labelcolor\gradbars@segmenttextcolor % \str_if_eq:eeT {\gradbars@segmenttextcolor}{auto}{\def\gradbars@labelcolor{black}} % \gradbarsMeasure\gradbars@segmentbox\gradbars@segmentfont{\color{\gradbars@labelcolor}\gradbars@segmentcontent} % \node[anchor=south,inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % at (\gradbars@labelx,\dim_use:N \l__gradbars_labelbottom_dim){\usebox\gradbars@segmentbox}; % \fi % } % % %\cs_new_protected:Npn \gradbarsMainBackground % { % \def\gradbars@labelcolor{black} % \ifgradbars@inside % \let\gradbars@background\gradbars@track % \clist_if_empty:NF \l__gradbars_band_clist % {\dim_compare:nNnT {\gradbars@labelx} > {\gradbars@bandxlo} % {\dim_compare:nNnT {\gradbars@labelx} < {\gradbars@bandxhi} % {\edef\gradbars@background{\gradbars@bandcolor! % \fp_eval:n {100*\gradbars@bandopacity}!\gradbars@track}}}} % \ifdim\gradbars@labelx>\gradbars@xstart\relax % \ifdim\gradbars@labelx<\gradbars@xstop\relax % \let\gradbars@background\gradbars@left % \ifgradbars@gradient % \pgfmathparse{100*(\gradbars@labelx-\gradbars@xstart)/(\gradbars@xstop-\gradbars@xstart)} % \edef\gradbars@background{\gradbars@right!\pgfmathresult!\gradbars@left} % \fi % \ifgradbars@stack % \fp_zero:N \l__gradbars_sum_fp % \int_zero:N \l__gradbars_index_int % \clist_map_inline:Nn \l__gradbars_stack_clist % {\fp_add:Nn \l__gradbars_sum_fp {##1}\int_incr:N \l__gradbars_index_int % \pgfmathsetlengthmacro\gradbars@segmenthi{\gradbarsPosition{\l__gradbars_sum_fp}*(\gradbars@width)} % \dim_compare:nNnT {\gradbars@labelx} < {\gradbars@segmenthi} % { % \gradbarsCategoryColor{\l__gradbars_index_int} % \let\gradbars@background\gradbars@segmentcolor % \clist_map_break: % }} % \fi % \fi % \fi % \gradbarsContrast{\gradbars@background} % \fi % } % %\ExplSyntaxOff %\DeclareDocumentCommand\gradbarslegend{O{} m}{% % \begingroup\gradbarsCaptureTikzAlt\gradbars@capturealttrue % \pgfkeys{/gradbars,#1,stack names={#2}}\gradbars@capturealtfalse% % \begingroup\font@name % \edef\gradbars@next{\endgroup % \def\noexpand\gradbars@width{\the\dimexpr\gradbars@width\relax}}% % \gradbars@next % \gradbarsResolveShapeLengths % \gradbarsStandaloneLegend % \endgroup} %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsStandaloneLegend % { % \gradbars@validtrue % \clist_set:No \l__gradbars_names_clist {\gradbars@stacknames} % \clist_set:No \l__gradbars_stackcolors_clist {\gradbars@stackcolors} % \clist_if_empty:NT \l__gradbars_names_clist {\gradbarsFail{Legend~names~must~not~be~empty}} % \clist_if_empty:NT \l__gradbars_stackcolors_clist {\gradbarsFail{Stack~colors~must~not~be~empty}} % \gradbarsValidatePatterns % \ifdim\gradbars@width>14pt\else\gradbarsFail{Legend~width~must~exceed~14pt}\fi % \ifgradbars@valid % \__gradbars_backend_draw:nn{category-legend} % {\ifpgfpicture \gradbarsDrawLegend % \else\gradbarsPrepareLegendAlt\tikz[baseline=0pt]{\gradbarsDrawLegend}\fi} % \fi % } %\ExplSyntaxOff %\ExplSyntaxOff %% Data import, print patterns and metric direction (v0.0.2). %\def\gradbars@better{higher} %\def\gradbars@pattern{none} %\def\gradbars@patterncolor{black} %\def\gradbars@stackpatterns{none} %\newif\ifgradbars@print %\pgfkeys{/gradbars, % print labels/.is if=gradbars@print, % better/.is choice, % better/higher/.code=\def\gradbars@better{higher}, % better/lower/.code=\def\gradbars@better{lower}, % pattern/.store in=\gradbars@pattern, % pattern color/.store in=\gradbars@patterncolor, % stack patterns/.store in=\gradbars@stackpatterns, % print/.style={outline=false,print labels=true,theme=gray,color=white,track color=black!8, % negative color=white,negative fill=solid,text color=black,segment text color=black, % pattern=diagonal,pattern color=black, % stack colors={white},stack patterns={diagonal,dots,crosshatch}, % threshold colors={black!10,black!25,black!45}} %} %\ExplSyntaxOn %\prop_const_from_keyval:Nn \c__gradbars_patterns_prop % {none=none,diagonal=north~east~lines,reverse=north~west~lines, % dots=dots,crosshatch=crosshatch,horizontal=horizontal~lines,vertical=vertical~lines} %\clist_new:N \l__gradbars_patterns_clist %\tl_new:N \l__gradbars_pattern_tl %\cs_new_protected:Npn \gradbarsPatternRect #1#2#3#4#5 % { % \int_compare:nNnTF {#1} = {0} % {\tl_set:No \l__gradbars_pattern_tl {\gradbars@pattern}} % {\clist_set:No \l__gradbars_patterns_clist {\gradbars@stackpatterns} % \tl_set:Nx \l__gradbars_pattern_tl % {\clist_item:Nn \l__gradbars_patterns_clist % {1+\int_mod:nn {#1-1}{\clist_count:N \l__gradbars_patterns_clist}}}} % \gradbarsCategoryPattern{#1} % \prop_get:NVNTF \c__gradbars_patterns_prop \l__gradbars_pattern_tl \l__gradbars_pattern_tl % {\tl_if_eq:NnF \l__gradbars_pattern_tl {none} % {\path[pattern=\l__gradbars_pattern_tl,pattern~color=\gradbars@patterncolor,draw=none] % (#2,#3) rectangle (#4,#5);}} % {\gradbarsFail{Unknown~pattern}} % } %\cs_new_eq:NN \gradbarsValidateBeforePatterns \gradbarsValidateExtras %\cs_set_protected:Npn \gradbarsValidateExtras % { % \gradbarsValidateBeforePatterns % \gradbarsValidatePatterns % } %\cs_new_protected:Npn \gradbarsValidatePatterns % { % \clist_set:No \l__gradbars_patterns_clist {\gradbars@stackpatterns} % \clist_if_empty:NT \l__gradbars_patterns_clist {\gradbarsFail{Stack~patterns~must~not~be~empty}} % \clist_put_left:No \l__gradbars_patterns_clist {\gradbars@pattern} % \clist_map_inline:Nn \l__gradbars_patterns_clist % {\prop_if_in:NnF \c__gradbars_patterns_prop {##1}{\gradbarsFail{Unknown~pattern:~##1}}} % } % %\ExplSyntaxOff %% Compact comparison shapes and reusable visual presets, v0.0.2. %\newif\ifgradbars@compare %\newif\ifgradbars@rangemode %\newif\ifgradbars@referencemissing %\newif\ifgradbars@rangemissing %\newif\ifgradbars@outline %\def\gradbars@shape{bar} %\def\gradbars@reference{0} %\def\gradbars@comparecolor{black!20} %\def\gradbars@compareratio{.45} %\def\gradbars@rangelo{0} %\def\gradbars@rangehi{0} %\def\gradbars@rangepoint{} %\def\gradbars@markersize{2pt} %\def\gradbars@stemwidth{.6pt} %\def\gradbars@outlinewidth{.4pt} %\def\gradbars@rowpadding{0pt} %\pgfkeys{/gradbars, % shape/.is choice, % shape/bar/.code=\def\gradbars@shape{bar}, % shape/lollipop/.code=\def\gradbars@shape{lollipop}, % compare color/.store in=\gradbars@comparecolor, % compare ratio/.store in=\gradbars@compareratio, % range point/.store in=\gradbars@rangepoint, % marker size/.store in=\gradbars@markersize, % stem width/.store in=\gradbars@stemwidth, % outline/.is if=gradbars@outline,outline/.default=true, % outline width/.store in=\gradbars@outlinewidth, % row padding/.store in=\gradbars@rowpadding, % preset/.is choice, % preset/paper/.style={theme=solid,shape=bar,outline=false, % height=5pt,rounded=0pt,track color=black!4,label=outside, % font=\small,label gap=.35em,row padding=.5pt,pattern=none,stack patterns={none},print labels=false}, % preset/report/.style={theme=solid,shape=bar,outline=false, % height=12pt,rounded=3pt,track color=black!6,label=outside, % font=\normalsize,label gap=.6em,row padding=2pt,target color=gradbarsInk, % threshold colors={lightred,gold,lightgreen},pattern=none,stack patterns={none},print labels=false}, % preset/presentation/.style={theme=solid,shape=bar,outline=false, % height=18pt,rounded=2pt,label=auto,text color=auto, % font=\large,label gap=.7em,row padding=4pt,track color=black!10, % pattern=none,stack patterns={none},print labels=false}, % preset/outline/.style={theme=gray,shape=bar,outline=true, % height=7pt,rounded=0pt,track color=white,left color=black!80, % compare color=black!35,label=outside,font=\small, % outline width=.35pt,stem width=.4pt,label gap=.4em,row padding=1pt, % pattern=none,stack patterns={none},print labels=false} %} %\def\gradbarsResolveShapeLengths{% % \begingroup\font@name % \edef\gradbars@next{\endgroup % \def\noexpand\gradbars@markersize{\the\dimexpr\gradbars@markersize\relax}% % \def\noexpand\gradbars@stemwidth{\the\dimexpr\gradbars@stemwidth\relax}% % \def\noexpand\gradbars@outlinewidth{\the\dimexpr\gradbars@outlinewidth\relax}% % \def\noexpand\gradbars@leftlabelwidth{\the\dimexpr\gradbars@labelwidth\relax}% % \def\noexpand\gradbars@baselineoffset{\the\dimexpr.5ex\relax}% % \def\noexpand\gradbars@baselineshift{\the\dimexpr\gradbars@baselineshift\relax}% % \def\noexpand\gradbars@rowpadding{\the\dimexpr\gradbars@rowpadding\relax}}% % \gradbars@next} %\DeclareDocumentCommand\gradcompare{O{} m m}{% % \begingroup\gradbars@comparetrue % \def\gradbars@reference{#2}% % \gradbar[shape=bar,#1]{#3}% % \endgroup} %\DeclareDocumentCommand\gradrange{O{} m m}{% % \begingroup\gradbars@rangemodetrue % \def\gradbars@rangelo{#2}\def\gradbars@rangehi{#3}% % \gradbar[shape=bar,#1]{#3}% % \endgroup} %\ExplSyntaxOn %\cs_new_eq:NN \gradbarsValidateBeforeShapes \gradbarsValidateExtras %\cs_set_protected:Npn \gradbarsValidateExtras % { % \gradbarsValidateBeforeShapes % \clist_map_inline:nn {markersize,stemwidth,outlinewidth} % {\dim_compare:nNnF {\use:c {gradbars@##1}} > {0pt} % {\gradbarsFail{Marker~and~line~sizes~must~be~positive}}} % \dim_compare:nNnT {\gradbars@rowpadding} < {0pt} % {\gradbarsFail{Row~padding~must~be~nonnegative}} % \ifgradbars@stack % \str_if_eq:eeF {\gradbars@shape}{bar}{\gradbarsFail{Stacked~bars~require~shape=bar}} % \fi % \ifgradbars@compare % \str_case_e:nnF {\gradbars@shape}{{bar}{}{dumbbell}{}} % {\gradbarsFail{Comparison~requires~shape=bar~or~dumbbell}} % \gradbarsCheckNumber{\gradbars@compareratio}{compare~ratio} % \gradbars@referencemissingfalse % \tl_set:Nx \l_tmpa_tl {\gradbars@reference}\tl_trim_spaces:N \l_tmpa_tl % \tl_if_empty:NT \l_tmpa_tl {\gradbars@referencemissingtrue} % \str_if_eq:VnT \l_tmpa_tl {NA}{\gradbars@referencemissingtrue} % \ifgradbars@referencemissing\else\gradbarsCheckNumber{\gradbars@reference}{reference}\fi % \ifgradbars@valid % \fp_compare:nF {0<\gradbars@compareratio<1}{\gradbarsFail{Compare~ratio~must~lie~strictly~between~0~and~1}} % \ifgradbars@referencemissing\else % \fp_compare:nNnT {\gradbars@min} = {0} % {\fp_compare:nNnT {\gradbars@reference} < {0} % {\gradbarsFail{Negative~reference~requires~a~negative~min}}} % \gradbarsRange{Reference}{\gradbars@reference} % \fi % \fi % \fi % \ifgradbars@rangemode % \str_if_eq:eeF {\gradbars@shape}{bar}{\gradbarsFail{Range~requires~shape=bar}} % \ifgradbars@error\gradbarsFail{Range~bars~do~not~accept~error~whiskers}\fi % \clist_if_empty:NF \l__gradbars_thresholds_clist % {\gradbarsFail{Range~bars~do~not~accept~thresholds}} % \gradbars@rangemissingfalse % \tl_set:Nx \l_tmpa_tl {\gradbars@rangelo}\tl_trim_spaces:N \l_tmpa_tl % \tl_if_empty:NT \l_tmpa_tl {\gradbars@rangemissingtrue} % \str_if_eq:VnT \l_tmpa_tl {NA}{\gradbars@rangemissingtrue} % \ifgradbars@rangemissing % \ifgradbars@missing\else\gradbarsFail{Both~range~endpoints~must~be~present~or~missing}\fi % \else % \ifgradbars@missing\gradbarsFail{Both~range~endpoints~must~be~present~or~missing}\fi % \gradbarsCheckNumber{\gradbars@rangelo}{range~lower~endpoint} % \fi % \tl_if_empty:oF {\gradbars@rangepoint}{\gradbarsCheckNumber{\gradbars@rangepoint}{range~point}} % \ifgradbars@valid % \ifgradbars@missing % \tl_if_empty:oF {\gradbars@rangepoint}{\gradbarsFail{Missing~range~cannot~have~a~point}} % \else % \fp_compare:nNnT {\gradbars@rangelo} > {\gradbars@rangehi} % {\gradbarsFail{Range~lower~endpoint~must~not~exceed~upper}} % \fp_compare:nNnT {\gradbars@min} = {0} % {\fp_compare:nNnT {\gradbars@rangelo} < {0} % {\gradbarsFail{Negative~range~requires~a~negative~min}}} % \gradbarsRange{Range~lower~endpoint}{\gradbars@rangelo} % \tl_if_empty:oF {\gradbars@rangepoint} % {\fp_compare:nF {\gradbars@rangelo<=\gradbars@rangepoint<=\gradbars@rangehi} % {\gradbarsFail{Range~point~must~lie~between~endpoints}}} % \cs_set:Npx \gradbars@start {\gradbarsPosition{\gradbars@rangelo}} % \cs_set:Npx \gradbars@stop {\gradbarsPosition{\gradbars@rangehi}} % \fi % \fi % \else % \tl_if_empty:oF {\gradbars@rangepoint}{\gradbarsFail{Range~point~requires~gradrange}} % \fi % } %% Format each endpoint independently using the ordinary number formatter. %\cs_new_eq:NN \gradbarsSingleLabel \gradbars@labelcontent %\cs_new_protected:Npn \gradbarsFormatEndpoint #1 % {\group_begin:\gradbars@missingfalse\def\gradbars@text{} % \cs_set:Npx \gradbars@number {\fp_eval:n {#1}} % \str_if_eq:eeT {\gradbars@format}{percent} % {\cs_set:Npx \gradbars@number {\fp_eval:n {100*(#1)/\gradbarsPercentBase}}} % \gradbarsSingleLabel\group_end:} %\cs_set_protected:Npn \gradbars@labelcontent % { % \tl_if_empty:oTF {\gradbars@text} % {\ifgradbars@compare % \gradbarsSingleLabel\,/\, % \ifgradbars@referencemissing\gradbars@missingtext % \else\gradbarsFormatEndpoint{\gradbars@reference}\fi % \else\ifgradbars@rangemode % \ifgradbars@missing\gradbars@missingtext % \else[\gradbarsFormatEndpoint{\gradbars@rangelo},\, % \gradbarsFormatEndpoint{\gradbars@rangehi}]\fi % \else\gradbarsSingleLabel\fi\fi} % {\gradbars@text} % } % % % %\ExplSyntaxOff % % %% v0.0.3: comparison, signed compositions, series and semantic palettes. %\definecolor{gradbarsOrange}{HTML}{D55E00} %\definecolor{gradbarsPurple}{HTML}{AA4499} %\definecolor{gradbarsCyan}{HTML}{56B4E9} %\definecolor{gradbarsGreen}{HTML}{009E73} %\def\gradbars@comparelabel{values} %\def\gradbars@stacktotals{net} %\def\gradbars@qualitytarget{} %\def\gradbars@qualityrange{} %\def\gradbars@sparkrange{auto} %\def\gradbars@sparkpoints{extrema} %\def\gradbars@sparkhigh{gradbarsTeal} %\def\gradbars@sparklow{gradbarsOrange} %\newif\ifgradbars@spark %\pgfkeys{/gradbars, % shape/dumbbell/.code=\def\gradbars@shape{dumbbell}, % shape/sparkline/.code=\def\gradbars@shape{sparkline}, % compare label/.is choice, % compare label/values/.code=\def\gradbars@comparelabel{values}, % compare label/delta/.code=\def\gradbars@comparelabel{delta}, % stack totals/.is choice, % stack totals/net/.code=\def\gradbars@stacktotals{net}, % stack totals/separate/.code=\def\gradbars@stacktotals{separate}, % better/target/.code=\def\gradbars@better{target}, % better/interval/.code=\def\gradbars@better{interval}, % quality target/.store in=\gradbars@qualitytarget, % quality range/.store in=\gradbars@qualityrange, % spark range/.is choice, % spark range/auto/.code=\def\gradbars@sparkrange{auto}, % spark range/fixed/.code=\def\gradbars@sparkrange{fixed}, % spark points/.is choice, % spark points/extrema/.code=\def\gradbars@sparkpoints{extrema}, % spark points/all/.code=\def\gradbars@sparkpoints{all}, % spark points/last/.code=\def\gradbars@sparkpoints{last}, % spark points/none/.code=\def\gradbars@sparkpoints{none}, % spark high color/.store in=\gradbars@sparkhigh, % spark low color/.store in=\gradbars@sparklow, % palette/.is choice, % palette/categorical/.style={stack colors={gradbarsBlue,gradbarsOrange,gradbarsGreen,gradbarsPurple,gradbarsCyan,gold}, % stack patterns={none},compare color=gradbarsOrange,negative color=gradbarsOrange}, % palette/sequential/.style={stack colors={gradbarsBlue!20,gradbarsBlue!40,gradbarsBlue!60,gradbarsBlue!80,gradbarsBlue}, % stack patterns={none}}, % palette/diverging/.style={stack colors={gradbarsOrange!85,gradbarsOrange!40,black!12,gradbarsTeal!40,gradbarsTeal!85}, % threshold colors={gradbarsOrange,gold,gradbarsTeal},negative color=gradbarsOrange, % compare color=gradbarsOrange,left color=gradbarsTeal,right color=gradbarsTeal!35,stack patterns={none}}, % palette/mono/.style={print,stack colors={white,black!10,black!20}, % stack patterns={diagonal,dots,crosshatch},compare color=black!45, % spark high color=black,spark low color=black}, %} %\DeclareDocumentCommand\graddumbbell{O{} m m}{% % \gradcompare[#1,shape=dumbbell]{#2}{#3}} %\ExplSyntaxOn %\ExplSyntaxOn %% Category identity is scoped and keyed by literal names, independent of order. %\prop_new:N \l__gradbars_category_colors_prop %\prop_new:N \l__gradbars_category_patterns_prop %\DeclareDocumentCommand\gradbarscategory{m m m} % { % \tl_if_blank:nTF {#1}{\gradbarsFail{Category~name~must~not~be~empty}} % {\prop_if_in:NnTF \c__gradbars_patterns_prop {#3} % {\prop_put:Nnn \l__gradbars_category_colors_prop {#1}{#2} % \prop_put:Nnn \l__gradbars_category_patterns_prop {#1}{#3}} % {\gradbarsFail{Unknown~category~pattern}}} % } %\cs_new_protected:Npn \gradbarsCategoryColor #1 % { % \cs_set:Npx \gradbars@segmentcolor % {\clist_item:Nn \l__gradbars_stackcolors_clist % {1+\int_mod:nn {#1-1}{\clist_count:N \l__gradbars_stackcolors_clist}}} % \tl_set:Nx \l_tmpa_tl {\clist_item:Nn \l__gradbars_names_clist {#1}} % \ifgradbars@print\else % \prop_get:NVNT \l__gradbars_category_colors_prop \l_tmpa_tl \l_tmpb_tl % {\cs_set:Npx \gradbars@segmentcolor {\exp_not:V \l_tmpb_tl}} % \fi % } %\cs_new_protected:Npn \gradbarsCategoryPattern #1 % { % \int_compare:nNnT {#1} > {0} % {\tl_set:Nx \l_tmpa_tl {\clist_item:Nn \l__gradbars_names_clist {#1}} % \prop_get:NVNT \l__gradbars_category_patterns_prop \l_tmpa_tl \l_tmpb_tl % {\tl_set_eq:NN \l__gradbars_pattern_tl \l_tmpb_tl}} % } %\fp_new:N \l__gradbars_distance_fp %\clist_new:N \l__gradbars_quality_clist %\cs_new_protected:Npn \gradbarsQuality % { % \str_case_e:nn {\gradbars@better} % {{target}{\gradbarsCheckNumber{\gradbars@qualitytarget}{quality~target}} % {interval}{\clist_set:Nx \l__gradbars_quality_clist {\gradbars@qualityrange} % \tl_set:Nx \l_tmpa_tl {\gradbars@qualityrange} % \regex_match:nVT {\A\s*,|,\s*,|,\s*\Z} \l_tmpa_tl % {\gradbarsFail{Quality~range~requires~two~endpoints}} % \int_compare:nNnF {\clist_count:N \l__gradbars_quality_clist} = {2} % {\gradbarsFail{Quality~range~requires~two~endpoints}} % \clist_map_inline:Nn \l__gradbars_quality_clist % {\gradbarsCheckNumber{##1}{quality~endpoint}}}} % \clist_if_empty:NT \l__gradbars_thresholds_clist % {\gradbarsFail{Target~and~interval~quality~require~distance~thresholds}} % \ifgradbars@stack\gradbarsFail{Stack~does~not~support~quality~evaluation}\fi % \ifgradbars@rangemode\gradbarsFail{Range~does~not~support~quality~evaluation}\fi % \ifgradbars@valid % \fp_compare:nNnT {\clist_item:Nn \l__gradbars_thresholds_clist {1}} < {0} % {\gradbarsFail{Distance~thresholds~must~be~nonnegative}} % \str_if_eq:eeTF {\gradbars@better}{target} % {\fp_set:Nn \l__gradbars_distance_fp {abs(\gradbars@value-\gradbars@qualitytarget)}} % {\fp_compare:nNnT {\clist_item:Nn \l__gradbars_quality_clist {1}} % > {\clist_item:Nn \l__gradbars_quality_clist {2}} % {\gradbarsFail{Quality~range~must~be~ordered}} % \fp_set:Nn \l__gradbars_distance_fp % {max(0,\clist_item:Nn \l__gradbars_quality_clist {1}-\gradbars@value, % \gradbars@value-\clist_item:Nn \l__gradbars_quality_clist {2})}} % \int_set:Nn \l_tmpa_int {1} % \fp_compare:nT {\l__gradbars_distance_fp <= \clist_item:Nn \l__gradbars_thresholds_clist {2}} % {\int_set:Nn \l_tmpa_int {2}} % \fp_compare:nT {\l__gradbars_distance_fp <= \clist_item:Nn \l__gradbars_thresholds_clist {1}} % {\int_set:Nn \l_tmpa_int {3}} % \cs_set:Npx \gradbars@left {\clist_item:Nn \l__gradbars_colors_clist {\l_tmpa_int}} % \gradbars@gradientfalse % \fi % } %\cs_new_eq:NN \gradbarsValidateBeforeThree \gradbarsValidateExtras %\cs_set_protected:Npn \gradbarsValidateExtras % { % \gradbarsValidateBeforeThree % \str_case_e:nn {\gradbars@better}{{target}{\gradbarsQuality}{interval}{\gradbarsQuality}} % \str_if_eq:eeT {\gradbars@shape}{dumbbell} % {\ifgradbars@compare\else\gradbarsFail{Dumbbell~requires~graddumbbell}\fi} % \str_if_eq:eeT {\gradbars@shape}{sparkline} % {\ifgradbars@spark\else\gradbarsFail{Sparkline~requires~gradspark}\fi} % \ifgradbars@spark % \str_if_eq:eeF {\gradbars@shape}{sparkline}{\gradbarsFail{Spark~requires~shape=sparkline}} % \ifgradbars@error\gradbarsFail{Spark~does~not~support~error~whiskers}\fi % \tl_if_empty:oF {\gradbars@target}{\gradbarsFail{Spark~does~not~support~bar~targets}} % \tl_if_empty:oF {\gradbars@band}{\gradbarsFail{Spark~does~not~support~bar~bands}} % \tl_if_empty:oF {\gradbars@thresholds}{\gradbarsFail{Spark~does~not~support~thresholds}} % \gradbarsValidateSpark % \fi % } %\cs_new_eq:NN \gradbarsLabelBeforeThree \gradbars@labelcontent %\cs_set_protected:Npn \gradbars@labelcontent % { % \tl_if_empty:oTF {\gradbars@text} % {\ifgradbars@compare % \str_if_eq:eeTF {\gradbars@comparelabel}{delta} % {\ifgradbars@missing\gradbars@missingtext\else % \ifgradbars@referencemissing\gradbars@missingtext\else % $\Delta$\,\gradbarsFormatEndpoint{\gradbars@value-\gradbars@reference}\fi\fi} % {\gradbarsLabelBeforeThree} % \else\ifgradbars@stack % \str_if_eq:eeTF {\gradbars@stacktotals}{separate} % {+\gradbarsFormatEndpoint{\gradbars@positive}\,/\,\gradbarsFormatEndpoint{\gradbars@negative}} % {\gradbarsLabelBeforeThree} % \else\gradbarsLabelBeforeThree\fi\fi} % {\gradbars@text} % } % % %\ExplSyntaxOn %% Auto series scaling applies to the y axis; it must not inherit bar clipping. %\cs_new_eq:NN \gradbarsValidateBeforeSpark \gradbarsValidate %\cs_set_protected:Npn \gradbarsValidate % { % \ifgradbars@spark % \str_if_eq:eeT{\gradbars@sparktype}{winloss} % {\cs_set:Npx\gradbars@min{\fp_eval:n{min(0,\l__gradbars_series_min_fp)}} % \cs_set:Npx\gradbars@max{\fp_eval:n{max(1,\l__gradbars_series_max_fp)}} % \str_if_eq:eeT{\gradbars@format}{percent} % {\gradbarsFail{Win-loss~does~not~support~percent~format}}} % \str_if_eq:eeT {\gradbars@sparkrange}{auto} % {\cs_set:Npx \gradbars@min {\fp_eval:n {min(0,\l__gradbars_series_min_fp)}} % \cs_set:Npx \gradbars@max {\fp_eval:n {max(1,\l__gradbars_series_max_fp)}} % \str_if_eq:eeT {\gradbars@format}{percent} % {\gradbarsFail{Auto~spark~range~does~not~support~percent~format}}} % \str_if_eq:eeF {\gradbars@label}{none}{\def\gradbars@label{outside}} % \fi % \let\gradbars@sparkbasecolor\gradbars@left % \gradbarsValidateBeforeSpark % \ifgradbars@spark\let\gradbars@left\gradbars@sparkbasecolor\fi % } % % %\ExplSyntaxOff %% Reference records: {value/color/line style/name}, names may be empty. %\def\gradbars@references{} %\def\gradbars@bulletbands{} %\newif\ifgradbars@bullet %\pgfkeys{/gradbars/.cd, % references/.store in=\gradbars@references, % bullet bands/.store in=\gradbars@bulletbands} %\DeclareDocumentCommand\gradbullet{O{} m}{% % \begingroup\gradbars@bullettrue % \gradbar[height=12pt,fill=solid,label=outside,#1,shape=bar]{#2}% % \endgroup} %\ExplSyntaxOn %\seq_new:N \l__gradbars_record_seq %\clist_new:N \l__gradbars_refs_clist %\clist_new:N \l__gradbars_bands_clist %\fp_new:N \l__gradbars_band_start_fp %\tl_new:N \l__gradbars_record_color_tl %\tl_new:N \l__gradbars_record_style_tl %\tl_new:N \l__gradbars_record_name_tl %\cs_new_protected:Npn \gradbarsRecord #1#2 % {\seq_set_split:Nnn \l__gradbars_record_seq {/}{#1} % \int_compare:nNnF {\seq_count:N \l__gradbars_record_seq} = {#2} % {\gradbarsFail{Wrong~number~of~fields~in~reference,~band~or~interval~record}}} %\cs_new_eq:NN \gradbarsValidateBeforeReferences \gradbarsValidateExtras %\cs_set_protected:Npn \gradbarsValidateExtras % { % \gradbarsValidateBeforeReferences % \clist_set:No \l__gradbars_refs_clist {\gradbars@references} % \clist_set:No \l__gradbars_bands_clist {\gradbars@bulletbands} % \ifgradbars@spark % \clist_if_empty:NF \l__gradbars_refs_clist % {\gradbarsFail{Spark~does~not~support~references}} % \fi % \clist_map_inline:Nn \l__gradbars_refs_clist % {\gradbarsRecord{##1}{4} % \ifgradbars@valid % \gradbarsCheckNumber{\seq_item:Nn \l__gradbars_record_seq {1}}{reference} % \ifgradbars@valid % \fp_compare:nT % {\seq_item:Nn \l__gradbars_record_seq {1}<\gradbars@min || % \seq_item:Nn \l__gradbars_record_seq {1}>\gradbars@max} % {\gradbarsFail{Reference~must~lie~within~range}} % \tl_set:Nx \l_tmpa_tl {\seq_item:Nn \l__gradbars_record_seq {3}} % \exp_args:NnV \clist_if_in:nnF {solid,dashed,dotted} \l_tmpa_tl % {\gradbarsFail{Reference~line~style~must~be~solid,~dashed~or~dotted}} % \fi % \fi} % \ifgradbars@bullet % \clist_if_empty:NT \l__gradbars_bands_clist % {\gradbarsFail{Bullet~requires~explicit~bullet~bands}} % \else % \clist_if_empty:NF \l__gradbars_bands_clist % {\gradbarsFail{Bullet~bands~require~gradbullet}} % \fi % \ifgradbars@valid % \fp_set:Nn \l__gradbars_band_start_fp {\gradbars@min} % \clist_map_inline:Nn \l__gradbars_bands_clist % {\gradbarsRecord{##1}{2} % \ifgradbars@valid % \gradbarsCheckNumber{\seq_item:Nn \l__gradbars_record_seq {1}}{band~endpoint} % \ifgradbars@valid % \fp_compare:nT % {\seq_item:Nn \l__gradbars_record_seq {1}<=\l__gradbars_band_start_fp || % \seq_item:Nn \l__gradbars_record_seq {1}>\gradbars@max} % {\gradbarsFail{Bullet~endpoints~must~increase~within~range}} % \fp_set:Nn \l__gradbars_band_start_fp {\seq_item:Nn \l__gradbars_record_seq {1}} % \fi % \fi} % \ifgradbars@bullet\ifgradbars@valid % \fp_compare:nNnF {\l__gradbars_band_start_fp} = {\gradbars@max} % {\gradbarsFail{Last~bullet~endpoint~must~equal~max}} % \fi\fi % \fi % } % % % %% Each interval record has name / lower / point (or NA) / upper / color. %\tl_new:N \l__gradbars_interval_rows_tl %\cs_new_protected:Npn \gradbarsIntervalRow #1#2#3#4#5 % {#1 & \gradrange[color=#5,range~point=#3]{#2}{#4}\\} %\DeclareDocumentCommand\gradintervals{O{} m} % {\group_begin: % \pgfkeys{/gradbars,#1} % \gradbars@validtrue % \tl_clear:N \l__gradbars_interval_rows_tl % \clist_if_empty:nT {#2}{\gradbarsFail{Interval~comparison~requires~records}} % \clist_map_inline:nn {#2} % {\gradbarsRecord{##1}{5} % \ifgradbars@valid % \tl_set:Nx \l__gradbars_record_name_tl {\seq_item:Nn \l__gradbars_record_seq {1}} % \tl_set:Nx \l_tmpa_tl {\seq_item:Nn \l__gradbars_record_seq {3}} % \str_if_eq:VnT \l_tmpa_tl {NA}{\tl_clear:N \l_tmpa_tl} % \tl_put_right:Nx \l__gradbars_interval_rows_tl % {\exp_not:N \gradbarsIntervalRow % {\exp_not:V \l__gradbars_record_name_tl} % {\seq_item:Nn \l__gradbars_record_seq {2}} % {\exp_not:V \l_tmpa_tl} % {\seq_item:Nn \l__gradbars_record_seq {4}} % {\seq_item:Nn \l__gradbars_record_seq {5}}} % \fi} % \ifgradbars@valid % \begin{tabular}{@{}l@{\hspace{.7em}}l@{}} % \l__gradbars_interval_rows_tl % \end{tabular} % \fi\group_end:} %\ExplSyntaxOff %% v0.0.4: overflow indicators, comparison annotations and marker shapes. %\def\gradbars@overflowmark{none} %\def\gradbars@markershape{circle} %\def\gradbars@markerfill{solid} %\def\gradbars@change{none} %\pgfkeys{/gradbars/.cd, % overflow mark/.is choice, % overflow mark/none/.code=\def\gradbars@overflowmark{none}, % overflow mark/arrow/.code=\def\gradbars@overflowmark{arrow}, % overflow mark/slash/.code=\def\gradbars@overflowmark{slash}, % marker shape/.is choice, % marker shape/circle/.code=\def\gradbars@markershape{circle}, % marker shape/square/.code=\def\gradbars@markershape{square}, % marker shape/diamond/.code=\def\gradbars@markershape{diamond}, % marker shape/triangle/.code=\def\gradbars@markershape{triangle}, % marker fill/.is choice, % marker fill/solid/.code=\def\gradbars@markerfill{solid}, % marker fill/hollow/.code=\def\gradbars@markerfill{hollow}, % compare annotation/.is choice, % compare annotation/none/.code=\def\gradbars@change{none}, % compare annotation/arrow/.code=\def\gradbars@change{arrow}, % compare annotation/bracket/.code=\def\gradbars@change{bracket}, % compare label/percent/.code=\def\gradbars@comparelabel{percent}} %\ExplSyntaxOn % % %\fp_new:N \l__gradbars_raw_low_fp %\fp_new:N \l__gradbars_raw_high_fp %\bool_new:N \l__gradbars_overflow_known_bool %\cs_new_protected:Npn \gradbarsOverflowSide #1#2 % {\begin{scope}[shift={(#1,.5*\gradbars@height)},xscale=#2] % \str_if_eq:eeTF {\gradbars@overflowmark}{arrow} % {\draw[draw=gradbarsInk,line~width=.7pt](-2pt,-2pt)--(1pt,0)--(-2pt,2pt);} % {\draw[draw=gradbarsInk,line~width=.7pt](-2pt,-2pt)--(0,2pt) (0,-2pt)--(2pt,2pt);} % \end{scope}} % %\cs_new_protected:Npn \gradbarsChangeLabel % {\group_begin: % \ifgradbars@missing\gradbars@missingtext\else % \ifgradbars@referencemissing\gradbars@missingtext\else % \str_if_eq:eeTF {\gradbars@comparelabel}{percent} % {\fp_compare:nNnTF {\gradbars@reference} = {0} % {\gradbars@missingtext} % {\def\gradbars@format{value}\def\gradbars@unit{\%}\def\gradbars@unitcode{}\def\gradbars@unittext{} % \fp_compare:nNnT {\gradbars@value-\gradbars@reference} > {0}{+} % \gradbarsFormatEndpoint{100*(\gradbars@value-\gradbars@reference)/abs(\gradbars@reference)}}} % {$\Delta$\,\def\gradbars@format{value} % \fp_compare:nNnT {\gradbars@value-\gradbars@reference} > {0}{+} % \gradbarsFormatEndpoint{\gradbars@value-\gradbars@reference}} % \fi\fi\group_end:} %\cs_new_eq:NN \gradbarsLabelBeforeFour \gradbars@labelcontent %\cs_set_protected:Npn \gradbars@labelcontent % {\ifgradbars@compare % \tl_if_empty:oTF {\gradbars@text} % {\str_if_eq:eeTF {\gradbars@comparelabel}{percent} % {\gradbarsChangeLabel}{\gradbarsLabelBeforeFour}} % {\gradbarsLabelBeforeFour} % \else\gradbarsLabelBeforeFour\fi} % %\ExplSyntaxOff %\ExplSyntaxOff %\RequirePackage{gradbars-tagging} %\ExplSyntaxOff %\ExplSyntaxOff %\ExplSyntaxOff %% v0.0.5: CSV selection, diverging heat and discrete spark observations. %\def\gradbars@heatpalette{sequential} %\def\gradbars@heatcenter{0} %\def\gradbars@heatcentercolor{white} %\def\gradbars@sparktype{line} %\def\gradbars@sparkbarwidth{.7} %\def\gradbars@sparkwincolor{gradbarsTeal} %\def\gradbars@sparklosscolor{gradbarsOrange} %\def\gradbars@sparkzerocolor{black!45} %\pgfkeys{/gradbars, % heat palette/.is choice, % heat palette/sequential/.style={heat low color=gradbarsBlueLight!15,heat high color=gradbarsBlue, % /gradbars/heat palette value=sequential}, % heat palette/diverging/.style={heat low color=gradbarsOrange,heat high color=gradbarsTeal, % heat center color=white,/gradbars/heat palette value=diverging}, % heat palette value/.store in=\gradbars@heatpalette, % heat center/.store in=\gradbars@heatcenter, % heat center color/.store in=\gradbars@heatcentercolor, % spark type/.is choice, % spark type/line/.code=\def\gradbars@sparktype{line}, % spark type/bar/.code=\def\gradbars@sparktype{bar}, % spark type/winloss/.code=\def\gradbars@sparktype{winloss}, % spark bar width/.store in=\gradbars@sparkbarwidth, % spark win color/.store in=\gradbars@sparkwincolor, % spark loss color/.store in=\gradbars@sparklosscolor, % spark zero color/.store in=\gradbars@sparkzerocolor} %\ExplSyntaxOn %\ExplSyntaxOn %\ExplSyntaxOn %\cs_new_eq:NN\gradbarsBuildAltBeforeSix\gradbarsBuildAlt %\cs_set_protected:Npn\gradbarsBuildAlt % {\gradbarsBuildAltBeforeSix % \ifgradbars@spark % \tl_put_left:Nx\l__gradbars_alt_tl{Spark~type:~\gradbars@sparktype.~} % \str_if_eq:eeT{\gradbars@sparktype}{winloss} % {\tl_put_right:Nn\l__gradbars_alt_tl{~Positive:~win;~negative:~loss;~zero:~tie.}} % \fi} %\ExplSyntaxOff %% v0.0.6: reusable scales, numeric summaries and table presentation. %\ExplSyntaxOn %\prop_new:N\l__gradbars_scale_groups_prop %\tl_new:N\l__gradbars_scale_min_tl %\tl_new:N\l__gradbars_scale_max_tl %\keys_define:nn{gradbars/scale} % {min .tl_set:N=\l__gradbars_scale_min_tl,max .tl_set:N=\l__gradbars_scale_max_tl} %\DeclareDocumentCommand\gradscale{m m} % {\gradbars@validtrue % \tl_clear:N\l__gradbars_scale_min_tl\tl_clear:N\l__gradbars_scale_max_tl % \keys_set:nn{gradbars/scale}{#2} % \tl_if_blank:nT{#1}{\gradbarsFail{Scale~name~must~not~be~empty}} % \gradbarsCheckNumber{\l__gradbars_scale_min_tl}{scale~min} % \gradbarsCheckNumber{\l__gradbars_scale_max_tl}{scale~max} % \ifgradbars@valid % \fp_compare:nNnTF{\l__gradbars_scale_max_tl}>{\l__gradbars_scale_min_tl} % {\prop_put:Nnx\l__gradbars_scale_groups_prop{#1} % {min=\l__gradbars_scale_min_tl,max=\l__gradbars_scale_max_tl}} % {\gradbarsFail{Scale~max~must~be~greater~than~min}} % \fi} %\cs_new_protected:Npn\gradbarsResolveScaleGroup % {\tl_if_empty:oF{\gradbars@scalegroup} % {\tl_set:No\l_tmpb_tl{\gradbars@scalegroup} % \prop_get:NVNTF\l__gradbars_scale_groups_prop\l_tmpb_tl\l_tmpa_tl % {\exp_args:NV\gradbarssetup\l_tmpa_tl % \ifgradbars@spark\pgfkeys{/gradbars,spark~range=fixed}\fi} % {\gradbarsFail{Unknown~scale~group:~\gradbars@scalegroup}}}} %\cs_new:Npn\gradbarsPercentBase % {\tl_if_empty:oTF{\gradbars@percentbase}{\gradbars@max}{\gradbars@percentbase}} %\cs_new_protected:Npn\gradbarsValidatePercentBase % {\gradbarsCheckNumber{\gradbarsPercentBase}{percent~base} % \ifgradbars@valid\fp_compare:nNnF{\gradbarsPercentBase}>{0} % {\gradbarsFail{Percent~base~must~be~positive}}\fi} %\cs_new_eq:NN\gradbarsBuildAltBeforeSummary\gradbarsBuildAlt %\cs_set_protected:Npn\gradbarsBuildAlt % {\gradbarsBuildAltBeforeSummary % \str_if_eq:eeT{\gradbars@format}{percent} % {\tl_put_right:Nx\l__gradbars_alt_tl{~Percent~base:~\gradbarsPercentBase.}}} %\ExplSyntaxOff %\ExplSyntaxOff %\RequirePackage{gradbars-numbers} %\ExplSyntaxOn %\ExplSyntaxOff % % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-keys.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Basic public pgfkeys family. %\ProvidesPackage{gradbars-keys}[2026/10/25 v1.1.0 gradbars keys] %\pgfkeys{/gradbars/.is family,/gradbars, % style/.code={\gradbarsUseStyle{#1}}, % missing text/.store in=\gradbars@missingtext, % number format/.is choice, % number format/fixed/.code=\def\gradbars@numberformat{fixed}, % number format/grouped/.code=\def\gradbars@numberformat{grouped}, % number format/scientific/.code=\def\gradbars@numberformat{scientific}, % band/.store in=\gradbars@band, % band color/.store in=\gradbars@bandcolor, % band opacity/.store in=\gradbars@bandopacity, % stack colors/.store in=\gradbars@stackcolors, % width/.store in=\gradbars@width, % height/.store in=\gradbars@height, % max/.store in=\gradbars@max, % min/.store in=\gradbars@min, % scale group/.store in=\gradbars@scalegroup, % percent base/.store in=\gradbars@percentbase, % rounded/.store in=\gradbars@rounded, % target/.store in=\gradbars@target, % target color/.store in=\gradbars@targetcolor, % negative color/.store in=\gradbars@negativecolor, % negative fill/.is choice, % negative fill/solid/.code=\gradbars@negativegradientfalse, % negative fill/gradient/.code=\gradbars@negativegradienttrue, % negative left color/.code={\def\gradbars@negativeleft{#1}\gradbars@negativegradienttrue}, % negative right color/.code={\def\gradbars@negativeright{#1}\gradbars@negativegradienttrue}, % thresholds/.store in=\gradbars@thresholds, % threshold colors/.store in=\gradbars@thresholdcolors, % error/.style={error minus=#1,error plus=#1}, % error minus/.store in=\gradbars@errorminus, % error plus/.store in=\gradbars@errorplus, % error color/.store in=\gradbars@errorcolor, % precision/.store in=\gradbars@precision, % unit/.store in=\gradbars@unit, % text/.store in=\gradbars@text, % alt/.store in=\gradbars@alt, % accessibility/.is choice, % accessibility/auto/.code=\def\gradbars@accessibility{auto}, % accessibility/artifact/.code=\def\gradbars@accessibility{artifact}, % accessibility/off/.code=\def\gradbars@accessibility{off}, % label gap/.store in=\gradbars@gap, % label width/.store in=\gradbars@labelwidth, % label align/.is choice, % label align/graphic/.code=\def\gradbars@labelalign{graphic}, % label align/cell/.code=\def\gradbars@labelalign{cell}, % font/.store in=\gradbars@font, % left color/.store in=\gradbars@left, % right color/.store in=\gradbars@right, % track color/.store in=\gradbars@track, % text color/.store in=\gradbars@textcolor, % color/.style={fill=solid,left color=#1}, % fill/.is choice, % fill/gradient/.code=\gradbars@gradienttrue, % fill/solid/.code=\gradbars@gradientfalse, % label/.is choice, % label/outside/.code=\def\gradbars@label{outside}, % label/inside/.code=\def\gradbars@label{inside}, % label/none/.code=\def\gradbars@label{none}, % label/end/.code=\def\gradbars@label{end}, % label/auto/.code=\def\gradbars@label{auto}, % label/left/.code=\def\gradbars@label{left}, % baseline/.is choice, % baseline/auto/.code=\def\gradbars@baseline{auto}, % baseline/text/.code=\def\gradbars@baseline{text}, % baseline/center/.code=\def\gradbars@baseline{center}, % baseline/bottom/.code=\def\gradbars@baseline{bottom}, % baseline shift/.store in=\gradbars@baselineshift, % value format/.is choice, % value format/value/.code=\def\gradbars@format{value}, % value format/percent/.code=\def\gradbars@format{percent}, % overflow/.is choice, % overflow/clip/.code=\def\gradbars@overflow{clip}, % overflow/error/.code=\def\gradbars@overflow{error}, % theme/.is choice, % theme/blue/.style={fill=gradient,left color=gradbarsBlue, % right color=gradbarsBlueLight,track color=gradbarsTrack,text color=gradbarsInk}, % theme/teal/.style={fill=gradient,left color=gradbarsTeal, % right color=gradbarsTealLight,track color=gradbarsTrack,text color=gradbarsInk}, % theme/solid/.style={fill=solid,left color=gradbarsBlue, % right color=gradbarsBlue,track color=gradbarsTrack,text color=gradbarsInk}, % theme/gray/.style={fill=solid,left color=black!65, % right color=black!65,track color=black!8,text color=black}, % theme/lbyellow/.style={fill=gradient,left color=lightblue!90, % right color=lightyellow!60,track color=gradbarsTrack,text color=gradbarsInk}, % theme/viblue/.style={fill=gradient,left color=violet!20, % right color=lightblue!70,track color=gradbarsTrack,text color=gradbarsInk}, % theme/cyblu/.style={fill=gradient,left color=cyan, % right color=blue!20,track color=gradbarsTrack,text color=gradbarsInk}, % theme/violet/.style={fill=gradient,left color=gradbarsViolet, % right color=gradbarsVioletLight,track color=gradbarsViolet!6,text color=gradbarsInk}, % theme/orange/.style={fill=gradient,left color=gradbarsWarmOrange, % right color=gradbarsWarmOrangeLight,track color=gradbarsWarmOrange!6,text color=gradbarsInk}, % theme/forest/.style={fill=gradient,left color=gradbarsForest, % right color=gradbarsForestLight,track color=gradbarsForest!6,text color=gradbarsInk}, %} %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-csv.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-lib-csv}[2026/10/25 v1.1.0 gradbars lib-csv] %\RequirePackage{collcell} %\ExplSyntaxOff %\DeclareDocumentCommand\gradbarscolumn{s m m}{% % \IfBooleanTF{#1}{\gradbarsDefineCompactColumn{#2}{#3}}{% % \gradbarsDefineColumn{#2}{#3}}} %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDefineColumn #1#2 % { % \regex_match:nnTF {\A[A-Za-z]\Z} {#1} % {\expandafter\newcolumntype\expandafter{#1} % {>{\collectcell{\gradbar[#2]}}l<{\endcollectcell}}} % {\PackageError{gradbars}{Column~name~must~be~one~ASCII~letter} % {Choose~a~single~unused~letter,~for~example~G.}} % } % %% Expand directly to \multicolumn: alignment must see \omit before any setup. %\cs_set:Npn \gradbarshead #1 {\multicolumn{1}{c}{#1}} %\dim_new:N \l__gradbars_column_blank_dim %\cs_new_protected:Npn \__gradbars_compact_cell:nn #1#2 % {\tl_if_blank:nTF {#2} % {\group_begin: % \gradbarssetup{#1} % \dim_set:Nn\l__gradbars_column_blank_dim{\gradbars@width} % \dim_compare:nNnTF{\l__gradbars_column_blank_dim}>{0pt} % {\hbox_to_wd:nn{\l__gradbars_column_blank_dim}{\hfil}} % {\gradbarsFail{Width~must~be~positive}} % \group_end:} % {\gradbar[baseline=text,label=inside,label~align=cell,#1]{#2}}} %\cs_new_protected:Npn \gradbarsDefineCompactColumn #1#2 % {\regex_match:nnTF {\A[A-Za-z]\Z}{#1} % {\clist_if_in:nnTF{c,l,r,p,m,b,w,W}{#1} % {\__gradbars_public_error:n{Column~already~defined~or~reserved:~#1}} % {\cs_if_exist:cTF{NC@find@#1} % {\__gradbars_public_error:n{Column~already~defined~or~reserved:~#1}} % {\newcolumntype{#1} % {>{\collectcell{\__gradbars_compact_cell:nn{#2}}}c<{\endcollectcell}}}}} % {\__gradbars_public_error:n{Column~name~must~be~one~ASCII~letter}}} % %\ExplSyntaxOff %\ExplSyntaxOn %% CSV is read as character data; fields are never executed as TeX. %\ior_new:N \l__gradbars_csv_ior %\prop_new:N \l__gradbars_csv_prop %\seq_new:N \l__gradbars_csv_fields_seq %\tl_new:N \l__gradbars_csv_field_tl %\tl_new:N \l__gradbars_csv_line_tl %\tl_new:N \l__gradbars_csv_value_tl %\tl_new:N \l__gradbars_csv_table_tl %\clist_new:N \l__gradbars_csv_missing_clist %\int_new:N \l__gradbars_csv_state_int %\int_new:N \l__gradbars_csv_row_int %\int_new:N \l__gradbars_csv_col_int %\int_new:N \l__gradbars_csv_width_int %\fp_new:N \l__gradbars_csv_min_fp %\fp_new:N \l__gradbars_csv_max_fp %\keys_define:nn {gradbars/csv} % {missing .clist_set:N=\l__gradbars_csv_missing_clist} %\cs_generate_variant:Nn \prop_put:Nnn {Nxn,Nxx,NVx} %\cs_generate_variant:Nn \prop_get:NnN {cxN} %\cs_generate_variant:Nn \prop_if_in:NnTF {cxTF} %\cs_new_protected:Npn \gradbarsCSVField % {\tl_trim_spaces:N \l__gradbars_csv_field_tl % \seq_put_right:NV \l__gradbars_csv_fields_seq \l__gradbars_csv_field_tl % \tl_clear:N \l__gradbars_csv_field_tl % \int_zero:N \l__gradbars_csv_state_int} %\cs_new_protected:Npn \gradbarsCSVParse #1 % { % \seq_clear:N \l__gradbars_csv_fields_seq % \tl_clear:N \l__gradbars_csv_field_tl % \int_zero:N \l__gradbars_csv_state_int % % states: 0=unquoted, 1=quoted, 2=closing quote, 3=trailing space. % \str_map_inline:nn {#1} % { % \int_case:nn {\l__gradbars_csv_state_int} % { % {0}{\str_case:nnF {##1} % {{,}{\gradbarsCSVField} % {"}{\tl_if_blank:VTF \l__gradbars_csv_field_tl % {\tl_clear:N \l__gradbars_csv_field_tl\int_set:Nn \l__gradbars_csv_state_int {1}} % {\gradbarsFail{Quote~inside~unquoted~CSV~field}}}} % {\tl_put_right:Nn \l__gradbars_csv_field_tl {##1}}} % {1}{\str_if_eq:nnTF {##1}{"} % {\int_set:Nn \l__gradbars_csv_state_int {2}} % {\tl_put_right:Nn \l__gradbars_csv_field_tl {##1}}} % {2}{\str_case:nnF {##1} % {{"}{\tl_put_right:Nn \l__gradbars_csv_field_tl {"}\int_set:Nn \l__gradbars_csv_state_int {1}} % {,}{\gradbarsCSVField}} % {\str_if_eq:nnTF {##1}{~} % {\int_set:Nn \l__gradbars_csv_state_int {3}} % {\gradbarsFail{Unexpected~text~after~CSV~quote}}}} % {3}{\str_if_eq:nnTF {##1}{,}{\gradbarsCSVField} % {\str_if_eq:nnF {##1}{~}{\gradbarsFail{Unexpected~text~after~CSV~quote}}}} % } % } % \int_compare:nNnT {\l__gradbars_csv_state_int} = {1} % {\gradbarsFail{Unclosed~CSV~quote;~multiline~fields~are~not~supported}} % \gradbarsCSVField % } %\cs_new_protected:Npn \gradbarsCSVLine #1 % { % \tl_set:Nn \l__gradbars_csv_line_tl {#1} % % pdfTeX reads UTF-8 as bytes; Unicode engines read a single BOM character. % \sys_if_engine_pdftex:TF % {\regex_replace_once:nnN {\A\x{EF}\x{BB}\x{BF}} {} \l__gradbars_csv_line_tl} % {\regex_replace_once:nnN {\A\x{FEFF}} {} \l__gradbars_csv_line_tl} % \tl_if_blank:VF \l__gradbars_csv_line_tl % { % \exp_args:NV \gradbarsCSVParse \l__gradbars_csv_line_tl % \int_compare:nNnTF {\l__gradbars_csv_row_int} = {0} % { % \int_set:Nn \l__gradbars_csv_width_int {\seq_count:N \l__gradbars_csv_fields_seq} % \int_zero:N \l__gradbars_csv_col_int % \seq_map_inline:Nn \l__gradbars_csv_fields_seq % {\int_incr:N \l__gradbars_csv_col_int % \tl_if_blank:nT {##1}{\gradbarsFail{CSV~header~must~not~be~empty}} % \prop_if_in:NnT \l__gradbars_csv_prop {col/##1}{\gradbarsFail{Duplicate~CSV~header:~##1}} % \prop_put:Nnx \l__gradbars_csv_prop {col/##1}{\int_use:N \l__gradbars_csv_col_int}} % } % { % \int_compare:nNnF {\seq_count:N \l__gradbars_csv_fields_seq} = {\l__gradbars_csv_width_int} % {\gradbarsFail{CSV~row~has~wrong~field~count}} % \int_zero:N \l__gradbars_csv_col_int % \seq_map_inline:Nn \l__gradbars_csv_fields_seq % {\int_incr:N \l__gradbars_csv_col_int % \prop_put:Nxn \l__gradbars_csv_prop % {row/\int_use:N \l__gradbars_csv_row_int/\int_use:N \l__gradbars_csv_col_int}{##1}} % } % \int_incr:N \l__gradbars_csv_row_int % } % } %\DeclareDocumentCommand\gradbarsloadcsv{O{} m m} % { % \gradbars@validtrue % \regex_match:nnF {\A[A-Za-z][A-Za-z0-9_\-]*\Z}{#2} % {\gradbarsFail{CSV~dataset~name~must~start~with~an~ASCII~letter}} % \clist_set:Nn \l__gradbars_csv_missing_clist {NA,N/A,null} % \keys_set:nn {gradbars/csv}{#1} % \prop_clear:N \l__gradbars_csv_prop % \int_zero:N \l__gradbars_csv_row_int % \file_if_exist:nTF {#3} % {\ior_open:Nn \l__gradbars_csv_ior {#3} % \ior_str_map_inline:Nn \l__gradbars_csv_ior {\gradbarsCSVLine{##1}} % \ior_close:N \l__gradbars_csv_ior} % {\gradbarsFail{CSV~file~not~found:~#3}} % \int_compare:nNnF {\l__gradbars_csv_row_int} > {0}{\gradbarsFail{CSV~requires~a~header}} % \ifgradbars@valid % \prop_put:Nnx \l__gradbars_csv_prop {rows}{\int_eval:n {\l__gradbars_csv_row_int-1}} % \prop_put:NnV \l__gradbars_csv_prop {missing}\l__gradbars_csv_missing_clist % \prop_if_exist:cF {l__gradbars_csv_#2_prop}{\prop_new:c {l__gradbars_csv_#2_prop}} % \prop_set_eq:cN {l__gradbars_csv_#2_prop}\l__gradbars_csv_prop % \fi % } %\cs_new_protected:Npn \gradbarsCSVColumn #1#2 % { % \gradbars@validtrue % \prop_if_exist:cTF {l__gradbars_csv_#1_prop} % {\prop_if_in:cxTF {l__gradbars_csv_#1_prop}{col/\tl_to_str:n {#2}} % {\prop_get:cxN {l__gradbars_csv_#1_prop}{col/\tl_to_str:n {#2}}\l_tmpa_tl % \int_set:Nn \l__gradbars_csv_col_int {\l_tmpa_tl}} % {\gradbarsFail{Unknown~CSV~column:~#2}}} % {\gradbarsFail{Unknown~CSV~dataset:~#1}} % } %\cs_new_protected:Npn \gradbarsCSVGet #1#2#3 % { % \gradbarsCSVColumn{#1}{#3} % \regex_match:nnF {\A[1-9][0-9]*\Z}{#2}{\gradbarsFail{CSV~row~must~be~a~positive~integer}} % \ifgradbars@valid % \prop_if_in:cxTF {l__gradbars_csv_#1_prop}{row/#2/\int_use:N \l__gradbars_csv_col_int} % {\prop_get:cxN {l__gradbars_csv_#1_prop}{row/#2/\int_use:N \l__gradbars_csv_col_int}\l__gradbars_csv_value_tl} % {\gradbarsFail{CSV~row~out~of~range}} % \fi % } %\cs_new_protected:Npn \gradbarsCSVNumber #1 % { % \prop_get:cnN {l__gradbars_csv_#1_prop}{missing}\l_tmpa_tl % \clist_set:NV \l__gradbars_csv_missing_clist \l_tmpa_tl % \bool_set_false:N \l_tmpa_bool % \tl_if_blank:VT \l__gradbars_csv_value_tl {\bool_set_true:N \l_tmpa_bool} % \clist_map_inline:Nn \l__gradbars_csv_missing_clist % {\str_if_eq:eeT {\l__gradbars_csv_value_tl}{\tl_to_str:n {##1}}{\bool_set_true:N \l_tmpa_bool}} % \bool_if:NTF \l_tmpa_bool % {\tl_set:Nn \l__gradbars_csv_value_tl {NA}} % {\gradbarsCheckNumber{\l__gradbars_csv_value_tl}{CSV~numeric~cell}} % } %\DeclareDocumentCommand\gradbarscsvcell{m m m} % {\group_begin:\gradbarsCSVGet{#1}{#2}{#3} % \ifgradbars@valid\tl_use:N \l__gradbars_csv_value_tl\fi\group_end:} %\DeclareDocumentCommand\gradbarcsv{O{} m m m} % {\group_begin:\gradbarsCSVGet{#2}{#3}{#4} % \ifgradbars@valid\gradbarsCSVNumber{#2} % \ifgradbars@valid\gradbar[#1]{\l__gradbars_csv_value_tl}\fi\fi\group_end:} %\cs_new_protected:Npn \gradbarsCSVRange #1#2 % { % \gradbarsCSVColumn{#1}{#2} % \fp_zero:N \l__gradbars_csv_min_fp % \fp_zero:N \l__gradbars_csv_max_fp % \ifgradbars@valid % \int_step_inline:nn {\prop_item:cn {l__gradbars_csv_#1_prop}{rows}} % {\prop_get:cxN {l__gradbars_csv_#1_prop}{row/##1/\int_use:N \l__gradbars_csv_col_int}\l__gradbars_csv_value_tl % \gradbarsCSVNumber{#1} % \ifgradbars@valid % \str_if_eq:VnF \l__gradbars_csv_value_tl {NA} % {\fp_set:Nn \l__gradbars_csv_min_fp {min(\l__gradbars_csv_min_fp,\l__gradbars_csv_value_tl)} % \fp_set:Nn \l__gradbars_csv_max_fp {max(\l__gradbars_csv_max_fp,\l__gradbars_csv_value_tl)}} % \fi} % % Keep a positive upper limit even for all-zero/all-missing/negative columns. % \fp_compare:nNnT {\l__gradbars_csv_max_fp} = {0}{\fp_set:Nn \l__gradbars_csv_max_fp {1}} % \fi % } %\DeclareDocumentCommand\gradbarscsvstyle{m m m} % {\gradbarsCSVRange{#2}{#3} % \ifgradbars@valid % \cs_set:cpx {gradbars@style@#1} % {min=\fp_to_decimal:N \l__gradbars_csv_min_fp,max=\fp_to_decimal:N \l__gradbars_csv_max_fp} % \fi} %\DeclareDocumentCommand\gradbarscsvtable{O{} m m m} % { % \group_begin: % \gradbarsCSVRange{#2}{#4} % \ifgradbars@valid % \tl_set:Nx \l__gradbars_csv_table_tl % {\exp_not:N \gradbarssetup{min=\fp_to_decimal:N \l__gradbars_csv_min_fp, % max=\fp_to_decimal:N \l__gradbars_csv_max_fp} % \exp_not:N \begin{tabular}{@{}ll@{}}\exp_not:N \hline % \tl_to_str:n {#3}&\tl_to_str:n {#4}\exp_not:N \\\exp_not:N \hline} % \int_step_inline:nn {\prop_item:cn {l__gradbars_csv_#2_prop}{rows}} % {\gradbarsCSVGet{#2}{##1}{#3} % \ifgradbars@valid % \tl_put_right:Nx \l__gradbars_csv_table_tl % {\exp_not:V \l__gradbars_csv_value_tl & % \exp_not:N \gradbarcsv[\exp_not:n {#1}]{#2}{##1}{\exp_not:n {#4}}\exp_not:N \\} % \fi} % \tl_put_right:Nn \l__gradbars_csv_table_tl {\hline\end{tabular}} % \ifgradbars@valid\tl_use:N \l__gradbars_csv_table_tl\fi % \fi % \group_end: % } %\ExplSyntaxOff % % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-distribution.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Distribution statistics and inline box plots. %\ProvidesPackage{gradbars-lib-distribution}[2026/10/25 v1.1.0 Distribution graphics] %\ExplSyntaxOn %\prop_new:N \l__gradbars_stats_prop %\seq_new:N \l__gradbars_samples_seq %\seq_new:N \l__gradbars_outliers_seq %\int_new:N \l__gradbars_sample_missing_int %\fp_new:N \l__gradbars_sample_sum_fp %\fp_new:N \l__gradbars_quantile_h_fp %\int_new:N \l__gradbars_quantile_j_int %\tl_new:N \l__gradbars_quantile_tl %\fp_new:N\l__gradbars_box_low_fp %\fp_new:N\l__gradbars_box_high_fp %\tl_new:N \l__gradbars_distribution_range_tl %\tl_set:Nn \l__gradbars_distribution_range_tl {auto} %\pgfkeys{/gradbars/box~range/.is~choice, % /gradbars/box~range/auto/.code={\tl_set:Nn\l__gradbars_distribution_range_tl{auto}}, % /gradbars/box~range/fixed/.code={\tl_set:Nn\l__gradbars_distribution_range_tl{fixed}}} %\cs_new:Npn \gradstat #1 {\prop_item:Nn\l__gradbars_stats_prop{#1}} %\cs_new_protected:Npn \__gradbars_quantile:nN #1#2 % {\fp_set:Nn\l__gradbars_quantile_h_fp{1+(\seq_count:N\l__gradbars_samples_seq-1)*(#1)} % \int_set:Nn\l__gradbars_quantile_j_int{\fp_eval:n{floor(\l__gradbars_quantile_h_fp)}} % \tl_set:Nx#2{\seq_item:Nn\l__gradbars_samples_seq{\l__gradbars_quantile_j_int}} % \int_compare:nNnT{\l__gradbars_quantile_j_int}<{\seq_count:N\l__gradbars_samples_seq} % {\tl_set:Nx#2{\fp_eval:n{#2+(\l__gradbars_quantile_h_fp-\l__gradbars_quantile_j_int)* % (\seq_item:Nn\l__gradbars_samples_seq{\l__gradbars_quantile_j_int+1}-#2)}}}} %\cs_new_protected:Npn \__gradbars_distribution_parse:n #1 % {\prop_clear:N\l__gradbars_stats_prop % \seq_clear:N\l__gradbars_samples_seq\seq_clear:N\l__gradbars_outliers_seq % \int_zero:N\l__gradbars_sample_missing_int\fp_zero:N\l__gradbars_sample_sum_fp % \tl_if_blank:nF{#1} % {\seq_set_split:Nnn\l_tmpa_seq{,}{#1} % \seq_map_inline:Nn\l_tmpa_seq % {\tl_set:Nn\l_tmpa_tl{##1}\tl_trim_spaces:N\l_tmpa_tl % \bool_lazy_or:nnTF{\tl_if_empty_p:N\l_tmpa_tl}{\str_if_eq_p:Vn\l_tmpa_tl{NA}} % {\int_incr:N\l__gradbars_sample_missing_int} % {\gradbarsCheckNumber{\l_tmpa_tl}{distribution~sample} % \ifgradbars@valid % \seq_put_right:Nx\l__gradbars_samples_seq{\fp_eval:n{\l_tmpa_tl}} % \fp_add:Nn\l__gradbars_sample_sum_fp{\l_tmpa_tl} % \fi}}} % \seq_sort:Nn\l__gradbars_samples_seq % {\fp_compare:nNnTF{##1}>{##2}{\sort_return_swapped:}{\sort_return_same:}} % \prop_put:Nnx\l__gradbars_stats_prop{n}{\seq_count:N\l__gradbars_samples_seq} % \prop_put:Nnx\l__gradbars_stats_prop{missing}{\int_use:N\l__gradbars_sample_missing_int} % \prop_put:Nnn\l__gradbars_stats_prop{method}{type-7;~1.5~IQR~observed~whiskers} % \seq_if_empty:NTF\l__gradbars_samples_seq % {\clist_map_inline:nn{min,max,q1,median,q3,iqr,low,high,mean} % {\prop_put:Nnn\l__gradbars_stats_prop{##1}{NA}}} % {\clist_map_inline:nn{q1/.25,median/.5,q3/.75} % {\seq_set_split:Nnn\l_tmpb_seq{/}{##1} % \__gradbars_quantile:nN{\seq_item:Nn\l_tmpb_seq{2}}\l__gradbars_quantile_tl % \prop_put:Nxx\l__gradbars_stats_prop{\seq_item:Nn\l_tmpb_seq{1}}{\l__gradbars_quantile_tl}} % \prop_put:Nnx\l__gradbars_stats_prop{min}{\seq_item:Nn\l__gradbars_samples_seq{1}} % \prop_put:Nnx\l__gradbars_stats_prop{max}{\seq_item:Nn\l__gradbars_samples_seq{-1}} % \prop_put:Nnx\l__gradbars_stats_prop{mean}{\fp_eval:n{\l__gradbars_sample_sum_fp/\gradstat{n}}} % \prop_put:Nnx\l__gradbars_stats_prop{iqr}{\fp_eval:n{\gradstat{q3}-\gradstat{q1}}} % \prop_put:Nnn\l__gradbars_stats_prop{low}{} % \seq_map_inline:Nn\l__gradbars_samples_seq % {\fp_compare:nTF{##1<\gradstat{q1}-1.5*\gradstat{iqr} || ##1>\gradstat{q3}+1.5*\gradstat{iqr}} % {\seq_put_right:Nn\l__gradbars_outliers_seq{##1}} % {\tl_if_empty:eT{\gradstat{low}}{\prop_put:Nnn\l__gradbars_stats_prop{low}{##1}} % \prop_put:Nnn\l__gradbars_stats_prop{high}{##1}}}} % \prop_put:Nnx\l__gradbars_stats_prop{outliers}{\seq_use:Nn\l__gradbars_outliers_seq{,}} % \prop_put:Nnx\l__gradbars_stats_prop{outlier~count}{\seq_count:N\l__gradbars_outliers_seq}} %\DeclareDocumentCommand\gradcomputesummary{m +m} % {\group_begin:\gradbars@validtrue\__gradbars_distribution_parse:n{#1} % \ifgradbars@valid#2\fi\group_end:} %\DeclareDocumentCommand\gradsummarytext{O{} m} % {\group_begin:\gradbarssetup{#1}\gradbars@validtrue\gradbarsValidateFormatter % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl{\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \str_if_eq:eeF{\gradbars@format}{value}{\gradbarsFail{Distribution~summaries~require~value~format=value}} % \ifgradbars@valid\gradcomputesummary{#2} % {n=\gradstat{n};~missing=\gradstat{missing};~ % \int_compare:nNnTF{\gradstat{n}}={0}{\gradbars@missingtext} % {Q1=\gradbarsFormatEndpoint{\gradstat{q1}};~ % median=\gradbarsFormatEndpoint{\gradstat{median}};~ % Q3=\gradbarsFormatEndpoint{\gradstat{q3}};~ % IQR=\gradbarsFormatEndpoint{\gradstat{iqr}};~ % whiskers=\gradbarsFormatEndpoint{\gradstat{low}}--\gradbarsFormatEndpoint{\gradstat{high}};~ % outliers=\gradstat{outlier~count}}}\fi\group_end:} %\keys_define:nn{gradbars/distribution/summary} % {n .code:n=\prop_put:Nnn\l__gradbars_stats_prop{n}{#1}, % missing .code:n=\prop_put:Nnn\l__gradbars_stats_prop{missing}{#1}, % q1 .code:n=\prop_put:Nnn\l__gradbars_stats_prop{q1}{#1}, % median .code:n=\prop_put:Nnn\l__gradbars_stats_prop{median}{#1}, % q3 .code:n=\prop_put:Nnn\l__gradbars_stats_prop{q3}{#1}, % low .code:n=\prop_put:Nnn\l__gradbars_stats_prop{low}{#1}, % high .code:n=\prop_put:Nnn\l__gradbars_stats_prop{high}{#1}, % min .code:n=\prop_put:Nnn\l__gradbars_stats_prop{min}{#1}, % max .code:n=\prop_put:Nnn\l__gradbars_stats_prop{max}{#1}, % mean .code:n=\prop_put:Nnn\l__gradbars_stats_prop{mean}{#1}, % outliers .code:n={\seq_set_from_clist:Nn\l__gradbars_outliers_seq{#1} % \prop_put:Nnn\l__gradbars_stats_prop{outliers}{#1} % \prop_put:Nnx\l__gradbars_stats_prop{outlier~count}{\seq_count:N\l__gradbars_outliers_seq}}} %\cs_new_protected:Npn\__gradbars_distribution_record:n #1 % {\prop_clear:N\l__gradbars_stats_prop\seq_clear:N\l__gradbars_outliers_seq % \prop_put:Nnn\l__gradbars_stats_prop{missing}{unknown} % \prop_put:Nnn\l__gradbars_stats_prop{outlier~count}{unknown} % \prop_put:Nnn\l__gradbars_stats_prop{outliers}{not~supplied} % \prop_put:Nnn\l__gradbars_stats_prop{method}{precomputed;~algorithm~not~verified} % \keys_set:nn{gradbars/distribution/summary}{#1} % \clist_map_inline:nn{n,q1,median,q3,low,high} % {\prop_if_in:NnF\l__gradbars_stats_prop{##1}{\gradbarsFail{Missing~summary~field:~##1}}} % \ifgradbars@valid % \tl_set:Nx\l_tmpa_tl{\gradstat{n}} % \regex_match:nVF{\A[1-9][0-9]*\Z}\l_tmpa_tl{\gradbarsFail{Summary~n~must~be~a~positive~integer}} % \clist_map_inline:nn{q1,median,q3,low,high,min,max,mean} % {\prop_if_in:NnT\l__gradbars_stats_prop{##1}{\gradbarsCheckNumber{\gradstat{##1}}{summary~##1}}} % \fi % \ifgradbars@valid % \fp_compare:nF{\gradstat{low}<=\gradstat{q1}<=\gradstat{median}<=\gradstat{q3}<=\gradstat{high}} % {\gradbarsFail{Summary~requires~low<=q1<=median<=q3<=high}} % \prop_put:Nnx\l__gradbars_stats_prop{iqr}{\fp_eval:n{\gradstat{q3}-\gradstat{q1}}} % \tl_set:Nx\l_tmpa_tl{\gradstat{missing}} % \str_if_eq:VnF\l_tmpa_tl{unknown} % {\regex_match:nVF{\A[0-9]+\Z}\l_tmpa_tl{\gradbarsFail{Summary~missing~must~be~a~nonnegative~integer}}} % \int_set:Nn\l_tmpa_int{1} % \fp_compare:nNnF{\gradstat{low}}={\gradstat{high}}{\int_set:Nn\l_tmpa_int{2}} % \int_compare:nNnT{\seq_count:N\l__gradbars_outliers_seq+\l_tmpa_int}>{\gradstat{n}} % {\gradbarsFail{Summary~n~cannot~contain~the~outliers~and~observed~whiskers}} % \prop_if_in:NnT\l__gradbars_stats_prop{min} % {\fp_compare:nNnT{\gradstat{min}}>{\gradstat{low}}{\gradbarsFail{Summary~minimum~exceeds~lower~whisker}}} % \prop_if_in:NnT\l__gradbars_stats_prop{max} % {\fp_compare:nNnT{\gradstat{max}}<{\gradstat{high}}{\gradbarsFail{Summary~maximum~below~upper~whisker}}} % \int_compare:nNnT{\gradstat{n}}={1} % {\fp_compare:nNnF{\gradstat{low}}={\gradstat{high}}{\gradbarsFail{Single~sample~summary~must~be~constant}}} % % \seq_map_inline:Nn\l__gradbars_outliers_seq % {\gradbarsCheckNumber{##1}{summary~outlier} % \ifgradbars@valid % \prop_if_in:NnT\l__gradbars_stats_prop{min} % {\fp_compare:nNnT{##1}<{\gradstat{min}}{\gradbarsFail{Summary~outlier~below~declared~minimum}}} % \prop_if_in:NnT\l__gradbars_stats_prop{max} % {\fp_compare:nNnT{##1}>{\gradstat{max}}{\gradbarsFail{Summary~outlier~above~declared~maximum}}} % \fi % \ifgradbars@valid\fp_compare:nF{##1<\gradstat{low} || ##1>\gradstat{high}} % {\gradbarsFail{Summary~outlier~must~lie~outside~whiskers}}\fi} % \clist_map_inline:nn{min,max} % {\prop_if_in:NnF\l__gradbars_stats_prop{##1} % {\prop_put:Nnx\l__gradbars_stats_prop{##1}{\str_if_eq:nnTF{##1}{min}{\gradstat{low}}{\gradstat{high}}}}} % \seq_map_inline:Nn\l__gradbars_outliers_seq % {\prop_put:Nnx\l__gradbars_stats_prop{min}{\fp_eval:n{min(##1,\gradstat{min})}} % \prop_put:Nnx\l__gradbars_stats_prop{max}{\fp_eval:n{max(##1,\gradstat{max})}}} % \prop_if_in:NnT\l__gradbars_stats_prop{mean} % {\fp_compare:nF{\gradstat{min}<=\gradstat{mean}<=\gradstat{max}} % {\gradbarsFail{Summary~mean~must~lie~within~extrema}}} % \fi} %\cs_new:Npn\__gradbars_box_x:n #1{\fp_eval:n{max(0,min(1,((#1)-\gradbars@min)/(\gradbars@max-\gradbars@min)))}} %\cs_new_protected:Npn\__gradbars_distribution_draw: % {\gradbarsResolveScaleGroup\gradbarsValidateFormatter % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl{\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \str_if_eq:eeF{\gradbars@format}{value}{\gradbarsFail{Box~plots~require~value~format=value}} % \int_compare:nNnT{\gradstat{n}}>{0} % {\tl_if_empty:oT{\gradbars@scalegroup} % {\str_if_eq:VnT\l__gradbars_distribution_range_tl{auto} % {\cs_set:Npx\gradbars@min{\gradstat{min}}\cs_set:Npx\gradbars@max{\gradstat{max}} % \fp_compare:nNnT{\gradbars@min}={\gradbars@max} % {\fp_set:Nn\l__gradbars_box_low_fp{\gradstat{min}} % \fp_set_eq:NN\l__gradbars_box_high_fp\l__gradbars_box_low_fp % \__gradbars_constant_range:NN\l__gradbars_box_low_fp\l__gradbars_box_high_fp % \cs_set:Npx\gradbars@min{\fp_use:N\l__gradbars_box_low_fp} % \cs_set:Npx\gradbars@max{\fp_use:N\l__gradbars_box_high_fp}}}}} % \gradbarsCheckNumber{\gradbars@min}{min}\gradbarsCheckNumber{\gradbars@max}{max} % \ifgradbars@valid % \fp_compare:nNnF{\gradbars@max}>{\gradbars@min}{\gradbarsFail{Max~must~be~greater~than~min}} % \dim_compare:nNnF{\gradbars@width}>{0pt}{\gradbarsFail{Width~must~be~positive}} % \dim_compare:nNnF{\gradbars@height}>{0pt}{\gradbarsFail{Height~must~be~positive}} % \fi % \ifgradbars@valid % \int_compare:nNnT{\gradstat{n}}>{0} % {\gradbarsRange{Box~minimum}{\gradstat{min}}\gradbarsRange{Box~maximum}{\gradstat{max}}} % \tl_set:Nx\l__gradbars_alt_tl{Box~plot:~n=\gradstat{n};~missing=\gradstat{missing};~ % Q1=\gradstat{q1};~median=\gradstat{median};~Q3=\gradstat{q3};~IQR=\gradstat{iqr};~ % whiskers=\gradstat{low}~to~\gradstat{high};~outlier~count=\gradstat{outlier~count};~ % outliers=\tl_if_empty:eTF{\gradstat{outliers}}{none}{\gradstat{outliers}}.~Method:~\gradstat{method}.~Scale:~\gradbars@min\c_space_tl to~\gradbars@max.} % \tl_if_empty:oF{\gradbars@unit}{\tl_put_right:Nx\l__gradbars_alt_tl{~Unit:~\exp_not:o{\gradbars@unit}.}} % \ifgradbars@print\def\gradbars@left{black}\fi % \str_if_eq:eeT{\gradbars@textcolor}{auto}{\def\gradbars@textcolor{black}} % \__gradbars_backend_draw:nn{boxplot} % {\gradbarsApplyAlt % \leavevmode\tikz[baseline=-.5ex,x=\gradbars@width,y=\gradbars@height] % {\path[use~as~bounding~box](0,0)rectangle(1,1); % \int_compare:nNnTF{\gradstat{n}}={0} % {\node[font=\gradbars@font]at(.5,.5){\gradbars@missingtext};} % {\draw[draw=\gradbars@left,line~width=.5pt] % (\__gradbars_box_x:n{\gradstat{low}},.5)--(\__gradbars_box_x:n{\gradstat{high}},.5); % \draw[draw=\gradbars@left,fill=\gradbars@left!15,line~width=.5pt] % (\__gradbars_box_x:n{\gradstat{q1}},.2)rectangle(\__gradbars_box_x:n{\gradstat{q3}},.8); % \draw[draw=\gradbars@textcolor,line~width=.8pt] % (\__gradbars_box_x:n{\gradstat{median}},.2)--(\__gradbars_box_x:n{\gradstat{median}},.8); % \clist_map_inline:nn{low,high} % {\draw[draw=\gradbars@left,line~width=.5pt] % (\__gradbars_box_x:n{\gradstat{##1}},.3)--(\__gradbars_box_x:n{\gradstat{##1}},.7);} % \seq_map_inline:Nn\l__gradbars_outliers_seq % {\draw[draw=\gradbars@left,fill=white](\__gradbars_box_x:n{##1},.5)circle[radius=1.2pt];} % \str_if_eq:eeF{\gradbars@label}{none} % {\node[anchor=west,font=\gradbars@font,inner~sep=0pt] % at([xshift=\gradbars@gap]1,.5){\gradbarsFormatEndpoint{\gradstat{median}}};}}} % } % \fi} %\DeclareDocumentCommand\gradboxplot{O{} m} % {\group_begin:\gradbars@validtrue\gradbarsCaptureTikzAlt\gradbars@capturealttrue % \gradbarssetup{height=3ex,label=none,#1}\gradbars@capturealtfalse % \__gradbars_distribution_parse:n{#2}\ifgradbars@valid\__gradbars_distribution_draw:\fi\group_end:} %\DeclareDocumentCommand\gradboxsummary{O{} m} % {\group_begin:\gradbars@validtrue\gradbarsCaptureTikzAlt\gradbars@capturealttrue % \gradbarssetup{height=3ex,label=none,#1}\gradbars@capturealtfalse % \__gradbars_distribution_record:n{#2}\ifgradbars@valid\__gradbars_distribution_draw:\fi\group_end:} %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-heat.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-lib-heat}[2026/10/25 v1.1.0 gradbars lib-heat] %\ExplSyntaxOff %\def\gradbars@heatlow{gradbarsBlueLight!15} %\def\gradbars@heathigh{gradbarsBlue} %\def\gradbars@heattext{auto} %\def\gradbars@heatmissing{gradbarsTrack} %% Named palettes select both interpolation mode and color roles. %\definecolor{gradbarsHeatRed}{HTML}{B91C1C} %\definecolor{gradbarsHeatBrown}{HTML}{92400E} %\pgfkeys{/gradbars, % heat palette/blue/.style={heat palette=sequential,heat low color=white,heat center color=white,heat high color=gradbarsBlue,heat text color=auto}, % heat palette/teal/.style={heat palette=sequential,heat low color=white,heat center color=white,heat high color=gradbarsTeal,heat text color=auto}, % heat palette/purple/.style={heat palette=sequential,heat low color=white,heat center color=white,heat high color=gradbarsPurple,heat text color=auto}, % heat palette/orange/.style={heat palette=sequential,heat low color=white,heat center color=white,heat high color=gradbarsWarmOrange,heat text color=auto}, % heat palette/purple-teal/.style={heat palette=diverging,heat low color=gradbarsPurple,heat center color=white,heat high color=gradbarsTeal,heat text color=auto}, % heat palette/blue-red/.style={heat palette=diverging,heat low color=gradbarsBlue,heat center color=white,heat high color=gradbarsHeatRed,heat text color=auto}, % heat palette/orange-blue/.style={heat palette=diverging,heat low color=gradbarsWarmOrange,heat center color=white,heat high color=gradbarsBlue,heat text color=auto}, % heat palette/brown-teal/.style={heat palette=diverging,heat low color=gradbarsHeatBrown,heat center color=white,heat high color=gradbarsTeal,heat text color=auto}, % heat low color/.store in=\gradbars@heatlow, % heat high color/.store in=\gradbars@heathigh, % heat text color/.store in=\gradbars@heattext, % heat missing color/.store in=\gradbars@heatmissing, % print/.append style={heat low color=white,heat high color=black!75}} %\ExplSyntaxOn %\DeclareDocumentCommand\gradheat{O{} m} % {\gradbarsHeatCell{height=3ex,#1}{#2}} %\cs_new_protected:Npn\gradbarsHeatCell #1#2 % {\leavevmode\group_begin: % \gradbarsCaptureTikzAlt\gradbars@capturealttrue % \pgfkeys{/gradbars,#1}\gradbars@capturealtfalse % \gradbars@stackfalse\gradbars@sparkfalse\gradbars@comparefalse\gradbars@rangemodefalse % \ifpgfpicture % \pgfinterruptpicture\font@name % \edef\gradbars@resolved{\noexpand\endpgfinterruptpicture % \def\noexpand\gradbars@width{\the\dimexpr\gradbars@width\relax} % \def\noexpand\gradbars@height{\the\dimexpr\gradbars@height\relax} % \def\noexpand\gradbars@rounded{\the\dimexpr\gradbars@rounded\relax}} % \gradbars@resolved % \fi % \gradbars@validtrue\gradbars@missingfalse % \gradbarsValidateFormatter % \gradbarsResolveScaleGroup % \tl_set:Nx\l_tmpa_tl{#2}\tl_trim_spaces:N\l_tmpa_tl % \tl_if_empty:NT\l_tmpa_tl{\gradbars@missingtrue} % \str_if_eq:VnT\l_tmpa_tl{NA}{\gradbars@missingtrue} % \def\gradbars@value{#2} % \gradbarsCheckNumber{\gradbars@min}{min}\gradbarsCheckNumber{\gradbars@max}{max} % \ifgradbars@missing\else\gradbarsCheckNumber{#2}{heat~value}\fi % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl % {\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \ifgradbars@valid % \fp_compare:nNnF{\gradbars@max}>{\gradbars@min}{\gradbarsFail{Max~must~be~greater~than~min}} % \str_if_eq:eeT{\gradbars@format}{percent} % {\fp_compare:nNnF{\gradbars@min}={0}{\gradbarsFail{Percent~format~requires~min=0}} % \fp_compare:nNnF{\gradbars@max}>{0}{\gradbarsFail{Percent~format~requires~positive~max}} % \gradbarsValidatePercentBase} % \dim_compare:nNnF{\gradbars@width}>{0pt}{\gradbarsFail{Width~must~be~positive}} % \dim_compare:nNnF{\gradbars@height}>{0pt}{\gradbarsFail{Height~must~be~positive}} % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\gradbarsCheckNumber{\gradbars@heatcenter}{heat~center} % \ifgradbars@valid\fp_compare:nF{\gradbars@min<=\gradbars@heatcenter<=\gradbars@max} % {\gradbarsFail{Heat~center~must~lie~within~range}}\fi} % \fi % \ifgradbars@valid % \ifgradbars@missing % \colorlet{gradbarsHeatCell}{\gradbars@heatmissing} % \else % \gradbarsRange{Heat~value}{#2} % \cs_set:Npx\gradbars@number{\fp_eval:n{\str_if_eq:eeTF{\gradbars@format}{percent}{100*(#2)/\gradbarsPercentBase}{#2}}} % \gradbarsHeatColor{#2} % \fi % \str_if_eq:eeTF{\gradbars@heattext}{auto} % {\gradbarsContrast{gradbarsHeatCell}}{\let\gradbars@labelcolor\gradbars@heattext} % \tl_set:Nn\l__gradbars_alt_tl{Heat~cell:~} % \ifgradbars@missing\tl_put_right:Nn\l__gradbars_alt_tl{missing.} % \else\tl_put_right:Nx\l__gradbars_alt_tl % {\fp_eval:n{#2}~\gradbars@unit.~Color~scale:~\gradbars@min\c_space_tl to~\gradbars@max.}\fi % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\tl_put_right:Nx\l__gradbars_alt_tl{~Diverging~center:~\gradbars@heatcenter.}} % \str_if_eq:eeT{\gradbars@format}{percent}{\tl_put_right:Nx\l__gradbars_alt_tl{~Percent~base:~\gradbarsPercentBase.}} % \tl_put_right:Nx\l__gradbars_alt_tl{~Direction:~\gradbars@better.} % \ifgradbars@valid % \__gradbars_backend_draw:nn{heat} % {\ifpgfpicture\begin{scope}\gradbarsHeatDraw\end{scope} % \else\gradbarsApplyAlt\tikz[baseline=(gradbarsheat.base)]{\gradbarsHeatDraw}\fi} % \fi % \fi\group_end:} %\cs_new_protected:Npn\gradbarsHeatDraw % {\node[fill=gradbarsHeatCell,text=\gradbars@labelcolor,inner~sep=2pt, % minimum~width=\gradbars@width,minimum~height=\gradbars@height, % font=\gradbars@font,rounded~corners=\gradbars@rounded](gradbarsheat) % {\str_if_eq:eeF{\gradbars@label}{none}{\gradbars@labelcontent}};} %\ExplSyntaxOff % %\ExplSyntaxOff %\ExplSyntaxOn %\fp_new:N\l__gradbars_heat_value_fp %\cs_new_protected:Npn\gradbarsHeatColor #1 % {\colorlet{gradbarsHeatLow}{\gradbars@heatlow} % \colorlet{gradbarsHeatHigh}{\gradbars@heathigh} % \colorlet{gradbarsHeatCenter}{\gradbars@heatcentercolor} % \ifgradbars@print % \colorlet{gradbarsHeatLow}{white}\colorlet{gradbarsHeatHigh}{black!75} % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\colorlet{gradbarsHeatLow}{black!75}\colorlet{gradbarsHeatCenter}{white}} % \fi % \str_if_eq:eeTF{\gradbars@heatpalette}{diverging} % {\str_if_eq:eeT{\gradbars@better}{lower} % {\colorlet{gradbarsHeatSwap}{gradbarsHeatLow} % \colorlet{gradbarsHeatLow}{gradbarsHeatHigh}\colorlet{gradbarsHeatHigh}{gradbarsHeatSwap}} % \fp_set:Nn\l__gradbars_heat_value_fp{max(\gradbars@min,min(\gradbars@max,#1))} % \fp_compare:nNnTF{\l__gradbars_heat_value_fp}={\gradbars@heatcenter} % {\colorlet{gradbarsHeatCell}{gradbarsHeatCenter}} % {\fp_compare:nNnTF{\l__gradbars_heat_value_fp}<{\gradbars@heatcenter} % {\colorlet{gradbarsHeatCell}{gradbarsHeatLow!\fp_eval:n{ % 100*(\gradbars@heatcenter-\l__gradbars_heat_value_fp)/(\gradbars@heatcenter-\gradbars@min)}!gradbarsHeatCenter}} % {\colorlet{gradbarsHeatCell}{gradbarsHeatHigh!\fp_eval:n{ % 100*(\l__gradbars_heat_value_fp-\gradbars@heatcenter)/(\gradbars@max-\gradbars@heatcenter)}!gradbarsHeatCenter}}}} % {\colorlet{gradbarsHeatCell}{gradbarsHeatHigh!\fp_eval:n{ % 100*\str_if_eq:eeTF{\gradbars@better}{lower}{(1-\gradbarsPosition{#1})}{\gradbarsPosition{#1}}}!gradbarsHeatLow}}} % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-legend.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Continuous and shared semantic legends. %\ProvidesPackage{gradbars-lib-legend}[2026/10/25 v1.1.0 Shared legends] %\ExplSyntaxOn %\cs_generate_variant:Nn\seq_set_from_clist:Nn{NV} %\cs_generate_variant:Nn\prop_to_keyval:N{c} %\tl_new:N\l__gradbars_legend_title_tl %\tl_new:N\l__gradbars_legend_ticks_tl %\tl_new:N\l__gradbars_legend_names_tl %\tl_new:N\l__gradbars_legend_orientation_tl %\tl_new:N\l__gradbars_legend_missing_tl %\tl_new:N\l__gradbars_legend_kind_tl %\tl_new:N\l__gradbars_legend_group_tl %\tl_new:N\l__gradbars_legend_snapshot_tl %\tl_new:N\l__gradbars_legend_signature_tl %\prop_new:N\l__gradbars_legends_prop %\prop_new:N\l__gradbars_legend_signatures_prop %\int_new:N\g__gradbars_legend_scale_int %\tl_new:N\l__gradbars_legend_scale_name_tl %\cs_new_protected:Npn\__gradbars_legend_scale_name: % {\int_gincr:N\g__gradbars_legend_scale_int % \tl_set:Nx\l__gradbars_legend_scale_name_tl{gradbars-internal-legend-\int_use:N\g__gradbars_legend_scale_int} % \prop_if_in:NVTF\l__gradbars_scale_groups_prop\l__gradbars_legend_scale_name_tl % {\__gradbars_legend_scale_name:}{}} % %\seq_new:N\l__gradbars_legend_ticks_seq %\fp_new:N\l__gradbars_legend_previous_fp %\fp_new:N\l__gradbars_legend_value_fp %\seq_new:N\l__gradbars_legend_tick_rows_seq %\box_new:N\l__gradbars_legend_tick_box %\dim_new:N\l__gradbars_legend_tick_left_dim %\dim_new:N\l__gradbars_legend_tick_right_dim %\dim_new:N\l__gradbars_legend_lane_a_dim %\dim_new:N\l__gradbars_legend_lane_b_dim %\cs_new_protected:Npn\__gradbars_legend_tick_layout: % {\seq_clear:N\l__gradbars_legend_tick_rows_seq % \dim_set:Nn\l__gradbars_legend_lane_a_dim{-10000pt} % \dim_set:Nn\l__gradbars_legend_lane_b_dim{-10000pt} % \seq_map_inline:Nn\l__gradbars_legend_ticks_seq % {\gradbarsSuspendMeasurementTagging % \hbox_set:Nn\l__gradbars_legend_tick_box{\gradbars@font\gradbarsFormatEndpoint{##1}} % \gradbarsResumeMeasurementTagging % \dim_set:Nn\l__gradbars_legend_tick_left_dim % {\fp_to_dim:n{\gradbarsPosition{##1}*\dim_to_fp:n{\gradbars@width}}-\box_wd:N\l__gradbars_legend_tick_box/2} % \dim_set:Nn\l__gradbars_legend_tick_right_dim % {\l__gradbars_legend_tick_left_dim+\box_wd:N\l__gradbars_legend_tick_box+2pt} % \dim_compare:nNnTF{\l__gradbars_legend_tick_left_dim}>{\l__gradbars_legend_lane_a_dim} % {\seq_put_right:Nn\l__gradbars_legend_tick_rows_seq{0} % \dim_set_eq:NN\l__gradbars_legend_lane_a_dim\l__gradbars_legend_tick_right_dim} % {\dim_compare:nNnTF{\l__gradbars_legend_tick_left_dim}>{\l__gradbars_legend_lane_b_dim} % {\seq_put_right:Nn\l__gradbars_legend_tick_rows_seq{1} % \dim_set_eq:NN\l__gradbars_legend_lane_b_dim\l__gradbars_legend_tick_right_dim} % {\gradbarsFail{Legend~tick~labels~overlap;~increase~width~or~reduce~ticks}}}}} %\tl_set:Nn\l__gradbars_legend_orientation_tl{horizontal} %\tl_set:Nn\l__gradbars_legend_missing_tl{true} %\tl_set:Nn\l__gradbars_legend_kind_tl{heat} %\pgfkeys{/gradbars, % legend~title/.store~in=\l__gradbars_legend_title_tl, % legend~ticks/.store~in=\l__gradbars_legend_ticks_tl, % legend~names/.store~in=\l__gradbars_legend_names_tl, % legend~orientation/.is~choice, % legend~orientation/horizontal/.code={\tl_set:Nn\l__gradbars_legend_orientation_tl{horizontal}}, % legend~orientation/vertical/.code={\tl_set:Nn\l__gradbars_legend_orientation_tl{vertical}}, % legend~missing/.is~choice, % legend~missing/true/.code={\tl_set:Nn\l__gradbars_legend_missing_tl{true}}, % legend~missing/false/.code={\tl_set:Nn\l__gradbars_legend_missing_tl{false}}, % legend~missing/.default=true, % legend~kind/.is~choice, % legend~kind/heat/.code={\tl_set:Nn\l__gradbars_legend_kind_tl{heat}}, % legend~kind/categorical/.code={\tl_set:Nn\l__gradbars_legend_kind_tl{categorical}}, % legend~kind/reference/.code={\tl_set:Nn\l__gradbars_legend_kind_tl{reference}}, % legend~group/.code={\__gradbars_legend_apply:n{#1}}} %\cs_new_protected:Npn\__gradbars_legend_signature: % {\tl_set:Nx\l__gradbars_legend_signature_tl % {\gradbars@min/\gradbars@max/\gradbars@heatlow/\gradbars@heathigh/ % \gradbars@heatpalette/\gradbars@heatcenter/\gradbars@heatcentercolor/\gradbars@better/ % \exp_not:o{\gradbars@unit}/\exp_not:o{\gradbars@unitcode}/\exp_not:o{\gradbars@unittext}/\gradbars@left/\gradbars@right/\gradbars@negativecolor/ % \gradbars@comparecolor/\gradbars@stackcolors/\gradbars@stackpatterns/ % \ifgradbars@print true\else false\fi} % \clist_map_inline:nn{heatmissing,targetcolor,bandcolor,bandopacity,errorcolor,thresholdcolors,target,band,references,errorminus,errorplus,thresholds,bulletbands,format,percentbase,sparkhigh,sparklow,sparkwincolor,sparklosscolor,sparkzerocolor} % {\tl_put_right:Nx\l__gradbars_legend_signature_tl{##1={\exp_not:v{gradbars@##1}}}}} %\cs_new_protected:Npn\__gradbars_legend_check: % {\tl_if_empty:NF\l__gradbars_legend_group_tl % {\__gradbars_legend_signature: % \str_if_eq:eeF{\l__gradbars_legend_signature_tl} % {\prop_item:NV\l__gradbars_legend_signatures_prop\l__gradbars_legend_group_tl} % {\gradbarsFail{Conflicting~scale,~unit~or~palette~for~shared~legend}}}} %\cs_new_eq:NN\__gradbars_resolve_before_legend:\gradbarsResolveScaleGroup %\cs_set_protected:Npn\gradbarsResolveScaleGroup % {\__gradbars_legend_check:\__gradbars_resolve_before_legend:\__gradbars_legend_check: % \tl_if_empty:NF\l__gradbars_legend_group_tl % {\ifgradbars@spark % \str_if_eq:eeT{\gradbars@sparktype}{winloss} % {\fp_compare:nF{\gradbars@min=-1 && \gradbars@max=1} % {\gradbarsFail{Shared~win-loss~legend~requires~min=-1,max=1}}} % \fi}} %\cs_new_protected:Npn\__gradbars_legend_validate: % {\gradbarsResolveScaleGroup\gradbarsValidateFormatter % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl{\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \gradbarsCheckNumber{\gradbars@min}{min}\gradbarsCheckNumber{\gradbars@max}{max} % \ifgradbars@valid % \str_if_eq:eeT{\gradbars@format}{percent} % {\fp_compare:nNnF{\gradbars@min}={0}{\gradbarsFail{Percent~legend~requires~min=0}} % \gradbarsValidatePercentBase} % \fp_compare:nNnF{\gradbars@max}>{\gradbars@min}{\gradbarsFail{Max~must~be~greater~than~min}} % \dim_compare:nNnF{\gradbars@width}>{0pt}{\gradbarsFail{Width~must~be~positive}} % \dim_compare:nNnF{\gradbars@height}>{0pt}{\gradbarsFail{Height~must~be~positive}} % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\gradbarsCheckNumber{\gradbars@heatcenter}{heat~center} % \ifgradbars@valid\fp_compare:nF{\gradbars@min<=\gradbars@heatcenter<=\gradbars@max} % {\gradbarsFail{Heat~center~must~lie~within~range}}\fi} % \fi} %\DeclareDocumentCommand\gradlegenddefine{m m} % {\prop_if_in:NnTF\l__gradbars_legends_prop{#1} % {\__gradbars_public_error:n{Legend~already~defined:~#1}} % {\__gradbars_name_valid:nTF{#1} % {\group_begin:\gradbars@validtrue % \tl_if_empty:NF\l__gradbars_legend_group_tl{\def\gradbars@scalegroup{}} % \tl_clear:N\l__gradbars_legend_group_tl % \gradbarssetup{#2}\__gradbars_legend_validate: % \__gradbars_legend_scale_name: % \tl_clear:N\l__gradbars_legend_snapshot_tl % \clist_map_inline:nn{min,max,heatlow,heathigh,heatpalette,heatcenter,heatcentercolor, % better,unit,unitcode,unittext,left,right,negativecolor,comparecolor,stackcolors,stackpatterns, % targetcolor,bandcolor,bandopacity,errorcolor,heatmissing,thresholdcolors, % target,band,references,errorminus,errorplus,thresholds,bulletbands,formatter,numberformat,format,percentbase, % sparkhigh,sparklow,sparkwincolor,sparklosscolor,sparkzerocolor} % {\tl_put_right:Nx\l__gradbars_legend_snapshot_tl % {\exp_not:N\def\exp_not:c{gradbars@##1}{\exp_not:v{gradbars@##1}}}} % \tl_put_right:Nx\l__gradbars_legend_snapshot_tl % {\ifgradbars@print\exp_not:N\gradbars@printtrue\else\exp_not:N\gradbars@printfalse\fi} % \clist_map_inline:nn{kind,names,title,ticks,orientation,missing} % {\tl_put_right:Nx\l__gradbars_legend_snapshot_tl % {\exp_not:N\tl_set:Nn\exp_not:c{l__gradbars_legend_##1_tl} % {\exp_not:v{l__gradbars_legend_##1_tl}}}} % \clist_map_inline:nn{colors,patterns} % {\tl_put_right:Nx\l__gradbars_legend_snapshot_tl % {\exp_not:N\prop_set_from_keyval:Nn\exp_not:c{l__gradbars_category_##1_prop} % {\exp_not:e{\prop_to_keyval:c{l__gradbars_category_##1_prop}}}}} % \__gradbars_legend_signature: % \ifgradbars@valid % \use:x{\group_end: % \prop_put:Nnn\exp_not:N\l__gradbars_scale_groups_prop{\l__gradbars_legend_scale_name_tl} % {min=\gradbars@min,max=\gradbars@max} % \prop_put:Nnn\exp_not:N\l__gradbars_legends_prop{#1} % {\exp_not:N\def\exp_not:N\gradbars@scalegroup{\l__gradbars_legend_scale_name_tl} % \exp_not:V\l__gradbars_legend_snapshot_tl} % \prop_put:Nnn\exp_not:N\l__gradbars_legend_signatures_prop{#1} % {\exp_not:V\l__gradbars_legend_signature_tl}} % \else\group_end:\fi} % {\__gradbars_public_error:n{Invalid~legend~name:~#1}}}} %% Snapshots are executable assignments, not key lists. %\cs_new_protected:Npn\__gradbars_legend_apply:n #1 % {\tl_if_blank:nTF{#1} % {\tl_clear:N\l__gradbars_legend_group_tl\def\gradbars@scalegroup{}} % {\prop_get:NnNTF\l__gradbars_legends_prop{#1}\l__gradbars_legend_snapshot_tl % {\tl_use:N\l__gradbars_legend_snapshot_tl\tl_set:Nn\l__gradbars_legend_group_tl{#1}} % {\gradbarsFail{Unknown~legend~group:~#1}}}} %\keys_define:nn{gradbars/legend/layout} % {width .code:n=\gradbarssetup{width=#1},height .code:n=\gradbarssetup{height=#1}, % legend~missing .code:n=\gradbarssetup{legend~missing=#1}, % legend~missing .default:n=true, % title .tl_set:N=\l__gradbars_legend_title_tl, % ticks .tl_set:N=\l__gradbars_legend_ticks_tl, % orientation .choices:nn={horizontal,vertical} % {\tl_set_eq:NN\l__gradbars_legend_orientation_tl\l_keys_choice_tl}, % precision .code:n=\gradbarssetup{precision=#1}, % number~format .code:n=\gradbarssetup{number~format=#1}, % font .code:n=\gradbarssetup{font={#1}}, % accessibility .code:n=\gradbarssetup{accessibility=#1},alt .code:n=\gradbarssetup{alt={#1}}} %\DeclareDocumentCommand\gradlegenduse{O{} m} % {\group_begin:\gradbars@validtrue\gradbarssetup{width=50mm,height=3mm} % \__gradbars_legend_apply:n{#2}\keys_set:nn{gradbars/legend/layout}{#1} % \ifgradbars@valid % \str_case:Vn\l__gradbars_legend_kind_tl % {{heat}{\gradheatlegend} % {categorical}{\exp_args:NV\gradbarslegend\l__gradbars_legend_names_tl} % {reference}{\exp_args:NV\gradreferencelegend\l__gradbars_legend_names_tl}} % \fi\group_end:} %\DeclareDocumentCommand\gradheatlegend{O{}} % {\group_begin:\gradbars@validtrue\gradbarssetup{#1}\__gradbars_legend_validate: % \ifgradbars@valid % \tl_if_empty:NTF\l__gradbars_legend_ticks_tl % {\seq_clear:N\l__gradbars_legend_ticks_seq % \seq_put_right:Nx\l__gradbars_legend_ticks_seq{\gradbars@min} % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\fp_compare:nT{\gradbars@min<\gradbars@heatcenter<\gradbars@max} % {\seq_put_right:Nx\l__gradbars_legend_ticks_seq{\gradbars@heatcenter}}} % \seq_put_right:Nx\l__gradbars_legend_ticks_seq{\gradbars@max}} % {\seq_set_from_clist:NV\l__gradbars_legend_ticks_seq\l__gradbars_legend_ticks_tl} % \fp_set:Nn\l__gradbars_legend_previous_fp{-inf} % \seq_map_inline:Nn\l__gradbars_legend_ticks_seq % {\gradbarsCheckNumber{##1}{legend~tick} % \ifgradbars@valid\fp_compare:nF{\l__gradbars_legend_previous_fp<##1 && \gradbars@min<=##1<=\gradbars@max} % {\gradbarsFail{Legend~ticks~must~increase~within~range}}\fp_set:Nn\l__gradbars_legend_previous_fp{##1}\fi} % \str_if_eq:VnT\l__gradbars_legend_orientation_tl{horizontal}{\ifgradbars@valid\__gradbars_legend_tick_layout:\fi} % \tl_set:Nx\l__gradbars_alt_tl{Continuous~\gradbars@heatpalette\c_space_tl color~legend.~ % Scale:~\gradbars@min\c_space_tl to~\gradbars@max.~Direction:~\gradbars@better.} % \str_if_eq:VnT\l__gradbars_legend_missing_tl{true} % {\tl_put_right:Nx\l__gradbars_alt_tl{~Missing:~\gradbars@missingtext.}} % \tl_if_empty:oF{\gradbars@unit}{\tl_put_right:Nx\l__gradbars_alt_tl{~Unit:~\exp_not:o{\gradbars@unit}.}} % \str_if_eq:eeT{\gradbars@format}{percent}{\tl_put_right:Nx\l__gradbars_alt_tl{~Percent~base:~\gradbarsPercentBase.}} % \str_if_eq:eeT{\gradbars@heatpalette}{diverging} % {\tl_put_right:Nx\l__gradbars_alt_tl{~Neutral~center:~\gradbars@heatcenter.}} % \tl_if_empty:NF\l__gradbars_legend_title_tl % {\tl_put_left:Nx\l__gradbars_alt_tl{\exp_not:V\l__gradbars_legend_title_tl.~}} % \ifgradbars@valid\__gradbars_backend_draw:nn{heat-legend}{\gradbarsApplyAlt % \leavevmode\tikz[baseline=0pt] % {\str_if_eq:VnTF\l__gradbars_legend_orientation_tl{horizontal} % {\begin{scope}[x=\gradbars@width,y=\gradbars@height] % \int_step_inline:nn{256} % {\gradbarsHeatColor{\fp_eval:n{\gradbars@min+(##1-.5)/256*(\gradbars@max-\gradbars@min)}} % \path[fill=gradbarsHeatCell,draw=none](\fp_eval:n{(##1-1)/256},0)rectangle(\fp_eval:n{##1/256},1);} % \draw[draw=black!65,line~width=.3pt](0,0)rectangle(1,1); % \seq_map_indexed_inline:Nn\l__gradbars_legend_ticks_seq % {\draw(\gradbarsPosition{##2},0)--++(0,-.25); % \node[anchor=north,font=\gradbars@font,inner~sep=2pt, % yshift={-\int_eval:n{5*\seq_item:Nn\l__gradbars_legend_tick_rows_seq{##1}}mm}] % at(\gradbarsPosition{##2},-.25){\gradbarsFormatEndpoint{##2}};} % \node[anchor=south,font=\gradbars@font,text~width=\gradbars@width,align=center]at(.5,1){\l__gradbars_legend_title_tl}; % \end{scope}} % {\begin{scope}[x=\gradbars@height,y=\gradbars@width] % \int_step_inline:nn{256} % {\gradbarsHeatColor{\fp_eval:n{\gradbars@min+(##1-.5)/256*(\gradbars@max-\gradbars@min)}} % \path[fill=gradbarsHeatCell,draw=none](0,\fp_eval:n{(##1-1)/256})rectangle(1,\fp_eval:n{##1/256});} % \draw[draw=black!65,line~width=.3pt](0,0)rectangle(1,1); % \seq_map_inline:Nn\l__gradbars_legend_ticks_seq % {\node[anchor=west,font=\gradbars@font]at(1,\gradbarsPosition{##1}){\gradbarsFormatEndpoint{##1}};} % \node[anchor=south,font=\gradbars@font,text~width=\gradbars@width,align=center]at(.5,1){\l__gradbars_legend_title_tl};\end{scope}} % \str_if_eq:VnT\l__gradbars_legend_missing_tl{true} % {\path[fill=\gradbars@heatmissing,draw=black!50](0,-16mm)rectangle(4mm,-13mm); % \node[anchor=west,font=\gradbars@font]at(5mm,-14.5mm){\gradbars@missingtext :~missing};}} % }\fi % \fi\group_end:} %\DeclareDocumentCommand\gradreferencelegend{O{} m} % {\group_begin:\gradbarssetup{#1}\gradbars@validtrue % \tl_set:Nn\l__gradbars_alt_tl{Reference~symbols:~#2.} % \__gradbars_backend_draw:nn{reference-legend}{\gradbarsApplyAlt\leavevmode\tikz[baseline=0pt] % {\int_zero:N\l_tmpa_int % \clist_map_inline:nn{#2} % {\seq_set_split:Nnn\l_tmpa_seq{/}{##1} % \int_compare:nNnTF{\seq_count:N\l_tmpa_seq}={2} % {\begin{scope}[yshift=-\int_eval:n{\l_tmpa_int}*5mm] % \str_case_e:nnF{\seq_item:Nn\l_tmpa_seq{1}} % {{target}{\draw[draw=\gradbars@targetcolor,line~width=1pt](3mm,-1.5mm)--(3mm,1.5mm);} % {reference}{\draw[dashed,draw=\gradbars@targetcolor](3mm,-1.5mm)--(3mm,1.5mm);} % {band}{\fill[\gradbars@bandcolor,opacity=\gradbars@bandopacity](0,-1.5mm)rectangle(6mm,1.5mm);} % {error}{\draw[draw=\gradbars@errorcolor](0,0)--(6mm,0)(0,-1mm)--(0,1mm)(6mm,-1mm)--(6mm,1mm);} % {box}{\draw(0,0)--(6mm,0)(1.5mm,-1mm)rectangle(4.5mm,1mm)(3mm,-1mm)--(3mm,1mm);}} % {\gradbarsFail{Unknown~reference~legend~symbol}} % \node[anchor=west,font=\gradbars@font]at(8mm,0){\seq_item:Nn\l_tmpa_seq{2}};\end{scope} % \int_incr:N\l_tmpa_int} % {\gradbarsFail{Reference~legend~requires~type/description}}}} % }\group_end:} %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-reports.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Opt-in domain recipes, not statistical inference. %\ProvidesPackage{gradbars-lib-reports}[2026/10/25 v1.1.0 Domain report presets] %\gradbarsstyle{report-correlation}{min=-1,max=1,heat palette=purple-teal, % heat center=0,precision=2,width=14mm,height=3ex,overflow=error,value format=value} %\gradbarsstyle{report-ablation}{min=0,max=100,width=40mm,height=3ex, % compare label=delta,precision=2,compare color=gradbarsCudOrange,color=gradbarsCudBlue} %\gradbarsstyle{report-metric}{min=0,max=100,width=35mm,height=3ex, % precision=2,theme=accessible,label=inside,label align=cell} %\gradtablestyle{correlation}{style=matrix,rules=booktabs,graphic width=14mm, % min graphic width=8mm,column sep=4pt,row padding=2pt,theme=none} %\gradtablestyle{ablation}{style=academic,graphic width=40mm, % row stretch=1.4,row padding=2pt,theme=teal} %\gradtablestyle{metrics}{style=research,graphic width=35mm, % row stretch=1.4,row padding=2pt,theme=accessible} %\DeclareDocumentCommand\gradcorrelation{O{} m} % {\gradheat[style=report-correlation,#1,min=-1,max=1,scale group={},overflow=error]{#2}} %\DeclareDocumentCommand\gradablation{O{} m m} % {\graddumbbell[style=report-ablation,#1]{#2}{#3}} %\DeclareDocumentCommand\gradmetric{O{} m} % {\gradbar[style=report-metric,#1]{#2}} %\DeclareDocumentCommand\gradcorrelationcolumn{O{} m m} % {\gradcolumn[type=heat,scale=fixed, % options={style=report-correlation},#1]{#2}{#3}} %\DeclareDocumentCommand\gradablationcolumn{O{} m m} % {\gradcolumn[type=dumbbell, % options={style=report-ablation},#1]{#2}{#3}} %\DeclareDocumentCommand\gradmetriccolumn{O{} m m} % {\gradcolumn[type=bar,scale=column,include zero=true,mark=both, % options={style=report-metric},#1]{#2}{#3}} %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-spark.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-lib-spark}[2026/10/25 v1.1.0 gradbars lib-spark] %\ExplSyntaxOn %\seq_new:N \l__gradbars_series_seq %\seq_new:N \l__gradbars_series_clean_seq %\fp_new:N \l__gradbars_series_min_fp %\fp_new:N \l__gradbars_series_max_fp %\fp_new:N \l__gradbars_series_low_fp %\fp_new:N \l__gradbars_series_high_fp %\bool_new:N \l__gradbars_series_any_bool %\bool_new:N \l__gradbars_series_prev_bool %\bool_new:N \l__gradbars_series_mark_bool %\int_new:N \l__gradbars_series_index_int %\cs_new_protected:Npn \gradbarsParseSpark #1 % { % \fp_zero:N \l__gradbars_series_min_fp % \fp_zero:N \l__gradbars_series_max_fp % \seq_set_split:Nnn \l__gradbars_series_seq {,}{#1} % \seq_clear:N \l__gradbars_series_clean_seq % \bool_set_false:N \l__gradbars_series_any_bool % \seq_map_inline:Nn \l__gradbars_series_seq % {\tl_set:Nx \l_tmpa_tl {##1}\tl_trim_spaces:N \l_tmpa_tl % \tl_if_empty:NT \l_tmpa_tl {\tl_set:Nn \l_tmpa_tl {NA}} % \str_if_eq:VnF \l_tmpa_tl {NA} % {\gradbarsCheckNumber{\l_tmpa_tl}{spark~observation} % \ifgradbars@valid % \bool_if:NTF \l__gradbars_series_any_bool % {\fp_set:Nn \l__gradbars_series_min_fp {min(\l__gradbars_series_min_fp,\l_tmpa_tl)} % \fp_set:Nn \l__gradbars_series_max_fp {max(\l__gradbars_series_max_fp,\l_tmpa_tl)}} % {\fp_set:Nn \l__gradbars_series_min_fp {\l_tmpa_tl} % \fp_set:Nn \l__gradbars_series_max_fp {\l_tmpa_tl} % \bool_set_true:N \l__gradbars_series_any_bool} % \fi} % \seq_put_right:NV \l__gradbars_series_clean_seq \l_tmpa_tl} % \seq_set_eq:NN \l__gradbars_series_seq \l__gradbars_series_clean_seq % \cs_set:Npx \gradbars@sparklast {\seq_item:Nn \l__gradbars_series_seq {-1}} % } %\DeclareDocumentCommand\gradspark{O{} m} % {\group_begin:\gradbars@validtrue\gradbarsParseSpark{#2} % \ifgradbars@valid % \gradbars@sparktrue % \gradbar[height=4ex,#1,shape=sparkline]{\gradbars@sparklast} % \fi\group_end:} %\cs_new_protected:Npn \gradbarsValidateSpark % { % \str_if_eq:eeTF {\gradbars@sparktype}{winloss} % {\fp_set:Nn\l__gradbars_series_low_fp{-1}\fp_set:Nn\l__gradbars_series_high_fp{1}} % {\str_if_eq:eeTF {\gradbars@sparkrange}{fixed} % {\fp_set:Nn \l__gradbars_series_low_fp {\gradbars@min} % \fp_set:Nn \l__gradbars_series_high_fp {\gradbars@max} % \seq_map_inline:Nn \l__gradbars_series_seq % {\str_if_eq:nnF {##1}{NA}{\gradbarsRange{Spark~observation}{##1}}}} % {\fp_set_eq:NN \l__gradbars_series_low_fp \l__gradbars_series_min_fp % \fp_set_eq:NN \l__gradbars_series_high_fp \l__gradbars_series_max_fp % \str_if_eq:eeT{\gradbars@sparktype}{bar} % {\fp_set:Nn\l__gradbars_series_low_fp{min(0,\l__gradbars_series_min_fp)} % \fp_set:Nn\l__gradbars_series_high_fp{max(0,\l__gradbars_series_max_fp)} % \fp_compare:nNnT{\l__gradbars_series_low_fp}={\l__gradbars_series_high_fp} % {\fp_set:Nn\l__gradbars_series_high_fp{1}}}}} % \str_if_eq:eeF{\gradbars@sparktype}{line} % {\gradbarsCheckNumber{\gradbars@sparkbarwidth}{spark~bar~width} % \ifgradbars@valid\fp_compare:nF{0<\gradbars@sparkbarwidth<=1} % {\gradbarsFail{Spark~bar~width~must~be~in~(0,1]}}\fi} % } %\cs_new_protected:Npn \gradbarsDrawSpark % { % \gradbarsMarkerBounds % \bool_set_false:N \l__gradbars_series_prev_bool % \int_zero:N \l__gradbars_series_index_int % \seq_map_inline:Nn \l__gradbars_series_seq % {\int_incr:N \l__gradbars_series_index_int % \str_if_eq:nnTF {##1}{NA} % {\bool_set_false:N \l__gradbars_series_prev_bool} % {\pgfmathsetlengthmacro\gradbars@sparkx % {\fp_eval:n {\seq_count:N \l__gradbars_series_seq=1 ? .5 : % (\l__gradbars_series_index_int-1)/max(1,\seq_count:N \l__gradbars_series_seq-1)}*\gradbars@width} % \fp_compare:nNnTF {\l__gradbars_series_low_fp} = {\l__gradbars_series_high_fp} % {\pgfmathsetlengthmacro\gradbars@sparky{.5*\gradbars@height}} % {\pgfmathsetlengthmacro\gradbars@sparky % {\fp_eval:n {max(0,min(1,(##1-\l__gradbars_series_low_fp)/ % (\l__gradbars_series_high_fp-\l__gradbars_series_low_fp)))}*\gradbars@height}} % \bool_if:NT \l__gradbars_series_prev_bool % {\draw[draw=\gradbars@left,line~width=\gradbars@stemwidth] % (\gradbars@sparkprevx,\gradbars@sparkprevy)--(\gradbars@sparkx,\gradbars@sparky);} % \bool_set_false:N \l__gradbars_series_mark_bool % \let\gradbars@pointcolor\gradbars@left % \str_case_e:nn {\gradbars@sparkpoints} % {{all}{\bool_set_true:N \l__gradbars_series_mark_bool} % {extrema}{\fp_compare:nNnT {##1} = {\l__gradbars_series_min_fp} % {\bool_set_true:N \l__gradbars_series_mark_bool\let\gradbars@pointcolor\gradbars@sparklow} % \fp_compare:nNnT {##1} = {\l__gradbars_series_max_fp} % {\bool_set_true:N \l__gradbars_series_mark_bool\let\gradbars@pointcolor\gradbars@sparkhigh}}} % \str_if_eq:eeF {\gradbars@sparkpoints}{none} % {\int_compare:nNnT {\l__gradbars_series_index_int} = {\seq_count:N \l__gradbars_series_seq} % {\bool_set_true:N \l__gradbars_series_mark_bool}} % \bool_if:NT \l__gradbars_series_mark_bool % {\gradbarsDrawMarker{\gradbars@sparkx}{\gradbars@sparky} % {\gradbars@pointcolor}{\gradbars@markerfill}} % \let\gradbars@sparkprevx\gradbars@sparkx\let\gradbars@sparkprevy\gradbars@sparky % \bool_set_true:N \l__gradbars_series_prev_bool}} % } % %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradbarsDrawSparkLine\gradbarsDrawSpark %\cs_set_protected:Npn\gradbarsDrawSpark % {\str_if_eq:eeTF{\gradbars@sparktype}{line}{\gradbarsDrawSparkLine}{\gradbarsDrawSparkBars}} %\cs_new_protected:Npn\gradbarsDrawSparkBars % {\int_zero:N\l__gradbars_series_index_int % \pgfmathsetlengthmacro\gradbars@sparkhalf % {\gradbars@sparkbarwidth/(2*\seq_count:N\l__gradbars_series_seq)*\gradbars@width} % \pgfmathsetlengthmacro\gradbars@sparkbase % {\fp_eval:n{max(0,min(1,-\l__gradbars_series_low_fp/ % (\l__gradbars_series_high_fp-\l__gradbars_series_low_fp)))}*\gradbars@height} % \draw[draw=\gradbars@sparkzerocolor,line~width=.3pt] % (0,\gradbars@sparkbase)--(\gradbars@width,\gradbars@sparkbase); % \seq_map_inline:Nn\l__gradbars_series_seq % {\int_incr:N\l__gradbars_series_index_int % \str_if_eq:nnF{##1}{NA} % {\pgfmathsetlengthmacro\gradbars@sparkx % {(\l__gradbars_series_index_int-.5)/\seq_count:N\l__gradbars_series_seq*\gradbars@width} % \str_if_eq:eeTF{\gradbars@sparktype}{winloss} % {\pgfmathsetlengthmacro\gradbars@sparky{\fp_eval:n{(sign(##1)+1)/2}*\gradbars@height} % \let\gradbars@sparkfill\gradbars@sparkwincolor % \fp_compare:nNnT{##1}<{0}{\let\gradbars@sparkfill\gradbars@sparklosscolor}} % {\pgfmathsetlengthmacro\gradbars@sparky % {\fp_eval:n{max(0,min(1,(##1-\l__gradbars_series_low_fp)/ % (\l__gradbars_series_high_fp-\l__gradbars_series_low_fp)))}*\gradbars@height} % \let\gradbars@sparkfill\gradbars@left % \fp_compare:nNnT{##1}<{0}{\let\gradbars@sparkfill\gradbars@negativecolor}} % \ifgradbars@print\def\gradbars@sparkfill{black!65} % \fp_compare:nNnT{##1}<{0}{\def\gradbars@sparkfill{black!35}}\fi % \dim_compare:nNnTF{\gradbars@sparky}={\gradbars@sparkbase} % {\draw[draw=\gradbars@sparkzerocolor,line~width=.8pt] % ([xshift=-\gradbars@sparkhalf]\gradbars@sparkx,\gradbars@sparkbase)-- % ([xshift=\gradbars@sparkhalf]\gradbars@sparkx,\gradbars@sparkbase);} % {\path[fill=\gradbars@sparkfill,draw=none] % ([xshift=-\gradbars@sparkhalf]\gradbars@sparkx,\gradbars@sparkbase) rectangle % ([xshift=\gradbars@sparkhalf]\gradbars@sparkx,\gradbars@sparky);}}}} % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-stack.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-lib-stack}[2026/10/25 v1.1.0 gradbars lib-stack] %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsParseStack #1 % { % \tl_set:Nx \l_tmpa_tl {#1} % % Empty elements are invalid, not silently dropped by clist normalization. % \regex_match:nVTF {\A\s*\Z|\A\s*,|,\s*,|,\s*\Z} \l_tmpa_tl % {\gradbarsFail{Stack~requires~a~nonempty~list~of~numbers}} { } % \clist_set:Nx \l__gradbars_stack_clist {#1} % \fp_zero:N \l__gradbars_sum_fp % \fp_zero:N \l__gradbars_positive_fp % \fp_zero:N \l__gradbars_negative_fp % \clist_map_inline:Nn \l__gradbars_stack_clist % { % \gradbarsCheckNumber{##1}{stack~segment} % \ifgradbars@valid % \fp_add:Nn \l__gradbars_sum_fp {##1} % \fp_compare:nNnTF {##1} < {0} % {\fp_add:Nn \l__gradbars_negative_fp {##1}} % {\fp_add:Nn \l__gradbars_positive_fp {##1}} % \fi % } % \cs_set:Npx \gradbars@total {\fp_to_decimal:N \l__gradbars_sum_fp} % \cs_set:Npx \gradbars@positive {\fp_to_decimal:N \l__gradbars_positive_fp} % \cs_set:Npx \gradbars@negative {\fp_to_decimal:N \l__gradbars_negative_fp} % \cs_set:Npx \gradbars@gross {\fp_eval:n {\gradbars@positive-\gradbars@negative}} % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawStack % { % \gradbarsStackReset % \int_zero:N \l_tmpa_int % \clist_map_inline:Nn \l__gradbars_stack_clist % { % \gradbarsStackStep{##1} % \int_incr:N \l_tmpa_int % \gradbarsCategoryColor{\l_tmpa_int} % \pgfmathsetlengthmacro\gradbars@segmentlo % {\gradbarsPosition{\l__gradbars_before_fp}*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@segmenthi % {\gradbarsPosition{\l__gradbars_sum_fp}*(\gradbars@width)} % \ifdim\gradbars@segmenthi>\gradbars@segmentlo\relax % \ifgradbars@outline % \draw[draw=\gradbars@segmentcolor,line~width=\gradbars@outlinewidth] % (\gradbars@segmentlo,0) rectangle (\gradbars@segmenthi,\gradbars@height); % \else % \path[fill=\gradbars@segmentcolor,draw=none] % (\gradbars@segmentlo,0) rectangle (\gradbars@segmenthi,\gradbars@height); % \gradbarsPatternRect{\l_tmpa_int}{\gradbars@segmentlo}{0}{\gradbars@segmenthi}{\gradbars@height} % \fi % \fi % } % } %\ExplSyntaxOff %\ExplSyntaxOff %\DeclareDocumentCommand\gradstack{O{} m}{% % \leavevmode\begingroup % \gradbars@validtrue % \gradbarsParseStack{#2}% % \ifgradbars@valid % \gradbars@stacktrue % \gradbar[#1]{\gradbars@total}% % \fi % \endgroup %} %\ExplSyntaxOff %\ExplSyntaxOn %\fp_new:N \l__gradbars_positive_fp %\fp_new:N \l__gradbars_negative_fp %\cs_new_protected:Npn \gradbarsStackReset % {\fp_zero:N \l__gradbars_positive_fp\fp_zero:N \l__gradbars_negative_fp} %\cs_new_protected:Npn \gradbarsStackStep #1 % { % \fp_compare:nNnTF {#1} < {0} % {\fp_set_eq:NN \l__gradbars_sum_fp \l__gradbars_negative_fp % \fp_add:Nn \l__gradbars_negative_fp {#1} % \fp_set_eq:NN \l__gradbars_before_fp \l__gradbars_negative_fp} % {\fp_set_eq:NN \l__gradbars_before_fp \l__gradbars_positive_fp % \fp_add:Nn \l__gradbars_positive_fp {#1} % \fp_set_eq:NN \l__gradbars_sum_fp \l__gradbars_positive_fp} % } % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-lib-table.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-lib-table}[2026/10/25 v1.1.0 gradbars lib-table] %\RequirePackage{booktabs} %\RequirePackage{colortbl} %\RequirePackage{longtable} %\ExplSyntaxOff %% gradtable buffers declarations and rows; no alignment tokens in user data. %\ExplSyntaxOn %\seq_new:N \l__gradtable_columns_seq %\seq_new:N \l__gradtable_rows_seq %\prop_new:N \l__gradtable_titles_prop %\prop_new:N \l__gradtable_types_prop %\prop_new:N \l__gradtable_options_prop %\prop_new:N \l__gradtable_widths_prop %\prop_new:N \l__gradtable_align_prop %\prop_new:N \l__gradtable_headalign_prop %\prop_new:N \l__gradtable_valign_prop %\prop_new:N \l__gradtable_colwidth_prop %\tl_new:N \l__gradtable_align_tl %\tl_new:N \l__gradtable_headalign_tl %\tl_new:N \l__gradtable_valign_tl %\tl_new:N \l__gradtable_default_align_tl %\tl_new:N \l__gradtable_default_headalign_tl %\tl_new:N \l__gradtable_default_valign_tl %\tl_new:N \l__gradtable_rules_tl %\tl_new:N \l__gradtable_stretch_tl %\tl_new:N \l__gradtable_header_spec_tl %\tl_new:N \l__gradtable_header_color_tl %\tl_new:N \l__gradtable_rule_color_tl %\dim_new:N \l__gradtable_colwidth_dim %\dim_new:N \l__gradtable_sep_dim %\dim_new:N \l__gradtable_padding_dim %\tl_new:N \l__gradtable_preset_tl %\tl_new:N \l__gradtable_type_tl %\tl_new:N \l__gradtable_options_tl %\tl_new:N \l__gradtable_id_tl %\tl_new:N \l__gradtable_preamble_tl %\tl_new:N \l__gradtable_body_tl %\clist_new:N \l__gradtable_cells_clist %\seq_new:N \l__gradtable_interval_seq %\dim_new:N \l__gradtable_graphic_dim %\dim_new:N \l__gradtable_text_dim %\dim_new:N \l__gradtable_label_dim %\dim_new:N \g__gradtable_measured_dim %\box_new:N \l__gradtable_measure_box %\int_new:N \l__gradtable_row_int %\int_new:N \l__gradtable_col_int %\bool_new:N \l__gradtable_valid_bool %\bool_new:N \l__gradtable_started_bool %\keys_define:nn {gradbars/table} % {preset .choice:, % preset / paper .code:n = \tl_set:Nn \l__gradtable_preset_tl {paper}, % preset / report .code:n = \tl_set:Nn \l__gradtable_preset_tl {report}, % preset / mono .code:n = \tl_set:Nn \l__gradtable_preset_tl {mono}, % graphic~width .dim_set:N = \l__gradtable_graphic_dim, % label~width .dim_set:N = \l__gradtable_label_dim, % text~width .dim_set:N = \l__gradtable_text_dim, % align .choices:nn = {auto,l,c,r}{\tl_set_eq:NN\l__gradtable_default_align_tl\l_keys_choice_tl}, % header~align .choices:nn = {auto,l,c,r}{\tl_set_eq:NN\l__gradtable_default_headalign_tl\l_keys_choice_tl}, % valign .choices:nn = {t,c,b}{\tl_set_eq:NN\l__gradtable_default_valign_tl\l_keys_choice_tl}, % rules .choices:nn = {booktabs,rows,grid,none}{\tl_set_eq:NN\l__gradtable_rules_tl\l_keys_choice_tl}, % row~stretch .tl_set:N = \l__gradtable_stretch_tl, % column~sep .dim_set:N = \l__gradtable_sep_dim, % row~padding .dim_set:N = \l__gradtable_padding_dim, % header~color .tl_set:N = \l__gradtable_header_color_tl, % rule~color .tl_set:N = \l__gradtable_rule_color_tl} %\keys_define:nn {gradbars/table/column} % {type .choices:nn = {text,number,bar,bullet,interval,compare,dumbbell,stack,spark,heat,boxplot} % {\tl_set_eq:NN \l__gradtable_type_tl \l_keys_choice_tl}, % options .tl_set:N = \l__gradtable_options_tl, % align .choices:nn = {auto,l,c,r}{\tl_set_eq:NN\l__gradtable_align_tl\l_keys_choice_tl}, % header~align .choices:nn = {auto,l,c,r}{\tl_set_eq:NN\l__gradtable_headalign_tl\l_keys_choice_tl}, % valign .choices:nn = {t,c,b}{\tl_set_eq:NN\l__gradtable_valign_tl\l_keys_choice_tl}, % width .dim_set:N = \l__gradtable_colwidth_dim} %\cs_new_protected:Npn \gradtableError #1 % {\bool_set_false:N \l__gradtable_valid_bool % \PackageError{gradbars}{Table~row~\int_use:N\l__gradtable_row_int, % ~column~\tl_use:N\l__gradtable_id_tl :~#1} % {Check~column~declarations~and~comma-separated~row~data.}} %\DeclareDocumentCommand\gradcolumn{O{} m m} % {\PackageError{gradbars}{gradcolumn~requires~gradtable}{Place~column~declarations~inside~gradtable.}} %\DeclareDocumentCommand\gradrow{m} % {\PackageError{gradbars}{gradrow~requires~gradtable}{Place~rows~inside~gradtable.}} %\cs_new_protected:Npn \gradtableColumn #1#2#3 % {\bool_if:NT \l__gradtable_started_bool {\gradtableError{Declare~columns~before~rows}} % \seq_if_empty:NF\l__gradtable_headers_seq{\gradtableError{Declare~columns~before~headers}} % \tl_set:Nn \l__gradtable_id_tl {#2} % \tl_if_blank:nT {#2}{\gradtableError{Column~identifier~must~not~be~empty}} % \prop_if_in:NnT \l__gradtable_types_prop {#2}{\gradtableError{Duplicate~column~identifier}} % \tl_set:Nn \l__gradtable_type_tl {text} % \tl_clear:N \l__gradtable_options_tl % \tl_set_eq:NN\l__gradtable_align_tl\l__gradtable_default_align_tl % \tl_set_eq:NN\l__gradtable_headalign_tl\l__gradtable_default_headalign_tl % \tl_set_eq:NN\l__gradtable_valign_tl\l__gradtable_default_valign_tl % \dim_zero:N\l__gradtable_colwidth_dim % \fp_set:Nn\l__gradtable_weight_fp{1} % \tl_set:Nn\l__gradtable_mark_tl{none} % \tl_set:Nn\l__gradtable_source_tl{#2} % \tl_set_eq:NN\l__gradtable_scale_tl\l__gradtable_default_scale_tl % \bool_set_eq:NN\l__gradtable_zero_bool\l__gradtable_default_zero_bool % \tl_set_eq:NN\l__gradtable_formatter_tl\l__gradtable_default_formatter_tl % \tl_set_eq:NN\l__gradtable_number_align_tl\l__gradtable_default_number_align_tl % \bool_set_false:N\l__gradtable_number_align_explicit_bool % \tl_set:Nn\l__gradtable_aggregate_tl{none} % \tl_set_eq:NN\l__gradtable_scale_group_tl\l__gradtable_default_scale_group_tl % \fp_set_eq:NN\l__gradtable_scale_padding_fp\l__gradtable_default_scale_padding_fp % \bool_set_eq:NN\l__gradtable_scale_nice_bool\l__gradtable_default_scale_nice_bool % \keys_set:nn {gradbars/table/column}{#1} % \str_if_eq:VnT\l__gradtable_type_tl{boxplot}{\gradbarsiflibraryloaded{distribution}{}{\gradtableError{Load~distribution~library~before~boxplot~columns}}} % \gradtableStoreNumericFormat{#2} % \dim_compare:nNnT{\l__gradtable_colwidth_dim}<{0pt}{\gradtableError{Column~width~must~be~nonnegative}} % \prop_put:Nnx\l__gradtable_fixed_prop{#2}{\dim_use:N\l__gradtable_colwidth_dim} % \prop_put:Nnx\l__gradtable_weights_prop{#2}{\fp_use:N\l__gradtable_weight_fp} % \str_if_eq:VnT\l__gradtable_align_tl{auto} % {\tl_set:Nn\l__gradtable_align_tl{l} % \str_if_eq:VnT\l__gradtable_type_tl{number}{\tl_set:Nn\l__gradtable_align_tl{r}}} % \str_if_eq:VnT\l__gradtable_headalign_tl{auto}{\tl_set_eq:NN\l__gradtable_headalign_tl\l__gradtable_align_tl} % \str_if_eq:VnT\l__gradtable_type_tl{text} % {\dim_compare:nNnT{\l__gradtable_colwidth_dim}={0pt}{\dim_set_eq:NN\l__gradtable_colwidth_dim\l__gradtable_text_dim}} % \prop_put:NnV\l__gradtable_marks_prop{#2}\l__gradtable_mark_tl % \str_if_eq:VnF\l__gradtable_mark_tl{none} % {\str_case:VnF\l__gradtable_type_tl{{number}{}{bar}{}{bullet}{}{heat}{}} % {\gradtableError{Mark~requires~number,~bar,~bullet~or~heat~column}}} % \prop_put:NnV\l__gradtable_sources_prop{#2}\l__gradtable_source_tl % \prop_put:NnV\l__gradtable_scales_prop{#2}\l__gradtable_scale_tl % \prop_put:NnV\l__gradtable_aggregates_prop{#2}\l__gradtable_aggregate_tl % \prop_put:NnV\l__gradtable_scale_groups_prop{#2}\l__gradtable_scale_group_tl % \prop_put:Nnx\l__gradtable_scale_padding_prop{#2}{\fp_to_decimal:N\l__gradtable_scale_padding_fp} % \prop_put:Nnx\l__gradtable_scale_nice_prop{#2}{\bool_if:NTF\l__gradtable_scale_nice_bool{true}{false}} % \str_if_eq:VnF\l__gradtable_aggregate_tl{none} % {\str_case:VnF\l__gradtable_type_tl{{number}{}{bar}{}{bullet}{}{heat}{}} % {\gradtableError{Aggregate~requires~a~scalar~numeric~column}}} % \tl_if_empty:NF\l__gradtable_scale_group_tl % {\str_if_eq:VnT\l__gradtable_scale_tl{column} % {\gradtableError{Scale~group~requires~scale=fixed}}} % \prop_put:Nnx\l__gradtable_zero_prop{#2}{\bool_if:NTF\l__gradtable_zero_bool{true}{false}} % \seq_put_right:Nn \l__gradtable_columns_seq {#2} % \prop_put:Nnn \l__gradtable_titles_prop {#2}{#3} % \prop_put:NnV \l__gradtable_types_prop {#2}\l__gradtable_type_tl % \prop_put:NnV \l__gradtable_options_prop {#2}\l__gradtable_options_tl % \prop_put:NnV\l__gradtable_align_prop{#2}\l__gradtable_align_tl % \prop_put:NnV\l__gradtable_headalign_prop{#2}\l__gradtable_headalign_tl % \prop_put:NnV\l__gradtable_valign_prop{#2}\l__gradtable_valign_tl % \prop_put:Nnx\l__gradtable_colwidth_prop{#2}{\dim_use:N\l__gradtable_colwidth_dim} % \prop_put:Nnx \l__gradtable_widths_prop {#2}{\dim_use:N\l__gradtable_label_dim}} %\cs_new_protected:Npn \gradtableRow #1 % {\bool_set_true:N \l__gradtable_started_bool % \int_incr:N \l__gradtable_row_int % \clist_set:Nn \l__gradtable_cells_clist {#1} % \int_compare:nNnTF {\clist_count:N\l__gradtable_cells_clist} = {\seq_count:N\l__gradtable_columns_seq} % {\seq_put_right:Nn \l__gradtable_rows_seq {#1}} % {\gradtableError{Wrong~number~of~cells;~use~NA~for~missing~data}}} % % % % % % % % % %\DeclareDocumentEnvironment{gradtable}{O{} +b} % {\group_begin: % \prop_clear:N\l__gradtable_fixed_prop % \prop_clear:N\l__gradtable_weights_prop % \prop_clear:N\l__gradtable_plots_prop % \prop_clear:N\l__gradtable_sources_prop % \prop_clear:N\l__gradtable_scales_prop % \prop_clear:N\l__gradtable_zero_prop % \prop_clear:N\l__gradtable_ranges_prop % \prop_clear:N\l__gradtable_aggregates_prop % \prop_clear:N\l__gradtable_formatters_prop % \prop_clear:N\l__gradtable_number_align_prop % \prop_clear:N\l__gradtable_decimal_left_prop % \prop_clear:N\l__gradtable_decimal_right_prop % \prop_clear:N\l__gradtable_scale_groups_prop % \prop_clear:N\l__gradtable_scale_padding_prop % \prop_clear:N\l__gradtable_scale_nice_prop % \prop_clear:N\l__gradtable_percent_bases_prop % \bool_set_false:N\l__gradtable_summary_bool % \seq_clear:N\l__gradtable_headers_seq % \prop_clear:N\l__gradtable_groups_prop % \prop_clear:N\l__gradtable_marks_prop % \seq_clear:N\l__gradtable_style_stack_seq % \seq_clear:N\l__gradtable_schema_stack_seq % \cs_set_eq:NN\gradtableSavedRuleColor\CT@arc@ % \seq_clear:N\l__gradtable_columns_seq\seq_clear:N\l__gradtable_rows_seq % \prop_clear:N\l__gradtable_titles_prop\prop_clear:N\l__gradtable_types_prop % \prop_clear:N\l__gradtable_options_prop\prop_clear:N\l__gradtable_widths_prop % \prop_clear:N\l__gradtable_align_prop\prop_clear:N\l__gradtable_headalign_prop % \prop_clear:N\l__gradtable_valign_prop\prop_clear:N\l__gradtable_colwidth_prop % \int_zero:N\l__gradtable_row_int\tl_clear:N\l__gradtable_id_tl % \bool_set_true:N\l__gradtable_valid_bool\bool_set_false:N\l__gradtable_started_bool % \keys_set:nn{gradbars/table}{preset=paper,graphic~width=32mm,text~width=22mm,label~width=18mm, % align=auto,header~align=auto,valign=t,rules=booktabs,row~stretch=auto, % column~sep=6pt,row~padding=0pt,header~color=auto,rule~color=black,group~color=gradbarsTrack,group~sep=4pt,width=0pt,min~text~width=12mm,min~graphic~width=12mm, % long=false,caption={},label={},continued~text={(continued)},data={},scale=fixed,include~zero=true, % sort={},sort~keys={},order=ascending,filter={},limit=0,scale~scope=data, % group~by={},rank~scope=table,group~summary=false,group~summary~scope=visible, % group~summary~label={Summary},group~missing~label={(ungrouped)}, % scale~group={},scale~padding=0,scale~nice=false,theme=none,font={}, % summary~color=auto,summary~font={\bfseries\boldmath}, % formatter=builtin,number~align=none,#1} % \str_if_eq:VnT\l__gradtable_stretch_tl{auto} % {\tl_set:Nn\l__gradtable_stretch_tl{1.2} % \str_if_eq:VnT\l__gradtable_preset_tl{report}{\tl_set:Nn\l__gradtable_stretch_tl{1.5}}} % \regex_match:nVTF{\A\d+(\.\d+)?\Z}\l__gradtable_stretch_tl % {\fp_compare:nNnF{\l__gradtable_stretch_tl}>{0}{\gradtableError{Row~stretch~must~be~positive}}} % {\gradtableError{Row~stretch~must~be~a~positive~decimal}} % \dim_compare:nNnT{\l__gradtable_sep_dim}<{0pt}{\gradtableError{Column~sep~must~be~nonnegative}} % \dim_compare:nNnT{\l__gradtable_padding_dim}<{0pt}{\gradtableError{Row~padding~must~be~nonnegative}} % \bool_set_false:N\l__gradtable_header_auto_bool % \str_if_eq:VnT\l__gradtable_header_color_tl{auto} % {\bool_set_true:N\l__gradtable_header_auto_bool\tl_clear:N\l__gradtable_header_color_tl % \str_if_eq:VnT\l__gradtable_theme_tl{none} % {\str_if_eq:VnT\l__gradtable_preset_tl{report}{\tl_set:Nn\l__gradtable_header_color_tl{gradbarsTrack}}}} % \gradtableResolveThemeColors % \dim_compare:nNnF{\l__gradtable_graphic_dim}>{0pt}{\gradtableError{Graphic~width~must~be~positive}} % \dim_compare:nNnF{\l__gradtable_text_dim}>{0pt}{\gradtableError{Text~width~must~be~positive}} % \dim_compare:nNnT{\l__gradtable_label_dim}<{0pt}{\gradtableError{Label~width~must~be~nonnegative}} % \gradtableValidateLayout % \RenewDocumentCommand\gradheader{+m}{\gradtableAddHeader{##1}} % \RenewDocumentCommand\gradcolumn{O{} m m}{\gradtableColumn{##1}{##2}{##3}} % \RenewDocumentCommand\gradrow{m}{\gradtableRow{##1}} % \RenewDocumentCommand\gradgroup{m}{\gradtableGroup{##1}} % \RenewDocumentCommand\graduseschema{m}{\gradtableUseSchema{##1}} % \RenewDocumentCommand\gradsummary{O{} m}{\gradtableSummaryDeclare{##1}{##2}} % #2 % \tl_if_empty:NF\l__gradtable_data_tl{\gradtableImportCSV} % \prop_if_in:NxT\l__gradtable_groups_prop{\int_eval:n{\l__gradtable_row_int+1}} % {\gradtableError{Group~requires~at~least~one~data~row}} % \seq_if_empty:NT\l__gradtable_columns_seq{\gradtableError{Table~requires~columns}} % \gradtableValidateSelection % \bool_if:NT\l__gradtable_valid_bool{\gradtableRender} % \cs_gset_eq:NN\CT@arc@\gradtableSavedRuleColor % \group_end:}{} %\ExplSyntaxOff % %% Reusable table definitions, group headings and column extrema. %\ExplSyntaxOn %\prop_new:N\g__gradtable_styles_prop %\prop_new:N\g__gradtable_schemas_prop %\prop_new:N\l__gradtable_groups_prop %\prop_new:N\l__gradtable_marks_prop %\prop_new:N\l__gradtable_best_prop %\prop_new:N\l__gradtable_second_prop %\seq_new:N\l__gradtable_style_stack_seq %\seq_new:N\l__gradtable_schema_stack_seq %\seq_new:N\l__gradtable_rank_seq %\tl_new:N\l__gradtable_mark_tl %\tl_new:N\l__gradtable_group_color_tl %\tl_new:N\g__gradtable_rank_direction_tl %\tl_new:N\l__gradtable_rank_direction_tl %\tl_new:N\l__gradtable_rank_value_tl %\dim_new:N\l__gradtable_group_sep_dim %\int_new:N\l__gradtable_rank_col_int %\cs_generate_variant:Nn\prop_if_in:NnT{NxT} %\cs_generate_variant:Nn\prop_get:NnNT{NxNT} %\keys_define:nn{gradbars/table} % {style .code:n=\gradtableUseStyle{#1}, % group~color .tl_set:N=\l__gradtable_group_color_tl, % group~sep .code:n={\dim_set:Nn\l__gradtable_group_sep_dim{#1} % \dim_compare:nNnT{\l__gradtable_group_sep_dim}<{0pt} % {\gradtableError{Group~sep~must~be~nonnegative}}}} %\keys_define:nn{gradbars/table/column} % {mark .choices:nn={none,best,both}{\tl_set_eq:NN\l__gradtable_mark_tl\l_keys_choice_tl}} %\DeclareDocumentCommand\gradtablestyle{m m} % {\tl_if_blank:nTF{#1}{\PackageError{gradbars}{Empty~table~style~name}{Supply~a~name.}} % {\prop_gput:Nnn\g__gradtable_styles_prop{#1}{#2}}} %\DeclareDocumentCommand\gradtableschema{m +m} % {\tl_if_blank:nTF{#1}{\PackageError{gradbars}{Empty~table~schema~name}{Supply~a~name.}} % {\prop_gput:Nnn\g__gradtable_schemas_prop{#1}{#2}}} %\cs_new_protected:Npn\gradtableUseStyle #1 % {\seq_if_in:NnTF\l__gradtable_style_stack_seq{#1} % {\gradtableError{Recursive~table~style~#1}} % {\prop_get:NnNTF\g__gradtable_styles_prop{#1}\l_tmpa_tl % {\seq_put_right:Nn\l__gradtable_style_stack_seq{#1} % \exp_args:NnV\keys_set:nn{gradbars/table}\l_tmpa_tl % \seq_pop_right:NN\l__gradtable_style_stack_seq\l_tmpa_tl} % {\gradtableError{Unknown~table~style~#1}}}} %\DeclareDocumentCommand\graduseschema{m} % {\PackageError{gradbars}{graduseschema~requires~gradtable}{Use~inside~gradtable.}} %\cs_new_protected:Npn\gradtableUseSchema #1 % {\seq_if_in:NnTF\l__gradtable_schema_stack_seq{#1} % {\gradtableError{Recursive~table~schema~#1}} % {\prop_get:NnNTF\g__gradtable_schemas_prop{#1}\l_tmpa_tl % {\seq_put_right:Nn\l__gradtable_schema_stack_seq{#1} % \tl_use:N\l_tmpa_tl % \seq_pop_right:NN\l__gradtable_schema_stack_seq\l_tmpa_tl} % {\gradtableError{Unknown~table~schema~#1}}}} %\DeclareDocumentCommand\gradgroup{m} % {\PackageError{gradbars}{gradgroup~requires~gradtable}{Use~inside~gradtable.}} %\cs_new_protected:Npn\gradtableGroup #1 % {\bool_set_true:N\l__gradtable_started_bool % \seq_if_empty:NT\l__gradtable_columns_seq{\gradtableError{Declare~columns~before~groups}} % \tl_if_blank:nT{#1}{\gradtableError{Group~title~must~not~be~empty}} % \prop_if_in:NxT\l__gradtable_groups_prop{\int_eval:n{\l__gradtable_row_int+1}} % {\gradtableError{Group~requires~at~least~one~data~row}} % \prop_put:Nxn\l__gradtable_groups_prop{\int_eval:n{\l__gradtable_row_int+1}}{#1}} % % % % % % % %\ExplSyntaxOff %% v0.0.4: column-spanning headers, constrained widths and long tables. %\ExplSyntaxOn %\seq_new:N\l__gradtable_headers_seq %\tl_new:N\l__gradtable_head_tl %\tl_new:N\l__gradtable_caption_tl %\tl_new:N\l__gradtable_label_tl %\tl_new:N\l__gradtable_continued_tl %\tl_new:N\l__gradtable_span_id_tl %\bool_new:N\l__gradtable_long_bool %\dim_new:N\l__gradtable_total_dim %\dim_new:N\l__gradtable_min_text_dim %\dim_new:N\l__gradtable_min_graphic_dim %\dim_new:N\l__gradtable_remaining_dim %\dim_new:N\l__gradtable_base_dim %\dim_new:N\l__gradtable_span_dim %\dim_new:N\g__gradtable_extent_dim %\fp_new:N\l__gradtable_weight_fp %\fp_new:N\l__gradtable_weight_sum_fp %\prop_new:N\l__gradtable_fixed_prop %\prop_new:N\l__gradtable_weights_prop %\prop_new:N\l__gradtable_flex_prop %\prop_new:N\l__gradtable_plots_prop %\prop_new:N\l__gradtable_overheads_prop %\int_new:N\l__gradtable_span_start_int %\int_new:N\l__gradtable_span_count_int %\keys_define:nn{gradbars/table} % {width .dim_set:N=\l__gradtable_total_dim, % min~text~width .dim_set:N=\l__gradtable_min_text_dim, % min~graphic~width .dim_set:N=\l__gradtable_min_graphic_dim, % long .bool_set:N=\l__gradtable_long_bool, % caption .tl_set:N=\l__gradtable_caption_tl, % label .tl_set:N=\l__gradtable_label_tl, % continued~text .tl_set:N=\l__gradtable_continued_tl} %\keys_define:nn{gradbars/table/column} % {weight .code:n={\regex_match:nnTF{\A\d+(\.\d+)?\Z}{#1} % {\fp_set:Nn\l__gradtable_weight_fp{#1} % \fp_compare:nNnF{#1}>{0}{\gradtableError{Column~weight~must~be~positive}}} % {\gradtableError{Column~weight~must~be~a~positive~decimal}}}} % %\DeclareDocumentCommand\gradheader{+m} % {\PackageError{gradbars}{gradheader~requires~gradtable}{Declare~headers~inside~gradtable.}} %\DeclareDocumentCommand\gradspan{m m} % {\PackageError{gradbars}{gradspan~requires~gradheader}{Place~spans~inside~gradheader.}} %\cs_new_protected:Npn\gradtableAddHeader #1 % {\bool_if:NT\l__gradtable_started_bool{\gradtableError{Declare~headers~before~rows}} % \int_zero:N\l__gradtable_span_count_int % \cs_set_eq:NN\gradtableSavedSpan\gradspan % \RenewDocumentCommand\gradspan{m m} % {\regex_match:nnTF{\A[1-9]\d*\Z}{##1} % {\int_add:Nn\l__gradtable_span_count_int{##1}} % {\gradtableError{Header~span~must~be~a~positive~integer}}} % #1 % \cs_set_eq:NN\gradspan\gradtableSavedSpan % \int_compare:nNnF{\l__gradtable_span_count_int}={\seq_count:N\l__gradtable_columns_seq} % {\gradtableError{Header~spans~must~cover~all~columns~exactly}} % \seq_put_right:Nn\l__gradtable_headers_seq{#1}} % % % % % % % %\ExplSyntaxOff % % %\ExplSyntaxOff %\ExplSyntaxOff %% v0.0.5: native CSV tables, column scales and scalar heat cells. %\ExplSyntaxOn %\tl_new:N\l__gradtable_data_tl %\seq_new:N\l__gradtable_data_rows_seq %\seq_new:N\l__gradtable_range_rows_seq %\tl_new:N\l__gradtable_source_tl %\tl_new:N\l__gradtable_scale_tl %\tl_new:N\l__gradtable_default_scale_tl %\bool_new:N\l__gradtable_zero_bool %\bool_new:N\l__gradtable_default_zero_bool %\prop_new:N\l__gradtable_sources_prop %\prop_new:N\l__gradtable_scales_prop %\prop_new:N\l__gradtable_zero_prop %\prop_new:N\l__gradtable_ranges_prop %\tl_new:N\l__gradtable_import_row_tl %\tl_new:N\l__gradtable_import_source_tl %\int_new:N\l__gradtable_import_row_int %\int_new:N\l__gradtable_scale_col_int %\seq_new:N\l__gradtable_scale_values_seq %\fp_new:N\l__gradtable_min_fp %\fp_new:N\l__gradtable_max_fp %\fp_new:N\l__gradtable_positive_fp %\fp_new:N\l__gradtable_negative_fp %\bool_new:N\l__gradtable_seen_bool %\keys_define:nn{gradbars/table} % {data .tl_set:N=\l__gradtable_data_tl, % scale .choices:nn={fixed,column}{\tl_set_eq:NN\l__gradtable_default_scale_tl\l_keys_choice_tl}, % include~zero .bool_set:N=\l__gradtable_default_zero_bool} %\keys_define:nn{gradbars/table/column} % {source .tl_set:N=\l__gradtable_source_tl, % scale .choices:nn={fixed,column}{\tl_set_eq:NN\l__gradtable_scale_tl\l_keys_choice_tl}, % include~zero .bool_set:N=\l__gradtable_zero_bool} % % % % % %\ExplSyntaxOff % %\ExplSyntaxOff %\ExplSyntaxOn %\tl_new:N\l__gradtable_sort_tl %\tl_new:N\l__gradtable_order_tl %\tl_new:N\l__gradtable_filter_tl %\tl_new:N\l__gradtable_scale_scope_tl %\int_new:N\l__gradtable_limit_int %\int_new:N\l__gradtable_sort_col_int %\int_new:N\l__gradtable_selection_col_int %\seq_new:N\l__gradtable_selected_seq %\seq_new:N\l__gradtable_filters_seq %\seq_new:N\l__gradtable_filter_parts_seq %\clist_new:N\l__gradtable_selection_cells_clist %\prop_new:N\l__gradtable_selection_rows_prop %\prop_new:N\l__gradtable_sort_values_prop %\prop_new:N\l__gradtable_sort_missing_prop %\tl_new:N\l__gradtable_selection_value_tl %\tl_new:N\l__gradtable_selection_type_tl %\tl_new:N\l__gradtable_filter_id_tl %\tl_new:N\l__gradtable_filter_op_tl %\tl_new:N\l__gradtable_filter_target_tl %\bool_new:N\l__gradtable_selected_bool %\cs_generate_variant:Nn\clist_map_inline:nn{Vn} %\cs_generate_variant:Nn\regex_extract_once:nnNTF{nVNTF} %\keys_define:nn{gradbars/table} % {sort .tl_set:N=\l__gradtable_sort_tl, % order .choices:nn={ascending,descending}{\tl_set_eq:NN\l__gradtable_order_tl\l_keys_choice_tl}, % filter .tl_set:N=\l__gradtable_filter_tl, % limit .code:n={\regex_match:nnTF{\A\d+\Z}{#1} % {\int_set:Nn\l__gradtable_limit_int{#1}}{\gradtableError{Limit~must~be~a~nonnegative~integer}}}, % scale~scope .choices:nn={data,visible}{\tl_set_eq:NN\l__gradtable_scale_scope_tl\l_keys_choice_tl}} % % % % % % % % % %\ExplSyntaxOff % %\ExplSyntaxOff %\ExplSyntaxOn %\tl_new:N\l__gradtable_aggregate_tl %\prop_new:N\l__gradtable_aggregates_prop %\tl_new:N\l__gradtable_scale_group_tl %\tl_new:N\l__gradtable_default_scale_group_tl %\prop_new:N\l__gradtable_scale_groups_prop %\fp_new:N\l__gradtable_scale_padding_fp %\fp_new:N\l__gradtable_default_scale_padding_fp %\bool_new:N\l__gradtable_scale_nice_bool %\bool_new:N\l__gradtable_default_scale_nice_bool %\prop_new:N\l__gradtable_scale_padding_prop %\prop_new:N\l__gradtable_scale_nice_prop %\prop_new:N\l__gradtable_percent_bases_prop %\fp_new:N\l__gradtable_padding_amount_fp %\fp_new:N\l__gradtable_nice_step_fp %\fp_new:N\l__gradtable_nice_power_fp %\tl_new:N\l__gradtable_theme_tl %\tl_new:N\l__gradtable_theme_color_tl %\tl_new:N\l__gradtable_font_tl %\tl_new:N\l__gradtable_summary_color_tl %\tl_new:N\l__gradtable_summary_font_tl %\bool_new:N\l__gradtable_header_auto_bool %\bool_new:N\l__gradtable_summary_bool %\tl_new:N\l__gradtable_summary_label_tl %\tl_new:N\l__gradtable_summary_scope_tl %\tl_new:N\l__gradtable_summary_label_id_tl %\prop_new:N\l__gradtable_summary_values_prop %\seq_new:N\l__gradtable_summary_rows_seq %\int_new:N\l__gradtable_summary_col_int %\int_new:N\l__gradtable_summary_count_int %\fp_new:N\l__gradtable_summary_sum_fp %\fp_new:N\l__gradtable_summary_min_fp %\fp_new:N\l__gradtable_summary_max_fp %\tl_new:N\l__gradtable_summary_value_tl %\keys_define:nn{gradbars/table} % {scale~group .tl_set:N=\l__gradtable_default_scale_group_tl, % scale~padding .code:n=\gradtableSetPadding\l__gradtable_default_scale_padding_fp{#1}, % scale~nice .bool_set:N=\l__gradtable_default_scale_nice_bool, % theme .choices:nn={none,blue,teal,violet,orange,forest,mono,accessible} % {\tl_set_eq:NN\l__gradtable_theme_tl\l_keys_choice_tl}, % font .tl_set:N=\l__gradtable_font_tl, % summary~color .tl_set:N=\l__gradtable_summary_color_tl, % summary~font .tl_set:N=\l__gradtable_summary_font_tl} %\keys_define:nn{gradbars/table/column} % {aggregate .choices:nn={none,count,sum,mean,min,max} % {\tl_set_eq:NN\l__gradtable_aggregate_tl\l_keys_choice_tl}, % scale~group .tl_set:N=\l__gradtable_scale_group_tl, % scale~padding .code:n=\gradtableSetPadding\l__gradtable_scale_padding_fp{#1}, % scale~nice .bool_set:N=\l__gradtable_scale_nice_bool} %\keys_define:nn{gradbars/table/summary} % {scope .choices:nn={visible,data}{\tl_set_eq:NN\l__gradtable_summary_scope_tl\l_keys_choice_tl}} % % % % %\DeclareDocumentCommand\gradsummary{O{} m} % {\PackageError{gradbars}{gradsummary~requires~gradtable}{Place~it~inside~gradtable.}} %\cs_new_protected:Npn\gradtableSummaryDeclare #1#2 % {\bool_if:NT\l__gradtable_summary_bool{\gradtableError{Only~one~summary~row~is~supported}} % \bool_set_true:N\l__gradtable_summary_bool % \tl_set:Nn\l__gradtable_summary_label_tl{#2} % \tl_set:Nn\l__gradtable_summary_scope_tl{visible} % \keys_set:nn{gradbars/table/summary}{#1}} % % % % % % %\gradtablestyle{academic}{preset=paper,rules=booktabs,header~align=c,row~stretch=1.2,column~sep=6pt} %\gradtablestyle{reference}{preset=paper,rules=booktabs,header~align=c, % row~stretch=1.25,column~sep=6pt,number~align=decimal} %\gradtablestyle{distribution}{preset=paper,rules=booktabs,header~align=c,row~stretch=1.6,column~sep=8pt,row~padding=3pt,graphic~width=45mm} %\gradtablestyle{accessible}{preset=paper,rules=rows,header~align=c,row~stretch=1.4,column~sep=7pt,row~padding=2pt,theme=accessible} %\gradtablestyle{matrix}{preset=paper,rules=rows,align=c,header~align=c, % row~stretch=1.35,column~sep=6pt,row~padding=1pt} %\gradtablestyle{compact}{preset=paper,rules=booktabs,header~align=c,row~stretch=1.05,column~sep=4pt, % graphic~width=24mm,label~width=12mm,text~width=18mm,font={\small}} %\gradtablestyle{dashboard}{preset=report,rules=rows,header~align=c,row~stretch=1.5,column~sep=8pt, % row~padding=2pt,theme=blue} %\ExplSyntaxOff % %\ExplSyntaxOff %\ExplSyntaxOff %% v0.0.7: stable lexicographic selection, automatic groups and group statistics. %\ExplSyntaxOn %\tl_new:N\l__gradtable_sort_keys_tl %\seq_new:N\l__gradtable_sort_keys_seq %\seq_new:N\l__gradtable_sort_parts_seq %\tl_new:N\l__gradtable_sort_id_tl %\tl_new:N\l__gradtable_sort_direction_tl %\clist_new:N\l__gradtable_sort_left_clist %\clist_new:N\l__gradtable_sort_right_clist %\tl_new:N\l__gradtable_sort_left_tl %\tl_new:N\l__gradtable_sort_right_tl %\bool_new:N\l__gradtable_sort_left_missing_bool %\bool_new:N\l__gradtable_sort_right_missing_bool %\int_new:N\l__gradtable_compare_int %\tl_new:N\l__gradtable_group_by_tl %\tl_new:N\l__gradtable_rank_scope_tl %\bool_new:N\l__gradtable_group_summary_bool %\tl_new:N\l__gradtable_group_summary_scope_tl %\tl_new:N\l__gradtable_group_summary_label_tl %\tl_new:N\l__gradtable_group_missing_label_tl %\prop_new:N\l__gradtable_group_ids_prop %\prop_new:N\l__gradtable_group_labels_prop %\prop_new:N\l__gradtable_row_groups_prop %\prop_new:N\l__gradtable_group_ends_prop %\prop_new:N\l__gradtable_group_best_prop %\prop_new:N\l__gradtable_group_second_prop %\prop_new:N\l__gradtable_group_summary_values_prop %\prop_new:N\g__gradtable_group_result_prop %\prop_new:N\g__gradtable_group_widths_prop %\int_new:N\l__gradtable_group_count_int %\int_new:N\l__gradtable_group_col_int %\int_new:N\l__gradtable_current_group_int %\tl_new:N\l__gradtable_group_key_tl %\tl_new:N\l__gradtable_group_id_tl %\seq_new:N\l__gradtable_group_input_seq %\cs_generate_variant:Nn\prop_put:Nnn{NVV,NxV} %\cs_generate_variant:Nn\prop_remove:Nn{Nx} %\keys_define:nn{gradbars/table} % {sort~keys .tl_set:N=\l__gradtable_sort_keys_tl, % group~by .tl_set:N=\l__gradtable_group_by_tl, % rank~scope .choices:nn={table,group}{\tl_set_eq:NN\l__gradtable_rank_scope_tl\l_keys_choice_tl}, % group~summary .bool_set:N=\l__gradtable_group_summary_bool, % group~summary~scope .choices:nn={visible,data}{\tl_set_eq:NN\l__gradtable_group_summary_scope_tl\l_keys_choice_tl}, % group~summary~label .tl_set:N=\l__gradtable_group_summary_label_tl, % group~missing~label .tl_set:N=\l__gradtable_group_missing_label_tl} % % % % % % % % % % % % % % % % %\ExplSyntaxOff % % %\ExplSyntaxOff %\ExplSyntaxOn %\tl_new:N\l__gradtable_default_formatter_tl %\tl_new:N\l__gradtable_formatter_tl %\tl_new:N\l__gradtable_default_number_align_tl %\tl_new:N\l__gradtable_number_align_tl %\bool_new:N\l__gradtable_number_align_explicit_bool %\prop_new:N\l__gradtable_formatters_prop %\prop_new:N\l__gradtable_number_align_prop %\prop_new:N\l__gradtable_decimal_left_prop %\prop_new:N\l__gradtable_decimal_right_prop %\dim_new:N\g__gradbars_decimal_left_dim %\dim_new:N\g__gradbars_decimal_right_dim %\dim_new:N\g__gradbars_decimal_full_dim %\box_new:N\l__gradbars_decimal_left_box %\box_new:N\l__gradbars_decimal_right_box %\tl_new:N\l__gradbars_decimal_integer_tl %\tl_new:N\l__gradbars_decimal_fraction_tl %\tl_new:N\l__gradbars_decimal_sign_tl %\seq_new:N\l__gradbars_decimal_parts_seq %\fp_new:N\l__gradbars_decimal_value_fp %\int_new:N\l__gradbars_decimal_exponent_int %\keys_define:nn{gradbars/table} % {formatter .code:n={\gradbarsCheckFormatter{#1}\tl_set:Nn\l__gradtable_default_formatter_tl{#1}}, % number~align .choices:nn={none,decimal}{\tl_set_eq:NN\l__gradtable_default_number_align_tl\l_keys_choice_tl}} %\keys_define:nn{gradbars/table/column} % {formatter .code:n={\gradbarsCheckFormatter{#1}\tl_set:Nn\l__gradtable_formatter_tl{#1}}, % number~align .choices:nn={none,decimal} % {\tl_set_eq:NN\l__gradtable_number_align_tl\l_keys_choice_tl\bool_set_true:N\l__gradtable_number_align_explicit_bool}} %\cs_new_protected:Npn\gradtableStoreNumericFormat #1 % {\str_if_eq:VnF\l__gradtable_type_tl{number} % {\bool_if:nT{\l__gradtable_number_align_explicit_bool && \str_if_eq_p:Vn\l__gradtable_number_align_tl{decimal}} % {\gradtableError{Decimal~alignment~requires~a~number~column}} % \tl_set:Nn\l__gradtable_number_align_tl{none}} % \prop_put:NnV\l__gradtable_formatters_prop{#1}\l__gradtable_formatter_tl % \prop_put:NnV\l__gradtable_number_align_prop{#1}\l__gradtable_number_align_tl} % % % % % %\int_new:N\l__gradtable_decimal_col_int % % %\gradtablestyle{research}{preset=paper,rules=booktabs,header~align=c,row~stretch=1.3, % column~sep=5pt,row~padding=1pt,group~sep=5pt,number~align=decimal, % summary~font={\bfseries\boldmath}} %\ExplSyntaxOff % % %\ExplSyntaxOff % %\ExplSyntaxOff %\RequirePackage{gradbars-table-data} %\RequirePackage{gradbars-table-layout} %\endinput % \end{macrocode} % \section{\texttt{gradbars-model.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Private validated model and layout preparation. %\ProvidesPackage{gradbars-model}[2026/10/25 v1.1.0 gradbars model] %\ExplSyntaxOn %\prop_new:N \l__gradbars_model_prop %\fp_new:N\l__gradbars_constant_value_fp %% Preserve the established +/-0.5 rule; use a bounded relative span only when %% that increment disappears at the numeric engine's significant-digit limit. %\cs_new_protected:Npn\__gradbars_constant_range:NN #1#2 % {\fp_set_eq:NN\l__gradbars_constant_value_fp#1 % \fp_sub:Nn#1{.5}\fp_add:Nn#2{.5} % \fp_compare:nNnF{#2}>{#1} % {\fp_set:Nn#1{max(-1e100,\l__gradbars_constant_value_fp-abs(\l__gradbars_constant_value_fp)*.05)} % \fp_set:Nn#2{min(1e100,\l__gradbars_constant_value_fp+abs(\l__gradbars_constant_value_fp)*.05)}}} % %\cs_new_protected:Npn \__gradbars_prepare_model: % { % \gradbars@validtrue % \gradbarsResolveScaleGroup % \gradbarsResolveShapeLengths % \gradbarsValidate % \gradbarsValidateExtras % \dim_compare:nNnT {\gradbars@rounded} < {0pt} % {\gradbarsFail{Rounded~radius~must~be~nonnegative}} % \dim_compare:nNnF {\gradbars@width} > {0pt} % {\gradbarsFail{Width~must~be~positive}} % \dim_compare:nNnF {\gradbars@height} > {0pt} % {\gradbarsFail{Height~must~be~positive}} % \prop_clear:N \l__gradbars_model_prop % \ifgradbars@valid % \prop_put:Nno \l__gradbars_model_prop {raw-value}{\gradbars@value} % \clist_map_inline:nn {min,max,zero,start,stop,end,shape} % {\prop_put:Nnx \l__gradbars_model_prop {##1}{\use:c{gradbars@##1}}} % \prop_put:Nnn \l__gradbars_model_prop {missing}{false} % \ifgradbars@missing % \prop_put:Nnn \l__gradbars_model_prop {missing}{true} % \fi % \fi % } %% Projection runs in the drawing font/coordinate context, preserving em/ex sizes. %\cs_new_protected:Npn \__gradbars_project_layout: % { % \pgfmathsetlengthmacro\gradbars@xzero{\gradbars@zero*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@xend{\gradbars@end*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@xstart{\gradbars@start*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@xstop{\gradbars@stop*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@radius % {min(\gradbars@rounded,.5*(\gradbars@height),.5*(\gradbars@width))} % } %\cs_new_protected:Npn \__gradbars_render: % { % \__gradbars_prepare_model: % \ifgradbars@valid \__gradbars_backend_core: \fi % } %\cs_new_eq:NN \gradbarsPrepareLayout \__gradbars_project_layout: %\cs_new_eq:NN \gradbars@render \__gradbars_render: %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-numbers.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-numbers}[2026/10/25 v1.1.0 gradbars numbers] %\ExplSyntaxOff %% v0.0.8: bounded scientific input, optional SI formatting and decimal anchors. %\ExplSyntaxOn %\def\gradbars@formatter{builtin} %\def\gradbars@unitcode{} %\def\gradbars@unittext{} %\pgfkeys{/gradbars, % formatter/.is~choice, % formatter/builtin/.code=\def\gradbars@formatter{builtin}, % formatter/siunitx/.code=\def\gradbars@formatter{siunitx}, % unit~code/.store~in=\gradbars@unitcode, % unit~text/.store~in=\gradbars@unittext} %\ExplSyntaxOn %\tl_new:N\l__gradbars_input_tl %\prg_new_protected_conditional:Npnn\gradbarsIfNumber:n #1{T,F,TF} % {\tl_set:Nx\l__gradbars_input_tl{#1}\tl_trim_spaces:N\l__gradbars_input_tl % \regex_match:nVTF{\A[+\-]?(\d{1,101}(\.\d{0,101})?|\.\d{1,101})([eE][+\-]?\d{1,3})?\Z}\l__gradbars_input_tl % {\fp_compare:nNnTF{abs(\l__gradbars_input_tl)}>{1e100} % {\prg_return_false:} % {\fp_compare:nNnTF{\l__gradbars_input_tl}={0}{\prg_return_true:} % {\fp_compare:nNnTF{abs(\l__gradbars_input_tl)}<{1e-100} % {\prg_return_false:}{\prg_return_true:}}}} % {\prg_return_false:}} %\prg_generate_conditional_variant:Nnn\gradbarsIfNumber:n{V}{T,F,TF} %\cs_set_protected:Npn\gradbarsCheckNumber #1#2 % {\gradbarsIfNumber:nF{#1} % {\gradbars@validfalse % \PackageError{gradbars}{Invalid~#2:~expected~a~decimal~or~scientific~number} % {Use~86.5~or~1.2e-3.~Nonzero~magnitudes~must~be~between~1e-100~and~1e100;~expressions,~NaN~and~infinity~are~not~accepted.}}} %\cs_new_protected:Npn\gradbarsValidateFormatter % {\str_if_eq:eeT{\gradbars@formatter}{siunitx} % {\@ifpackageloaded{siunitx} % {\cs_if_exist:NF\unit{\gradbarsFail{Formatter~siunitx~requires~siunitx~v3}}} % {\gradbarsFail{Formatter~siunitx~requires~loading~siunitx~v3~before~use}}} % \tl_if_empty:oF{\gradbars@unitcode} % {\str_if_eq:eeF{\gradbars@formatter}{siunitx}{\gradbarsFail{Unit~code~requires~formatter=siunitx}} % \tl_if_empty:oT{\gradbars@unittext}{\gradbarsFail{Unit~code~requires~readable~unit~text}} % \tl_if_empty:oF{\gradbars@unit}{\gradbarsFail{Use~unit~or~unit~code,~not~both}} % \str_if_eq:eeT{\gradbars@format}{percent}{\gradbarsFail{Percent~labels~cannot~use~unit~code}}}} %\cs_new_eq:NN\gradbarsValidateBeforeEight\gradbarsValidate %\cs_set_protected:Npn\gradbarsValidate{\gradbarsValidateFormatter\gradbarsValidateBeforeEight} %\cs_new_protected:Npn\gradbarsNumericSuffix % {\str_if_eq:eeTF{\gradbars@format}{percent}{\%} % {\tl_if_empty:oTF{\gradbars@unitcode}{\gradbars@unit} % {\,\exp_args:No\unit{\gradbars@unitcode}}}} %\cs_new_protected:Npn\gradbarsSIOptions % {\sisetup{mode=math,reset-math-version=false,propagate-math-font=true, % output-decimal-marker={.},round-mode=places,round-precision=\gradbars@precision, % round-pad=true,round-half=up,group-minimum-digits=4,group-separator={\,},exponent-mode=fixed,fixed-exponent=0} % \str_if_eq:eeT{\gradbars@numberformat}{scientific}{\sisetup{exponent-mode=scientific}} % \str_if_eq:eeT{\gradbars@numberformat}{grouped}{\sisetup{group-separator={,}}}} %\bool_new:N\l__gradbars_decimal_active_bool %\bool_new:N\l__gradbars_decimal_measure_bool %\cs_new_eq:NN\gradbarsSingleLabelBeforeEight\gradbarsSingleLabel %\cs_set_protected:Npn\gradbarsSingleLabel % {\gradbarsValidateFormatter % \bool_if:NTF\l__gradbars_decimal_active_bool % {\gradbarsDecimalPrint{\gradbars@number}} % {\str_if_eq:eeTF{\gradbars@formatter}{siunitx} % {\tl_if_empty:oTF{\gradbars@text} % {\ifgradbars@missing\gradbars@missingtext\else % \group_begin:\gradbarsSIOptions\exp_args:No\num{\gradbars@number}\gradbarsNumericSuffix\group_end:\fi} % {\gradbars@text}} % {\gradbarsSingleLabelBeforeEight}}} %\cs_new_eq:NN\gradbarsApplyAltBeforeEight\gradbarsApplyAlt %\cs_set_protected:Npn\gradbarsApplyAlt % {\tl_if_empty:oF{\gradbars@unitcode} % {\tl_put_right:Nx\l__gradbars_alt_tl{~Unit:~\exp_not:o{\gradbars@unittext}.}} % \gradbarsApplyAltBeforeEight} % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-render-tikz.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-render-tikz}[2026/10/25 v1.1.0 gradbars render-tikz] %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawBand % { % \clist_if_empty:NF \l__gradbars_band_clist % { % \pgfmathsetlengthmacro\gradbars@bandxlo{\gradbarsPosition{\gradbars@bandlo}*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@bandxhi{\gradbarsPosition{\gradbars@bandhi}*(\gradbars@width)} % \path[fill=\gradbars@bandcolor,fill~opacity=\gradbars@bandopacity,draw=none] % (\gradbars@bandxlo,-2pt) rectangle ([yshift=2pt]\gradbars@bandxhi,\gradbars@height); % } % } % %\ExplSyntaxOff %\ExplSyntaxOff %\def\gradbars@labelcontent{% % \ifx\gradbars@text\@empty % \ifgradbars@missing\gradbars@missingtext\else % \begingroup % \def\gradbars@temp{scientific}% % \ifx\gradbars@numberformat\gradbars@temp % \pgfmathprintnumber[sci,sci zerofill,precision=\gradbars@precision]{\gradbars@number}% % \else % \def\gradbars@temp{grouped}% % \ifx\gradbars@numberformat\gradbars@temp % \pgfmathprintnumber[fixed,fixed zerofill,precision=\gradbars@precision,1000 sep={\mathord{,}}]{\gradbars@number}% % \else % \pgfmathprintnumber[fixed,fixed zerofill,precision=\gradbars@precision,1000 sep={\,}]{\gradbars@number}% % \fi % \fi % \def\gradbars@temp{percent}% % \ifx\gradbars@format\gradbars@temp\%\else\gradbars@unit\fi % \endgroup % \fi % \else\gradbars@text\fi %} % %\def\gradbars@draw{% % \tikzset{gradbars label background/.style={}}% % \ifgradbars@print % \tikzset{gradbars label background/.style={fill=white,inner sep=1pt}}% % \fi % \gradbarsPrepareLayout % \gradbarsDrawTrack % \gradbarsDrawBand % \gradbarsDrawShape % \ifgradbars@spark\else\ifdim\gradbars@xzero>0pt % \draw[gradbarsInk!65,line width=.35pt] % (\gradbars@xzero,0)--(\gradbars@xzero,\gradbars@height); % \fi\fi % \ifx\gradbars@target\@empty\else % \pgfmathsetlengthmacro\gradbars@xtarget{\gradbars@targetpos*(\gradbars@width)}% % \draw[draw=\gradbars@targetcolor,line width=.6pt] % ([yshift=-1pt]\gradbars@xtarget,0)-- % ([yshift=1pt]\gradbars@xtarget,\gradbars@height); % \fi % \ifgradbars@missing\else\ifgradbars@error % \pgfmathsetlengthmacro\gradbars@xlo{\gradbars@errorlo*(\gradbars@width)}% % \pgfmathsetlengthmacro\gradbars@xhi{\gradbars@errorhi*(\gradbars@width)}% % \draw[draw=\gradbars@errorcolor,line width=.5pt] % ([yshift=.5*\gradbars@height]\gradbars@xlo,0)-- % ([yshift=.5*\gradbars@height]\gradbars@xhi,0); % \foreach \gradbars@cap in {\gradbars@xlo,\gradbars@xhi}{ % \draw[draw=\gradbars@errorcolor,line width=.5pt] % ([yshift=.2*\gradbars@height]\gradbars@cap,0)-- % ([yshift=.8*\gradbars@height]\gradbars@cap,0); % } % \fi\fi % \gradbarsDrawReferences % \gradbarsDrawOverflow % \gradbarsDrawChange % \gradbarsResetLabels % \ifgradbars@stack % \gradbarsDrawSegmentLabels % \ifgradbars@legend\gradbarsDrawLegend\fi % \fi % \gradbarsDrawMainLabel % \gradbarsResolveBaseline % \coordinate (gradbarsbaseline) at (0,\gradbars@baseliney); % \path[use as bounding box] (0,-\gradbars@rowpadding) % rectangle (\gradbars@width,{\gradbars@height+\gradbars@rowpadding}); %} %\ExplSyntaxOn %\cs_new_protected:Npn \__gradbars_render_tikz: { % \ifpgfpicture % \begin{scope}\gradbars@draw\end{scope}% % \else % \gradbarsPrepareAlt % \tikz[baseline=(gradbarsbaseline)]{\gradbars@draw}% % \fi %} % %\ExplSyntaxOff % %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsContrast #1 % { % \convertcolorspec{named}{#1}{rgb}\gradbars@rgb % \clist_set:Nx \l_tmpa_clist {\gradbars@rgb} % \fp_zero:N \l__gradbars_luminance_fp % \int_step_inline:nn {3} % { % \fp_set:Nn \l_tmpa_fp {\clist_item:Nn \l_tmpa_clist {##1}} % \fp_compare:nNnTF {\l_tmpa_fp} > {0.04045} % {\fp_set:Nn \l_tmpa_fp {((\l_tmpa_fp+0.055)/1.055)^2.4}} % {\fp_set:Nn \l_tmpa_fp {\l_tmpa_fp/12.92}} % \fp_add:Nn \l__gradbars_luminance_fp % {\l_tmpa_fp*\clist_item:nn {0.2126,0.7152,0.0722}{##1}} % } % \fp_compare:nNnTF {\l__gradbars_luminance_fp} > {0.179} % {\def\gradbars@labelcolor{black}}{\def\gradbars@labelcolor{white}} % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawSegmentLabels % { % \str_if_eq:eeF {\gradbars@segmentlabels}{none} % { % \gradbarsStackReset % \int_zero:N \l__gradbars_index_int % \clist_map_inline:Nn \l__gradbars_stack_clist % { % \int_incr:N \l__gradbars_index_int % \gradbarsStackStep{##1} % \pgfmathsetlengthmacro\gradbars@segmentlo{\gradbarsPosition{\l__gradbars_before_fp}*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@segmenthi{\gradbarsPosition{\l__gradbars_sum_fp}*(\gradbars@width)} % \ifdim\gradbars@segmenthi>\gradbars@segmentlo\relax % \gradbarsCategoryColor{\l__gradbars_index_int} % \def\gradbars@segmentcontent % {\def\gradbars@text{}\def\gradbars@unit{}\def\gradbars@unitcode{}\def\gradbars@unittext{}\def\gradbars@format{value} % \cs_set:Npx \gradbars@number {\fp_eval:n {##1}} % \str_case_e:nn {\gradbars@segmentlabels} % {{percent}{\def\gradbars@format{percent}} % {name~percent}{\def\gradbars@format{percent}}} % \str_if_eq:eeT {\gradbars@format}{percent} % {\cs_set:Npx \gradbars@number {\fp_eval:n {100*abs(##1)/\gradbars@gross}}} % \tl_clear:N \l_tmpb_tl % \str_case_e:nn {\gradbars@segmentlabels} % {{name}{\tl_set:Nn \l_tmpb_tl {name}} % {name~value}{\tl_set:Nn \l_tmpb_tl {both}} % {name~percent}{\tl_set:Nn \l_tmpb_tl {both}}} % \tl_if_empty:NF \l_tmpb_tl % {\clist_item:Nn \l__gradbars_names_clist {\l__gradbars_index_int}} % \str_if_eq:VnT \l_tmpb_tl {both}{:\space} % \str_if_eq:VnF \l_tmpb_tl {name}{\gradbarsSingleLabel}} % \gradbarsMeasure\gradbars@segmentbox\gradbars@segmentfont{\gradbars@segmentcontent} % \gradbarsPlaceSegment % \fi % } % } % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawLegend % { % \dim_set:Nn \l_tmpa_dim {6pt} % \int_zero:N \l__gradbars_index_int % \clist_map_inline:Nn \l__gradbars_names_clist % { % \int_incr:N \l__gradbars_index_int % \gradbarsCategoryColor{\l__gradbars_index_int} % \gradbarsMeasure\gradbars@segmentbox\gradbars@font % {\parbox[t]{\dimexpr\gradbars@width-14pt\relax}{\raggedright\strut ##1\strut}} % \ifgradbars@outline % \draw[draw=\gradbars@segmentcolor,line~width=\gradbars@outlinewidth] % (0,-\dim_use:N \l_tmpa_dim) rectangle (8pt,-\dim_eval:n {\l_tmpa_dim+6pt}); % \else % \path[fill=\gradbars@segmentcolor,draw=none] % (0,-\dim_use:N \l_tmpa_dim) rectangle (8pt,-\dim_eval:n {\l_tmpa_dim+6pt}); % \gradbarsPatternRect{\l__gradbars_index_int}{0}{-\dim_use:N \l_tmpa_dim} % {8pt}{-\dim_eval:n {\l_tmpa_dim+6pt}} % \fi % \node[anchor=north~west,inner~sep=0pt,outer~sep=0pt,text=gradbarsInk] % at (14pt,-\dim_use:N \l_tmpa_dim){\usebox\gradbars@segmentbox}; % \dim_add:Nn \l_tmpa_dim {\ht\gradbars@segmentbox+\dp\gradbars@segmentbox+4pt} % } % } %\ExplSyntaxOff %\ExplSyntaxOn %\dim_new:N \l__gradbars_labelslot_dim %\cs_new_protected:Npn \__gradbars_draw_graphic_label: % { % \str_if_eq:eeF {\gradbars@label}{none} % { % \gradbarsMeasure\gradbars@labelbox\gradbars@font{\gradbars@labelcontent} % \let\gradbars@placement\gradbars@label % \gradbars@insidefalse % \str_if_eq:eeT {\gradbars@placement}{auto} % {\def\gradbars@placement{outside} % \ifdim\dimexpr\wd\gradbars@labelbox+4pt\relax<\dimexpr\gradbars@xstop-\gradbars@xstart\relax % \def\gradbars@placement{center}\fi} % \str_if_eq:eeF {\gradbars@labeloverflow}{allow} % {\str_if_eq:eeT {\gradbars@placement}{inside} % {\ifdim\dimexpr\wd\gradbars@labelbox+4pt\relax>\gradbars@width\relax % \def\gradbars@placement{outside}\fi} % \str_if_eq:eeT {\gradbars@placement}{end} % {\ifdim\wd\gradbars@labelbox>\gradbars@width\relax % \def\gradbars@placement{outside}\fi}} % \str_case_e:nn {\gradbars@placement} % {{inside}{\gradbars@insidetrue}{center}{\gradbars@insidetrue}} % \ifgradbars@inside % \str_if_eq:eeF {\gradbars@shape}{bar} % {\def\gradbars@placement{outside}\gradbars@insidefalse} % \ifgradbars@stack % \fp_compare:nNnT {\gradbars@negative} < {0} % {\def\gradbars@placement{outside}\gradbars@insidefalse} % \fi % \ifgradbars@compare \def\gradbars@placement{outside}\gradbars@insidefalse\fi % \ifgradbars@outline \def\gradbars@placement{outside}\gradbars@insidefalse\fi % \ifgradbars@rangemode % \tl_if_empty:oF {\gradbars@rangepoint} % {\def\gradbars@placement{outside}\gradbars@insidefalse} % \fi % \fi % \ifgradbars@inside % \str_if_eq:eeF {\gradbars@labeloverflow}{allow} % {\ifdim\dimexpr\ht\gradbars@labelbox+\dp\gradbars@labelbox+2pt\relax>\gradbars@height\relax % \def\gradbars@placement{outside}\gradbars@insidefalse\fi} % \ifgradbars@stack % \str_if_eq:eeF {\gradbars@segmentlabels}{none} % {\def\gradbars@placement{outside}\gradbars@insidefalse} % \fi % \ifgradbars@error \def\gradbars@placement{outside}\gradbars@insidefalse\fi % \ifgradbars@inside % \str_if_eq:eeTF {\gradbars@placement}{center} % {\pgfmathsetlengthmacro\gradbars@labelx{.5*(\gradbars@xstart+\gradbars@xstop)}} % {\pgfmathsetlengthmacro\gradbars@labelx{\gradbars@width-2pt-.5*\wd\gradbars@labelbox}} % \ifx\gradbars@target\@empty\else % \pgfmathsetlengthmacro\gradbars@distance{abs(\gradbars@xtarget-\gradbars@labelx)} % \ifdim\gradbars@distance<\dimexpr.5\wd\gradbars@labelbox+2pt\relax % \def\gradbars@placement{outside}\gradbars@insidefalse\fi % \fi % \fi % \fi % \let\gradbars@labelcolor\gradbars@textcolor % \str_if_eq:eeT {\gradbars@textcolor}{auto}{\gradbarsMainBackground} % \gradbarsMeasure\gradbars@labelbox\gradbars@font{\color{\gradbars@labelcolor}\gradbars@labelcontent} % \ifgradbars@inside % \node[inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % [gradbars~label~background] % at (\gradbars@labelx,.5*\gradbars@height){\usebox\gradbars@labelbox}; % \else % \str_if_eq:eeTF {\gradbars@placement}{left} % {\dim_set:Nn \l__gradbars_labelslot_dim {\gradbars@leftlabelwidth} % \str_if_eq:eeF {\gradbars@labeloverflow}{allow} % {\dim_set:Nn \l__gradbars_labelslot_dim % {\dim_max:nn {\l__gradbars_labelslot_dim}{\wd\gradbars@labelbox}}} % \node[anchor=east,inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % at (-\gradbars@gap,.5*\gradbars@height) % {\makebox[\dim_use:N \l__gradbars_labelslot_dim][r]{\usebox\gradbars@labelbox}};} % {\str_if_eq:eeTF {\gradbars@placement}{end} % {\pgfmathsetlengthmacro\gradbars@labelx % {max(.5*\wd\gradbars@labelbox,min(\gradbars@xend,\gradbars@width-.5*\wd\gradbars@labelbox))} % \node[anchor=south,inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % at (\gradbars@labelx,\dim_use:N \l__gradbars_top_dim){\usebox\gradbars@labelbox};} % {\dim_set:Nn \l__gradbars_labelslot_dim {\gradbars@labelwidth} % \str_if_eq:eeF {\gradbars@labeloverflow}{allow} % {\dim_set:Nn \l__gradbars_labelslot_dim % {\dim_max:nn {\l__gradbars_labelslot_dim}{\wd\gradbars@labelbox}}} % \node[anchor=west,inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % at ([xshift=\gradbars@gap,yshift=.5*\gradbars@height]\gradbars@width,0) % {\makebox[\dim_use:N \l__gradbars_labelslot_dim][r]{\usebox\gradbars@labelbox}};}} % \fi % } % } %\cs_new_protected:Npn \gradbarsDrawMainLabel % {\bool_lazy_and:nnTF % {\str_if_eq_p:ee{\gradbars@labelalign}{cell}} % {\str_if_eq_p:ee{\gradbars@label}{inside} || \str_if_eq_p:ee{\gradbars@label}{auto}} % {\def\gradbars@placement{center}\gradbars@insidetrue % \pgfmathsetlengthmacro\gradbars@labelx{.5*\gradbars@width} % \let\gradbars@labelcolor\gradbars@textcolor % \str_if_eq:eeT{\gradbars@textcolor}{auto}{\gradbarsMainBackground} % \gradbarsMeasure\gradbars@labelbox\gradbars@font % {\color{\gradbars@labelcolor}\gradbars@labelcontent} % \node[inner~sep=0pt,outer~sep=0pt,text=\gradbars@labelcolor] % [gradbars~label~background] at (\gradbars@labelx,.5*\gradbars@height) % {\usebox\gradbars@labelbox};} % {\__gradbars_draw_graphic_label:}} %\cs_new_protected:Npn \gradbarsResolveBaseline % { % \pgfmathsetlengthmacro\gradbars@baseliney{.5*\gradbars@height-\gradbars@baselineoffset} % \str_case_e:nn {\gradbars@baseline} % { % {center}{\pgfmathsetlengthmacro\gradbars@baseliney{.5*\gradbars@height}} % {bottom}{\def\gradbars@baseliney{0pt}} % {text} % {\str_if_eq:eeT {\gradbars@label}{none} % {\gradbarsMeasure\gradbars@labelbox\gradbars@font{\strut}} % \pgfmathsetlengthmacro\gradbars@baseliney % {.5*\gradbars@height-.5*(\ht\gradbars@labelbox-\dp\gradbars@labelbox)} % \str_if_eq:eeF {\gradbars@label}{none} % {\str_if_eq:eeT {\gradbars@placement}{end} % {\pgfmathsetlengthmacro\gradbars@baseliney % {\dim_use:N \l__gradbars_top_dim+\dp\gradbars@labelbox}}}} % } % \pgfmathsetlengthmacro\gradbars@baseliney{\gradbars@baseliney-\gradbars@baselineshift} % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawTrack % { % \str_if_eq:eeTF {\gradbars@shape}{lollipop} % {\draw[draw=\gradbars@track,line~width=\gradbars@stemwidth] % (0,.5*\gradbars@height)--(\gradbars@width,.5*\gradbars@height);} % {\ifgradbars@outline % \path[rounded~corners=\gradbars@radius,fill=\gradbars@track, % draw=gradbarsInk!35,line~width=\gradbars@outlinewidth] % (0,0) rectangle (\gradbars@width,\gradbars@height); % \else % \path[rounded~corners=\gradbars@radius,fill=\gradbars@track,draw=none] % (0,0) rectangle (\gradbars@width,\gradbars@height); % \fi} % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawDot #1 % { % \pgfmathsetlengthmacro\gradbars@dotradius{min(\gradbars@markersize,.5*\gradbars@height)} % \ifgradbars@outline % \path[fill=white,draw=\gradbars@left,line~width=\gradbars@stemwidth] % (#1,.5*\gradbars@height) circle[radius=\gradbars@dotradius]; % \else % \path[fill=\gradbars@left,draw=none] % (#1,.5*\gradbars@height) circle[radius=\gradbars@dotradius]; % \fi % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawShape % { % \str_if_eq:eeTF {\gradbars@shape}{lollipop} % {\ifgradbars@missing\else % \draw[draw=\gradbars@left,line~width=\gradbars@stemwidth] % (\gradbars@xzero,.5*\gradbars@height)--(\gradbars@xend,.5*\gradbars@height); % \gradbarsDrawDot{\gradbars@xend} % \fi} % { % \ifgradbars@compare % \ifgradbars@referencemissing\else % \pgfmathsetlengthmacro\gradbars@xref{\gradbarsPosition{\gradbars@reference}*(\gradbars@width)} % \ifgradbars@outline % \draw[draw=\gradbars@comparecolor,line~width=\gradbars@outlinewidth] % (\gradbars@xzero,0) rectangle (\gradbars@xref,\gradbars@height); % \else % \path[rounded~corners=\gradbars@radius,fill=\gradbars@comparecolor,draw=none] % (\gradbars@xzero,0) rectangle (\gradbars@xref,\gradbars@height); % \fi % \fi % \begin{scope}[yshift={.5*(1-\gradbars@compareratio)*\gradbars@height}] % \pgfmathsetlengthmacro\gradbars@height{\gradbars@compareratio*\gradbars@height} % \pgfmathsetlengthmacro\gradbars@radius{min(\gradbars@radius,.5*\gradbars@height)} % \gradbarsDrawBarBody % \end{scope} % \else % \gradbarsDrawBarBody % \ifgradbars@rangemode\ifgradbars@missing\else % \draw[draw=\gradbars@left,line~width=\gradbars@stemwidth] % (\gradbars@xstart,0)--(\gradbars@xstart,\gradbars@height) % (\gradbars@xstop,0)--(\gradbars@xstop,\gradbars@height); % \tl_if_empty:oF {\gradbars@rangepoint} % {\pgfmathsetlengthmacro\gradbars@xpoint{\gradbarsPosition{\gradbars@rangepoint}*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@dotradius{min(\gradbars@markersize,.5*\gradbars@height)} % \gradbarsDrawMarker{\gradbars@xpoint}{.5*\gradbars@height}{gradbarsInk}{hollow}} % \fi\fi % \fi % } % } %\ExplSyntaxOff %\ExplSyntaxOff %\def\gradbarsDrawBarBody{% % \ifdim\gradbars@xstop>\gradbars@xstart\relax % \pgfmathsetlengthmacro\gradbars@fillradius{min(\gradbars@radius,.5*(\gradbars@xstop-\gradbars@xstart))}% % \begin{scope} % \clip[rounded corners=\gradbars@radius] % (0,0) rectangle (\gradbars@width,\gradbars@height); % \ifgradbars@stack % \clip[rounded corners=\gradbars@fillradius] % (\gradbars@xstart,0) rectangle (\gradbars@xstop,\gradbars@height); % \gradbarsDrawStack % \else\ifgradbars@outline % \draw[rounded corners=\gradbars@fillradius,draw=\gradbars@left,line width=\gradbars@outlinewidth] % (\gradbars@xstart,0) rectangle (\gradbars@xstop,\gradbars@height); % \else\ifgradbars@gradient % \path[rounded corners=\gradbars@fillradius,shade, % left color=\gradbars@left,right color=\gradbars@right] % (\gradbars@xstart,0) rectangle (\gradbars@xstop,\gradbars@height); % \else % \path[rounded corners=\gradbars@fillradius,fill=\gradbars@left,draw=none] % (\gradbars@xstart,0) rectangle (\gradbars@xstop,\gradbars@height); % \fi\fi\fi % \ifgradbars@stack\else\ifgradbars@outline\else % \clip[rounded corners=\gradbars@fillradius] % (\gradbars@xstart,0) rectangle (\gradbars@xstop,\gradbars@height); % \gradbarsPatternRect{0}{\gradbars@xstart}{0}{\gradbars@xstop}{\gradbars@height} % \fi % \fi % \end{scope} % \fi %} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN \gradbarsShapeBeforeThree \gradbarsDrawShape %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn \gradbarsDrawShape % { % \str_case_e:nnF {\gradbars@shape} % {{dumbbell}{\gradbarsDrawDumbbell}{sparkline}{\gradbarsDrawSpark}} % {\gradbarsShapeBeforeThree} % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawDumbbell % { % \gradbarsMarkerBounds % \ifgradbars@referencemissing\else % \pgfmathsetlengthmacro\gradbars@xref{\gradbarsPosition{\gradbars@reference}*\gradbars@width} % \ifgradbars@missing\else % \draw[draw=\gradbars@left,line~width=\gradbars@stemwidth] % (\gradbars@xref,.5*\gradbars@height)--(\gradbars@xend,.5*\gradbars@height); % \fi % \group_begin:\let\gradbars@left\gradbars@comparecolor % \gradbars@outlinetrue\gradbarsDrawDot{\gradbars@xref}\group_end: % \fi % \ifgradbars@missing\else\gradbarsDrawDot{\gradbars@xend}\fi % } %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsMarkerBounds % {\path % (-\gradbars@markersize,-\gradbars@markersize) rectangle % ([xshift=\gradbars@markersize,yshift=\gradbars@markersize]\gradbars@width,\gradbars@height);} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN \gradbarsTrackBeforeThree \gradbarsDrawTrack %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn \gradbarsDrawTrack % {\group_begin: % \str_if_eq:eeT {\gradbars@shape}{dumbbell}{\def\gradbars@shape{lollipop}} % \gradbarsTrackBeforeThree\group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawReferences % {\int_zero:N \l_tmpa_int % \clist_map_inline:Nn \l__gradbars_refs_clist % {\seq_set_split:Nnn \l__gradbars_record_seq {/}{##1} % \tl_set:Nx \l__gradbars_record_color_tl {\seq_item:Nn \l__gradbars_record_seq {2}} % \tl_set:Nx \l__gradbars_record_style_tl {\seq_item:Nn \l__gradbars_record_seq {3}} % \tl_set:Nx \l__gradbars_record_name_tl {\seq_item:Nn \l__gradbars_record_seq {4}} % \pgfmathsetlengthmacro\gradbars@rx % {\gradbarsPosition{\seq_item:Nn \l__gradbars_record_seq {1}}*(\gradbars@width)} % \draw[draw=\l__gradbars_record_color_tl,line~width=.6pt, % \l__gradbars_record_style_tl] % (\gradbars@rx,-1pt)--(\gradbars@rx,{\gradbars@height+1pt}); % \tl_if_blank:VF \l__gradbars_record_name_tl % {\node[anchor=south,inner~sep=1pt,font=\scriptsize, % text=\l__gradbars_record_color_tl] % at (\gradbars@rx,{\gradbars@height+2pt+10pt*\int_mod:nn{\l_tmpa_int}{2}}) % {\l__gradbars_record_name_tl};} % \int_incr:N \l_tmpa_int}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN \gradbarsBandBeforeBullet \gradbarsDrawBand %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn \gradbarsDrawBand % {\ifgradbars@bullet % \fp_set:Nn \l__gradbars_band_start_fp {\gradbars@min} % \clist_map_inline:Nn \l__gradbars_bands_clist % {\seq_set_split:Nnn \l__gradbars_record_seq {/}{##1} % \tl_set:Nx \l__gradbars_record_color_tl {\seq_item:Nn \l__gradbars_record_seq {2}} % \pgfmathsetlengthmacro\gradbars@bx % {\gradbarsPosition{\l__gradbars_band_start_fp}*(\gradbars@width)} % \pgfmathsetlengthmacro\gradbars@ex % {\gradbarsPosition{\seq_item:Nn \l__gradbars_record_seq {1}}*(\gradbars@width)} % \path[fill=\l__gradbars_record_color_tl,draw=none] % (\gradbars@bx,0) rectangle (\gradbars@ex,\gradbars@height); % \fp_set:Nn \l__gradbars_band_start_fp {\seq_item:Nn \l__gradbars_record_seq {1}}} % \fi\gradbarsBandBeforeBullet} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN \gradbarsShapeBeforeBullet \gradbarsDrawShape %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn \gradbarsDrawShape % {\ifgradbars@bullet % \begin{scope}[yshift=.3*\gradbars@height,yscale=.4] % \gradbarsShapeBeforeBullet % \end{scope} % \else\gradbarsShapeBeforeBullet\fi} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawMarker #1#2#3#4 % {\group_begin: % \tl_set:Nn \l_tmpa_tl {#3} % \str_if_eq:eeT {#4}{hollow}{\tl_set:Nn \l_tmpa_tl {white}} % \begin{scope}[shift={(#1,#2)}] % \tikzset{gradbars~mark/.style={draw=#3,fill=\l_tmpa_tl,line~width=\gradbars@stemwidth}} % \str_case_e:nn {\gradbars@markershape} % {{circle}{\path[gradbars~mark] (0,0) circle[radius=\gradbars@markersize];} % {square}{\path[gradbars~mark] (-\gradbars@markersize,-\gradbars@markersize) % rectangle (\gradbars@markersize,\gradbars@markersize);} % {diamond}{\path[gradbars~mark] (0,\gradbars@markersize)--(\gradbars@markersize,0) % --(0,-\gradbars@markersize)--(-\gradbars@markersize,0)--cycle;} % {triangle}{\path[gradbars~mark] (0,\gradbars@markersize) % --(\gradbars@markersize,-\gradbars@markersize)--(-\gradbars@markersize,-\gradbars@markersize)--cycle;}} % \end{scope}\group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn \gradbarsDrawDot #1 % {\ifgradbars@outline % \gradbarsDrawMarker{#1}{.5*\gradbars@height}{\gradbars@left}{hollow} % \else\gradbarsDrawMarker{#1}{.5*\gradbars@height}{\gradbars@left}{\gradbars@markerfill}\fi} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawOverflow % {\str_if_eq:eeF {\gradbars@overflowmark}{none} % {\bool_set_true:N \l__gradbars_overflow_known_bool % \ifgradbars@missing\bool_set_false:N \l__gradbars_overflow_known_bool\fi % \ifgradbars@compare\ifgradbars@referencemissing\else % \bool_set_true:N \l__gradbars_overflow_known_bool\fi\fi % \ifgradbars@spark\bool_set_eq:NN \l__gradbars_overflow_known_bool \l__gradbars_series_any_bool\fi % \bool_if:NT \l__gradbars_overflow_known_bool { % \fp_set:Nn \l__gradbars_raw_low_fp {\gradbars@value} % \fp_set_eq:NN \l__gradbars_raw_high_fp \l__gradbars_raw_low_fp % \ifgradbars@stack % \fp_set:Nn \l__gradbars_raw_low_fp {\gradbars@negative} % \fp_set:Nn \l__gradbars_raw_high_fp {\gradbars@positive} % \fi % \ifgradbars@rangemode % \fp_set:Nn \l__gradbars_raw_low_fp {\gradbars@rangelo} % \fp_set:Nn \l__gradbars_raw_high_fp {\gradbars@rangehi} % \fi % \ifgradbars@compare\ifgradbars@referencemissing\else % \fp_set:Nn \l__gradbars_raw_low_fp {min(\gradbars@value,\gradbars@reference)} % \fp_set:Nn \l__gradbars_raw_high_fp {max(\gradbars@value,\gradbars@reference)} % \ifgradbars@missing % \fp_set:Nn \l__gradbars_raw_low_fp {\gradbars@reference} % \fp_set_eq:NN \l__gradbars_raw_high_fp \l__gradbars_raw_low_fp % \fi % \fi\fi % \ifgradbars@error % \fp_set:Nn \l__gradbars_raw_low_fp {min(\l__gradbars_raw_low_fp,\gradbars@value-\gradbars@errorminus)} % \fp_set:Nn \l__gradbars_raw_high_fp {max(\l__gradbars_raw_high_fp,\gradbars@value+\gradbars@errorplus)} % \fi % \ifgradbars@spark % \fp_set_eq:NN \l__gradbars_raw_low_fp \l__gradbars_series_min_fp % \fp_set_eq:NN \l__gradbars_raw_high_fp \l__gradbars_series_max_fp % \fi % \fp_compare:nNnT {\l__gradbars_raw_low_fp} < {\gradbars@min}{\gradbarsOverflowSide{0pt}{-1}} % \fp_compare:nNnT {\l__gradbars_raw_high_fp} > {\gradbars@max}{\gradbarsOverflowSide{\gradbars@width}{1}} % }}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradbarsDrawChange % {\ifgradbars@compare\ifgradbars@missing\else\ifgradbars@referencemissing\else % \str_if_eq:eeF {\gradbars@change}{none} % {\pgfmathsetlengthmacro\gradbars@cx{\gradbarsPosition{\gradbars@reference}*\gradbars@width} % \begin{scope}[yshift={\gradbars@height+5pt}] % \str_if_eq:eeTF {\gradbars@change}{arrow} % {\dim_compare:nNnF {\gradbars@xend} = {\gradbars@cx} % {\draw[->,draw=gradbarsInk,line~width=.5pt](\gradbars@cx,0)--(\gradbars@xend,0);}} % {\draw[draw=gradbarsInk,line~width=.5pt] % (\gradbars@cx,-2pt)--(\gradbars@cx,0)--(\gradbars@xend,0)--(\gradbars@xend,-2pt);} % \node[anchor=south,inner~sep=1pt,font=\scriptsize,text=gradbarsInk] % at ({.5*(\gradbars@cx+\gradbars@xend)},1pt){\gradbarsChangeLabel}; % \end{scope}} % \fi\fi\fi} %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-table-data.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Private table data layer. %\ProvidesPackage{gradbars-table-data}[2026/10/25 v1.1.0 gradbars table data] %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableRank % {\prop_clear:N\l__gradtable_best_prop\prop_clear:N\l__gradtable_second_prop % \int_zero:N\l__gradtable_rank_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_rank_col_int % \str_if_eq:eeF{\prop_item:Nn\l__gradtable_marks_prop{##1}}{none} % {\group_begin:\gradtableConfigure{##1} % \tl_gset:Nx\g__gradtable_rank_direction_tl{\gradbars@better}\group_end: % \tl_set_eq:NN\l__gradtable_rank_direction_tl\g__gradtable_rank_direction_tl % \str_case:VnF\l__gradtable_rank_direction_tl{{higher}{}{lower}{}} % {\gradtableError{Mark~requires~better=higher~or~lower}} % \seq_clear:N\l__gradtable_rank_seq % \seq_map_inline:Nn\l__gradtable_rows_seq % {\clist_set:Nn\l__gradtable_cells_clist{####1} % \tl_set:Nx\l__gradtable_rank_value_tl % {\clist_item:Nn\l__gradtable_cells_clist{\l__gradtable_rank_col_int}} % \tl_trim_spaces:N\l__gradtable_rank_value_tl % \gradbarsIfNumber:VT\l__gradtable_rank_value_tl % {\seq_put_right:Nx\l__gradtable_rank_seq{\fp_eval:n{\l__gradtable_rank_value_tl}}}} % \seq_remove_duplicates:N\l__gradtable_rank_seq % \seq_sort:Nn\l__gradtable_rank_seq % {\str_if_eq:VnTF\l__gradtable_rank_direction_tl{higher} % {\fp_compare:nNnTF{####1}<{####2}{\sort_return_swapped:}{\sort_return_same:}} % {\fp_compare:nNnTF{####1}>{####2}{\sort_return_swapped:}{\sort_return_same:}}} % \seq_if_empty:NF\l__gradtable_rank_seq % {\prop_put:Nnx\l__gradtable_best_prop{##1}{\seq_item:Nn\l__gradtable_rank_seq{1}}} % \int_compare:nNnT{\seq_count:N\l__gradtable_rank_seq}>{1} % {\prop_put:Nnx\l__gradtable_second_prop{##1}{\seq_item:Nn\l__gradtable_rank_seq{2}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableImportCSV % {\seq_if_empty:NF\l__gradtable_rows_seq % {\gradtableError{Data~tables~cannot~also~contain~manual~rows}} % \prop_if_exist:cTF{l__gradbars_csv_\l__gradtable_data_tl _prop} % {\seq_map_inline:Nn\l__gradtable_columns_seq % {\tl_set:Nn\l__gradtable_id_tl{##1} % \prop_get:NnN\l__gradtable_sources_prop{##1}\l__gradtable_import_source_tl % \exp_args:NVV\gradbarsCSVColumn\l__gradtable_data_tl\l__gradtable_import_source_tl % \ifgradbars@valid\else\bool_set_false:N\l__gradtable_valid_bool\fi} % \bool_if:NT\l__gradtable_valid_bool % {\int_step_inline:nn{\prop_item:cn{l__gradbars_csv_\l__gradtable_data_tl _prop}{rows}} % {\int_set:Nn\l__gradtable_import_row_int{##1} % \tl_clear:N\l__gradtable_import_row_tl % \seq_map_inline:Nn\l__gradtable_columns_seq % {\tl_set:Nn\l__gradtable_id_tl{####1} % \prop_get:NnN\l__gradtable_sources_prop{####1}\l__gradtable_import_source_tl % \use:x{\exp_not:N\gradbarsCSVGet{\l__gradtable_data_tl}{##1}{\l__gradtable_import_source_tl}} % \str_if_eq:eeF{\prop_item:Nn\l__gradtable_types_prop{####1}}{text} % {\gradtableMapCSVMissing} % \tl_if_empty:NF\l__gradtable_import_row_tl{\tl_put_right:Nn\l__gradtable_import_row_tl{,}} % \tl_put_right:Nx\l__gradtable_import_row_tl{{\exp_not:V\l__gradbars_csv_value_tl}}} % \exp_args:NV\gradtableRow\l__gradtable_import_row_tl} % \seq_set_eq:NN\l__gradtable_data_rows_seq\l__gradtable_rows_seq % \gradtableSelectRows}} % {\gradtableError{Unknown~CSV~dataset:~\l__gradtable_data_tl}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableMapCSVMissing % {\prop_get:cnN{l__gradbars_csv_\l__gradtable_data_tl _prop}{missing}\l_tmpa_tl % \clist_set:NV\l__gradbars_csv_missing_clist\l_tmpa_tl % \bool_set_false:N\l_tmpa_bool % \tl_if_blank:VT\l__gradbars_csv_value_tl{\bool_set_true:N\l_tmpa_bool} % \clist_map_inline:Nn\l__gradbars_csv_missing_clist % {\str_if_eq:eeT{\l__gradbars_csv_value_tl}{\tl_to_str:n{##1}}{\bool_set_true:N\l_tmpa_bool}} % \bool_if:NT\l_tmpa_bool{\tl_set:Nn\l__gradbars_csv_value_tl{NA}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableScaleValue #1 % {\tl_set:Nn\l_tmpb_tl{#1}\tl_trim_spaces:N\l_tmpb_tl % \tl_if_empty:NF\l_tmpb_tl % {\str_if_eq:VnF\l_tmpb_tl{NA} % {\gradbarsIfNumber:VTF\l_tmpb_tl % {\bool_if:NTF\l__gradtable_seen_bool % {\fp_set:Nn\l__gradtable_min_fp{min(\l__gradtable_min_fp,\l_tmpb_tl)} % \fp_set:Nn\l__gradtable_max_fp{max(\l__gradtable_max_fp,\l_tmpb_tl)}} % {\fp_set:Nn\l__gradtable_min_fp{\l_tmpb_tl} % \fp_set:Nn\l__gradtable_max_fp{\l_tmpb_tl} % \bool_set_true:N\l__gradtable_seen_bool}} % {\gradtableError{Auto~scale~requires~decimal~or~scientific~numbers~or~NA}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableScaleCell #1 % {\str_case:VnF\l__gradtable_type_tl % {{compare}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{/}{#1}} % {dumbbell}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{/}{#1}} % {interval}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{/}{#1}} % {boxplot}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{,}{#1}} % {spark}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{,}{#1}} % {stack}{\seq_set_split:Nnn\l__gradtable_scale_values_seq{,}{#1}}} % {\seq_set_from_clist:Nn\l__gradtable_scale_values_seq{{#1}}} % \str_if_eq:VnTF\l__gradtable_type_tl{stack} % {\fp_zero:N\l__gradtable_positive_fp\fp_zero:N\l__gradtable_negative_fp % \str_if_eq:nnF{#1}{NA} % {\seq_map_inline:Nn\l__gradtable_scale_values_seq % {\gradbars@validtrue\gradbarsCheckNumber{##1}{stack~segment} % \ifgradbars@valid % \fp_compare:nNnTF{##1}<{0} % {\fp_add:Nn\l__gradtable_negative_fp{##1}} % {\fp_add:Nn\l__gradtable_positive_fp{##1}} % \else\bool_set_false:N\l__gradtable_valid_bool\fi} % \exp_args:Ne\gradtableScaleValue{\fp_to_decimal:N\l__gradtable_positive_fp} % \exp_args:Ne\gradtableScaleValue{\fp_to_decimal:N\l__gradtable_negative_fp}}} % {\seq_map_inline:Nn\l__gradtable_scale_values_seq{\gradtableScaleValue{##1}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAutoRanges % {\seq_set_eq:NN\l__gradtable_range_rows_seq\l__gradtable_rows_seq % \tl_if_empty:NF\l__gradtable_data_tl % {\str_if_eq:VnT\l__gradtable_scale_scope_tl{data} % {\seq_set_eq:NN\l__gradtable_range_rows_seq\l__gradtable_data_rows_seq}} % \int_zero:N\l__gradtable_scale_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_scale_col_int % \tl_set:Nn\l__gradtable_id_tl{##1} % \prop_get:NnN\l__gradtable_types_prop{##1}\l__gradtable_type_tl % \str_if_eq:VnF\l__gradtable_type_tl{text} % {\str_if_eq:eeT{\prop_item:Nn\l__gradtable_scales_prop{##1}}{column} % {\bool_set_false:N\l__gradtable_seen_bool % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_range_rows_seq % {\int_incr:N\l__gradtable_row_int % \clist_set:Nn\l__gradtable_cells_clist{####1} % \exp_args:Ne\gradtableScaleCell % {\clist_item:Nn\l__gradtable_cells_clist{\l__gradtable_scale_col_int}}} % \bool_if:NTF\l__gradtable_seen_bool % {\str_if_eq:eeT{\prop_item:Nn\l__gradtable_zero_prop{##1}}{true} % {\fp_set:Nn\l__gradtable_min_fp{min(0,\l__gradtable_min_fp)} % \fp_set:Nn\l__gradtable_max_fp{max(0,\l__gradtable_max_fp)}} % \fp_compare:nNnT{\l__gradtable_min_fp}={\l__gradtable_max_fp} % {\str_if_eq:eeTF{\prop_item:Nn\l__gradtable_zero_prop{##1}}{true} % {\fp_set:Nn\l__gradtable_max_fp{1}} % {\__gradbars_constant_range:NN\l__gradtable_min_fp\l__gradtable_max_fp}}} % {\fp_zero:N\l__gradtable_min_fp\fp_set:Nn\l__gradtable_max_fp{1}} % \gradtableAdjustRange{##1} % \prop_put:Nnx\l__gradtable_ranges_prop{##1} % {min=\fp_to_decimal:N\l__gradtable_min_fp,max=\fp_to_decimal:N\l__gradtable_max_fp % \str_if_eq:VnT\l__gradtable_type_tl{spark}{,spark~range=fixed}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableValidateSelection % {\tl_if_empty:NT\l__gradtable_data_tl % {\bool_if:nT{!\tl_if_empty_p:N\l__gradtable_sort_tl || % !\tl_if_empty_p:N\l__gradtable_filter_tl || \int_compare_p:nNn{\l__gradtable_limit_int}>{0}} % {\gradtableError{Sort,~filter~and~limit~require~a~CSV~data~source}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSelectionType #1 % {\prop_get:NnNTF\l__gradtable_types_prop{#1}\l__gradtable_selection_type_tl % {\str_case:VnF\l__gradtable_selection_type_tl{{text}{}{number}{}{bar}{}{bullet}{}{heat}{}} % {\gradtableError{Sort~and~filter~require~a~scalar~or~text~column}}} % {\gradtableError{Unknown~selection~column:~#1}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSelectionValue #1 % {\tl_set:Nx\l__gradtable_selection_value_tl % {\clist_item:Nn\l__gradtable_selection_cells_clist{#1}} % \tl_trim_spaces:N\l__gradtable_selection_value_tl} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableColumnIndex #1 % {\int_zero:N\l__gradtable_selection_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_selection_col_int % \str_if_eq:nnT{##1}{#1}{\seq_map_break:}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtablePrepareFilters % {\seq_clear:N\l__gradtable_filters_seq % \clist_map_inline:Vn\l__gradtable_filter_tl % {\tl_set:Nn\l_tmpa_tl{##1} % \regex_extract_once:nVNTF{\A\s*([^<>=!]+?)\s*(>=|<=|!=|=|>|<)\s*(.*?)\s*\Z} % \l_tmpa_tl\l__gradtable_filter_parts_seq % {\tl_set:Nx\l__gradtable_filter_id_tl{\seq_item:Nn\l__gradtable_filter_parts_seq{2}} % \tl_trim_spaces:N\l__gradtable_filter_id_tl % \tl_set:Nx\l__gradtable_filter_op_tl{\seq_item:Nn\l__gradtable_filter_parts_seq{3}} % \tl_set:Nx\l__gradtable_filter_target_tl{\seq_item:Nn\l__gradtable_filter_parts_seq{4}} % \tl_trim_spaces:N\l__gradtable_filter_target_tl % \exp_args:NV\gradtableSelectionType\l__gradtable_filter_id_tl % \str_if_eq:VnTF\l__gradtable_selection_type_tl{text} % {\str_case:VnF\l__gradtable_filter_op_tl{{=}{}{!=}{}} % {\gradtableError{Text~filters~support~only~=~and~!=}}} % {\str_if_eq:VnTF\l__gradtable_filter_target_tl{NA} % {\str_case:VnF\l__gradtable_filter_op_tl{{=}{}{!=}{}} % {\gradtableError{Missing~filters~support~only~=NA~and~!=NA}}} % {\gradbars@validtrue\gradbarsCheckNumber{\l__gradtable_filter_target_tl}{filter~value} % \ifgradbars@valid\else\bool_set_false:N\l__gradtable_valid_bool\fi}} % \bool_if:NT\l__gradtable_valid_bool % {\exp_args:NV\gradtableColumnIndex\l__gradtable_filter_id_tl % \seq_put_right:Nx\l__gradtable_filters_seq % {{\int_use:N\l__gradtable_selection_col_int} % {\exp_not:V\l__gradtable_selection_type_tl}{\exp_not:V\l__gradtable_filter_op_tl} % {\exp_not:V\l__gradtable_filter_target_tl}}}} % {\gradtableError{Filter~requires~column~operator~value}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableApplyFilter #1#2#3#4 % {\gradtableSelectionValue{#1} % \str_if_eq:nnTF{#2}{text} % {\str_if_eq:eeTF{\tl_to_str:V\l__gradtable_selection_value_tl}{\tl_to_str:n{#4}} % {\str_if_eq:nnT{#3}{!=}{\bool_set_false:N\l__gradtable_selected_bool}} % {\str_if_eq:nnT{#3}{=}{\bool_set_false:N\l__gradtable_selected_bool}}} % {\str_if_eq:nnTF{#4}{NA} % {\str_if_eq:VnTF\l__gradtable_selection_value_tl{NA} % {\str_if_eq:nnT{#3}{!=}{\bool_set_false:N\l__gradtable_selected_bool}} % {\str_if_eq:nnT{#3}{=}{\bool_set_false:N\l__gradtable_selected_bool}}} % {\str_if_eq:VnTF\l__gradtable_selection_value_tl{NA} % {\bool_set_false:N\l__gradtable_selected_bool} % {\gradbars@validtrue\gradbarsCheckNumber{\l__gradtable_selection_value_tl}{filter~cell} % \ifgradbars@valid % \str_case:nn{#3} % {{=}{\fp_compare:nNnF{\l__gradtable_selection_value_tl}={#4}{\bool_set_false:N\l__gradtable_selected_bool}} % {!=}{\fp_compare:nNnT{\l__gradtable_selection_value_tl}={#4}{\bool_set_false:N\l__gradtable_selected_bool}} % {>}{\fp_compare:nNnF{\l__gradtable_selection_value_tl}>{#4}{\bool_set_false:N\l__gradtable_selected_bool}} % {<}{\fp_compare:nNnF{\l__gradtable_selection_value_tl}<{#4}{\bool_set_false:N\l__gradtable_selected_bool}} % {>=}{\fp_compare:nNnT{\l__gradtable_selection_value_tl}<{#4}{\bool_set_false:N\l__gradtable_selected_bool}} % {<=}{\fp_compare:nNnT{\l__gradtable_selection_value_tl}>{#4}{\bool_set_false:N\l__gradtable_selected_bool}}} % \else\bool_set_false:N\l__gradtable_valid_bool\bool_set_false:N\l__gradtable_selected_bool\fi}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSortTie #1#2 % {\int_compare:nNnTF{#1}>{#2}{\sort_return_swapped:}{\sort_return_same:}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSortCompare #1#2 % {\str_if_eq:eeTF{\prop_item:Nn\l__gradtable_sort_missing_prop{#1}}{true} % {\str_if_eq:eeTF{\prop_item:Nn\l__gradtable_sort_missing_prop{#2}}{true} % {\gradtableSortTie{#1}{#2}}{\sort_return_swapped:}} % {\str_if_eq:eeTF{\prop_item:Nn\l__gradtable_sort_missing_prop{#2}}{true} % {\sort_return_same:} % {\tl_set:Nx\l_tmpa_tl{\prop_item:Nn\l__gradtable_sort_values_prop{#1}} % \tl_set:Nx\l_tmpb_tl{\prop_item:Nn\l__gradtable_sort_values_prop{#2}} % \str_if_eq:VnTF\l__gradtable_selection_type_tl{text} % {\str_if_eq:VVTF\l_tmpa_tl\l_tmpb_tl{\gradtableSortTie{#1}{#2}} % {\str_if_eq:VnTF\l__gradtable_order_tl{ascending} % {\str_compare:eNeTF{\l_tmpa_tl}>{\l_tmpb_tl}{\sort_return_swapped:}{\sort_return_same:}} % {\str_compare:eNeTF{\l_tmpa_tl}<{\l_tmpb_tl}{\sort_return_swapped:}{\sort_return_same:}}}} % {\fp_compare:nNnTF{\l_tmpa_tl}={\l_tmpb_tl}{\gradtableSortTie{#1}{#2}} % {\str_if_eq:VnTF\l__gradtable_order_tl{ascending} % {\fp_compare:nNnTF{\l_tmpa_tl}>{\l_tmpb_tl}{\sort_return_swapped:}{\sort_return_same:}} % {\fp_compare:nNnTF{\l_tmpa_tl}<{\l_tmpb_tl}{\sort_return_swapped:}{\sort_return_same:}}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSelectRows % {\gradtablePrepareFilters % \seq_clear:N\l__gradtable_selected_seq % \prop_clear:N\l__gradtable_selection_rows_prop % \prop_clear:N\l__gradtable_sort_values_prop\prop_clear:N\l__gradtable_sort_missing_prop % \int_zero:N\l__gradtable_import_row_int % \seq_map_inline:Nn\l__gradtable_data_rows_seq % {\int_incr:N\l__gradtable_import_row_int % \clist_set:Nn\l__gradtable_selection_cells_clist{##1} % \bool_set_true:N\l__gradtable_selected_bool % \seq_map_inline:Nn\l__gradtable_filters_seq % {\bool_if:NT\l__gradtable_selected_bool{\gradtableApplyFilter####1}} % \bool_if:NT\l__gradtable_selected_bool % {\seq_put_right:Nx\l__gradtable_selected_seq{\int_use:N\l__gradtable_import_row_int} % \prop_put:Nxn\l__gradtable_selection_rows_prop{\int_use:N\l__gradtable_import_row_int}{##1}}} % \gradtablePrepareSortKeys % \bool_if:NT\l__gradtable_valid_bool % {\seq_if_empty:NF\l__gradtable_sort_keys_seq % {\seq_sort:Nn\l__gradtable_selected_seq{\gradtableMultiCompare{##1}{##2}}}} % \seq_clear:N\l__gradtable_rows_seq % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_selected_seq % {\bool_if:nT{\int_compare_p:nNn{\l__gradtable_limit_int}={0} || % \int_compare_p:nNn{\l__gradtable_row_int}<{\l__gradtable_limit_int}} % {\prop_get:NnN\l__gradtable_selection_rows_prop{##1}\l_tmpa_tl % \seq_put_right:NV\l__gradtable_rows_seq\l_tmpa_tl % \int_incr:N\l__gradtable_row_int}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSetPadding #1#2 % {\gradbars@validtrue\gradbarsCheckNumber{#2}{scale~padding} % \ifgradbars@valid % \fp_compare:nNnTF{#2}<{0}{\gradtableError{Scale~padding~must~be~nonnegative}} % {\fp_set:Nn#1{#2}} % \else\bool_set_false:N\l__gradtable_valid_bool\fi} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAdjustRange #1 % {\fp_set:Nn\l__gradtable_padding_amount_fp % {(\l__gradtable_max_fp-\l__gradtable_min_fp)*\prop_item:Nn\l__gradtable_scale_padding_prop{#1}/100} % \bool_if:nT{\fp_compare_p:nNn{\l__gradtable_padding_amount_fp}>{0} || % \str_if_eq_p:ee{\prop_item:Nn\l__gradtable_scale_nice_prop{#1}}{true}} % {\prop_put:Nnx\l__gradtable_percent_bases_prop{#1}{\fp_to_decimal:N\l__gradtable_max_fp}} % \fp_compare:nNnF{\l__gradtable_min_fp}={0} % {\fp_sub:Nn\l__gradtable_min_fp{\l__gradtable_padding_amount_fp}} % \fp_compare:nNnF{\l__gradtable_max_fp}={0} % {\fp_add:Nn\l__gradtable_max_fp{\l__gradtable_padding_amount_fp}} % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_scale_nice_prop{#1}}{true} % {\fp_set:Nn\l__gradtable_nice_step_fp{(\l__gradtable_max_fp-\l__gradtable_min_fp)/5} % \fp_set:Nn\l__gradtable_nice_power_fp{10^floor(ln(\l__gradtable_nice_step_fp)/ln(10))} % \fp_set:Nn\l__gradtable_nice_step_fp{\l__gradtable_nice_step_fp/\l__gradtable_nice_power_fp} % \fp_set:Nn\l__gradtable_nice_step_fp % {(\l__gradtable_nice_step_fp<=1?1:(\l__gradtable_nice_step_fp<=2?2: % (\l__gradtable_nice_step_fp<=5?5:10)))*\l__gradtable_nice_power_fp} % \fp_set:Nn\l__gradtable_min_fp % {floor(\l__gradtable_min_fp/\l__gradtable_nice_step_fp)*\l__gradtable_nice_step_fp} % \fp_set:Nn\l__gradtable_max_fp % {ceil(\l__gradtable_max_fp/\l__gradtable_nice_step_fp)*\l__gradtable_nice_step_fp}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableBuildSummary % {\prop_clear:N\l__gradtable_summary_values_prop % \tl_clear:N\l__gradtable_summary_label_id_tl % \bool_if:NT\l__gradtable_summary_bool % {\seq_set_eq:NN\l__gradtable_summary_rows_seq\l__gradtable_rows_seq % \tl_if_empty:NF\l__gradtable_data_tl % {\str_if_eq:VnT\l__gradtable_summary_scope_tl{data} % {\seq_set_eq:NN\l__gradtable_summary_rows_seq\l__gradtable_data_rows_seq}} % \int_zero:N\l__gradtable_summary_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_summary_col_int % \tl_set:Nn\l__gradtable_id_tl{##1} % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_types_prop{##1}}{text} % {\tl_if_empty:NT\l__gradtable_summary_label_id_tl % {\tl_set:Nn\l__gradtable_summary_label_id_tl{##1}}} % \prop_get:NnN\l__gradtable_aggregates_prop{##1}\l__gradtable_aggregate_tl % \str_if_eq:VnF\l__gradtable_aggregate_tl{none}{\gradtableAggregateColumn{##1}}} % \tl_if_empty:NF\l__gradtable_summary_label_tl % {\tl_if_empty:NT\l__gradtable_summary_label_id_tl % {\gradtableError{A~summary~label~requires~a~text~column}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAggregateColumn #1 % {\int_zero:N\l__gradtable_summary_count_int\fp_zero:N\l__gradtable_summary_sum_fp % \seq_map_inline:Nn\l__gradtable_summary_rows_seq % {\clist_set:Nn\l__gradtable_cells_clist{##1} % \tl_set:Nx\l__gradtable_summary_value_tl % {\clist_item:Nn\l__gradtable_cells_clist{\l__gradtable_summary_col_int}} % \tl_trim_spaces:N\l__gradtable_summary_value_tl % \tl_if_empty:NF\l__gradtable_summary_value_tl % {\str_if_eq:VnF\l__gradtable_summary_value_tl{NA} % {\gradbars@validtrue\gradbarsCheckNumber{\l__gradtable_summary_value_tl}{aggregate~value} % \ifgradbars@valid % \int_incr:N\l__gradtable_summary_count_int % \fp_add:Nn\l__gradtable_summary_sum_fp{\l__gradtable_summary_value_tl} % \int_compare:nNnTF{\l__gradtable_summary_count_int}={1} % {\fp_set:Nn\l__gradtable_summary_min_fp{\l__gradtable_summary_value_tl} % \fp_set_eq:NN\l__gradtable_summary_max_fp\l__gradtable_summary_min_fp} % {\fp_set:Nn\l__gradtable_summary_min_fp{min(\l__gradtable_summary_min_fp,\l__gradtable_summary_value_tl)} % \fp_set:Nn\l__gradtable_summary_max_fp{max(\l__gradtable_summary_max_fp,\l__gradtable_summary_value_tl)}} % \else\bool_set_false:N\l__gradtable_valid_bool\fi}}} % \tl_set:Nn\l__gradtable_summary_value_tl{NA} % \str_case:Vn\l__gradtable_aggregate_tl % {{count}{\tl_set:Nx\l__gradtable_summary_value_tl{\int_use:N\l__gradtable_summary_count_int}} % {sum}{\tl_set:Nx\l__gradtable_summary_value_tl{\fp_to_decimal:N\l__gradtable_summary_sum_fp}}} % \int_compare:nNnT{\l__gradtable_summary_count_int}>{0} % {\str_case:Vn\l__gradtable_aggregate_tl % {{mean}{\tl_set:Nx\l__gradtable_summary_value_tl % {\fp_eval:n{\l__gradtable_summary_sum_fp/\l__gradtable_summary_count_int}}} % {min}{\tl_set:Nx\l__gradtable_summary_value_tl{\fp_to_decimal:N\l__gradtable_summary_min_fp}} % {max}{\tl_set:Nx\l__gradtable_summary_value_tl{\fp_to_decimal:N\l__gradtable_summary_max_fp}}}} % \prop_put:NnV\l__gradtable_summary_values_prop{#1}\l__gradtable_summary_value_tl} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableValidateSelectionBeforeSeven\gradtableValidateSelection %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableValidateSelection % {\gradtableValidateSelectionBeforeSeven % \tl_if_empty:NT\l__gradtable_data_tl % {\bool_if:nT{!\tl_if_empty_p:N\l__gradtable_sort_keys_tl || !\tl_if_empty_p:N\l__gradtable_group_by_tl} % {\gradtableError{Sort~keys~and~group~by~require~a~CSV~data~source}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtablePrepareSortKeys % {\seq_clear:N\l__gradtable_sort_keys_seq % \tl_if_empty:NTF\l__gradtable_sort_keys_tl % {\tl_if_empty:NF\l__gradtable_sort_tl % {\tl_set_eq:NN\l__gradtable_sort_id_tl\l__gradtable_sort_tl % \tl_set_eq:NN\l__gradtable_sort_direction_tl\l__gradtable_order_tl % \gradtableAddSortKey}} % {\tl_if_empty:NF\l__gradtable_sort_tl{\gradtableError{Use~sort~or~sort~keys,~not~both}} % \clist_map_inline:Vn\l__gradtable_sort_keys_tl % {\seq_set_split:Nnn\l__gradtable_sort_parts_seq{/}{##1} % \int_compare:nNnTF{\seq_count:N\l__gradtable_sort_parts_seq}={2} % {\tl_set:Nx\l__gradtable_sort_id_tl{\seq_item:Nn\l__gradtable_sort_parts_seq{1}} % \tl_set:Nx\l__gradtable_sort_direction_tl{\seq_item:Nn\l__gradtable_sort_parts_seq{2}} % \tl_trim_spaces:N\l__gradtable_sort_id_tl\tl_trim_spaces:N\l__gradtable_sort_direction_tl % \str_case:VnF\l__gradtable_sort_direction_tl{{ascending}{}{descending}{}} % {\gradtableError{Sort~key~direction~must~be~ascending~or~descending}} % \gradtableAddSortKey} % {\gradtableError{Sort~keys~require~column/direction}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAddSortKey % {\exp_args:NV\gradtableSelectionType\l__gradtable_sort_id_tl % \exp_args:NV\gradtableColumnIndex\l__gradtable_sort_id_tl % \bool_if:NT\l__gradtable_valid_bool % {\seq_put_right:Nx\l__gradtable_sort_keys_seq % {{\int_use:N\l__gradtable_selection_col_int}{\exp_not:V\l__gradtable_selection_type_tl} % {\exp_not:V\l__gradtable_sort_direction_tl}} % \seq_map_inline:Nn\l__gradtable_selected_seq % {\clist_set:Nx\l__gradtable_selection_cells_clist{\prop_item:Nn\l__gradtable_selection_rows_prop{##1}} % \gradtableSelectionValue{\l__gradtable_selection_col_int} % \str_if_eq:VnF\l__gradtable_selection_type_tl{text} % {\bool_if:nF{\tl_if_empty_p:N\l__gradtable_selection_value_tl || \str_if_eq_p:Vn\l__gradtable_selection_value_tl{NA}} % {\gradbars@validtrue\gradbarsCheckNumber{\l__gradtable_selection_value_tl}{sort~cell} % \ifgradbars@valid\else\bool_set_false:N\l__gradtable_valid_bool\fi}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableMultiCompare #1#2 % {\clist_set:Nx\l__gradtable_sort_left_clist{\prop_item:Nn\l__gradtable_selection_rows_prop{#1}} % \clist_set:Nx\l__gradtable_sort_right_clist{\prop_item:Nn\l__gradtable_selection_rows_prop{#2}} % \int_zero:N\l__gradtable_compare_int % \seq_map_inline:Nn\l__gradtable_sort_keys_seq % {\gradtableCompareKey##1 % \int_compare:nNnF{\l__gradtable_compare_int}={0}{\seq_map_break:}} % \int_compare:nNnTF{\l__gradtable_compare_int}={0}{\gradtableSortTie{#1}{#2}} % {\int_compare:nNnTF{\l__gradtable_compare_int}>{0}{\sort_return_swapped:}{\sort_return_same:}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableCompareKey #1#2#3 % {\tl_set:Nx\l__gradtable_sort_left_tl{\clist_item:Nn\l__gradtable_sort_left_clist{#1}} % \tl_set:Nx\l__gradtable_sort_right_tl{\clist_item:Nn\l__gradtable_sort_right_clist{#1}} % \tl_trim_spaces:N\l__gradtable_sort_left_tl\tl_trim_spaces:N\l__gradtable_sort_right_tl % \bool_set:Nn\l__gradtable_sort_left_missing_bool{\tl_if_empty_p:N\l__gradtable_sort_left_tl} % \bool_set:Nn\l__gradtable_sort_right_missing_bool{\tl_if_empty_p:N\l__gradtable_sort_right_tl} % \str_if_eq:nnF{#2}{text} % {\str_if_eq:VnT\l__gradtable_sort_left_tl{NA}{\bool_set_true:N\l__gradtable_sort_left_missing_bool} % \str_if_eq:VnT\l__gradtable_sort_right_tl{NA}{\bool_set_true:N\l__gradtable_sort_right_missing_bool}} % \bool_if:NTF\l__gradtable_sort_left_missing_bool % {\bool_if:NF\l__gradtable_sort_right_missing_bool{\int_set:Nn\l__gradtable_compare_int{1}}} % {\bool_if:NTF\l__gradtable_sort_right_missing_bool{\int_set:Nn\l__gradtable_compare_int{-1}} % {\str_if_eq:nnTF{#2}{text} % {\str_if_eq:VVF\l__gradtable_sort_left_tl\l__gradtable_sort_right_tl % {\str_compare:eNeTF{\l__gradtable_sort_left_tl}>{\l__gradtable_sort_right_tl} % {\int_set:Nn\l__gradtable_compare_int{1}}{\int_set:Nn\l__gradtable_compare_int{-1}}}} % {\fp_compare:nNnF{\l__gradtable_sort_left_tl}={\l__gradtable_sort_right_tl} % {\fp_compare:nNnTF{\l__gradtable_sort_left_tl}>{\l__gradtable_sort_right_tl} % {\int_set:Nn\l__gradtable_compare_int{1}}{\int_set:Nn\l__gradtable_compare_int{-1}}}} % \str_if_eq:nnT{#3}{descending}{\int_set:Nn\l__gradtable_compare_int{-\l__gradtable_compare_int}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableNewDataGroup % {\int_incr:N\l__gradtable_group_count_int % \tl_set:Nx\l__gradtable_group_id_tl{\int_use:N\l__gradtable_group_count_int} % \prop_put:NVV\l__gradtable_group_ids_prop\l__gradtable_group_key_tl\l__gradtable_group_id_tl % \tl_if_empty:NTF\l__gradtable_group_key_tl % {\prop_put:NVV\l__gradtable_group_labels_prop\l__gradtable_group_id_tl\l__gradtable_group_missing_label_tl} % {\prop_put:NVV\l__gradtable_group_labels_prop\l__gradtable_group_id_tl\l__gradtable_group_key_tl} % \seq_clear_new:c{l__gradtable_group_\l__gradtable_group_id_tl _seq} % \seq_clear_new:c{l__gradtable_group_data_\l__gradtable_group_id_tl _seq}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableReadGroupKey #1 % {\clist_set:Nn\l__gradtable_cells_clist{#1} % \tl_set:Nx\l__gradtable_group_key_tl{\clist_item:Nn\l__gradtable_cells_clist{\l__gradtable_group_col_int}} % \tl_trim_spaces:N\l__gradtable_group_key_tl} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableBuildGroups % {\prop_clear:N\l__gradtable_group_ids_prop\prop_clear:N\l__gradtable_group_labels_prop % \prop_clear:N\l__gradtable_row_groups_prop\prop_clear:N\l__gradtable_group_ends_prop % \int_zero:N\l__gradtable_group_count_int % \tl_if_empty:NTF\l__gradtable_group_by_tl % {\bool_if:nT{\l__gradtable_group_summary_bool || \str_if_eq_p:Vn\l__gradtable_rank_scope_tl{group}} % {\prop_if_empty:NT\l__gradtable_groups_prop{\gradtableError{Group~statistics~require~group~by~or~gradgroup}} % \seq_set_eq:NN\l__gradtable_group_input_seq\l__gradtable_rows_seq % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_group_input_seq % {\int_incr:N\l__gradtable_row_int % \prop_get:NxNTF\l__gradtable_groups_prop{\int_use:N\l__gradtable_row_int}\l__gradtable_group_key_tl % {\gradtableNewDataGroup} % {\int_compare:nNnT{\l__gradtable_group_count_int}={0} % {\tl_clear:N\l__gradtable_group_key_tl\gradtableNewDataGroup % \prop_put:NxV\l__gradtable_groups_prop{1}\l__gradtable_group_missing_label_tl}} % \seq_put_right:cn{l__gradtable_group_\l__gradtable_group_id_tl _seq}{##1} % \seq_put_right:cn{l__gradtable_group_data_\l__gradtable_group_id_tl _seq}{##1} % \prop_put:NxV\l__gradtable_row_groups_prop{\int_use:N\l__gradtable_row_int}\l__gradtable_group_id_tl % \prop_put:Nxx\l__gradtable_group_ends_prop{\int_use:N\l__gradtable_row_int}{\l__gradtable_group_id_tl} % \prop_remove:Nx\l__gradtable_group_ends_prop{\int_eval:n{\l__gradtable_row_int-1}} % \prop_if_in:NxT\l__gradtable_groups_prop{\int_use:N\l__gradtable_row_int} % {\int_compare:nNnT{\l__gradtable_row_int}>{1} % {\prop_put:Nxx\l__gradtable_group_ends_prop{\int_eval:n{\l__gradtable_row_int-1}}{\int_eval:n{\l__gradtable_group_count_int-1}}}}}}} % {\prop_if_empty:NF\l__gradtable_groups_prop{\gradtableError{Do~not~combine~group~by~with~gradgroup}} % \exp_args:NV\gradtableSelectionType\l__gradtable_group_by_tl % \str_if_eq:VnF\l__gradtable_selection_type_tl{text}{\gradtableError{Group~by~requires~a~text~column}} % \exp_args:NV\gradtableColumnIndex\l__gradtable_group_by_tl % \int_set_eq:NN\l__gradtable_group_col_int\l__gradtable_selection_col_int % \bool_if:NT\l__gradtable_valid_bool % {\seq_map_inline:Nn\l__gradtable_data_rows_seq % {\gradtableReadGroupKey{##1} % \prop_get:NVNTF\l__gradtable_group_ids_prop\l__gradtable_group_key_tl\l__gradtable_group_id_tl % {}{\gradtableNewDataGroup} % \seq_put_right:cn{l__gradtable_group_data_\l__gradtable_group_id_tl _seq}{##1}} % \seq_map_inline:Nn\l__gradtable_rows_seq % {\gradtableReadGroupKey{##1} % \prop_get:NVN\l__gradtable_group_ids_prop\l__gradtable_group_key_tl\l__gradtable_group_id_tl % \seq_put_right:cn{l__gradtable_group_\l__gradtable_group_id_tl _seq}{##1}} % \seq_clear:N\l__gradtable_rows_seq\prop_clear:N\l__gradtable_groups_prop % \int_zero:N\l__gradtable_row_int % \int_step_inline:nn{\l__gradtable_group_count_int} % {\seq_if_empty:cF{l__gradtable_group_##1_seq} % {\prop_get:NnN\l__gradtable_group_labels_prop{##1}\l__gradtable_group_key_tl % \prop_put:NxV\l__gradtable_groups_prop{\int_eval:n{\l__gradtable_row_int+1}}\l__gradtable_group_key_tl % \seq_map_inline:cn{l__gradtable_group_##1_seq} % {\seq_put_right:Nn\l__gradtable_rows_seq{####1}\int_incr:N\l__gradtable_row_int % \prop_put:Nxn\l__gradtable_row_groups_prop{\int_use:N\l__gradtable_row_int}{##1}} % \prop_put:Nxn\l__gradtable_group_ends_prop{\int_use:N\l__gradtable_row_int}{##1}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableRankBeforeSeven\gradtableRank %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableRank % {\gradtableRankBeforeSeven % \prop_clear:N\l__gradtable_group_best_prop\prop_clear:N\l__gradtable_group_second_prop % \str_if_eq:VnT\l__gradtable_rank_scope_tl{group} % {\int_step_inline:nn{\l__gradtable_group_count_int} % {\group_begin:\seq_set_eq:Nc\l__gradtable_rows_seq{l__gradtable_group_##1_seq} % \gradtableRankBeforeSeven\prop_gset_eq:NN\g__gradtable_group_result_prop\l__gradtable_best_prop % \group_end: % \prop_map_inline:Nn\g__gradtable_group_result_prop % {\prop_put:Nnn\l__gradtable_group_best_prop{##1/####1}{####2}} % \group_begin:\seq_set_eq:Nc\l__gradtable_rows_seq{l__gradtable_group_##1_seq} % \gradtableRankBeforeSeven\prop_gset_eq:NN\g__gradtable_group_result_prop\l__gradtable_second_prop % \group_end: % \prop_map_inline:Nn\g__gradtable_group_result_prop % {\prop_put:Nnn\l__gradtable_group_second_prop{##1/####1}{####2}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableBuildSummaryBeforeSeven\gradtableBuildSummary %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableBuildSummary % {\gradtableBuildSummaryBeforeSeven % \prop_clear:N\l__gradtable_group_summary_values_prop % \bool_if:NT\l__gradtable_group_summary_bool % {\int_step_inline:nn{\l__gradtable_group_count_int} % {\seq_if_empty:cF{l__gradtable_group_##1_seq} % {\group_begin:\bool_set_true:N\l__gradtable_summary_bool % \tl_set_eq:NN\l__gradtable_summary_label_tl\l__gradtable_group_summary_label_tl % \tl_set_eq:NN\l__gradtable_summary_scope_tl\l__gradtable_group_summary_scope_tl % \seq_set_eq:Nc\l__gradtable_rows_seq{l__gradtable_group_##1_seq} % \seq_set_eq:Nc\l__gradtable_data_rows_seq{l__gradtable_group_data_##1_seq} % \gradtableBuildSummaryBeforeSeven % \prop_gset_eq:NN\g__gradtable_group_result_prop\l__gradtable_summary_values_prop % \group_end: % \prop_map_inline:Nn\g__gradtable_group_result_prop % {\prop_put:Nnn\l__gradtable_group_summary_values_prop{##1/####1}{####2}}}}}} %\ExplSyntaxOff %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-table-layout.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Private table layout layer. %\ProvidesPackage{gradbars-table-layout}[2026/10/25 v1.1.0 gradbars table layout] %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableConfigure #1 % {\prop_get:NnN \l__gradtable_types_prop {#1}\l__gradtable_type_tl % \prop_get:NnN \l__gradtable_options_prop {#1}\l__gradtable_options_tl % \pgfkeys{/gradbars,scale~group={},preset=paper,fill=solid,precision=1,overflow~mark=arrow} % \str_case:Vn \l__gradtable_preset_tl % {{report}{\pgfkeys{/gradbars,preset=report}} % {mono}{\pgfkeys{/gradbars,theme=gray,print}}} % \gradtableConfigureTheme % \pgfkeys{/gradbars,width=\l__gradtable_graphic_dim} % \str_if_eq:VnT\l__gradtable_type_tl{heat}{\pgfkeys{/gradbars,height=3ex}} % \prop_get:NnN\l__gradtable_formatters_prop{#1}\l_tmpa_tl % \pgfkeys{/gradbars,unit~code={},unit~text={},formatter/.expand~once=\l_tmpa_tl} % \prop_get:NnN\l__gradtable_number_align_prop{#1}\l__gradtable_number_align_tl % \exp_args:NV \gradbarssetup \l__gradtable_options_tl % \gradbarsValidateFormatter % \prop_get:NnN\l__gradtable_scale_groups_prop{#1}\l_tmpa_tl % \tl_if_empty:NF\l_tmpa_tl{\pgfkeys{/gradbars/scale~group/.expand~once=\l_tmpa_tl}} % \tl_if_empty:oF{\gradbars@scalegroup} % {\str_if_eq:eeT{\prop_item:Nn\l__gradtable_scales_prop{#1}}{column} % {\gradtableError{Scale~group~requires~scale=fixed}}} % \prop_get:NnNT\l__gradtable_ranges_prop{#1}\l_tmpa_tl % {\exp_args:NV\gradbarssetup\l_tmpa_tl} % \tl_if_empty:oT{\gradbars@percentbase} % {\prop_get:NnNT\l__gradtable_percent_bases_prop{#1}\l_tmpa_tl % {\pgfkeys{/gradbars/percent~base/.expand~once=\l_tmpa_tl}}} % \gradbarsResolveScaleGroup % \prop_get:NnNT\l__gradtable_plots_prop{#1}\l_tmpa_tl % {\pgfkeys{/gradbars/width/.expand~once=\l_tmpa_tl}} % \pgfkeys{/gradbars,label=outside,label~width=\prop_item:Nn\l__gradtable_widths_prop{#1}} % \str_if_eq:VnT\l__gradtable_type_tl{heat} % {\dim_compare:nNnT{\prop_item:Nn\l__gradtable_colwidth_prop{#1}}>{0pt} % {\pgfkeys{/gradbars,width=\prop_item:Nn\l__gradtable_colwidth_prop{#1}}} % \pgfkeys{/gradbars,label=inside}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableNumber #1 % {\tl_set:Nn \l_tmpa_tl {#1}\tl_trim_spaces:N \l_tmpa_tl % \str_if_eq:VnTF \l_tmpa_tl {NA} % {\gradbars@missingtext} % {\gradbars@validtrue\gradbarsCheckNumber{#1}{table~number} % \tl_set:Nx \l_tmpa_tl {\gradbars@precision} % \regex_match:nVTF {\A [0-6] \Z} \l_tmpa_tl {} % {\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \str_if_eq:eeT {\gradbars@format}{percent} % {\gradbarsCheckNumber{\gradbars@max}{max} % \ifgradbars@valid\fp_compare:nNnF {\gradbars@max}>{0} % {\gradbarsFail{Percent~format~requires~positive~max}}\fi\gradbarsValidatePercentBase} % \ifgradbars@valid % \gradbars@missingfalse\def\gradbars@value{#1} % \gradbarsFormatEndpoint{#1} % \fi}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableContent #1 % {\str_case:Vn \l__gradtable_type_tl % {{text}{#1} % {number}{\gradtableNumber{#1}} % {bar}{\gradbar{#1}} % {bullet}{\gradbullet{#1}} % {heat}{\gradbarsHeatCell{}{#1}} % {compare}{\gradtablePair{\gradcompare}{#1}} % {dumbbell}{\gradtablePair{\graddumbbell}{#1}} % {stack}{\str_if_eq:nnTF{#1}{NA}{\gradbar{NA}}{\gradstack{#1}}} % {boxplot}{\gradboxplot[box~range=fixed]{#1}} % {spark}{\gradspark{#1}} % {interval}{\str_if_eq:nnTF {#1}{NA} % {\gradrange{NA}{NA}} % {\seq_set_split:Nnn \l__gradtable_interval_seq {/}{#1} % \int_compare:nNnTF {\seq_count:N\l__gradtable_interval_seq} = {3} % {\tl_set:Nx \l_tmpa_tl {\seq_item:Nn\l__gradtable_interval_seq{2}} % \str_if_eq:VnT \l_tmpa_tl {NA}{\tl_clear:N\l_tmpa_tl} % \pgfkeys{/gradbars/range~point/.expand~once=\l_tmpa_tl} % \exp_args:Nee \gradrange % {\seq_item:Nn\l__gradtable_interval_seq{1}} % {\seq_item:Nn\l__gradtable_interval_seq{3}}} % {\gradbarsFail{Interval~requires~lower/point/upper}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableMeasure #1#2 % {\group_begin: % \gradbarsSuspendMeasurementTagging % \tl_set:Nn \l__gradtable_id_tl {#1} % \gradtableConfigure{#1} % \gradtableHighlight{#1}{#2} % \cs_set_eq:NN \gradtableSavedPackageError \PackageError % \cs_set_protected:Npn \PackageError ##1##2##3 % {\gradtableSavedPackageError{##1} % {Table~row~\int_use:N\l__gradtable_row_int,~column~#1:~##2}{##3}} % \dim_gset:Nn \g__gradtable_measured_dim {\prop_item:Nn\l__gradtable_widths_prop{#1}} % \cs_set_eq:NN \gradtableSavedLabel \gradbarsDrawMainLabel % \cs_set_protected:Npn \gradbarsDrawMainLabel % {\gradbarsMeasure\gradbars@labelbox\gradbars@font{\gradbars@labelcontent} % \dim_gset:Nn \g__gradtable_measured_dim % {\dim_max:nn{\g__gradtable_measured_dim}{\wd\gradbars@labelbox}} % \gradtableSavedLabel} % \hbox_set:Nn \l__gradtable_measure_box {\gradtableContent{#2}} % \str_if_eq:VnT \l__gradtable_type_tl {number} % {\dim_gset:Nn \g__gradtable_measured_dim % {\dim_max:nn{\g__gradtable_measured_dim}{\box_wd:N\l__gradtable_measure_box}}} % \gradbarsResumeMeasurementTagging % \group_end: % \prop_put:Nnx \l__gradtable_widths_prop {#1}{\dim_use:N\g__gradtable_measured_dim}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableCell #1#2 % {\group_begin:\tl_set:Nn\l__gradtable_id_tl{#1}\gradtableConfigure{#1} % \gradtableHighlight{#1}{#2} % \str_if_eq:VnTF \l__gradtable_type_tl {number} % {\makebox[\dim_max:nn{\prop_item:Nn\l__gradtable_widths_prop{#1}}{\prop_item:Nn\l__gradtable_colwidth_prop{#1}}] % [\prop_item:Nn\l__gradtable_align_prop{#1}]{\gradtableContent{#2}}} % {\str_if_eq:VnTF\l__gradtable_type_tl{text}{\gradtableContent{#2}} % {\hbox_set:Nn\l__gradtable_measure_box{\gradtableContent{#2}} % \dim_compare:nNnT{\l__gradtable_total_dim}>{0pt} % {\dim_compare:nNnT{\box_wd:N\l__gradtable_measure_box} % >{\prop_item:Nn\l__gradtable_colwidth_prop{#1}+.2pt} % {\gradtableError{Graphic~exceeds~allocated~column;~increase~width~or~simplify~labels}}} % \makebox[\dim_max:nn{\box_wd:N\l__gradtable_measure_box}{\prop_item:Nn\l__gradtable_colwidth_prop{#1}}] % [\prop_item:Nn\l__gradtable_align_prop{#1}]{\box_use:N\l__gradtable_measure_box}}} % \group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new:Npn\gradtableAlignCode #1 % {\str_case:nn{#1}{{l}{\raggedright}{c}{\centering}{r}{\raggedleft}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new:Npn\gradtableVerticalCode #1 % {\str_case:nn{#1}{{t}{p}{c}{m}{b}{b}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn \gradtableRender % {\gradtableBuildGroups % \gradtableAutoRanges % \tl_use:N\l__gradtable_font_tl % \gradtableBuildSummary % \gradtableRank % \gradtableScan % \gradtableMeasureSummary % \dim_compare:nNnT{\l__gradtable_total_dim}>{0pt}{\gradtableAllocate} % \tl_set:Nn\l__gradtable_preamble_tl{@{}} % \tl_clear:N\l__gradtable_body_tl % \str_case:Vn\l__gradtable_rules_tl % {{booktabs}{\tl_set:Nn\l__gradtable_body_tl{\toprule}} % {rows}{\tl_set:Nn\l__gradtable_body_tl{\toprule}} % {grid}{\tl_set:Nn\l__gradtable_body_tl{\hline}\tl_set:Nn\l__gradtable_preamble_tl{|}}} % \gradtableBuildHeaders % \int_zero:N\l__gradtable_col_int % \seq_map_inline:Nn \l__gradtable_columns_seq % {\int_incr:N\l__gradtable_col_int % \int_compare:nNnT{\l__gradtable_col_int}>{1}{\tl_put_right:Nn\l__gradtable_body_tl{&}} % \bool_if:nTF{\dim_compare_p:nNn{\l__gradtable_total_dim}>{0pt} || % \str_if_eq_p:ee{\prop_item:Nn\l__gradtable_types_prop{##1}}{text}} % {\tl_put_right:Nx\l__gradtable_preamble_tl % {>{\exp_not:N\gradtableAlignCode{\prop_item:Nn\l__gradtable_align_prop{##1}}\exp_not:N\arraybackslash} % \str_if_eq:eeTF{\prop_item:Nn\l__gradtable_types_prop{##1}}{text} % {\exp_args:Ne\gradtableVerticalCode{\prop_item:Nn\l__gradtable_valign_prop{##1}}}{p} % {\prop_item:Nn\l__gradtable_colwidth_prop{##1}}}} % {\tl_put_right:Nx\l__gradtable_preamble_tl{\prop_item:Nn\l__gradtable_align_prop{##1}}} % \str_if_eq:VnT\l__gradtable_rules_tl{grid}{\tl_put_right:Nn\l__gradtable_preamble_tl{|}} % \tl_clear:N\l__gradtable_header_spec_tl % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\int_compare:nNnT{\l__gradtable_col_int}={1}{\tl_put_right:Nn\l__gradtable_header_spec_tl{|}}} % {\int_compare:nNnT{\l__gradtable_col_int}={1}{\tl_put_right:Nn\l__gradtable_header_spec_tl{@{}}}} % \tl_if_empty:NF\l__gradtable_header_color_tl % {\dim_set_eq:NN\l_tmpa_dim\l__gradtable_sep_dim % \dim_set_eq:NN\l_tmpb_dim\l__gradtable_sep_dim % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\dim_set:Nn\l_tmpa_dim{\dim_max:nn{0pt}{\l_tmpa_dim-\arrayrulewidth}} % \dim_set_eq:NN\l_tmpb_dim\l_tmpa_dim} % {\int_compare:nNnT{\l__gradtable_col_int}={1}{\dim_zero:N\l_tmpa_dim} % \int_compare:nNnT{\l__gradtable_col_int}={\seq_count:N\l__gradtable_columns_seq}{\dim_zero:N\l_tmpb_dim}} % \tl_put_right:Nx\l__gradtable_header_spec_tl % {>{\exp_not:N\columncolor{\exp_not:V\l__gradtable_header_color_tl} % [\dim_use:N\l_tmpa_dim][\dim_use:N\l_tmpb_dim]}}} % \bool_if:nTF{\dim_compare_p:nNn{\l__gradtable_total_dim}>{0pt} || % \str_if_eq_p:ee{\prop_item:Nn\l__gradtable_types_prop{##1}}{text}} % {\tl_put_right:Nx\l__gradtable_header_spec_tl % {>{\exp_not:N\gradtableAlignCode{\prop_item:Nn\l__gradtable_headalign_prop{##1}}\exp_not:N\arraybackslash} % p{\prop_item:Nn\l__gradtable_colwidth_prop{##1}}}} % {\tl_put_right:Nx\l__gradtable_header_spec_tl{\prop_item:Nn\l__gradtable_headalign_prop{##1}}} % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\tl_put_right:Nn\l__gradtable_header_spec_tl{|}} % {\int_compare:nNnT{\l__gradtable_col_int}={\seq_count:N\l__gradtable_columns_seq} % {\tl_put_right:Nn\l__gradtable_header_spec_tl{@{}}}} % \tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\multicolumn{1}{\exp_not:V\l__gradtable_header_spec_tl} % {\exp_not:N\gradtableHeader{##1}}}} % \str_if_eq:VnF\l__gradtable_rules_tl{grid}{\tl_put_right:Nn\l__gradtable_preamble_tl{@{}}} % \tl_put_right:Nn\l__gradtable_body_tl{\\} % \str_case:Vn\l__gradtable_rules_tl % {{booktabs}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}} % {rows}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}} % {grid}{\tl_put_right:Nn\l__gradtable_body_tl{\hline}}} % \tl_set_eq:NN\l__gradtable_head_tl\l__gradtable_body_tl % \tl_clear:N\l__gradtable_body_tl % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_rows_seq % {\int_incr:N\l__gradtable_row_int % \gradtableInsertGroup % \clist_set:Nn\l__gradtable_cells_clist{##1} % \int_zero:N\l__gradtable_col_int % \clist_map_inline:Nn\l__gradtable_cells_clist % {\int_incr:N\l__gradtable_col_int % \tl_set:Nx\l__gradtable_id_tl{\seq_item:Nn\l__gradtable_columns_seq{\l__gradtable_col_int}} % \int_compare:nNnT{\l__gradtable_col_int}>{1}{\tl_put_right:Nn\l__gradtable_body_tl{&}} % \tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\gradtableGroupedCell{\int_use:N\l__gradtable_row_int}{\exp_not:V\l__gradtable_id_tl}{\exp_not:n{####1}}}} % \bool_set_false:N\l_tmpa_bool % \prop_if_in:NxT\l__gradtable_group_ends_prop{\int_use:N\l__gradtable_row_int} % {\bool_set_true:N\l_tmpa_bool} % \bool_if:nTF{(\l__gradtable_summary_bool && % \int_compare_p:nNn{\l__gradtable_row_int}={\seq_count:N\l__gradtable_rows_seq}) || % (\l__gradtable_group_summary_bool && \l_tmpa_bool)} % {\tl_put_right:Nn\l__gradtable_body_tl{\\*}} % {\tl_put_right:Nn\l__gradtable_body_tl{\\}} % \str_if_eq:VnT\l__gradtable_rules_tl{grid}{\tl_put_right:Nn\l__gradtable_body_tl{\hline}} % \gradtableAppendGroupSummary % \str_if_eq:VnT\l__gradtable_rules_tl{rows} % {\int_compare:nNnT{\l__gradtable_row_int}<{\seq_count:N\l__gradtable_rows_seq} % {\tl_put_right:Nn\l__gradtable_body_tl{\midrule}}}} % \gradtableAppendSummary % \cs_set:Npx\arraystretch{\l__gradtable_stretch_tl} % \setlength\tabcolsep{\l__gradtable_sep_dim} % \setlength\extrarowheight{\l__gradtable_padding_dim} % \exp_args:NV\arrayrulecolor\l__gradtable_rule_color_tl % \bool_if:NTF\l__gradtable_long_bool{\gradtableLong} % {\exp_args:NV\tabular\l__gradtable_preamble_tl % \l__gradtable_head_tl\l__gradtable_body_tl\gradtableBottom % \endtabular}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableHeader #1 % {\textbf{\prop_item:Nn\l__gradtable_titles_prop{#1}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableInsertGroup % {\prop_get:NxNT\l__gradtable_groups_prop{\int_use:N\l__gradtable_row_int}\l_tmpa_tl % {\str_if_eq:VnF\l__gradtable_rules_tl{grid} % {\tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\noalign{\exp_not:N\vskip\dim_use:N\l__gradtable_group_sep_dim}}} % \tl_set:Nn\l_tmpb_tl{@{}} % \dim_zero:N\l_tmpa_dim % \str_if_eq:VnT\l__gradtable_rules_tl{grid} % {\tl_set:Nn\l_tmpb_tl{|} % \dim_set:Nn\l_tmpa_dim{\dim_max:nn{0pt}{\l__gradtable_sep_dim-\arrayrulewidth}}} % \tl_if_empty:NF\l__gradtable_group_color_tl % {\tl_put_right:Nx\l_tmpb_tl % {>{\exp_not:N\columncolor{\exp_not:V\l__gradtable_group_color_tl} % [\dim_use:N\l_tmpa_dim][\dim_use:N\l_tmpa_dim]}}} % \dim_compare:nNnTF{\l__gradtable_total_dim}>{0pt} % {\dim_set_eq:NN\l__gradtable_span_dim\l__gradtable_total_dim % \str_if_eq:VnT\l__gradtable_rules_tl{grid} % {\dim_sub:Nn\l__gradtable_span_dim{2\l__gradtable_sep_dim+2\arrayrulewidth}} % \tl_put_right:Nx\l_tmpb_tl % {>{\exp_not:N\raggedright\exp_not:N\arraybackslash}p{\dim_use:N\l__gradtable_span_dim}}} % {\tl_put_right:Nn\l_tmpb_tl{l}} % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\tl_put_right:Nn\l_tmpb_tl{|}}{\tl_put_right:Nn\l_tmpb_tl{@{}}} % \tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\multicolumn{\seq_count:N\l__gradtable_columns_seq}{\exp_not:V\l_tmpb_tl} % {\exp_not:N\gradtableGroupTitle{\exp_not:V\l_tmpa_tl}}\exp_not:N\\*} % \str_if_eq:VnT\l__gradtable_rules_tl{grid} % {\tl_put_right:Nn\l__gradtable_body_tl{\gradtableGroupRule}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new:Npn\gradtableGroupRule % {\noalign{\nobreak{\CT@arc@\hrule height\arrayrulewidth}\nobreak}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableGroupTitle #1 % {\rule{0pt}{\dim_eval:n{\ht\strutbox+\l__gradtable_group_sep_dim}}\textbf{#1}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtablePair #1#2 % {\str_if_eq:nnTF{#2}{NA}{#1{NA}{NA}} % {\seq_set_split:Nnn\l__gradtable_interval_seq{/}{#2} % \int_compare:nNnTF{\seq_count:N\l__gradtable_interval_seq}={2} % {\exp_args:Nee#1{\seq_item:Nn\l__gradtable_interval_seq{1}} % {\seq_item:Nn\l__gradtable_interval_seq{2}}} % {\gradbarsFail{Comparison~requires~reference/current}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableBest #1{{\bfseries\boldmath #1}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableHighlight #1#2 % {\cs_set_eq:NN\gradtableEmphasis\use:n % \tl_set:Nn\l_tmpa_tl{#2}\tl_trim_spaces:N\l_tmpa_tl % \gradbarsIfNumber:VT\l_tmpa_tl % {\prop_get:NnNT\l__gradtable_best_prop{#1}\l_tmpb_tl % {\fp_compare:nNnT{#2}={\l_tmpb_tl}{\cs_set_eq:NN\gradtableEmphasis\gradtableBest}} % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_marks_prop{#1}}{both} % {\prop_get:NnNT\l__gradtable_second_prop{#1}\l_tmpb_tl % {\fp_compare:nNnT{#2}={\l_tmpb_tl}{\cs_set_eq:NN\gradtableEmphasis\underline}}}} % \str_if_eq:VnTF\l__gradtable_type_tl{number} % {\cs_set_eq:NN\gradtableOriginalNumber\gradtableNumber % \cs_set_protected:Npn\gradtableNumber##1{\gradtableEmphasis{\gradtableOriginalNumber{##1}}}} % {\cs_set_eq:NN\gradtableOriginalLabel\gradbars@labelcontent % \cs_set_protected:Npn\gradbars@labelcontent{\gradtableEmphasis{\gradtableOriginalLabel}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableValidateLayout % {\dim_compare:nNnT{\l__gradtable_total_dim}<{0pt}{\gradtableError{Table~width~must~be~nonnegative}} % \dim_compare:nNnF{\l__gradtable_min_text_dim}>{0pt}{\gradtableError{Min~text~width~must~be~positive}} % \dim_compare:nNnF{\l__gradtable_min_graphic_dim}>{0pt}{\gradtableError{Min~graphic~width~must~be~positive}} % \bool_if:NTF\l__gradtable_long_bool % {\ifinner\gradtableError{Long~table~requires~outer~paragraph~mode}\fi % \if@twocolumn\gradtableError{Long~table~requires~one-column~mode}\fi % \tl_if_empty:NF\l__gradtable_label_tl % {\tl_if_empty:NT\l__gradtable_caption_tl{\gradtableError{Table~label~requires~caption}}}} % {\tl_if_empty:NF\l__gradtable_caption_tl{\gradtableError{Caption~option~requires~long=true}} % \tl_if_empty:NF\l__gradtable_label_tl{\gradtableError{Label~option~requires~long=true}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableBuildHeaders % {\seq_map_inline:Nn\l__gradtable_headers_seq % {\int_set:Nn\l__gradtable_span_start_int{1} % \cs_set_eq:NN\gradtableSavedSpan\gradspan % \RenewDocumentCommand\gradspan{m m}{\gradtableBuildSpan{####1}{####2}} % ##1 % \cs_set_eq:NN\gradspan\gradtableSavedSpan % \tl_put_right:Nn\l__gradtable_body_tl{\\} % \str_case:Vn\l__gradtable_rules_tl % {{grid}{\tl_put_right:Nn\l__gradtable_body_tl{\hline}} % {booktabs}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}} % {rows}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableBuildSpan #1#2 % {\int_compare:nNnT{\l__gradtable_span_start_int}>{1}{\tl_put_right:Nn\l__gradtable_body_tl{&}} % \tl_clear:N\l__gradtable_header_spec_tl % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\int_compare:nNnT{\l__gradtable_span_start_int}={1}{\tl_put_right:Nn\l__gradtable_header_spec_tl{|}}} % {\int_compare:nNnT{\l__gradtable_span_start_int}={1}{\tl_put_right:Nn\l__gradtable_header_spec_tl{@{}}}} % \tl_if_empty:NF\l__gradtable_header_color_tl % {\dim_set_eq:NN\l_tmpa_dim\l__gradtable_sep_dim % \dim_set_eq:NN\l_tmpb_dim\l__gradtable_sep_dim % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\dim_set:Nn\l_tmpa_dim{\dim_max:nn{0pt}{\l_tmpa_dim-\arrayrulewidth}} % \dim_set_eq:NN\l_tmpb_dim\l_tmpa_dim} % {\int_compare:nNnT{\l__gradtable_span_start_int}={1}{\dim_zero:N\l_tmpa_dim} % \int_compare:nNnT{\l__gradtable_span_start_int+#1-1}={\seq_count:N\l__gradtable_columns_seq} % {\dim_zero:N\l_tmpb_dim}} % \tl_put_right:Nx\l__gradtable_header_spec_tl % {>{\exp_not:N\columncolor{\exp_not:V\l__gradtable_header_color_tl} % [\dim_use:N\l_tmpa_dim][\dim_use:N\l_tmpb_dim]}}} % \dim_compare:nNnTF{\l__gradtable_total_dim}>{0pt} % {\dim_set:Nn\l__gradtable_span_dim{2\l__gradtable_sep_dim*(#1-1)} % \str_if_eq:VnT\l__gradtable_rules_tl{grid} % {\dim_add:Nn\l__gradtable_span_dim{\arrayrulewidth*(#1-1)}} % \int_step_inline:nnnn{\l__gradtable_span_start_int}{1}{\l__gradtable_span_start_int+#1-1} % {\tl_set:Nx\l__gradtable_span_id_tl{\seq_item:Nn\l__gradtable_columns_seq{##1}} % \dim_add:Nn\l__gradtable_span_dim{\prop_item:NV\l__gradtable_colwidth_prop\l__gradtable_span_id_tl}} % \tl_put_right:Nx\l__gradtable_header_spec_tl % {>{\exp_not:N\centering\exp_not:N\arraybackslash}p{\dim_use:N\l__gradtable_span_dim}}} % {\tl_put_right:Nn\l__gradtable_header_spec_tl{c}} % \str_if_eq:VnTF\l__gradtable_rules_tl{grid} % {\tl_put_right:Nn\l__gradtable_header_spec_tl{|}} % {\int_compare:nNnT{\l__gradtable_span_start_int+#1-1}={\seq_count:N\l__gradtable_columns_seq} % {\tl_put_right:Nn\l__gradtable_header_spec_tl{@{}}}} % \tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\multicolumn{#1}{\exp_not:V\l__gradtable_header_spec_tl}{\exp_not:N\textbf{\exp_not:n{#2}}}} % \int_add:Nn\l__gradtable_span_start_int{#1}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableScan % {\int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_rows_seq % {\int_incr:N\l__gradtable_row_int % \clist_set:Nn\l__gradtable_cells_clist{##1} % \int_zero:N\l__gradtable_col_int % \clist_map_inline:Nn\l__gradtable_cells_clist % {\int_incr:N\l__gradtable_col_int % \tl_set:Nx\l__gradtable_id_tl{\seq_item:Nn\l__gradtable_columns_seq{\l__gradtable_col_int}} % \exp_args:NV\gradtableMeasure\l__gradtable_id_tl{####1}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableExtent #1#2 % {\group_begin:\gradtableConfigure{#1}\gradtableHighlight{#1}{#2} % \gradbarsSuspendMeasurementTagging % \dim_gset:Nn\g__gradtable_extent_dim{\prop_item:Nn\l__gradtable_overheads_prop{#1}} % \str_case:VnF\l__gradtable_type_tl{{text}{}{number}{}} % {\hbox_set:Nn\l__gradtable_measure_box{\gradtableContent{#2}} % \dim_gset:Nn\g__gradtable_extent_dim % {\dim_max:nn{\prop_item:Nn\l__gradtable_overheads_prop{#1}} % {\box_wd:N\l__gradtable_measure_box-\gradbars@width}}} % \gradbarsResumeMeasurementTagging % \group_end: % \prop_put:Nnx\l__gradtable_overheads_prop{#1}{\dim_use:N\g__gradtable_extent_dim}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAllocate % {\prop_clear:N\l__gradtable_overheads_prop\prop_clear:N\l__gradtable_flex_prop % \seq_map_inline:Nn\l__gradtable_columns_seq % {\group_begin:\gradtableConfigure{##1} % \dim_gset:Nn\g__gradtable_extent_dim % {\prop_item:Nn\l__gradtable_widths_prop{##1}+\gradbars@gap+2pt} % \str_if_eq:VnT\l__gradtable_type_tl{heat}{\dim_gzero:N\g__gradtable_extent_dim} % \group_end: % \prop_put:Nnx\l__gradtable_overheads_prop{##1}{\dim_use:N\g__gradtable_extent_dim}} % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_rows_seq % {\int_incr:N\l__gradtable_row_int\clist_set:Nn\l__gradtable_cells_clist{##1}\int_zero:N\l__gradtable_col_int % \clist_map_inline:Nn\l__gradtable_cells_clist % {\int_incr:N\l__gradtable_col_int % \tl_set:Nx\l__gradtable_id_tl{\seq_item:Nn\l__gradtable_columns_seq{\l__gradtable_col_int}} % \exp_args:NV\gradtableExtent\l__gradtable_id_tl{####1}}} % \dim_set:Nn\l__gradtable_remaining_dim % {\l__gradtable_total_dim-2\l__gradtable_sep_dim*(\seq_count:N\l__gradtable_columns_seq-1)} % \str_if_eq:VnT\l__gradtable_rules_tl{grid} % {\dim_sub:Nn\l__gradtable_remaining_dim % {2\l__gradtable_sep_dim+\arrayrulewidth*(\seq_count:N\l__gradtable_columns_seq+1)}} % \fp_zero:N\l__gradtable_weight_sum_fp % \seq_map_inline:Nn\l__gradtable_columns_seq % {\tl_set:Nn\l__gradtable_id_tl{##1} % \tl_set:Nx\l__gradtable_type_tl{\prop_item:Nn\l__gradtable_types_prop{##1}} % \dim_set:Nn\l__gradtable_base_dim{\prop_item:Nn\l__gradtable_fixed_prop{##1}} % \fp_zero:N\l__gradtable_weight_fp % \str_if_eq:VnTF\l__gradtable_type_tl{number} % {\dim_set:Nn\l__gradtable_base_dim % {\dim_max:nn{\l__gradtable_base_dim}{\prop_item:Nn\l__gradtable_widths_prop{##1}}}} % {\dim_compare:nNnTF{\l__gradtable_base_dim}>{0pt} % {\str_if_eq:VnF\l__gradtable_type_tl{text} % {\dim_compare:nNnT{\l__gradtable_base_dim} % <{\prop_item:Nn\l__gradtable_overheads_prop{##1}+\l__gradtable_min_graphic_dim} % {\gradtableError{Fixed~column~too~narrow~for~labels~and~graphic}}}} % {\fp_set:Nn\l__gradtable_weight_fp{\prop_item:Nn\l__gradtable_weights_prop{##1}} % \str_if_eq:VnTF\l__gradtable_type_tl{text} % {\dim_set_eq:NN\l__gradtable_base_dim\l__gradtable_min_text_dim} % {\dim_set:Nn\l__gradtable_base_dim % {\prop_item:Nn\l__gradtable_overheads_prop{##1}+\l__gradtable_min_graphic_dim}}}} % \bool_if:nT{(\l__gradtable_summary_bool || \l__gradtable_group_summary_bool) && \str_if_eq_p:Vn\l__gradtable_type_tl{heat}} % {\dim_compare:nNnTF{\prop_item:Nn\l__gradtable_fixed_prop{##1}}>{0pt} % {\dim_compare:nNnT{\l__gradtable_base_dim}<{\prop_item:Nn\l__gradtable_widths_prop{##1}+4pt} % {\gradtableError{Heat~column~too~narrow~for~its~label~or~summary}}} % {\dim_set:Nn\l__gradtable_base_dim % {\dim_max:nn{\l__gradtable_base_dim}{\prop_item:Nn\l__gradtable_widths_prop{##1}+4pt}}}} % \prop_put:Nnx\l__gradtable_colwidth_prop{##1}{\dim_use:N\l__gradtable_base_dim} % \prop_put:Nnx\l__gradtable_flex_prop{##1}{\fp_use:N\l__gradtable_weight_fp} % \fp_add:Nn\l__gradtable_weight_sum_fp{\l__gradtable_weight_fp} % \dim_sub:Nn\l__gradtable_remaining_dim{\l__gradtable_base_dim}} % \dim_compare:nNnT{\l__gradtable_remaining_dim}<{0pt} % {\gradtableError{Table~width~too~small;~increase~width~or~reduce~minimum~widths~and~spacing}} % \fp_compare:nNnT{\l__gradtable_weight_sum_fp}={0} % {\dim_compare:nNnT{\l__gradtable_remaining_dim}>{.1pt} % {\gradtableError{Table~width~requires~a~flexible~text~or~graphic~column}}} % \seq_map_inline:Nn\l__gradtable_columns_seq % {\fp_set:Nn\l__gradtable_weight_fp{\prop_item:Nn\l__gradtable_flex_prop{##1}} % \fp_compare:nNnT{\l__gradtable_weight_fp}>{0} % {\dim_set:Nn\l_tmpa_dim{\fp_to_dim:n % {\dim_to_fp:n{\l__gradtable_remaining_dim}*\l__gradtable_weight_fp/\l__gradtable_weight_sum_fp}} % \prop_put:Nnx\l__gradtable_colwidth_prop{##1} % {\dim_eval:n{\prop_item:Nn\l__gradtable_colwidth_prop{##1}+\l_tmpa_dim}} % \dim_sub:Nn\l__gradtable_remaining_dim{\l_tmpa_dim} % \fp_sub:Nn\l__gradtable_weight_sum_fp{\l__gradtable_weight_fp}} % \str_case_e:nnF{\prop_item:Nn\l__gradtable_types_prop{##1}}{{text}{}{number}{}} % {\prop_put:Nnx\l__gradtable_plots_prop{##1} % {\dim_eval:n{\prop_item:Nn\l__gradtable_colwidth_prop{##1}-\prop_item:Nn\l__gradtable_overheads_prop{##1}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new:Npn\gradtableBottom % {\str_case:Vn\l__gradtable_rules_tl{{booktabs}{\bottomrule}{rows}{\bottomrule}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableLong % {\par\setlength\LTleft{0pt}\setlength\LTright{\fill} % \dim_compare:nNnT{\l__gradtable_total_dim}>{0pt}{\setlength\LTcapwidth{\l__gradtable_total_dim}} % \exp_args:NV\longtable\l__gradtable_preamble_tl % \tl_if_empty:NF\l__gradtable_caption_tl % {\caption{\l__gradtable_caption_tl} % \tl_if_empty:NF\l__gradtable_label_tl{\exp_args:NV\label\l__gradtable_label_tl}\\} % \l__gradtable_head_tl\endfirsthead % \tl_if_empty:NTF\l__gradtable_caption_tl % {\tl_if_empty:NF\l__gradtable_continued_tl % {\multicolumn{\seq_count:N\l__gradtable_columns_seq}{c}{\l__gradtable_continued_tl}\\}} % {\caption[]{\l__gradtable_caption_tl\space\l__gradtable_continued_tl}\\} % \l__gradtable_head_tl\endhead % \gradtableBottom % \tl_if_empty:NF\l__gradtable_continued_tl % {\multicolumn{\seq_count:N\l__gradtable_columns_seq}{r}{\footnotesize\l__gradtable_continued_tl}\\} % \endfoot % \gradtableBottom\endlastfoot % \l__gradtable_body_tl % \endlongtable} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableConfigureTheme % {\str_case:Vn\l__gradtable_theme_tl % {{accessible}{\pgfkeys{/gradbars,palette=accessible,heat~palette=accessible-sequential}} % {blue}{\pgfkeys{/gradbars,theme=blue,heat~low~color=gradbarsBlue!8,heat~high~color=gradbarsBlue}} % {teal}{\pgfkeys{/gradbars,theme=teal,heat~low~color=gradbarsTeal!8,heat~high~color=gradbarsTeal}} % {violet}{\pgfkeys{/gradbars,theme=violet,heat~low~color=gradbarsViolet!8,heat~high~color=gradbarsViolet}} % {orange}{\pgfkeys{/gradbars,theme=orange,heat~low~color=gradbarsWarmOrange!8,heat~high~color=gradbarsWarmOrange}} % {forest}{\pgfkeys{/gradbars,theme=forest,heat~low~color=gradbarsForest!8,heat~high~color=gradbarsForest}} % {mono}{\pgfkeys{/gradbars,theme=gray,print}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableResolveThemeColors % {\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsBlue} % \str_case:Vn\l__gradtable_theme_tl % {{accessible}{\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsCudBlue}} % {teal}{\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsTeal}} % {violet}{\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsViolet}} % {orange}{\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsWarmOrange}} % {forest}{\tl_set:Nn\l__gradtable_theme_color_tl{gradbarsForest}} % {mono}{\tl_set:Nn\l__gradtable_theme_color_tl{black}}} % \str_if_eq:VnF\l__gradtable_theme_tl{none} % {\bool_if:NT\l__gradtable_header_auto_bool % {\tl_set:Nx\l__gradtable_header_color_tl{\l__gradtable_theme_color_tl !8}}} % \str_if_eq:VnT\l__gradtable_summary_color_tl{auto} % {\tl_clear:N\l__gradtable_summary_color_tl % \str_if_eq:VnF\l__gradtable_theme_tl{none} % {\tl_set:Nx\l__gradtable_summary_color_tl{\l__gradtable_theme_color_tl !8}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSummaryContent #1 % {\tl_use:N\l__gradtable_summary_font_tl % \str_if_eq:eeTF{#1}{\l__gradtable_summary_label_id_tl} % {\tl_use:N\l__gradtable_summary_label_tl} % {\prop_get:NnNT\l__gradtable_summary_values_prop{#1}\l__gradtable_summary_value_tl % {\str_if_eq:eeT{\prop_item:Nn\l__gradtable_aggregates_prop{#1}}{count} % {\def\gradbars@precision{0}\def\gradbars@unit{}\def\gradbars@unitcode{}\def\gradbars@unittext{}\def\gradbars@format{value}} % \exp_args:NV\gradtableNumber\l__gradtable_summary_value_tl}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableMeasureSummary % {\bool_if:NT\l__gradtable_summary_bool % {\seq_map_inline:Nn\l__gradtable_columns_seq % {\group_begin:\gradtableConfigure{##1}\gradbarsSuspendMeasurementTagging % \hbox_set:Nn\l__gradtable_measure_box{\gradtableSummaryContent{##1}} % \dim_gset:Nn\g__gradtable_measured_dim{\box_wd:N\l__gradtable_measure_box} % \gradbarsResumeMeasurementTagging\group_end: % \prop_put:Nnx\l__gradtable_widths_prop{##1} % {\dim_max:nn{\prop_item:Nn\l__gradtable_widths_prop{##1}}{\g__gradtable_measured_dim}} % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_types_prop{##1}}{text} % {\dim_compare:nNnT{\g__gradtable_measured_dim}>{\prop_item:Nn\l__gradtable_colwidth_prop{##1}} % {\dim_compare:nNnT{\l__gradtable_total_dim}={0pt} % {\prop_put:Nnx\l__gradtable_colwidth_prop{##1}{\dim_use:N\g__gradtable_measured_dim}}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableSummaryCell #1 % {\group_begin:\gradtableConfigure{#1} % \str_if_eq:VnTF\l__gradtable_type_tl{text}{\gradtableSummaryContent{#1}} % {\makebox[\dim_max:nn{\prop_item:Nn\l__gradtable_widths_prop{#1}} % {\prop_item:Nn\l__gradtable_colwidth_prop{#1}}] % [\str_case:VnF\l__gradtable_type_tl % {{number}{\prop_item:Nn\l__gradtable_align_prop{#1}}{heat}{c}}{r}] % {\gradtableSummaryContent{#1}}}\group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAppendSummary % {\bool_if:NT\l__gradtable_summary_bool % {\str_case:Vn\l__gradtable_rules_tl % {{booktabs}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}} % {rows}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}}} % \tl_if_empty:NF\l__gradtable_summary_color_tl % {\tl_put_right:Nx\l__gradtable_body_tl{\exp_not:N\rowcolor{\exp_not:V\l__gradtable_summary_color_tl}}} % \int_zero:N\l__gradtable_summary_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_summary_col_int % \int_compare:nNnT{\l__gradtable_summary_col_int}>{1}{\tl_put_right:Nn\l__gradtable_body_tl{&}} % \tl_put_right:Nn\l__gradtable_body_tl{\gradtableSummaryCell{##1}}} % \tl_put_right:Nn\l__gradtable_body_tl{\\} % \str_if_eq:VnT\l__gradtable_rules_tl{grid}{\tl_put_right:Nn\l__gradtable_body_tl{\hline}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableHighlightBeforeSeven\gradtableHighlight %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableHighlight #1#2 % {\str_if_eq:VnT\l__gradtable_rank_scope_tl{group} % {\prop_clear:N\l__gradtable_best_prop\prop_clear:N\l__gradtable_second_prop % \prop_get:NxN\l__gradtable_row_groups_prop{\int_use:N\l__gradtable_row_int}\l__gradtable_group_id_tl % \prop_get:NxNT\l__gradtable_group_best_prop{\l__gradtable_group_id_tl/#1}\l_tmpa_tl % {\prop_put:NnV\l__gradtable_best_prop{#1}\l_tmpa_tl} % \prop_get:NxNT\l__gradtable_group_second_prop{\l__gradtable_group_id_tl/#1}\l_tmpa_tl % {\prop_put:NnV\l__gradtable_second_prop{#1}\l_tmpa_tl}} % \gradtableHighlightBeforeSeven{#1}{#2}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableGroupedCell #1#2#3 % {\group_begin:\int_set:Nn\l__gradtable_row_int{#1}\gradtableCell{#2}{#3}\group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableUseGroupSummary #1 % {\bool_set_true:N\l__gradtable_summary_bool % \tl_set_eq:NN\l__gradtable_summary_label_tl\l__gradtable_group_summary_label_tl % \prop_clear:N\l__gradtable_summary_values_prop\tl_clear:N\l__gradtable_summary_label_id_tl % \seq_map_inline:Nn\l__gradtable_columns_seq % {\str_if_eq:eeT{\prop_item:Nn\l__gradtable_types_prop{##1}}{text} % {\tl_if_empty:NT\l__gradtable_summary_label_id_tl{\tl_set:Nn\l__gradtable_summary_label_id_tl{##1}}} % \prop_get:NnNT\l__gradtable_group_summary_values_prop{#1/##1}\l_tmpa_tl % {\prop_put:NnV\l__gradtable_summary_values_prop{##1}\l_tmpa_tl}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableMeasureSummaryBeforeSeven\gradtableMeasureSummary %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableMeasureSummary % {\gradtableMeasureSummaryBeforeSeven % \bool_if:NT\l__gradtable_group_summary_bool % {\int_step_inline:nn{\l__gradtable_group_count_int} % {\seq_if_empty:cF{l__gradtable_group_##1_seq} % {\group_begin:\gradtableUseGroupSummary{##1}\gradtableMeasureSummaryBeforeSeven % \prop_gset_eq:NN\g__gradtable_group_widths_prop\l__gradtable_widths_prop % \prop_gset_eq:NN\g__gradtable_group_result_prop\l__gradtable_colwidth_prop\group_end: % \prop_set_eq:NN\l__gradtable_widths_prop\g__gradtable_group_widths_prop % \prop_set_eq:NN\l__gradtable_colwidth_prop\g__gradtable_group_result_prop}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableGroupSummaryCell #1#2 % {\group_begin:\gradtableUseGroupSummary{#1}\gradtableSummaryCell{#2}\group_end:} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableAppendGroupSummary % {\bool_if:NT\l__gradtable_group_summary_bool % {\prop_get:NxNT\l__gradtable_group_ends_prop{\int_use:N\l__gradtable_row_int}\l__gradtable_group_id_tl % {\str_case:Vn\l__gradtable_rules_tl % {{booktabs}{\tl_put_right:Nn\l__gradtable_body_tl{\midrule}}} % \tl_if_empty:NF\l__gradtable_summary_color_tl % {\tl_put_right:Nx\l__gradtable_body_tl{\exp_not:N\rowcolor{\exp_not:V\l__gradtable_summary_color_tl}}} % \int_zero:N\l__gradtable_summary_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_summary_col_int % \int_compare:nNnT{\l__gradtable_summary_col_int}>{1}{\tl_put_right:Nn\l__gradtable_body_tl{&}} % \tl_put_right:Nx\l__gradtable_body_tl % {\exp_not:N\gradtableGroupSummaryCell{\l__gradtable_group_id_tl}{\exp_not:n{##1}}}} % \bool_if:nTF{\l__gradtable_summary_bool && \int_compare_p:nNn{\l__gradtable_row_int}={\seq_count:N\l__gradtable_rows_seq}} % {\tl_put_right:Nn\l__gradtable_body_tl{\\*}}{\tl_put_right:Nn\l__gradtable_body_tl{\\}} % \str_if_eq:VnT\l__gradtable_rules_tl{grid}{\tl_put_right:Nn\l__gradtable_body_tl{\hline}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableConfigureBeforeEight\gradtableConfigure %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableConfigure #1 % {\tl_set:Nn\l__gradtable_id_tl{#1}\gradtableConfigureBeforeEight{#1}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradbarsDecimalParts #1 % {\fp_set:Nn\l__gradbars_decimal_value_fp{#1} % \int_zero:N\l__gradbars_decimal_exponent_int % \str_if_eq:eeT{\gradbars@numberformat}{scientific} % {\fp_compare:nNnF{\l__gradbars_decimal_value_fp}={0} % {\int_set:Nn\l__gradbars_decimal_exponent_int{\fp_eval:n{floor(ln(abs(\l__gradbars_decimal_value_fp))/ln(10))}} % \fp_set:Nn\l__gradbars_decimal_value_fp % {\l__gradbars_decimal_value_fp/10^\l__gradbars_decimal_exponent_int}}} % \fp_compare:nNnTF{\l__gradbars_decimal_value_fp}<{0} % {\fp_set:Nn\l__gradbars_decimal_value_fp{-round(abs(\l__gradbars_decimal_value_fp),\gradbars@precision,1)}} % {\fp_set:Nn\l__gradbars_decimal_value_fp{round(\l__gradbars_decimal_value_fp,\gradbars@precision,1)}} % \str_if_eq:eeT{\gradbars@numberformat}{scientific} % {\fp_compare:nT{abs(\l__gradbars_decimal_value_fp)>=10} % {\fp_set:Nn\l__gradbars_decimal_value_fp{\l__gradbars_decimal_value_fp/10} % \int_incr:N\l__gradbars_decimal_exponent_int}} % \tl_clear:N\l__gradbars_decimal_sign_tl % \fp_compare:nNnT{\l__gradbars_decimal_value_fp}<{0}{\tl_set:Nn\l__gradbars_decimal_sign_tl{\ensuremath{-}}} % \seq_set_split:Nnx\l__gradbars_decimal_parts_seq{.}{\fp_to_decimal:n{abs(\l__gradbars_decimal_value_fp)}} % \tl_set:Nx\l__gradbars_decimal_integer_tl{\seq_item:Nn\l__gradbars_decimal_parts_seq{1}} % \tl_clear:N\l__gradbars_decimal_fraction_tl % \int_compare:nNnT{\seq_count:N\l__gradbars_decimal_parts_seq}>{1} % {\tl_set:Nx\l__gradbars_decimal_fraction_tl{\seq_item:Nn\l__gradbars_decimal_parts_seq{2}}} % \int_while_do:nn{\tl_count:N\l__gradbars_decimal_fraction_tl<\gradbars@precision} % {\tl_put_right:Nn\l__gradbars_decimal_fraction_tl{0}} % \hbox_set:Nn\l__gradbars_decimal_left_box % {\l__gradbars_decimal_sign_tl % \str_if_eq:eeTF{\gradbars@formatter}{siunitx} % {\group_begin:\gradbarsSIOptions\sisetup{round-mode=none,exponent-mode=fixed,fixed-exponent=0} % \exp_args:NV\num\l__gradbars_decimal_integer_tl\group_end:} % {\str_if_eq:eeTF{\gradbars@numberformat}{grouped} % {\pgfmathprintnumber[fixed,precision=0,1000~sep={\mathord{,}}]{\l__gradbars_decimal_integer_tl}} % {\pgfmathprintnumber[fixed,precision=0,1000~sep={\,}]{\l__gradbars_decimal_integer_tl}}}} % \hbox_set:Nn\l__gradbars_decimal_right_box % {\int_compare:nNnT{\gradbars@precision}>{0}{\ensuremath{.\l__gradbars_decimal_fraction_tl}} % \str_if_eq:eeT{\gradbars@numberformat}{scientific} % {\ensuremath{{}\times10^{\int_use:N\l__gradbars_decimal_exponent_int}}} % \gradbarsNumericSuffix} % \dim_gset:Nn\g__gradbars_decimal_left_dim{\box_wd:N\l__gradbars_decimal_left_box} % \dim_gset:Nn\g__gradbars_decimal_right_dim{\box_wd:N\l__gradbars_decimal_right_box} % \dim_gset:Nn\g__gradbars_decimal_full_dim{\g__gradbars_decimal_left_dim+\g__gradbars_decimal_right_dim}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradbarsDecimalPrint #1 % {\gradbarsDecimalParts{#1} % \bool_if:NTF\l__gradbars_decimal_measure_bool % {\box_use:N\l__gradbars_decimal_left_box\box_use:N\l__gradbars_decimal_right_box} % {\prop_if_in:NVTF\l__gradtable_decimal_left_prop\l__gradtable_id_tl % {\makebox[\prop_item:NV\l__gradtable_decimal_left_prop\l__gradtable_id_tl][r]{\box_use:N\l__gradbars_decimal_left_box} % \makebox[\prop_item:NV\l__gradtable_decimal_right_prop\l__gradtable_id_tl][l]{\box_use:N\l__gradbars_decimal_right_box}} % {\box_use:N\l__gradbars_decimal_left_box\box_use:N\l__gradbars_decimal_right_box}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableNumberBeforeEight\gradtableNumber %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableNumber #1 % {\str_if_eq:VnTF\l__gradtable_number_align_tl{decimal} % {\bool_set_true:N\l__gradbars_decimal_active_bool % \str_if_eq:nnTF{#1}{NA} % {\bool_if:NTF\l__gradbars_decimal_measure_bool % {\gradbars@missingtext} % {\prop_if_in:NVTF\l__gradtable_decimal_left_prop\l__gradtable_id_tl % {\makebox[\dim_eval:n{\prop_item:NV\l__gradtable_decimal_left_prop\l__gradtable_id_tl+ % \prop_item:NV\l__gradtable_decimal_right_prop\l__gradtable_id_tl}][c]{\gradbars@missingtext}} % {\gradbars@missingtext}}} % {\gradtableNumberBeforeEight{#1}}} % {\gradtableNumberBeforeEight{#1}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableMeasureDecimalValue #1#2#3 % {\group_begin:\gradbarsSuspendMeasurementTagging\gradtableConfigure{#1} % \str_if_eq:nnTF{#3}{summary} % {\tl_use:N\l__gradtable_summary_font_tl % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_aggregates_prop{#1}}{count} % {\def\gradbars@precision{0}\def\gradbars@unit{}\def\gradbars@unitcode{}\def\gradbars@unittext{}\def\gradbars@format{value}}} % {\gradtableHighlight{#1}{#2}} % \bool_set_true:N\l__gradbars_decimal_measure_bool % \dim_gzero:N\g__gradbars_decimal_left_dim\dim_gzero:N\g__gradbars_decimal_right_dim % \hbox_set:Nn\l__gradtable_measure_box{\gradtableNumber{#2}} % \dim_gset:Nn\g__gradbars_decimal_full_dim{\box_wd:N\l__gradtable_measure_box} % \gradbarsResumeMeasurementTagging\group_end: % \prop_put:Nnx\l__gradtable_decimal_left_prop{#1} % {\dim_max:nn{\prop_item:Nn\l__gradtable_decimal_left_prop{#1}}{\g__gradbars_decimal_left_dim}} % \prop_put:Nnx\l__gradtable_decimal_right_prop{#1} % {\dim_max:nn{\prop_item:Nn\l__gradtable_decimal_right_prop{#1}}{\g__gradbars_decimal_right_dim}} % \prop_put:Nnx\l__gradtable_widths_prop{#1} % {\dim_max:nn{\prop_item:Nn\l__gradtable_widths_prop{#1}}{\g__gradbars_decimal_full_dim}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_protected:Npn\gradtableMeasureDecimals % {\prop_clear:N\l__gradtable_decimal_left_prop\prop_clear:N\l__gradtable_decimal_right_prop % \int_zero:N\l__gradtable_decimal_col_int % \seq_map_inline:Nn\l__gradtable_columns_seq % {\int_incr:N\l__gradtable_decimal_col_int % \str_if_eq:eeT{\prop_item:Nn\l__gradtable_number_align_prop{##1}}{decimal} % {\prop_put:Nnn\l__gradtable_decimal_left_prop{##1}{0pt} % \prop_put:Nnn\l__gradtable_decimal_right_prop{##1}{0pt} % \int_zero:N\l__gradtable_row_int % \seq_map_inline:Nn\l__gradtable_rows_seq % {\int_incr:N\l__gradtable_row_int\clist_set:Nn\l__gradtable_cells_clist{####1} % \exp_args:Nne\gradtableMeasureDecimalValue{##1} % {\clist_item:Nn\l__gradtable_cells_clist{\l__gradtable_decimal_col_int}}{data}} % \bool_if:NT\l__gradtable_summary_bool % {\prop_get:NnNT\l__gradtable_summary_values_prop{##1}\l_tmpa_tl % {\exp_args:NnV\gradtableMeasureDecimalValue{##1}\l_tmpa_tl{summary}}} % \bool_if:NT\l__gradtable_group_summary_bool % {\int_step_inline:nn{\l__gradtable_group_count_int} % {\prop_get:NnNT\l__gradtable_group_summary_values_prop{####1/##1}\l_tmpa_tl % {\exp_args:NnV\gradtableMeasureDecimalValue{##1}\l_tmpa_tl{summary}}}} % \dim_set:Nn\l_tmpa_dim{\prop_item:Nn\l__gradtable_decimal_left_prop{##1}+ % \prop_item:Nn\l__gradtable_decimal_right_prop{##1}} % \dim_set:Nn\l_tmpb_dim{\prop_item:Nn\l__gradtable_widths_prop{##1}} % \dim_compare:nNnT{\l_tmpb_dim}>{\l_tmpa_dim} % {\prop_put:Nnx\l__gradtable_decimal_right_prop{##1} % {\dim_eval:n{\l_tmpb_dim-\prop_item:Nn\l__gradtable_decimal_left_prop{##1}}}} % \prop_put:Nnx\l__gradtable_widths_prop{##1} % {\dim_max:nn{\l_tmpb_dim}{\l_tmpa_dim}} % \dim_compare:nNnT{\prop_item:Nn\l__gradtable_fixed_prop{##1}}>{0pt} % {\dim_compare:nNnT{\prop_item:Nn\l__gradtable_widths_prop{##1}}>{\prop_item:Nn\l__gradtable_fixed_prop{##1}} % {\tl_set:Nn\l__gradtable_id_tl{##1}\gradtableError{Decimal~column~width~too~narrow;~increase~width}}}}}} %\ExplSyntaxOff %\ExplSyntaxOn %\cs_new_eq:NN\gradtableMeasureSummaryBeforeEight\gradtableMeasureSummary %\ExplSyntaxOff %\ExplSyntaxOn %\cs_set_protected:Npn\gradtableMeasureSummary % {\gradtableMeasureSummaryBeforeEight\gradtableMeasureDecimals} %\ExplSyntaxOff %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-tagging.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Internal implementation unless documented. %\ProvidesPackage{gradbars-tagging}[2026/10/25 v1.1.0 gradbars tagging] %\ExplSyntaxOff %% Accessible descriptions use the supported TikZ tagging interface. No tagging %% is activated by this package; ordinary documents keep their existing output. %\def\gradbarsCaptureTikzAlt{% % % Capture explicit /tikz/alt options locally, without changing the global key. % \pgfkeysifdefined{/tikz/alt/.@cmd}{% % \pgfkeys{/tikz/alt/.append code={\ifgradbars@capturealt\def\gradbars@alt{##1}\fi}}% % }{\pgfkeys{/tikz/alt/.code={\def\gradbars@alt{##1}}}}% %} %\ExplSyntaxOn %\tl_new:N \l__gradbars_alt_tl %\seq_new:N \l__gradbars_alt_fields_seq %\int_new:N \l__gradbars_alt_index_int %\cs_new_protected:Npn \gradbarsAltValue #1 % { % \tl_set:Nx \l_tmpa_tl {#1} % \tl_trim_spaces:N \l_tmpa_tl % \tl_if_empty:NTF \l_tmpa_tl % {\tl_put_right:Nn \l__gradbars_alt_tl {missing}} % {\str_if_eq:VnTF \l_tmpa_tl {NA} % {\tl_put_right:Nn \l__gradbars_alt_tl {missing}} % {\tl_put_right:Nx \l__gradbars_alt_tl {\fp_eval:n {\l_tmpa_tl}}}} % } %\cs_new_protected:Npn \gradbarsBuildAlt % { % \tl_clear:N \l__gradbars_alt_tl % \ifgradbars@spark % \tl_put_right:Nn \l__gradbars_alt_tl {Equally~spaced~series:~} % \int_zero:N \l__gradbars_alt_index_int % \seq_map_inline:Nn \l__gradbars_series_seq % {\int_incr:N \l__gradbars_alt_index_int % \int_compare:nNnT {\l__gradbars_alt_index_int}>{1} % {\tl_put_right:Nn \l__gradbars_alt_tl {;~}} % \tl_put_right:Nx \l__gradbars_alt_tl % {observation~\int_use:N\l__gradbars_alt_index_int :~} % \gradbarsAltValue{##1}} % \tl_put_right:Nn \l__gradbars_alt_tl {.~Final~observation:~} % \gradbarsAltValue{\gradbars@sparklast} % \tl_put_right:Nx \l__gradbars_alt_tl % {.~Vertical~range:~\fp_use:N\l__gradbars_series_low_fp\c_space_tl to~\fp_use:N\l__gradbars_series_high_fp.} % \else\ifgradbars@stack % \tl_put_right:Nn \l__gradbars_alt_tl {Stacked~contributions:~} % \int_zero:N \l__gradbars_alt_index_int % \clist_map_inline:Nn \l__gradbars_stack_clist % {\int_incr:N \l__gradbars_alt_index_int % \int_compare:nNnT {\l__gradbars_alt_index_int}>{1} % {\tl_put_right:Nn \l__gradbars_alt_tl {;~}} % \clist_if_empty:NTF \l__gradbars_names_clist % {\tl_put_right:Nx \l__gradbars_alt_tl % {segment~\int_use:N\l__gradbars_alt_index_int}} % {\tl_put_right:Nx \l__gradbars_alt_tl % {\clist_item:Nn\l__gradbars_names_clist{\l__gradbars_alt_index_int}}} % \tl_put_right:Nn \l__gradbars_alt_tl {:~}\gradbarsAltValue{##1}} % \tl_put_right:Nx \l__gradbars_alt_tl % {.~Net:~\gradbars@total.~Positive~subtotal:~\gradbars@positive.\c_space_tl % Negative~subtotal:~\gradbars@negative.} % \else\ifgradbars@compare % \tl_put_right:Nn \l__gradbars_alt_tl {Reference:~} % \ifgradbars@referencemissing % \tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\gradbarsAltValue{\gradbars@reference}\fi % \tl_put_right:Nn \l__gradbars_alt_tl {.~Current:~} % \ifgradbars@missing\tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\gradbarsAltValue{\gradbars@value}\fi % \tl_put_right:Nn \l__gradbars_alt_tl {.~Change:~} % \ifgradbars@missing\tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\ifgradbars@referencemissing\tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\gradbarsAltValue{\gradbars@value-\gradbars@reference}\fi\fi % \str_if_eq:eeT {\gradbars@comparelabel}{percent} % {\tl_put_right:Nn \l__gradbars_alt_tl {.~Relative~change:~} % \ifgradbars@missing\tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\ifgradbars@referencemissing\tl_put_right:Nn \l__gradbars_alt_tl {missing} % \else\fp_compare:nNnTF {\gradbars@reference}={0} % {\tl_put_right:Nn \l__gradbars_alt_tl {undefined~for~a~zero~reference}} % {\gradbarsAltValue{100*(\gradbars@value-\gradbars@reference)/abs(\gradbars@reference)} % \tl_put_right:Nn \l__gradbars_alt_tl {~percent}}\fi\fi} % \tl_put_right:Nn \l__gradbars_alt_tl {.} % \else\ifgradbars@rangemode % \tl_put_right:Nn \l__gradbars_alt_tl {Interval:~} % \ifgradbars@rangemissing\tl_put_right:Nn \l__gradbars_alt_tl {missing.} % \else % \gradbarsAltValue{\gradbars@rangelo} % \tl_put_right:Nn \l__gradbars_alt_tl {~to~}\gradbarsAltValue{\gradbars@rangehi} % \tl_put_right:Nn \l__gradbars_alt_tl {.} % \tl_if_empty:oF {\gradbars@rangepoint} % {\tl_put_right:Nn \l__gradbars_alt_tl {~Point~estimate:~} % \gradbarsAltValue{\gradbars@rangepoint}\tl_put_right:Nn \l__gradbars_alt_tl {.}} % \fi % \else % \tl_put_right:Nn \l__gradbars_alt_tl {Value:~} % \ifgradbars@missing\tl_put_right:Nn \l__gradbars_alt_tl {missing.} % \else\gradbarsAltValue{\gradbars@value}\tl_put_right:Nn \l__gradbars_alt_tl {.}\fi % \fi\fi\fi\fi % \tl_if_empty:oF {\gradbars@unit} % {\tl_put_right:Nx \l__gradbars_alt_tl {~Unit:~\exp_not:o{\gradbars@unit}.}} % \ifgradbars@spark\else % \tl_put_right:Nx \l__gradbars_alt_tl % {~Scale:~\fp_eval:n{\gradbars@min}~to~\fp_eval:n{\gradbars@max}.} % \ifgradbars@error % \tl_put_right:Nx \l__gradbars_alt_tl % {~Error~distances:~minus~\gradbars@errorminus,~plus~\gradbars@errorplus.} % \fi % \tl_if_empty:oF {\gradbars@target} % {\tl_put_right:Nx \l__gradbars_alt_tl {~Target:~\gradbars@target.}} % \clist_map_inline:Nn \l__gradbars_refs_clist % {\seq_set_split:Nnn\l__gradbars_alt_fields_seq{/}{##1} % \tl_put_right:Nx\l__gradbars_alt_tl % {~Reference~\seq_item:Nn\l__gradbars_alt_fields_seq{4}:\c_space_tl % \seq_item:Nn\l__gradbars_alt_fields_seq{1}.}} % \tl_if_empty:oF {\gradbars@band} % {\tl_put_right:Nx\l__gradbars_alt_tl {~Reference~band:~\gradbars@band.}} % \ifgradbars@bullet % \tl_put_right:Nn\l__gradbars_alt_tl {~Background~grade~upper~bounds:~} % \clist_map_inline:Nn\l__gradbars_bands_clist % {\seq_set_split:Nnn\l__gradbars_alt_fields_seq{/}{##1} % \tl_put_right:Nx\l__gradbars_alt_tl % {\seq_item:Nn\l__gradbars_alt_fields_seq{1};~}} % \fi % \fi % } %\cs_new_protected:Npn \gradbarsApplyAlt % { % \cs_if_exist:NT \tag_if_active:T % {\tag_if_active:T % {\pgfkeysifdefined{/tikz/alt/.@cmd} % {\str_case_e:nn {\gradbars@accessibility} % {{auto}{\tl_if_empty:oF{\gradbars@alt} % {\tl_set:No\l__gradbars_alt_tl{\gradbars@alt}} % \tikzset{alt={\l__gradbars_alt_tl}}} % {artifact}{\tikzset{artifact}}}} % {}}} % } %\cs_new_protected:Npn \gradbarsPrepareAlt % {\cs_if_exist:NT\tag_if_active:T % {\tag_if_active:T{\gradbarsBuildAlt\gradbarsApplyAlt}}} %\cs_new_protected:Npn \gradbarsPrepareLegendAlt % {\cs_if_exist:NT\tag_if_active:T % {\tag_if_active:T % {\tl_set:Nx\l__gradbars_alt_tl % {Legend~categories:~\clist_use:Nn\l__gradbars_names_clist{;~}.} % \gradbarsApplyAlt}}} %\cs_new_protected:Npn \gradbarsSuspendMeasurementTagging % {\cs_if_exist:NT\tag_suspend:n{\tag_suspend:n{gradbars-measurement}}} %\cs_new_protected:Npn \gradbarsResumeMeasurementTagging % {\cs_if_exist:NT\tag_resume:n{\tag_resume:n{gradbars-measurement}}} %\ExplSyntaxOff % %\ExplSyntaxOff % %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars-tblr-tagging.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Explicit table semantics via tabularray hooks. %\ProvidesPackage{gradbars-tblr-tagging}[2026/10/25 v1.1.0 Tagged tabularray tables] %\ExplSyntaxOn %\cs_generate_variant:Nn\prop_gput:Nnn{Nxx} %\__gradbars_check_module:n{gradbars-tblr-tagging} %\bool_new:N\l__gradbars_tblr_tag_bool %\bool_new:N\l__gradbars_tblr_tag_active_bool %\bool_new:N\l__gradbars_tblr_repeat_reset_bool %\bool_new:N\l__gradbars_tblr_rebuilding_bool %\prop_new:N\g__gradbars_tblr_cells_prop %\prop_new:N\g__gradbars_tblr_cell_types_prop %\prop_new:N\l__gradbars_tblr_header_links_prop %\prop_new:N\l__gradbars_tblr_header_visit_prop %\clist_new:N\l__gradbars_tblr_header_cells_clist %\tl_new:N\l__gradbars_tblr_headers_pdf_tl %\box_new:N\g__gradbars_tblr_repeat_box %\int_new:N\l__gradbars_tblr_head_rows_int %\clist_new:N\l__gradbars_tblr_head_cols_clist %\tl_new:N\l__gradbars_tblr_caption_tl %\tl_new:N\l__gradbars_tblr_repeat_tl %\tl_set:Nn\l__gradbars_tblr_repeat_tl{artifact} %\prop_new:N\l__gradbars_tblr_row_structs_prop %\int_new:N\g__gradbars_tblr_attr_int %\tl_new:N\l__gradbars_tblr_attribute_tl %\keys_define:nn{gradbars/tblr/tagging} % {head~rows .int_set:N=\l__gradbars_tblr_head_rows_int, % row~headers .clist_set:N=\l__gradbars_tblr_head_cols_clist, % header~cells .clist_set:N=\l__gradbars_tblr_header_cells_clist, % cell~headers .code:n=\prop_set_from_keyval:Nn\l__gradbars_tblr_header_links_prop{#1}, % caption .tl_set:N=\l__gradbars_tblr_caption_tl, % header~repeat .choice:, % header~repeat/artifact .code:n=\tl_set:Nn\l__gradbars_tblr_repeat_tl{artifact}, % header~repeat/describe .code:n=\tl_set:Nn\l__gradbars_tblr_repeat_tl{describe}} %\DeclareDocumentCommand\gradtblrtagging{m} % {\par\bool_set_true:N\l__gradbars_tblr_tag_bool % \int_set:Nn\l__gradbars_tblr_head_rows_int{1} % \clist_clear:N\l__gradbars_tblr_head_cols_clist % \clist_clear:N\l__gradbars_tblr_header_cells_clist % \prop_clear:N\l__gradbars_tblr_header_links_prop % \tl_set:Nn\l__gradbars_tblr_repeat_tl{artifact} % \tl_clear:N\l__gradbars_tblr_caption_tl % \keys_set:nn{gradbars/tblr/tagging}{#1} % \cs_if_exist:NTF\tag_if_active:TF % {\tag_if_active:F{\__gradbars_public_error:n{Table~tagging~requires~DocumentMetadata~tagging=on}}} % {\__gradbars_public_error:n{Table~tagging~requires~DocumentMetadata~tagging=on}}} %\cs_new_protected:Npn\__gradbars_tblr_table_begin: % {\bool_if:NT\l__gradbars_tblr_tag_bool % {\bool_if:NT\l__gradbars_tblr_tag_active_bool{\__gradbars_public_error:n{Nested~tagged~tables~are~not~supported}} % \bool_set_true:N\l__gradbars_tblr_tag_active_bool % \bool_set_false:N\l__gradbars_tblr_repeat_reset_bool % \prop_clear:N\l__gradbars_tblr_row_structs_prop % \prop_gclear:N\g__gradbars_tblr_cells_prop % \prop_gclear:N\g__gradbars_tblr_cell_types_prop % \tag_mc_end_push:\tagpdfparaOff % \clist_map_inline:nn{para/semantic/begin,para/semantic/end,para/textblock/begin,para/textblock/end,minipage/before,minipage/after,parbox/before,parbox/after} % {\socket_if_exist:nT{tagsupport/##1}{\AssignTaggingSocketPlug{##1}{noop}}} % \tag_struct_begin:n{tag=Table} % \tl_if_empty:NF\l__gradbars_tblr_caption_tl % {\tag_struct_begin:n{tag=Caption}\tag_mc_begin:n{tag=Caption} % \noindent\l__gradbars_tblr_caption_tl\par % \tag_mc_end:\tag_struct_end:} % \int_compare:nNnT{\l__gradbars_tblr_head_rows_int}<{0} % {\__gradbars_public_error:n{Header~row~count~must~be~nonnegative}} % \int_compare:nNnT{\l__gradbars_tblr_head_rows_int}>{\c@rowcount} % {\__gradbars_public_error:n{Header~row~count~exceeds~table~rows}} % \clist_map_inline:Nn\l__gradbars_tblr_head_cols_clist % {\int_compare:nNnF{##1}>{0}{\__gradbars_public_error:n{Header~columns~must~be~positive}} % \int_compare:nNnT{##1}>{\c@colcount}{\__gradbars_public_error:n{Header~column~exceeds~table~columns}}} % % Allocate rows in reading order; tabularray builds footers before body. % \int_step_inline:nn{\c@rowcount} % {\tag_struct_begin:n{tag=TR} % \prop_put:Nnx\l__gradbars_tblr_row_structs_prop{##1}{\tag_get:n{struct_num}} % \tag_struct_end:}}} %\cs_new_protected:Npn\__gradbars_tblr_cell_begin: % {\bool_if:NT\l__gradbars_tblr_tag_active_bool % {\bool_lazy_and:nnT{!\lTblrMeasuringBool}{!\lTblrCellOmittedBool} % {\bool_if:NTF\l__gradbars_tblr_rebuilding_bool % {\exp_args:Ne\tag_struct_begin:n{tag=P, % parent=\prop_item:Ne\g__gradbars_tblr_cells_prop{\int_use:N\c@rownum/\int_use:N\c@colnum}}} % {\tl_set:Nn\l_tmpa_tl{TD}\tl_clear:N\l__gradbars_tblr_attribute_tl % \int_compare:nT{\c@rownum<=\l__gradbars_tblr_head_rows_int} % {\tl_set:Nn\l_tmpa_tl{TH}\tl_set:Nn\l__gradbars_tblr_attribute_tl{/Scope/Column}} % \clist_if_in:NeT\l__gradbars_tblr_head_cols_clist{\int_use:N\c@colnum} % {\tl_set:Nn\l_tmpa_tl{TH} % \tl_if_empty:NTF\l__gradbars_tblr_attribute_tl % {\tl_set:Nn\l__gradbars_tblr_attribute_tl{/Scope/Row}} % {\tl_set:Nn\l__gradbars_tblr_attribute_tl{/Scope/Both}}} % \clist_if_in:NeT\l__gradbars_tblr_header_cells_clist{\int_use:N\c@rownum/\int_use:N\c@colnum} % {\tl_set:Nn\l_tmpa_tl{TH}} % \prop_gput:Nxx\g__gradbars_tblr_cell_types_prop{\int_use:N\c@rownum/\int_use:N\c@colnum}{\l_tmpa_tl} % \int_gincr:N\g__gradbars_tblr_attr_int % \tag_attr_new:ee{gradbars-cell-\int_use:N\g__gradbars_tblr_attr_int} % {/O/Table/RowSpan~\int_use:N\lTblrCellRowSpanInt % /ColSpan~\int_use:N\lTblrCellColSpanInt\l__gradbars_tblr_attribute_tl} % \exp_args:Ne\tag_struct_begin:n % {tag=\l_tmpa_tl,parent=\prop_item:Ne\l__gradbars_tblr_row_structs_prop{\int_use:N\c@rownum}, % attribute=gradbars-cell-\int_use:N\g__gradbars_tblr_attr_int} % \prop_gput:Nxx\g__gradbars_tblr_cells_prop{\int_use:N\c@rownum/\int_use:N\c@colnum}{\tag_get:n{struct_num}}} % \tag_mc_begin:n{tag=Span}}}} %\cs_new_protected:Npn\__gradbars_tblr_cell_end: % {\bool_if:NT\l__gradbars_tblr_tag_active_bool % {\bool_lazy_and:nnT{!\lTblrMeasuringBool}{!\lTblrCellOmittedBool}{\tag_mc_end:\tag_struct_end:}}} %\cs_new_protected:Npn\__gradbars_tblr_header_visit:n #1 % {\str_case_e:nnF{\prop_item:Nn\l__gradbars_tblr_header_visit_prop{#1}} % {{visiting}{\__gradbars_public_error:n{Cyclic~table~header~association:~#1}} % {done}{}} % {\prop_put:Nnn\l__gradbars_tblr_header_visit_prop{#1}{visiting} % \prop_get:NnNT\l__gradbars_tblr_header_links_prop{#1}\l_tmpa_tl % {\exp_args:NV\clist_map_inline:nn\l_tmpa_tl{\__gradbars_tblr_header_visit:n{##1}}} % \prop_put:Nnn\l__gradbars_tblr_header_visit_prop{#1}{done}}} %\cs_new_protected:Npn\__gradbars_tblr_link_headers: % {\prop_clear:N\l__gradbars_tblr_header_visit_prop % \clist_map_inline:Nn\l__gradbars_tblr_header_cells_clist % {\str_if_eq:eeF{\prop_item:Nn\g__gradbars_tblr_cell_types_prop{##1}}{TH} % {\__gradbars_public_error:n{Header~cell~does~not~exist~or~is~covered:~##1}}} % \prop_map_inline:Nn\l__gradbars_tblr_header_links_prop % {\__gradbars_tblr_header_visit:n{##1} % \prop_if_in:NnTF\g__gradbars_tblr_cells_prop{##1} % {\tl_clear:N\l__gradbars_tblr_headers_pdf_tl % \clist_map_inline:nn{##2} % {\str_if_eq:eeTF{\prop_item:Nn\g__gradbars_tblr_cell_types_prop{####1}}{TH} % {\tl_put_right:Nx\l__gradbars_tblr_headers_pdf_tl % {\__tag_struct_get_id:n{\prop_item:Nn\g__gradbars_tblr_cells_prop{####1}}}} % {\__gradbars_public_error:n{Association~requires~an~existing~TH~cell:~####1}}} % \exp_args:Nene\tag_struct_gput:nnn % {\prop_item:Nn\g__gradbars_tblr_cells_prop{##1}}{attribute} % {/O/Table/Headers[\l__gradbars_tblr_headers_pdf_tl]}} % {\__gradbars_public_error:n{Unknown~association~target~cell:~##1}}}} %\cs_new_protected:Npn\__gradbars_tblr_table_end: % {\bool_if:NT\l__gradbars_tblr_tag_active_bool % {\__gradbars_tblr_link_headers:\par\tag_struct_end:\tag_mc_begin_pop:n{} % \bool_set_false:N\l__gradbars_tblr_tag_active_bool}} %% The private adapter is isolated and tested against tabularray 2025C. %% Artifact mode resets copied attributes. Describe mode rebuilds fresh content %% beneath the original logical cells, never duplicating TR/TH/TD or MCIDs. %\cs_new_protected:Npn\__gradbars_tblr_output_after: % {\bool_if:NT\l__gradbars_tblr_tag_active_bool % {\str_if_eq:VnT\lTblrPortraitTypeTl{long} % {\int_compare:nNnT{\lTblrRowHeadInt+\lTblrRowFootInt}>{0} % {\sys_if_engine_luatex:TF % {\bool_if:NF\l__gradbars_tblr_repeat_reset_bool % {\tag_mc_begin:n{artifact} % \tag_mc_reset_box:N\l__tblr_row_foot_box % \str_if_eq:VnT\l__gradbars_tblr_repeat_tl{artifact} % {\tag_mc_reset_box:N\l__tblr_row_head_box} % \tag_mc_end: % \bool_set_true:N\l__gradbars_tblr_repeat_reset_bool} % \str_if_eq:VnT\l__gradbars_tblr_repeat_tl{describe} % {\bool_lazy_and:nnT{\int_compare_p:nNn{\lTblrRowHeadInt}>{0}}{\int_compare_p:nNn{\lTblrRowLastInt}<{\c@rowcount-\lTblrRowFootInt}} % {\group_begin: % \bool_set_true:N\l__gradbars_tblr_rebuilding_bool % \__tblr_build_one_table:nnNN{1}{\lTblrRowHeadInt}\c_true_bool\c_true_bool % \box_gset_eq:NN\g__gradbars_tblr_repeat_box\l__tblr_table_box % \group_end: % \box_set_eq:NN\l__tblr_row_head_box\g__gradbars_tblr_repeat_box}}} % {\__gradbars_public_error:n{Repeated~tagged~longtblr~headers~require~LuaLaTeX}}}}}} %\AddToTblrHook{table/before}[gradbars-structure]{\__gradbars_tblr_table_begin:} %\AddToTblrHook{cell/before}[gradbars-structure]{\__gradbars_tblr_cell_begin:} %\AddToTblrHook{cell/after}[gradbars-structure]{\__gradbars_tblr_cell_end:} %\AddToTblrHook{private/output/after}[gradbars-structure]{\__gradbars_tblr_output_after:} %\AddToTblrHook{table/after}[gradbars-structure]{\__gradbars_tblr_table_end:} %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{gradbars.sty}} % \begin{macrocode} %% Author and maintainer: SuFan (GitHub: Tape5try) %% Copyright (c) 2026 SuFan. MIT License; see LICENSE. %\NeedsTeXFormat{LaTeX2e}[2025/11/01] %\ProvidesPackage{gradbars}[2026/10/25 v1.1.0 Modular inline data graphics] %\RequirePackage{expl3}[2025/12/29] %\RequirePackage{xparse} %\ExplSyntaxOn %\tl_new:N\g__gradbars_requested_libraries_tl %\tl_gset:Nn\g__gradbars_requested_libraries_tl{all} %\keys_define:nn{gradbars/package} % {libraries .tl_gset:N=\g__gradbars_requested_libraries_tl, % unknown .code:n={\PackageError{gradbars}{Unknown~package~option:~\l_keys_key_str}{Use~libraries=all,~none,~or~a~braced~list.}}} %\DeclareOption*{\exp_args:Nno\keys_set:nn{gradbars/package}{\CurrentOption}} %\ProcessOptions*\relax %\ExplSyntaxOff %\RequirePackage{gradbars-core} %\RequirePackage{gradbars-accessible} %\RequirePackage{gradbars-api} %\RequirePackage{gradbars-backend} %\ExplSyntaxOn %\clist_map_inline:nn{core,keys,numbers,model,render-tikz,tagging,accessible,api,backend} % {\__gradbars_check_module:n{gradbars-#1}} %\gradbarsdeclarelibrary{core}{}{gradbars-core.sty} %\prop_gput:Nnn\g__gradbars_library_state_prop{core}{loaded} %\gradbarsdeclarelibrary{stack}{core}{gradbars-lib-stack.sty} %\gradbarsdeclarelibrary{spark}{core}{gradbars-lib-spark.sty} %\gradbarsdeclarelibrary{heat}{core}{gradbars-lib-heat.sty} %\gradbarsdeclarelibrary{csv}{core}{gradbars-lib-csv.sty} %\gradbarsdeclarelibrary{distribution}{core}{gradbars-lib-distribution.sty} %\gradbarsdeclarelibrary{legend}{core,heat}{gradbars-lib-legend.sty} %\gradbarsdeclarelibrary{reports}{table,legend}{gradbars-lib-reports.sty} %\gradbarsdeclarelibrary{table}{core,stack,spark,heat,csv}{gradbars-lib-table.sty} %\str_case:VnF\g__gradbars_requested_libraries_tl % {{all}{\usegradbarslibrary{stack,spark,heat,csv,table}}{none}{}} % {\exp_args:NV\usegradbarslibrary\g__gradbars_requested_libraries_tl} %\ExplSyntaxOff %\endinput % \end{macrocode} % \section{\texttt{tblrlibgradbars.sty}} % \begin{macrocode} %% Author: SuFan; MIT License. Optional public tabularray integration. %\NeedsTeXFormat{LaTeX2e}[2025/11/01] %\ProvidesPackage{tblrlibgradbars}[2026/10/25 v1.1.0 gradbars tabularray library] %\RequirePackage{tabularray}[2025/11/27] %\IfPackageAtLeastTF{tabularray}{2025/11/27}{}{% % \PackageError{gradbars}{The gradbars library requires tabularray 2025C or newer}{Update tabularray before loading this library.}} %\IfPackageLoadedTF{gradbars}{}{\RequirePackage[libraries=none]{gradbars}} %\usegradbarslibrary{heat,stack,spark,distribution} %\UseTblrLibrary{hook} %\ExplSyntaxOn %\__gradbars_check_module:n{tblrlibgradbars} %\AddToTblrHook{trial/before}[gradbars] % {\cs_if_exist:NT\tag_suspend:n{\tag_suspend:n{gradbars-tblr-trial}}} %\AddToTblrHook{trial/after}[gradbars] % {\cs_if_exist:NT\tag_resume:n{\tag_resume:n{gradbars-tblr-trial}}} %\tl_new:N\l__gradbars_tblr_defaults_tl %\tl_new:N\l__gradbars_tblr_width_tl %\tl_set:Nn\l__gradbars_tblr_width_tl{auto} %\dim_new:N\l__gradbars_tblr_width_dim %\dim_new:N\l__gradbars_tblr_graphic_dim %\box_new:N\l__gradbars_tblr_box %\seq_new:N\l__gradbars_tblr_pair_seq %\pgfkeys{/gradbars/cell~width/.code={\tl_set:Nn\l__gradbars_tblr_width_tl{#1}}} %\DeclareDocumentCommand\gradtblrsetup{m}{\tl_put_right:Nn\l__gradbars_tblr_defaults_tl{,#1}} %\cs_new_protected:Npn\__gradbars_tblr_number:n #1 % {\gradbars@validtrue\gradbars@missingfalse % \gradbarsResolveScaleGroup\gradbarsValidateFormatter % \tl_set:Nx\l_tmpa_tl{#1}\tl_trim_spaces:N\l_tmpa_tl % \tl_if_empty:NT\l_tmpa_tl{\gradbars@missingtrue} % \str_if_eq:VnT\l_tmpa_tl{NA}{\gradbars@missingtrue} % \tl_set:Nx\l_tmpa_tl{\gradbars@precision} % \regex_match:nVF{\A[0-6]\Z}\l_tmpa_tl % {\gradbarsFail{Precision~must~be~an~integer~from~0~to~6}} % \ifgradbars@missing\else % \gradbarsCheckNumber{#1}{cell~value} % \str_if_eq:eeT{\gradbars@format}{percent} % {\gradbarsCheckNumber{\gradbars@min}{min} % \gradbarsCheckNumber{\gradbars@max}{max} % \ifgradbars@valid % \fp_compare:nNnF{\gradbars@min}={0} % {\gradbarsFail{Percent~format~requires~min=0}} % \gradbarsValidatePercentBase % \fi} % \ifgradbars@valid % \cs_set:Npx\gradbars@number{\fp_eval:n % {\str_if_eq:eeTF{\gradbars@format}{percent}{100*(#1)/\gradbarsPercentBase}{#1}}} % \fi % \fi % \ifgradbars@valid{\gradbars@font\gradbarsSingleLabel}\fi} %\cs_new_protected:Npn\__gradbars_tblr_pair:nn #1#2 % {\tl_set:Nn\l_tmpa_tl{#2}\tl_trim_spaces:N\l_tmpa_tl % \tl_if_empty:NT\l_tmpa_tl{\tl_set:Nn\l_tmpa_tl{NA/NA}} % \str_if_eq:VnT\l_tmpa_tl{NA}{\tl_set:Nn\l_tmpa_tl{NA/NA}} % \exp_args:NNnV\seq_set_split:Nnn\l__gradbars_tblr_pair_seq{/}\l_tmpa_tl % \int_compare:nNnTF{\seq_count:N\l__gradbars_tblr_pair_seq}={2} % {\use:x{\exp_not:c{grad#1} % {\seq_item:Nn\l__gradbars_tblr_pair_seq{1}} % {\seq_item:Nn\l__gradbars_tblr_pair_seq{2}}}} % {\__gradbars_public_error:n{Tblr~#1~requires~two~values~separated~by~/}}} %\cs_new_protected:Npn\__gradbars_tblr_draw:nn #1#2 % {\str_case:nnF{#1} % {{bar}{\gradbar{#2}} % {heat}{\use:x{\exp_not:N\gradheat[height=\dim_eval:n{\gradbars@height}]{\exp_not:n{#2}}}} % {number}{\__gradbars_tblr_number:n{#2}} % {compare}{\__gradbars_tblr_pair:nn{compare}{#2}} % {dumbbell}{\__gradbars_tblr_pair:nn{dumbbell}{#2}} % {range}{\__gradbars_tblr_pair:nn{range}{#2}} % {spark}{\use:x{\exp_not:N\gradspark[height=\dim_eval:n{\gradbars@height}]{\exp_not:n{#2}}}} % {stack}{\str_if_eq:nnTF{#2}{NA}{\gradbar{NA}}{\gradstack{#2}}} % {bullet}{\use:x{\exp_not:N\gradbullet[height=\dim_eval:n{\gradbars@height},label=\gradbars@label]{\exp_not:n{#2}}}} % {boxplot}{\use:x{\exp_not:N\gradboxplot[height=\dim_eval:n{\gradbars@height}]{\exp_not:n{#2}}}}} % {\__gradbars_public_error:n{Unknown~tblr~graphic~type:~#1}}} %\DeclareDocumentCommand\gradtblrcell{O{} m m} % {\leavevmode\group_begin: % \gradbarssetup{baseline=text,label=inside,label~align=cell} % \exp_args:NV\gradbarssetup\l__gradbars_tblr_defaults_tl % \gradbarssetup{#1} % \str_case:nn{#2}{{spark}{\str_if_eq:eeT{\gradbars@label}{inside}{\gradbarssetup{label=none}}} % {stack}{\str_if_eq:eeT{\gradbars@label}{inside}{\gradbarssetup{label=none}}}} % \str_if_eq:VnTF\l__gradbars_tblr_width_tl{auto} % {\dim_set:Nn\l__gradbars_tblr_width_dim{\linewidth} % % Natural-width trials run inside a paper-wide varwidth box. % \dim_compare:nNnF{\linewidth}<{\paperwidth} % {\dim_set:Nn\l__gradbars_tblr_width_dim{\gradbars@width}}} % {\dim_set:Nn\l__gradbars_tblr_width_dim{\l__gradbars_tblr_width_tl}} % \dim_compare:nNnTF{\l__gradbars_tblr_width_dim}>{0pt} % {\dim_set_eq:NN\l__gradbars_tblr_graphic_dim\l__gradbars_tblr_width_dim % \bool_lazy_or:nnT{\str_if_eq_p:nn{#2}{dumbbell}}{\str_if_eq_p:nn{#2}{spark}} % {\dim_sub:Nn\l__gradbars_tblr_graphic_dim{\gradbars@markersize+\gradbars@markersize}} % \bool_lazy_or:nnT{\str_if_eq_p:nn{#2}{spark}}{\str_if_eq_p:nn{#2}{dumbbell}}{\dim_sub:Nn\l__gradbars_tblr_graphic_dim{1pt}} % \str_if_eq:nnT{#2}{boxplot}{\gradbarssetup{label=none}} % \str_if_eq:nnF{#2}{number} % {\str_if_eq:nnF{#2}{heat} % {\str_case_e:nn{\gradbars@label} % {{left}{\dim_sub:Nn\l__gradbars_tblr_graphic_dim{\gradbars@labelwidth+\gradbars@gap}} % {outside}{\dim_sub:Nn\l__gradbars_tblr_graphic_dim{\gradbars@labelwidth+\gradbars@gap}}}}} % \dim_compare:nNnTF{\l__gradbars_tblr_graphic_dim}>{0pt} % {\cs_set:Npx\gradbars@width{\dim_use:N\l__gradbars_tblr_graphic_dim} % \hbox_set:Nn\l__gradbars_tblr_box{\__gradbars_tblr_draw:nn{#2}{#3}} % \str_if_eq:eeF{\gradbars@labeloverflow}{allow} % {\dim_compare:nNnT{\box_wd:N\l__gradbars_tblr_box}>{\l__gradbars_tblr_width_dim+.1pt} % {\__gradbars_public_error:n{Tblr~content~exceeds~cell~width~(\dim_eval:n{\box_wd:N\l__gradbars_tblr_box}~>~\dim_use:N\l__gradbars_tblr_width_dim);~increase~cell~width~or~label~width}}} % \hbox_to_wd:nn{\l__gradbars_tblr_width_dim}{\hss\box_use_drop:N\l__gradbars_tblr_box\hss}} % {\__gradbars_public_error:n{Tblr~cell~width~must~exceed~label~width~and~gap}}} % {\__gradbars_public_error:n{Tblr~cell~width~must~be~positive}} % \group_end:} %\DeclareDocumentCommand\gradbarTblr{O{} m}{\gradtblrcell[#1]{bar}{#2}} %\DeclareDocumentCommand\gradheatTblr{O{} m}{\gradtblrcell[#1]{heat}{#2}} %\DeclareDocumentCommand\gradnumberTblr{O{} m}{\gradtblrcell[#1]{number}{#2}} %\DeclareDocumentCommand\gradcompareTblr{O{} m}{\gradtblrcell[#1]{compare}{#2}} %\NewTblrColumnType{G}[2][]{Q[c,m,wd=#2,cmd={\gradbarTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{H}[2][]{Q[c,m,wd=#2,cmd={\gradheatTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{N}[2][]{Q[c,m,wd=#2,cmd={\gradnumberTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{D}[2][]{Q[c,m,wd=#2,cmd={\gradcompareTblr[cell~width=#2,#1]}]} %\DeclareDocumentCommand\graddumbbellTblr{O{} m}{\gradtblrcell[#1]{dumbbell}{#2}} %\DeclareDocumentCommand\gradrangeTblr{O{} m}{\gradtblrcell[#1]{range}{#2}} %\DeclareDocumentCommand\gradsparkTblr{O{} m}{\gradtblrcell[#1]{spark}{#2}} %\DeclareDocumentCommand\gradstackTblr{O{} m}{\gradtblrcell[#1]{stack}{#2}} %\DeclareDocumentCommand\gradbulletTblr{O{} m}{\gradtblrcell[#1]{bullet}{#2}} %\DeclareDocumentCommand\gradboxplotTblr{O{} m}{\gradtblrcell[#1]{boxplot}{#2}} %\NewTblrColumnType{J}[2][]{Q[c,m,wd=#2,cmd={\graddumbbellTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{R}[2][]{Q[c,m,wd=#2,cmd={\gradrangeTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{V}[2][]{Q[c,m,wd=#2,cmd={\gradsparkTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{K}[2][]{Q[c,m,wd=#2,cmd={\gradstackTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{U}[2][]{Q[c,m,wd=#2,cmd={\gradbulletTblr[cell~width=#2,#1]}]} %\NewTblrColumnType{B}[2][]{Q[c,m,wd=#2,cmd={\gradboxplotTblr[cell~width=#2,#1]}]} %\NewTblrEnviron{gradtblr} %\SetTblrInner[gradtblr]{hlines={.3pt,black!18},colsep=6pt,rowsep=4pt, % cells={c,m},row{1}={font=\bfseries,bg=gradbarsTeal!8,cmd=}} %\ExplSyntaxOff %\RequirePackage{gradbars-tblr-tagging} %\endinput % \end{macrocode}