1

I would like to produce different (child, parent, sandclock) graphs using (mainly/often) the same nodes, therefore I would like to separate the nodes content and its structure.

Question: Is there a possibility to populate nodes using a csv (or similar file)? E.g. by looking up the id to get the names, birthdates, etc.? If so, how?

Demo csvfile content:

id,forename,surname,birthdate,location,comment,sex,filname.jpg

Demo node from https://tex.stackexchange.com/a/389534/112503:

\documentclass[landscape,paper=a5]{scrartcl}
\usepackage[all]{genealogytree}
\begin{filecontents*}{file.csv}
id,forename,surname,birthdate,location,comment,sex,filname.jpg
\end{filecontents*}
\usepackage{mwe}

\begin{document}
    \newcommand{\treetitle}{Mr. X}
    
    \begin{tcolorbox}[enhanced,sharp corners,boxrule=0.6pt,left=0pt,right=0pt,
        colback=blue!50!black,interior style image=goldshade.png,
        halign=center,center title,fonttitle=\bfseries,
        title={\treetitle},
        ]
        
        \begin{genealogypicture}[
            processing=database,
            database format=full marriage below,
            node size=2.4cm,
            level size=3.5cm,
            level distance=6mm,
            list separators hang,
            name font=\bfseries,
            surn code={\textcolor{red!50!black}{#1}},
            place text={\newline}{},
            date format=d.mon.yyyy,
            tcbset={
                male/.style={colframe=blue,colback=blue!5},
                female/.style={colframe=red,colback=red!5}
            },
            box={fit basedim=7pt,boxsep=2pt,
                halign=flush left,before upper=\parskip1pt,segmentation style=solid,
                \gtrDBsex
                ,drop fuzzy shadow,
                if image defined={add to width=25mm,right=25mm,segmentation style={solid,shorten >=24mm},
                    underlay={\begin{tcbclipinterior}\path[fill overzoom image=
                            \gtrDBimage
                            ]
                            ([xshift=-24mm]interior.south east) rectangle (interior.north east);
                    \end{tcbclipinterior}},
                }{},
            },
            edges=rounded,
            symbols record reset,
            ]
            sandclock{
                child{
                    g[id=SurnameForename1990]{
                        sex-from-csv,
                        name={forename-from-csv \surn{surename-from-csv}},
                        birth={birthdate-from-csv}{location-from-csv},
                        comment={comment-from-csv},
                        image=example-image-a, %<--filename-from-csv
                    }
                }
            }
        \end{genealogypicture}
    \end{tcolorbox}
    
\end{document}
9
  • Please expand your code fragments to something which can be compiled when people copy-paste it into an editor. Doesn't the package provide a facility for using data from a separate file? Or am I misremembering?
    – cfr
    Commented Sep 13, 2017 at 14:00
  • @cfr I'll add a small example shortly. I think you remember wrong: The so called databasefile contains the nodes' structure (parent-/child-/sandclock-graph) and the nodes data - if I understand the manual right.
    – lAtExFaN
    Commented Sep 13, 2017 at 17:04
  • I added some kind of an MWE for further investigations (code taken from here: tex.stackexchange.com/a/389534/112503)
    – lAtExFaN
    Commented Sep 13, 2017 at 17:29
  • As I've already said: I did not find a solution in the genealogytree manual. Do you?
    – lAtExFaN
    Commented Sep 14, 2017 at 8:20
  • Sorry. Missed that.
    – cfr
    Commented Sep 14, 2017 at 13:56

1 Answer 1

4

You have a raw-data-file persdata-raw.txt of the kind

id, forename, surname, sex, birthdate, birthplace, comment, filname.jpg
father, John, Surname, male, 01-02-1777, Somewhere,    , 
mother, Marta,    , female, 01-02-1800, Paris,    , 
.....

So you need a help-file persdate-help.tex of the kind

\gtrset{database/.cd,
persdata/father/.style={name=John Surname,birth={01-02-1777}{Somewhere},comment={},},
persdata/mother/.style={name=Marta ,birth={01-02-1800}{Paris},comment={},},
.....
.....
}

with a new key persdata (see here), that means

\gtrset{
  database/.cd,
  persdata/.is choice,
% with that:
  persdata/JaneID/.style={name=Jane, birth={1-1-1777}{somewhere}}
% ...
% ...
}

with that I can use the syntax p[]{persdata=JaneID}.

So I use a newwrite and pgfplotstable to create persdata-help.tex.

With the arrangement

  \genealogytree[
    template=signpost, 
    processing=database,
  ]{
    parent{
      g{persdata=c1}
      c{persdata=c2}
      c{persdata=c3}
      p[]{persdata=father}
      p[box={width=33mm}]{persdata=mother}
    }
  }

I get:

enter image description here

\def\PersDataRawFilename{persdata-raw.txt}
\begin{filecontents*}[overwrite]{\PersDataRawFilename}
id, forename, surname, sex, birthdate, birthplace, comment, filname.jpg
father, John, Surname, male, 01-02-1777, Somewhere,    , 
mother, Marta,    , female, 01-02-1800, Paris,    , 
c1, Moe,    , male, 01-02-1810,    ,    , 
c2, Boe,    , female, 01-02-1811,    ,    , 
c3, Doe,    , male, 01-02-1812, Unknown, {A comment}, 
\end{filecontents*}



\documentclass[landscape]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.17}

\usepackage{newverbs}
\Verbdef\leftbrace|{|
\Verbdef\rightbrace|}|
\Verbdef\bslash|\|
\Verbdef\aspace| |

\usepackage[all]{genealogytree}
\gtrset{
  database/.cd,
  persdata/.is choice,
%  persdata/JaneID/.style={name=Jane, birth={1-1-1777}{somewhere},},
%  persdata/JohnID/.style={name=John, birth={1-1-1777}{somewhere},},
}

% ==========================================
% Create Helpfile ================================
\pgfplotstableread[col sep=comma, header=true]{persdata-raw.txt}\PersData
\pgfplotstablegetrowsof{\PersData}
\pgfmathtruncatemacro\RowNo{\pgfplotsretval-1}

\def\PersDataHelpFilename{persdata-help.tex}
\newwrite\PersDataHelpFile
\immediate\openout\PersDataHelpFile=\PersDataHelpFilename%
% Write Head:
\immediate\write\PersDataHelpFile{%
   \bslash gtrset\leftbrace database/.cd,}
% Write Entries:
\foreach \n in {0,...,\RowNo}{% ==================
% Read in from raw data:
\pgfplotstablegetelem{\n}{id}\of{\PersData}
\xdef\ID{\pgfplotsretval}
\pgfplotstablegetelem{\n}{forename}\of{\PersData}
\xdef\Forename{\pgfplotsretval}
\pgfplotstablegetelem{\n}{surname}\of{\PersData}
\xdef\Surname{\pgfplotsretval}
\pgfplotstablegetelem{\n}{birthdate}\of{\PersData}
\xdef\Birthdate{\pgfplotsretval}
\pgfplotstablegetelem{\n}{birthplace}\of{\PersData}
\xdef\Birthplace{\pgfplotsretval}
\pgfplotstablegetelem{\n}{comment}\of{\PersData}
\xdef\Comment{\pgfplotsretval}
% Write out:
\immediate\write\PersDataHelpFile{%%
  persdata/\ID/.style=\leftbrace %
      name=\Forename\aspace\Surname,%
      birth=\leftbrace\Birthdate\rightbrace\leftbrace\Birthplace\rightbrace,%
      comment=\leftbrace\Comment\rightbrace,%
      \rightbrace,%
}%%
}% ==================
% Write closing Brace:
\immediate\write\PersDataHelpFile{\rightbrace}% 
\immediate\closeout\PersDataHelpFile
% ==========================================
% ==========================================
% Read in Helpfile in document: 
\input{\PersDataHelpFilename}


%\usepackage{mwe}
\begin{document}
% Test: \RowNo
\pgfplotstabletypeset[string type, 
assign column name/.style={/pgfplots/table/column name={\textbf{#1}}},
]{\PersData}

\bigskip
\begin{tikzpicture}[]
  \genealogytree[
    template=signpost, 
    processing=database,
  ]{
    parent{
      g{persdata=c1}
      c{persdata=c2}
      c{persdata=c3}
      p[]{persdata=father}
      p[box={width=33mm}]{persdata=mother}
    }
  }
\end{tikzpicture}
\end{document}


If the help file persdate-help.tex should only to be written if something has changed in the raw data file persdata-raw.txt, the query IfFileHasChangedTF can be used (see here):

enter image description here

% https://tex.stackexchange.com/questions/557511/how-to-query-if-a-file-has-changed-a-iffilehaschanged-conditional?
\begin{filecontents*}{IfFileHasChanged.tex}
\RequirePackage{expl3}
\ExplSyntaxOn
\file_if_exist:nTF { myfile.txt }
  {
    \ior_open:Nn \g_tmpa_ior { myfile.txt }
    \ior_str_get:NN \g_tmpa_ior \l_tmpa_tl
    \ior_close:N \g_tmpa_ior
    \tl_put_right:Nn \l_tmpa_tl { ~change. }
  }
  { \tl_set:Nn \l_tmpa_tl { This~is~my~file. } }
\iow_open:Nn \g_tmpa_iow { myfile.txt }
\iow_now:Nx \g_tmpa_iow { \l_tmpa_tl }
\iow_close:N \g_tmpa_iow
\ExplSyntaxOff

\usepackage{xparse}
\pagestyle{empty}
\ExplSyntaxOn
\prop_new:N \g__cis_file_mdfive_prop
\tl_new:N \l__cis_tmpa_tl
\tl_new:N \l__cis_tmpb_tl
\NewDocumentCommand \IfFileChangedTF { m +m +m }
  { \cis_file_if_changed:nTF {#1} {#2} {#3} }
\prg_new_protected_conditional:Npnn \cis_file_if_changed:n #1 { T, F, TF }
  {
    \file_if_exist:nTF {#1}
      {
        \file_get_mdfive_hash:nN {#1} \l__cis_tmpb_tl
        \prop_get:NnNTF \g__cis_file_mdfive_prop {#1} \l__cis_tmpa_tl
          {
            \str_if_eq:NNTF \l__cis_tmpa_tl \l__cis_tmpb_tl
              { \prg_return_false: }
              {
                \__cis_mdfive_update:nN {#1} \l__cis_tmpb_tl
                \prg_return_true:
              }
          }
          {
            \__cis_mdfive_update:nN {#1} \l__cis_tmpb_tl
            \prg_return_true:
          }
      }
      { \msg_error:nnn { cis } { file-not-found } {#1} }
  }
\makeatletter
\cs_new_protected:Npn \cis@mdfive@update #1 #2
  { \prop_gput:Nnx \g__cis_file_mdfive_prop {#1} {#2} }
\cs_new_protected:Npn \cis@mdfive@save #1 #2
  { \iow_now:Nx \@auxout { \exp_not:N \cis@mdfive@update {#1} {#2} } }
\cs_new_protected:Npn \__cis_mdfive_update:nN #1 #2
  { \cis@mdfive@update {#1} {#2} }
\AtEndDocument
  {
    \prop_map_inline:Nn \g__cis_file_mdfive_prop
      { \cis@mdfive@save {#1} {#2} }
  }
\makeatother
\msg_new:nnn { cis } { file-not-found }
  { File~'#1'~not~found. }
\ExplSyntaxOff
\end{filecontents*}


\def\PersDataRawFilename{persdata-raw.txt}
\begin{filecontents*}[overwrite]{\PersDataRawFilename}
id, forename, surname, sex, birthdate, birthplace, comment, filname.jpg
father, John, Surname, male, 01-02-1777, Somewhere,    , 
mother, Marta,    , female, 01-02-1800, Paris,    , 
c1, Moe,    , male, 01-02-1810,    ,    , 
c2, Boe,    , female, 01-02-1811,    ,    , 
c3, Doe,    , male, 01-02-1812, Unknown, {A comment}, 
\end{filecontents*}



\documentclass[landscape]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.17}

\usepackage{newverbs}
\Verbdef\leftbrace|{|
\Verbdef\rightbrace|}|
\Verbdef\bslash|\|
\Verbdef\aspace| |

\usepackage[all]{genealogytree}
\gtrset{
  database/.cd,
  persdata/.is choice,
%  persdata/JaneID/.style={name=Jane, birth={1-1-1777}{somewhere},},
%  persdata/JohnID/.style={name=John, birth={1-1-1777}{somewhere},},
}

% ==========================================
% Create Helpfile ================================
\def\PersDataHelpFilename{persdata-help.tex}

\pgfplotstableread[col sep=comma, header=true]{\PersDataRawFilename}\PersData
\pgfplotstablegetrowsof{\PersData}
\pgfmathtruncatemacro\RowNo{\pgfplotsretval-1}

\newcommand\MakePersDataHelpfile{%===== command  start ===
\newwrite\PersDataHelpFile
\immediate\openout\PersDataHelpFile=\PersDataHelpFilename%
% Write Head:
\immediate\write\PersDataHelpFile{%
   \bslash gtrset\leftbrace database/.cd,}
% Write Entries:
\foreach \n in {0,...,\RowNo}{% ==================
% Read in from raw data:
\pgfplotstablegetelem{\n}{id}\of{\PersData}
\xdef\ID{\pgfplotsretval}
\pgfplotstablegetelem{\n}{forename}\of{\PersData}
\xdef\Forename{\pgfplotsretval}
\pgfplotstablegetelem{\n}{surname}\of{\PersData}
\xdef\Surname{\pgfplotsretval}
\pgfplotstablegetelem{\n}{birthdate}\of{\PersData}
\xdef\Birthdate{\pgfplotsretval}
\pgfplotstablegetelem{\n}{birthplace}\of{\PersData}
\xdef\Birthplace{\pgfplotsretval}
\pgfplotstablegetelem{\n}{comment}\of{\PersData}
\xdef\Comment{\pgfplotsretval}
% Write out:
\immediate\write\PersDataHelpFile{%%
  persdata/\ID/.style=\leftbrace %
      name=\Forename\aspace\Surname,%
      birth=\leftbrace\Birthdate\rightbrace\leftbrace\Birthplace\rightbrace,%
      comment=\leftbrace\Comment\rightbrace,%
      \rightbrace,%
}%%
}% ==================
% Write closing Brace:
\immediate\write\PersDataHelpFile{\rightbrace}% 
\immediate\closeout\PersDataHelpFile
}% ============ command end   ================
% ==========================================
%\MakePersDataHelpfile %    run command

% Check if Raw Data has changed 1/2
\input{IfFileHasChanged.tex}

%\usepackage{mwe}
\begin{document}
% \texttt{\PersDataRawFilename} has \RowNo rows. 
%
% Check if Raw Data has changed 2/2
\IfFileChangedTF{\PersDataRawFilename}  
  {\MakePersDataHelpfile \def\yesno{yes}}   
       {   \IfFileExists{\PersDataHelpFilename}{}{\MakePersDataHelpfile} 
          \def\yesno{no}    }
% Read in Helpfile in document: 
\input{\PersDataHelpFilename}
% Check if Raw Data has changed - Info
\texttt{\PersDataRawFilename} has changed? \yesno
% \IfFileChangedTF{\PersDataRawFilename}  {yes}   {no} % not 2 times!

\bigskip
\pgfplotstabletypeset[string type, 
assign column name/.style={/pgfplots/table/column name={\textbf{#1}}},
]{\PersData}

\bigskip
\begin{tikzpicture}[]
  \genealogytree[
    template=signpost, 
    processing=database,
  ]{
    parent{
      g{persdata=c1}
      c{persdata=c2}
      c{persdata=c3}
      p[]{persdata=father}
      p[box={width=33mm}]{persdata=mother}
    }
  }
\end{tikzpicture}
\end{document}
1
  • 2
    +1 How can this have no upvote! Commented Jun 5, 2021 at 23:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .