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}

Oni
  • 705
lAtExFaN
  • 1,131
  • 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 Sep 13 '17 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 Sep 13 '17 at 17:04
  • I added some kind of an MWE for further investigations (code taken from here: https://tex.stackexchange.com/a/389534/112503) – lAtExFaN Sep 13 '17 at 17:29
  • As I've already said: I did not find a solution in the genealogytree manual. Do you? – lAtExFaN Sep 14 '17 at 08:20
  • Sorry. Missed that. – cfr Sep 14 '17 at 13:56
  • csv files are not supported by the package, but you can split your data into partial files which can be included using the input command, see page 72 of the documentation. A file may contain a single node only and may have its ID as file name. – Thomas F. Sturm Sep 14 '17 at 16:09
  • @ThomasF.Sturm thanks for the clarification! I already use input (with a single large graph - the data overhead/overlapping/redundancy resulted in my question) and I also thought about storing each node in a separate file. But, because editing these many files is less convenient in comparison of a single csv file I thought there must/should be a more convenient way. You don't plan to enhance the package to support external data lookup, aren't you? ;-) – lAtExFaN Sep 14 '17 at 18:05
  • No, I fear that I do not have such plans... But, I have the idea of a Gedcom-to-LaTeX converter/exporter as a third party tool. Currently, no one has implemented such a tool... Well, we will see :-) – Thomas F. Sturm Sep 15 '17 at 05:27
  • If you have a GEDCOM file (most genealogy software can export to it), I wrote a script that can create trees from such a file: https://github.com/mikkelee/genealogytree-mkgraph – meide Aug 05 '20 at 16:07

1 Answers1

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}

cis
  • 8,073
  • 1
  • 16
  • 45