%% tikzviolinplots.sty
%% Copyright 2025 Pedro Callil-Soares
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Pedro Callil-Soares.
%
% This work consists of the files tikzviolinplots.sty and
% tikzviolinplots.tex.

\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{tikzviolinplots}[2025/04/27 v0.9.1 Violin plot creation in pgfplots]

\RequirePackage{pgfplots}
\RequirePackage{pgfplotstable}
\RequirePackage{ifthen}
\RequirePackage{stringstrings}
\RequirePackage{pgfkeys}


\DeclareOption*{\PackageWarning{tikzviolinplots}{Unknown option: ‘\CurrentOption’}}
\ProcessOptions\relax

\pgfkeys{
       /violinplot/.is family, /violinplot,
       default/.style = {
               col sep=comma,
               kernel=gaussian,
               bandwidth=NONE,
               index=DATA,
               frequencies=FREQINTERNALVIOLIN,
               samples=50,
               relative position=0
               color=black,
               label={LABEL},
               invert={FALSE},
               average mark=x,
               average size=3pt,
               average color=black,
               average opacity=1.0,
               average fill=white,
               average fill opacity=0.5,
               dataset mark=*,
               dataset size=1pt,
               dataset color=black,
               dataset opacity=1.0,
               dataset fill=black,
               dataset fill opacity=0.2,
               dataset jitter=0.0
       },
       col sep/.estore in = \violin@colsep,
       kernel/.estore in = \violin@kernel,
       bandwidth/.estore in = \violin@bandwidth,
       index/.estore in = \violin@index,
       frequencies/.estore in = \violin@frequencies,
       samples/.estore in = \violin@samples,
       relative position/.estore in = \violin@delta,
       color/.estore in = \violin@color,
       label/.estore in = \violin@label,
       invert/.estore in = \violin@invert,
       average mark/.estore in = \violin@avg@mark,
       average size/.estore in = \violin@avg@size,
       average color/.estore in = \violin@avg@color,
       average opacity/.estore in = \violin@avg@opacity,
       average fill/.estore in = \violin@avg@fillcolor,
       average fill opacity/.estore in = \violin@avg@fillopacity,
       dataset mark/.estore in = \violin@pts@mark,
       dataset size/.estore in = \violin@pts@size,
       dataset color/.estore in = \violin@pts@color,
       dataset opacity/.estore in = \violin@pts@opacity,
       dataset fill/.estore in = \violin@pts@fillcolor,
       dataset fill opacity/.estore in = \violin@pts@fillopacity,
       dataset jitter/.estore in = \violin@pts@jitter,
       /violinplotwholefile/.is family, /violinplotwholefile,
       default/.style = {
               col sep=comma,
               kernel=gaussian,
               bandwidth=NONE,
               index=DATA,
               samples=50,
               relative position=0
               color=black,
               label={LABEL},
               average mark=x,
               average size=3pt,
               average color=black,
               average opacity=1.0,
               average fill=white,
               average fill opacity=0.5,
               dataset mark=*,
               dataset size=1pt,
               dataset color=black,
               dataset opacity=1.0,
               dataset fill=black,
               dataset fill opacity=0.2,
               dataset jitter=0.0,
               spacing=1.0,
               indexes={A,B,C},
               primary color=blue,
               secondary color=black,
               labels={A,B,C},
       },
       col sep/.estore in = \violin@batch@colsep,
       kernel/.estore in = \violin@batch@kernel,
       bandwidth/.estore in = \violin@batch@bandwidth,
       index/.estore in = \violin@batch@index,
       samples/.estore in = \violin@batch@samples,
       relative position/.estore in = \violin@batch@delta,
       color/.estore in = \violin@batch@color,
       label/.estore in = \violin@batch@label,
       average mark/.estore in = \violin@batch@avg@mark,
       average size/.estore in = \violin@batch@avg@size,
       average color/.estore in = \violin@batch@avg@color,
       average opacity/.estore in = \violin@batch@avg@opacity,
       average fill/.estore in = \violin@batch@avg@fillcolor,
       average fill opacity/.estore in = \violin@batch@avg@fillopacity,
       dataset mark/.estore in = \violin@batch@pts@mark,
       dataset size/.estore in = \violin@batch@pts@size,
       dataset color/.estore in = \violin@batch@pts@color,
       dataset opacity/.estore in = \violin@batch@pts@opacity,
       dataset fill/.estore in = \violin@batch@pts@fillcolor,
       dataset fill opacity/.estore in = \violin@batch@pts@fillopacity,
       dataset jitter/.estore in = \violin@batch@pts@jitter,
       spacing/.estore in = \violin@batch@delta,
       indexes/.estore in = \violin@batch@indexes,
       primary color/.estore in = \violin@batch@color@primary,
       secondary color/.estore in = \violin@batch@color@secondary,
       labels/.estore in = \violin@batch@labels,
}

\newcommand{\violinsetoptions}[2][]{%

       \def\violin@scaled{false}
       \def\violin@datapoints{false}
       \def\violin@averages{false}
       \def\violin@nomirror{false}
       \def\violin@reverseaxis{false}
       \def\violin@axisoptions{#2}

       \@for\kdeoption:=#1\do{
               \noblanks[q]{\kdeoption}
               \ifthenelse{
                       \equal{\thestring}{scaled}
               }{
                       \def\violin@scaled{true}
               }{}
               \ifthenelse{
                       \equal{\thestring}{datapoints}
               }{
                       \def\violin@datapoints{true}
               }{}
               \ifthenelse{
                       \equal{\thestring}{averages}
               }{
                       \def\violin@averages{true}
               }{}
               \ifthenelse{
                       \equal{\thestring}{nomirror}
               }{
                       \def\violin@nomirror{true}
               }{}
               \ifthenelse{
                       \equal{\thestring}{reverseaxis}
               }{
                       \def\violin@reverseaxis{true}
               }{}
       }

       \ifthenelse{
               \equal{\violin@reverseaxis}{true}
       }{
               \begin{axis}[
                       axis on top,
                       yticklabels={,,},
                       ymajorticks=false,
                       \violin@axisoptions,
               ]
               \end{axis}
       }{
               \begin{axis}[
                       axis on top,
                       xticklabels={,,},
                       xmajorticks=false,
                       \violin@axisoptions,
               ]
               \end{axis}
       }

       \@for\kdeoption:=\violin@axisoptions\do{
               \noblanks[e]{\kdeoption}
               \let\violin@opt\thestring
               \whereisword[q]{\violin@opt}{xmin}
               \ifthenelse{
                       \equal{\theresult}{0}
               }{}{
                       \let\violin@axis@xmin\violin@opt
               }
               \whereisword[q]{\violin@opt}{xmax}
               \ifthenelse{
                       \equal{\theresult}{0}
               }{}{
                       \let\violin@axis@xmax\violin@opt
               }
               \whereisword[q]{\violin@opt}{ymin}
               \ifthenelse{
                       \equal{\theresult}{0}
               }{}{
                       \let\violin@axis@ymin\violin@opt
               }
               \whereisword[q]{\violin@opt}{ymax}
               \ifthenelse{
                       \equal{\theresult}{0}
               }{}{
                       \let\violin@axis@ymax\violin@opt
               }
       }

       \def\violin@axislimits{
               \violin@axis@xmin,\violin@axis@xmax,
               \violin@axis@ymin,\violin@axis@ymax,
       }

       \let\violin@axisoptions\violin@axislimits

}

\newcommand{\violinplot}[2][]{%

       \pgfkeys{/violinplot, default, #1}

       \def\violin@filename{#2}

       \pgfplotstableread[%
               col sep=\violin@colsep,
               trim cells=true,
       ]{\violin@filename}\theviolin@dataset@table

       \pgfplotstablegetrowsof{\theviolin@dataset@table}
       \pgfmathparse{int(\pgfmathresult-1)}
       \let\violin@filename@lastindex\pgfmathresult

       \pgfmathparse{0}
       \let\violin@dataset@stddev\pgfmathresult
       \let\violin@dataset@average\pgfmathresult
       \let\violin@dataset@weightsum\pgfmathresult
       \let\violin@weight@row\pgfmathresult

       % Calculating averages
       \pgfplotstableforeachcolumnelement{\violin@index}\of\theviolin@dataset@table\as\xi{%
               \ifthenelse{
                       \equal{\violin@frequencies}{FREQINTERNALVIOLIN}
               }{
                       \pgfmathparse{1}
                       \let\violin@dataset@weight\pgfmathresult
               }{
                       \pgfplotstablegetelem{\violin@weight@row}{\violin@frequencies}\of{\theviolin@dataset@table}
                       \let\violin@dataset@weight\pgfplotsretval
                       \pgfmathparse{\violin@weight@row+1}
                       \let\violin@weight@row\pgfmathresult
               }
               \pgfmathparse{\violin@dataset@weightsum+\violin@dataset@weight}
               \let\violin@dataset@weightsum\pgfmathresult
               \pgfmathparse{\violin@dataset@average+\xi*\violin@dataset@weight}
               \let\violin@dataset@average\pgfmathresult
       }
       \pgfmathparse{\violin@dataset@average/\violin@dataset@weightsum}
       \let\violin@dataset@average\pgfmathresult

       \ifthenelse{
               \equal{\violin@datapoints}{true}
       }{
               \pgfplotstablecreatecol[
                       create col/assign/.code={
                               \let\entry\violin@delta
                               \pgfkeyslet{/pgfplots/table/create col/next content}\entry
                       }
               ]{deltacol}\theviolin@dataset@table
       }{}

       \ifthenelse{
               \equal{\violin@reverseaxis}{true}
       }{
               \def\violin@axis@x{y}
               \def\violin@axis@y{x}
       }{
               \def\violin@axis@x{x}
               \def\violin@axis@y{y}
       }

       % Bandwidth calculation
       \ifthenelse{%
               \equal{\violin@bandwidth}{NONE}%
       }{%
               \pgfmathparse{0}
               \let\violin@weight@row\pgfmathresult
               % Standard deviation calculation
               \pgfplotstableforeachcolumnelement{\violin@index}\of\theviolin@dataset@table\as\xi{%
                       \ifthenelse{
                               \equal{\violin@frequencies}{FREQINTERNALVIOLIN}
                       }{
                               \pgfmathparse{1}
                               \let\violin@dataset@weight\pgfmathresult
                       }{
                               \pgfplotstablegetelem{\violin@weight@row}{\violin@frequencies}\of{\theviolin@dataset@table}
                               \let\violin@dataset@weight\pgfplotsretval
                               \pgfmathparse{\violin@weight@row+1}
                               \let\violin@weight@row\pgfmathresult
                       }
                       \pgfmathparse{\violin@dataset@stddev+\violin@dataset@weight*(\xi-\violin@dataset@average)^2}
                       \let\violin@dataset@stddev\pgfmathresult
               }
               \pgfmathparse{sqrt(\violin@dataset@stddev/\violin@dataset@weightsum)}
               \let\violin@dataset@stddev\pgfmathresult
               \pgfmathparse{1.06*\violin@dataset@stddev*(\violin@dataset@weightsum^(-0.2))}%
               \let\violin@bandwidth\pgfmathresult
       }{%
       }

       % Setting limits for curve
       \pgfplotstablegetelem{0}{\violin@index}\of{\theviolin@dataset@table}
       \let\violin@dataset@min\pgfplotsretval
       \let\violin@dataset@max\pgfplotsretval
       \pgfplotstableforeachcolumnelement{\violin@index}\of\theviolin@dataset@table\as\xi{%
               \pgfmathparse{%
                       \xi > \violin@dataset@min ? int(0) : int(1)%
               }
               \ifthenelse{
                       \pgfmathresult = 1
               }{
                       \let\violin@dataset@min\xi
               }{
               }
       }
       \pgfmathparse{\violin@dataset@min - 3*\violin@bandwidth}
       \let\violin@dataset@min\pgfmathresult

       \pgfplotstableforeachcolumnelement{\violin@index}\of\theviolin@dataset@table\as\xi{%
               \pgfmathparse{%
                       \xi < \violin@dataset@max ? int(0) : int(1)%
               }
               \ifthenelse{
                       \pgfmathresult = 1
               }{
                       \let\violin@dataset@max\xi
               }{
               }
       }
       \pgfmathparse{\violin@dataset@max + 3*\violin@bandwidth}
       \let\violin@dataset@max\pgfmathresult

       % Creating curve domain
       \pgfplotstableset{
               create on use/list/.style={create col/expr={
                       \violin@dataset@min + (\violin@dataset@max-\violin@dataset@min)
                       *(\pgfplotstablerow/(\violin@samples-1))
               }}
       }


       % Calculating KDE
       \pgfplotstablenew[columns={list}]{\violin@samples}\violin@kde

       \pgfmathparse{0.0}
       \let\violin@kde@max\pgfmathresult

       \pgfplotstablecreatecol[
               create col/assign/.code={
                       \pgfmathparse{%
                               1.0/(\violin@dataset@weightsum*\violin@bandwidth)
                       }
                       \let\violin@kde@factor\pgfmathresult
                       \pgfmathparse{0}
                       \let\violin@kde@accum\pgfmathresult
                       \let\violin@weight@row\pgfmathresult
                       \pgfplotstableforeachcolumnelement{\violin@index}\of\theviolin@dataset@table\as\xi{%
                               \ifthenelse{
                                       \equal{\violin@frequencies}{FREQINTERNALVIOLIN}
                               }{
                                       \pgfmathparse{1}
                                       \let\violin@dataset@weight\pgfmathresult
                               }{
                                       \pgfplotstablegetelem{\violin@weight@row}{\violin@frequencies}\of{\theviolin@dataset@table}
                                       \let\violin@dataset@weight\pgfplotsretval
                                       \pgfmathparse{\violin@weight@row+1}
                                       \let\violin@weight@row\pgfmathresult
                               }
                               \pgfmathparse{%
                                       ((\xi-\thisrow{list})/%
                                       \violin@bandwidth)}
                               \let\violin@u\pgfmathresult
                               \ifthenelse{
                                       \equal{\violin@kernel}{gaussian}
                               }{
                                       \pgfmathparse{\violin@kde@accum + %
                                               \violin@dataset@weight*e^(-0.5*\violin@u*\violin@u)/sqrt(2*pi)}
                                       \let\violin@kde@accum\pgfmathresult
                               }{}
                               \ifthenelse{
                                       \equal{\violin@kernel}{logistic}
                               }{
                                       \pgfmathparse{\violin@kde@accum + %
                                               \violin@dataset@weight*1/(e^\violin@u + 2 + e^(-\violin@u))
                                       }
                                       \let\violin@kde@accum\pgfmathresult
                               }{}
                               \ifthenelse{
                                       \equal{\violin@kernel}{parabolic}
                               }{
                                       \pgfmathparse{%
                                               abs(\violin@u) < 1 ? int(0) : int(1)%
                                       }
                                       \ifthenelse{
                                               \equal{\pgfmathresult}{0}
                                       }{
                                               \pgfmathparse{\violin@kde@accum + %
                                                       \violin@dataset@weight*0.75*(1-\violin@u*\violin@u)
                                               }
                                       }{
                                               \pgfmathparse{\violin@kde@accum}
                                       }
                                       \let\violin@kde@accum\pgfmathresult
                               }{}
                               \ifthenelse{
                                       \equal{\violin@kernel}{uniform}
                               }{
                                       \pgfmathparse{%
                                               abs(\violin@u) < 1 ? int(0) : int(1)%
                                       }
                                       \ifthenelse{
                                               \equal{\pgfmathresult}{0}
                                       }{
                                               \pgfmathparse{\violin@kde@accum + \violin@dataset@weight*0.5}
                                       }{
                                               \pgfmathparse{\violin@kde@accum}
                                       }
                                       \let\violin@kde@accum\pgfmathresult
                               }{}
                               \ifthenelse{
                                       \equal{\violin@kernel}{triangular}
                               }{
                                       \pgfmathparse{%
                                               abs(\violin@u) < 1 ? int(0) : int(1)%
                                       }
                                       \ifthenelse{
                                               \equal{\pgfmathresult}{0}
                                       }{
                                               \pgfmathparse{\violin@kde@accum + %
                                                       \violin@dataset@weight*(1-abs(\violin@u))}
                                       }{
                                               \pgfmathparse{\violin@kde@accum}
                                       }
                                       \let\violin@kde@accum\pgfmathresult
                               }{}
                       }
                       \pgfmathparse{\violin@kde@accum*\violin@kde@factor}
                       \let\entry\pgfmathresult
                       \pgfkeyslet{/pgfplots/table/create col/next content}\entry
               }
       ]{kdecol}\violin@kde

       \pgfplotstableforeachcolumnelement{kdecol}\of\violin@kde\as\entry{%
               \pgfmathparse{%
                       \entry < \violin@kde@max ? int(0) : int(1)%
               }
               \ifthenelse{
                       \pgfmathresult = 1
               }{
                       \let\violin@kde@max\entry
               }{
               }
       }

       \pgfplotstablemodifyeachcolumnelement{kdecol}\of\violin@kde\as\cell{%
               \let\pgfplotstablezero\violin@delta
               \ifthenelse{
                       \pgfplotstablerow = 0
               }{
                       \let\cell\pgfplotstablezero
               }{
                       \pgfmathparse{int(\violin@samples-1)}
                       \ifthenelse{
                               \pgfplotstablerow = \pgfmathresult
                       }{
                               \let\cell\pgfplotstablezero
                       }{
                               \ifthenelse{
                                       \equal{\violin@nomirror}{true}
                               }{
                                       \pgfmathparse{1.9}
                               }{
                                       \pgfmathparse{1}
                               }
                               \let\violin@mirror@factor\pgfmathresult
                               \ifthenelse{
                                       \equal{\violin@scaled}{true}
                               }{
                                       \pgfmathparse{\violin@delta+\violin@mirror@factor*0.5*\cell/\violin@kde@max}
                               }{
                                       \pgfmathparse{\violin@delta+\violin@mirror@factor*\cell}
                               }
                               \let\cell\pgfmathresult
                       }
               }
       }

       \ifthenelse{
               \equal{\violin@nomirror}{false}
       }{
               \pgfplotstablecreatecol[
                       create col/assign/.code={
                               \pgfmathparse{-\thisrow{kdecol}+2*\violin@delta}
                               \let\entry\pgfmathresult
                               \pgfkeyslet{/pgfplots/table/create col/next content}\entry
                       }
               ]{kdecolinv}\violin@kde
       }{
               \ifthenelse{
                       \equal{\violin@invert}{true}
               }{
                       \pgfplotstablemodifyeachcolumnelement{kdecol}\of\violin@kde\as\cell{%
                               \pgfmathparse{-\cell+2*\violin@delta}
                               \let\cell\pgfmathresult
                       }
               }{}
       }

       \ifthenelse{
               \equal{\violin@reverseaxis}{true}
       }{
               \pgfkeys{
                       /pgfplots/xticklabels={,,},
                       /pgfplots/yticklabels={\violin@label},
                       /pgfplots/ytick={\violin@delta},
                       /pgfplots/xmajorticks=false,
               }
       }{
               \pgfkeys{
                       /pgfplots/yticklabels={,,},
                       /pgfplots/xticklabels={\violin@label},
                       /pgfplots/xtick={\violin@delta},
                       /pgfplots/ymajorticks=false,
               }
       }

       \begin{axis}[
               \violin@axisoptions,
               axis on top,
               axis line style={draw=none},
               tick style={draw=none},
       ]
               \addplot[
                       no marks,
                       color=\violin@color,
               ] table [
                       \violin@axis@x=kdecol, \violin@axis@y=list
               ] {\violin@kde};
               \addplot[
                       no marks,
                       fill=\violin@color,
                       opacity=0.50,
               ] table [
                       \violin@axis@x=kdecol, \violin@axis@y=list
               ] {\violin@kde};
               \ifthenelse{
                       \equal{\violin@nomirror}{false}
               }{
                       \addplot[
                               no marks,
                               color=\violin@color,
                       ] table [
                               \violin@axis@x=kdecolinv, \violin@axis@y=list
                       ] {\violin@kde};
                       \addplot[
                               no marks,
                               fill=\violin@color,
                               opacity=0.50,
                       ] table [
                               \violin@axis@x=kdecolinv, \violin@axis@y=list
                       ] {\violin@kde};
               }{}
               \ifthenelse{
                       \equal{\violin@nomirror}{true}
               }{
                       \ifthenelse{
                               \equal{\violin@reverseaxis}{false}
                       }{
                               \addplot[
                                       no marks,
                                       color=black,
                               ] coordinates {
                                       (\violin@delta,\pgfkeysvalueof{/pgfplots/ymin})%
                                       (\violin@delta,\pgfkeysvalueof{/pgfplots/ymax})
                               };
                       }{
                               \addplot[
                                       no marks,
                                       color=black,
                               ] coordinates {
                                       (\pgfkeysvalueof{/pgfplots/xmin},\violin@delta)%
                                       (\pgfkeysvalueof{/pgfplots/xmax},\violin@delta)
                               };
                       }
               }{}
               \ifthenelse{
                       \equal{\violin@averages}{true}
               }{
                       \ifthenelse{
                               \equal{\violin@reverseaxis}{true}
                       }{
                               \addplot[
                                       only marks,
                                       mark=\violin@avg@mark,
                                       mark size=\violin@avg@size,
                                       color=\violin@avg@color,
                                       opacity=\violin@avg@opacity,
                                       fill=\violin@avg@fillcolor,
                                       fill opacity=\violin@avg@fillopacity,
                               ] coordinates {
                                       (\violin@dataset@average,\violin@delta)
                               };
                       }{
                               \addplot[
                                       only marks,
                                       mark=\violin@avg@mark,
                                       mark size=\violin@avg@size,
                                       color=\violin@avg@color,
                                       opacity=\violin@avg@opacity,
                                       fill=\violin@avg@fillcolor,
                                       fill opacity=\violin@avg@fillopacity,
                               ] coordinates {
                                       (\violin@delta,\violin@dataset@average)
                               };
                       }
               }{}
               \ifthenelse{
                       \equal{\violin@datapoints}{true}
               }{
                       \addplot[
                               only marks,
                               mark=\violin@pts@mark,
                               mark size=\violin@pts@size,
                               color=\violin@pts@color,
                               opacity=\violin@pts@opacity,
                               fill=\violin@pts@fillcolor,
                               fill opacity=\violin@pts@fillopacity,
                               \violin@axis@x\space filter/.expression={\violin@axis@x + \violin@pts@jitter * rand}
                       ] table [
                               \violin@axis@x=deltacol,
                               \violin@axis@y=\violin@index,
                       ] {\theviolin@dataset@table};
               }{}
       \end{axis}

}

\newcommand{\violin@getnth}[2]{%
       \pgfmathparse{int(0)}
       \let\violin@getnth@counter\pgfmathresult
       \let\violin@nthelem\pgfmathresult
       \@for\violin@listelem:=#1\do{
               \ifthenelse{
                       \equal{#2}{\violin@getnth@counter}
               }{
                       \let\violin@nthelem\violin@listelem
                       \pgfmathparse{int(\violin@getnth@counter+1)}
                       \let\violin@getnth@counter\pgfmathresult
               }{
                       \pgfmathparse{int(\violin@getnth@counter+1)}
                       \let\violin@getnth@counter\pgfmathresult
               }
       }
}

\newcommand{\violinplotwholefile}[2][]{%

       \pgfkeys{/violinplotwholefile, default, #1}
       \def\violin@batch@filename{#2}

       \pgfmathparse{0}
       \let\violin@batch@numofplots\pgfmathresult
       \@for\index:=\violin@batch@indexes\do{
               \pgfmathparse{int(\violin@batch@numofplots+1)}
               \let\violin@batch@numofplots\pgfmathresult
       }

       \pgfmathparse{0}
       \let\violin@batch@color@deg\pgfmathresult
       \let\violin@batch@counter\pgfmathresult
       \let\violin@batch@relativepos\pgfmathresult

       \@for\violin@batch@index:=\violin@batch@indexes\do{
               \ifthenelse{%
                       \equal{1}{\violin@batch@numofplots}
               }{%
                       \pgfmathparse{50}
               }{%
                       \pgfmathparse{int(\violin@batch@counter*%
                               (100/(\violin@batch@numofplots-1)))}
               }
               \let\violin@batch@color@deg\pgfmathresult
               \edef\violin@batch@color{\violin@batch@color@primary!\violin@batch@color@deg!\violin@batch@color@secondary}

               \violin@getnth{\violin@batch@labels}{\violin@batch@counter}
               \let\violin@batch@label\violin@nthelem

               \pgfmathparse{1+\violin@batch@counter*\violin@batch@delta}
               \let\violin@batch@relativepos\pgfmathresult

               \violinplot[%
                       col sep = \violin@batch@colsep,
                       bandwidth=\violin@batch@bandwidth,
                       kernel = \violin@batch@kernel,
                       index=\violin@batch@index,
                       relative position=\violin@batch@relativepos,
                       samples = \violin@batch@samples,
                       color=\violin@batch@color,
                       label={\violin@batch@label},
                       average mark = \violin@batch@avg@mark,
                       average size = \violin@batch@avg@size,
                       average color = \violin@batch@avg@color,
                       average opacity = \violin@batch@avg@opacity,
                       average fill = \violin@batch@avg@fillcolor,
                       average fill opacity = \violin@batch@avg@fillopacity,
                       dataset mark = \violin@batch@pts@mark,
                       dataset size = \violin@batch@pts@size,
                       dataset color = \violin@batch@pts@color,
                       dataset opacity = \violin@batch@pts@opacity,
                       dataset fill = \violin@batch@pts@fillcolor,
                       dataset fill opacity = \violin@batch@pts@fillopacity,
                       dataset jitter = \violin@batch@pts@jitter
               ]{\violin@batch@filename}

               \pgfmathparse{int(\violin@batch@counter+1)}
               \let\violin@batch@counter\pgfmathresult
       }

}