updated the local user-docu.

This commit is contained in:
2026-03-02 11:03:44 +01:00
parent 403aa07993
commit 85fe4a1d59
82 changed files with 557 additions and 10803 deletions
+161 -37
View File
@@ -6,15 +6,15 @@
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MusrRoot - an Extensible Open File Format for μSR &mdash; musrfit 1.9.9 documentation</title>
<title>MusrRoot - an Extensible Open File Format for μSR &mdash; musrfit V1.10.0</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=7a5cd723" />
<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=4320943d"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/documentation_options.js?v=1d24b1d9"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
@@ -134,13 +134,20 @@ which allows to inspect these files. This browser (<code class="docutils literal
if they derive from <code class="docutils literal notranslate"><span class="pre">TObject</span></code>.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file format to be described below is only using a small subset of possible ROOT objects, namely:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">TFolder</span></code>: this are the top level objects in the <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TFolder</span></code>/<code class="docutils literal notranslate"><span class="pre">TDirectory</span></code>: this are the top level objects in the <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TH1F</span></code>: Hold the μ-decay-histograms.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TObjArray</span></code>: Holding collection of header information.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TObjArray</span></code>/<code class="docutils literal notranslate"><span class="pre">TDirectory</span></code>: Holding collection of header information.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TObjString</span></code>: Holding the content of any header information.</p></li>
</ul>
<p>Since all these objects are deriving form <code class="docutils literal notranslate"><span class="pre">TObject</span></code>, they will be directly accessible via the <code class="docutils literal notranslate"><span class="pre">TBrowser</span></code>-object.
For instance, the μ-decay-histograms can be directly plotted, are even fitted, out of the box.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Since <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> has bee marked as deprecated from the ROOT team, we
will gradually switch over to use <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> instead. This will have a minimal impact on
the following, as you will see. In the description to follow, the term “folder” will be used
synonymous with “directory”. Only if necessary it will be distinguished.</p>
</div>
</section>
<section id="id1">
<h2>MusrRoot an Extensible Open File Format for μSR<a class="headerlink" href="#id1" title="Link to this heading"></a></h2>
@@ -173,7 +180,7 @@ For instance, the μ-decay-histograms can be directly plotted, are even fitted,
in <code class="docutils literal notranslate"><span class="pre">C/C++</span></code> notation, starting with 1) is the histogram number. The title and name of the histogram (see description of the <code class="docutils literal notranslate"><span class="pre">TH1F</span></code> ROOT class) contains the label of the histogram, like top, forward, etc. How many of these histograms are present is accessible through the <code class="docutils literal notranslate"><span class="pre">RunInfo</span></code> folder in which the necessary header information are found (details see next sections). The folder <code class="docutils literal notranslate"><span class="pre">SCAnaModule</span></code> contains histograms of some of the slow-control parameters, as for instance the sample temperature versus time, the applied field versus time, etc. Again the label of the histogram will give more specific information about its content.</p>
<section id="run-information-contained-in-runheader">
<h3>Run Information Contained in <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code><a class="headerlink" href="#run-information-contained-in-runheader" title="Link to this heading"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> contains all needed meta-information to describe a μSR-run. The list of the minimal number of required “folders” of the <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> is given in the following structure:</p>
<p>The <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> contains all needed meta-information to describe a μSR-run. The list of the minimal number of required “folders” of the <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> is given in the following structure (<em>deprecated</em>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">RunHeader</span> <span class="p">(</span><span class="n">TFolder</span><span class="p">)</span> <span class="o">---|</span>
<span class="o">|-</span> <span class="n">RunInfo</span> <span class="p">(</span><span class="n">TObjArray</span><span class="p">)</span>
<span class="o">|-</span> <span class="n">DetectorInfo</span> <span class="p">(</span><span class="n">TObjArray</span><span class="p">)</span>
@@ -182,8 +189,24 @@ in <code class="docutils literal notranslate"><span class="pre">C/C++</span></co
<span class="o">|-</span> <span class="n">BeamlineInfo</span> <span class="p">(</span><span class="n">TObjArray</span><span class="p">)</span>
</pre></div>
</div>
<p>In case it is already switched to <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code>, it will look like this (default starting 2026):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">RunHeader</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span> <span class="o">---|</span>
<span class="o">|-</span> <span class="n">RunInfo</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span>
<span class="o">|-</span> <span class="n">DetectorInfo</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span>
<span class="o">|-</span> <span class="n">SampleEnvironmentInfo</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span>
<span class="o">|-</span> <span class="n">MagneticFieldEnvironmentInfo</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span>
<span class="o">|-</span> <span class="n">BeamlineInfo</span> <span class="p">(</span><span class="n">TDirectory</span><span class="p">)</span>
</pre></div>
</div>
<p>In brackets the object type is given. <code class="docutils literal notranslate"><span class="pre">RunInfo</span></code> contains most information relevant for the user and will be itemized in <a class="reference internal" href="#musr-root-overview"><span class="std std-ref">RunInfo Overview</span></a> and <a class="reference internal" href="#run-info-required"><span class="std std-ref">RunInfo Required</span></a>. <code class="docutils literal notranslate"><span class="pre">DetectorInfo</span></code> contains detector specific information, like detector name, time zero bin, etc. (details is found under <a class="reference internal" href="#detector-info-required"><span class="std std-ref">DetectorInfo Required</span></a>). <code class="docutils literal notranslate"><span class="pre">SampleEnvironmentInfo</span></code> (details under <a class="reference internal" href="#sample-environment-info-required"><span class="std std-ref">SampleEnvironmentInfo Required</span></a>), and <code class="docutils literal notranslate"><span class="pre">MagneticFieldEnvironmentInfo</span></code> (details under <a class="reference internal" href="#magnetic-field-environment-info-required"><span class="std std-ref">MagneticFieldEnvironmentInfo Required</span></a>) store additional, more detailed information concerning the sample environment. <code class="docutils literal notranslate"><span class="pre">BeamlineInfo</span></code> stores beamline relevant information (details under <a class="reference internal" href="#beamline-info-required"><span class="std std-ref">BeamlineInfo Required</span></a>).</p>
<p>Before elaborating more on the required items within this structure, a few words on the ROOT types used here: <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> is a <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> object. All the “sub-directory” entries are of type <code class="docutils literal notranslate"><span class="pre">TObjArray</span></code> and collect items of type <code class="docutils literal notranslate"><span class="pre">TObjString</span></code> or other <code class="docutils literal notranslate"><span class="pre">TObjArray</span></code> (<em>i.e.</em> sub-directories and sub-sub-directories, etc.).</p>
<p>Before elaborating more on the required items within this structure, a few words on the ROOT types used here: <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> is a <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> (<em>deprecated</em>) or a <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> object.</p>
<ol class="arabic simple">
<li><p>In case of the <em>deprecated</em> <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> <cite>RunHeader`</cite>, all the “sub-directory” entries are of type
<code class="docutils literal notranslate"><span class="pre">TObjArray</span></code> and collect items of type <code class="docutils literal notranslate"><span class="pre">TObjString</span></code> or other <code class="docutils literal notranslate"><span class="pre">TObjArray</span></code>
(<em>i.e.</em> sub-directories and sub-sub-directories, etc.).</p></li>
<li><p>In case the top entry <code class="docutils literal notranslate"><span class="pre">RunHeader</span></code> is a <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> object, all potential “sub-directories” are
indeed <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> objects as well. In this case, the data are represented by <code class="docutils literal notranslate"><span class="pre">TObjString</span></code> objects.</p></li>
</ol>
<section id="runinfo-overview">
<span id="musr-root-overview"></span><span id="index-1"></span><h4><code class="docutils literal notranslate"><span class="pre">RunInfo</span></code> Overview<a class="headerlink" href="#runinfo-overview" title="Link to this heading"></a></h4>
<table class="docutils align-default">
@@ -306,8 +329,47 @@ is introduced to deal with physical quantities. They always can be represented i
</div>
</li>
</ol>
<p>Not all of these values are needed to be given and depending on which are given, the representation in the <code class="docutils literal notranslate"><span class="pre">MusrRootv</span> <span class="pre">file</span> <span class="pre">will</span> <span class="pre">be</span> <span class="pre">different</span> <span class="pre">(handled</span> <span class="pre">by</span> <span class="pre">``TMusrRunHeader</span></code>). Examples are given in the comment column of the table above. For details see <a class="reference internal" href="#musr-run-physical-quantity"><span class="std std-ref">TMusrRunPhysicalQuantity - Possible Representations</span></a>.</p>
<p>A mock-up <code class="docutils literal notranslate"><span class="pre">TBrowser</span></code> print-out would look like the one shown in the following figure. You might notice, that at the end of each entry you find a <code class="docutils literal notranslate"><span class="pre">-&#64;X</span></code>, where <code class="docutils literal notranslate"><span class="pre">X</span></code> is a number. This is an encoding of the internal type of the entry and is the price to be payed not using derived types. The next section will explain this in much more detail.</p>
<p>Not all of these values are needed to be given and depending on which are given, the representation in the <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file will be different (handled by <code class="docutils literal notranslate"><span class="pre">TMusrRunHeader</span></code>). Examples are given in the comment column of the table above. For details see <a class="reference internal" href="#musr-run-physical-quantity"><span class="std std-ref">TMusrRunPhysicalQuantity - Possible Representations</span></a>.</p>
<p>A mock-up <code class="docutils literal notranslate"><span class="pre">TBrowser</span></code> print-out would look like the one shown in the following figure. You might notice, that at the end of each entry you find a <code class="docutils literal notranslate"><span class="pre">-&#64;X</span></code>, where <code class="docutils literal notranslate"><span class="pre">X</span></code> is a number. This is an encoding of the internal type of the entry and is the price to be payed not using derived types. Here is a table with the data representation</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>X</p></th>
<th class="head"><p>data type</p></th>
<th class="head"><p>comment</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>0</p></td>
<td><p>TString</p></td>
<td><p>default ROOT type</p></td>
</tr>
<tr class="row-odd"><td><p>1</p></td>
<td><p>Int_t</p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>2</p></td>
<td><p>Double_t</p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>3</p></td>
<td><p>TMusrRunPhysicalQuantity</p></td>
<td><p>TMusrRunHeader type</p></td>
</tr>
<tr class="row-even"><td><p>4</p></td>
<td><p>TStringVector</p></td>
<td><p>type cast to vector&lt;TString&gt;</p></td>
</tr>
<tr class="row-odd"><td><p>5</p></td>
<td><p>TIntVector</p></td>
<td><p>type cast to vector&lt;Int_T&gt;</p></td>
</tr>
<tr class="row-even"><td><p>6</p></td>
<td><p>TDoubleVector</p></td>
<td><p>type cast to vector&lt;Double_t&gt;</p></td>
</tr>
</tbody>
</table>
<p>The next section will explain this in much more detail.</p>
<img alt="_images/MusrRoot-RunInfo.png" src="_images/MusrRoot-RunInfo.png" />
<p><code class="docutils literal notranslate"><span class="pre">TMusrRunHeader</span></code> mock up. The red shaded entries are of type <code class="docutils literal notranslate"><span class="pre">TMusrRunPhysicalQuantity</span></code></p>
</section>
@@ -338,11 +400,11 @@ is derived which is extending the base class to the needs of the instrument.</p>
<section id="writing-a-musrroot-run-header">
<h4>Writing a MusrRoot Run Header<a class="headerlink" href="#writing-a-musrroot-run-header" title="Link to this heading"></a></h4>
<p>An example program <code class="docutils literal notranslate"><span class="pre">write_musrRoot_runHeader</span></code> which is writing a full run header is part of the <code class="docutils literal notranslate"><span class="pre">musrfit</span></code> package. Here I will concentrate just on the most essential parts. First one needs an instance of <code class="docutils literal notranslate"><span class="pre">TMusrRunHeader</span></code></p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TMusrRunHeader</span><span class="w"> </span><span class="o">*</span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TMusrRunHeader</span><span class="p">();</span>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="w"> </span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="p">();</span>
<span class="n">TMusrRunPhysicalQuantity</span><span class="w"> </span><span class="n">prop</span><span class="p">;</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">header</span></code> is the instance of <code class="docutils literal notranslate"><span class="pre">TMusrRunHeader</span></code>. <code class="docutils literal notranslate"><span class="pre">prop</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">TMusrRunPhysicalQuantity</span></code> which will be needed further down in the description. In the next step some run header entries will be added</p>
<p><code class="docutils literal notranslate"><span class="pre">header</span></code> is the instance of <code class="docutils literal notranslate"><span class="pre">TMusrRunHeader</span></code>. Here the concept of a unique pointer (<code class="docutils literal notranslate"><span class="pre">std::unique_ptr</span></code>) has been used to ensure that no memory leaks are present. <code class="docutils literal notranslate"><span class="pre">prop</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">TMusrRunPhysicalQuantity</span></code> which will be needed further down in the description. In the next step some run header entries will be added</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;RunInfo/File Name&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;deltat_tdc_gps_2871.root&quot;</span><span class="p">);</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;RunInfo/Run Title&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;here comes the run title&quot;</span><span class="p">);</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;RunInfo/Run Number&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">2871</span><span class="p">);</span>
@@ -364,18 +426,52 @@ is derived which is extending the base class to the needs of the instrument.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;DetectorInfo/Detector001/Time Zero Bin&quot;</span><span class="p">,</span><span class="w"> </span><span class="mf">3419.0</span><span class="p">);</span>
</pre></div>
</div>
<p>To write the whole run header into a file would look something like this:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TFile</span><span class="w"> </span><span class="o">*</span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TFile</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;RECREATE&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;write_musrRoot_runHeader&quot;</span><span class="p">);</span>
<p>To write the whole run header into a file would look something like this (<em>deprecated</em> <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> version):</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// create TMusrRunHeader object</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="w"> </span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="p">();</span>
<span class="c1">// set some stuff</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;DetectorInfo/Detector001/Time Zero Bin&quot;</span><span class="p">,</span><span class="w"> </span><span class="mf">3419.0</span><span class="p">);</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;Something/Somewhere/Strange&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Test String&quot;</span><span class="p">);</span>
<span class="c1">// add more stuff in the header (not shown)</span>
<span class="c1">// create TFile object. It is assumed the fileName is given</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;RECREATE&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;write_musrRoot_runHeader&quot;</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="o">-&gt;</span><span class="n">IsZombie</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">delete</span><span class="w"> </span><span class="n">f</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// create the needed TFolder object</span>
<span class="n">TFolder</span><span class="w"> </span><span class="o">*</span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TFolder</span><span class="p">(</span><span class="s">&quot;RunHeader&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;MusrRoot Run Header Info&quot;</span><span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TFolder</span><span class="o">&gt;</span><span class="w"> </span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TFolder</span><span class="o">&gt;</span><span class="p">(</span><span class="s">&quot;RunHeader&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;MusrRoot Run Header Info&quot;</span><span class="p">);</span>
<span class="c1">// create the &quot;folder&quot; structure</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">header</span><span class="o">-&gt;</span><span class="n">FillFolder</span><span class="p">(</span><span class="n">runHeader</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">runHeader</span><span class="o">-&gt;</span><span class="n">Write</span><span class="p">();</span><span class="w"> </span><span class="c1">// write run header to file</span>
<span class="p">}</span>
<span class="n">f</span><span class="o">-&gt;</span><span class="n">Close</span><span class="p">();</span>
</pre></div>
</div>
<p>In the <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> version it will look like this:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// create TMusrRunHeader object</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="w"> </span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="p">();</span>
<span class="c1">// set some stuff</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;DetectorInfo/Detector001/Time Zero Bin&quot;</span><span class="p">,</span><span class="w"> </span><span class="mf">3419.0</span><span class="p">);</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="s">&quot;Something/Somewhere/Strange&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Test String&quot;</span><span class="p">);</span>
<span class="c1">// add more stuff in the header (not shown)</span>
<span class="c1">// create TFile object. It is assumed the fileName is given</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;RECREATE&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;write_musrRoot_runHeader&quot;</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="o">-&gt;</span><span class="n">IsZombie</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// create the needed TDirectory object</span>
<span class="n">TDirectory</span><span class="o">*</span><span class="w"> </span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">f</span><span class="o">-&gt;</span><span class="n">mkdir</span><span class="p">(</span><span class="s">&quot;RunHeader&quot;</span><span class="p">);</span>
<span class="c1">// create the &quot;directory&quot; structure</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">header</span><span class="o">-&gt;</span><span class="n">FillFolder</span><span class="p">(</span><span class="n">runHeader</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">header</span><span class="o">-&gt;</span><span class="n">FillDirectory</span><span class="p">(</span><span class="n">runHeader</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">runHeader</span><span class="o">-&gt;</span><span class="n">Write</span><span class="p">();</span><span class="w"> </span><span class="c1">// write run header to file</span>
<span class="p">}</span>
@@ -385,41 +481,69 @@ is derived which is extending the base class to the needs of the instrument.</p>
</section>
<section id="reading-a-musrroot-run-header">
<h4>Reading a MusrRoot Run Header<a class="headerlink" href="#reading-a-musrroot-run-header" title="Link to this heading"></a></h4>
<p>The following code snippet shows how the extract the full run header from the <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file.</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TFile</span><span class="w"> </span><span class="o">*</span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TFile</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;READ&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;read_musrRoot_runHeader&quot;</span><span class="p">);</span>
<p>The following code snippet shows how the extract the full run header from the <code class="docutils literal notranslate"><span class="pre">MusrRoot</span></code> file.
First in the <em>deprecate</em> <code class="docutils literal notranslate"><span class="pre">TFolder</span></code> version:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// create TFile. It is assumed that fileName is present</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;READ&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;read_musrRoot_runHeader&quot;</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="o">-&gt;</span><span class="n">IsZombie</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">delete</span><span class="w"> </span><span class="n">f</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">TFolder</span><span class="w"> </span><span class="o">*</span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="c1">// get the TFolder object from the TFile</span>
<span class="n">TFolder</span><span class="w"> </span><span class="o">*</span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">nullptr</span><span class="p">;</span>
<span class="n">f</span><span class="o">-&gt;</span><span class="n">GetObject</span><span class="p">(</span><span class="s">&quot;RunHeader&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">runHeader</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">runHeader</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** Couldn&#39;t get top folder RunHeader&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">closeFile</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">runHeader</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">nullptr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** Couldn&#39;t get top folder RunHeader&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">TMusrRunHeader</span><span class="w"> </span><span class="o">*</span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TMusrRunHeader</span><span class="p">(</span><span class="n">fileName</span><span class="p">);</span>
<span class="c1">// create the TMusrRunHeader object</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="w"> </span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">);</span>
<span class="c1">// fill the internal data structure of the TMusrRunHeader object</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">header</span><span class="o">-&gt;</span><span class="n">ExtractAll</span><span class="p">(</span><span class="n">runHeader</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** couldn&#39;t extract all RunHeader information&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">closeFile</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** couldn&#39;t extract all RunHeader information&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">f</span><span class="o">-&gt;</span><span class="n">Close</span><span class="p">();</span>
<span class="k">delete</span><span class="w"> </span><span class="n">f</span><span class="p">;</span>
</pre></div>
</div>
<p>The routine <code class="docutils literal notranslate"><span class="pre">ExtractAll(TFolder</span> <span class="pre">*runHeader)</span></code> decodes all the <code class="docutils literal notranslate"><span class="pre">TObjString</span></code> objects and fills internal data structures. This means when reading a MusrRoot -file the above handling is always needed. After the <code class="docutils literal notranslate"><span class="pre">ExtractAll</span></code> call, parameters can be extracted via the getter routines available. For instance to read the Run Number, the code would look like</p>
<p>The same with the <code class="docutils literal notranslate"><span class="pre">TDirectory</span></code> version:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// create TFile. It is assumed that fileName is present</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TFile</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;READ&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;read_musrRoot_runHeader&quot;</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="o">-&gt;</span><span class="n">IsZombie</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// get the TDirectory object from the TFile. Note: Here on the top level a TDirectoryFile is needed</span>
<span class="n">TDirectoryFile</span><span class="w"> </span><span class="o">*</span><span class="n">runHeader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">nullptr</span><span class="p">;</span>
<span class="n">f</span><span class="o">-&gt;</span><span class="n">GetObject</span><span class="p">(</span><span class="s">&quot;RunHeader&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">runHeader</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">runHeader</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">nullptr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** Couldn&#39;t get top folder RunHeader&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// create the TMusrRunHeader object</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="w"> </span><span class="n">header</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">TMusrRunHeader</span><span class="o">&gt;</span><span class="p">(</span><span class="n">fileName</span><span class="p">);</span>
<span class="c1">// fill the internal data structure of the TMusrRunHeader object</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">header</span><span class="o">-&gt;</span><span class="n">ExtractAll</span><span class="p">(</span><span class="n">runHeader</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cerr</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;&gt;&gt; **ERROR** couldn&#39;t extract all RunHeader information&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">f</span><span class="o">-&gt;</span><span class="n">Close</span><span class="p">();</span>
</pre></div>
</div>
<p>The overloaded routine <code class="docutils literal notranslate"><span class="pre">ExtractAll(TFolder</span> <span class="pre">*runHeader)</span></code> and <code class="docutils literal notranslate"><span class="pre">ExtractAll(TDirectory</span> <span class="pre">*runHeader)</span></code> decodes all the <code class="docutils literal notranslate"><span class="pre">TObjString</span></code> objects and fills internal data structures. This means when reading a MusrRoot -file the above handling is always needed. After the <code class="docutils literal notranslate"><span class="pre">ExtractAll</span></code> call, parameters can be extracted via the getter routines available. For instance to read the Run Number, the code would look like</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">Bool_t</span><span class="w"> </span><span class="n">ok</span><span class="p">;</span>
<span class="n">Int_t</span><span class="w"> </span><span class="n">ival</span><span class="p">;</span>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Get</span><span class="p">(</span><span class="s">&quot;RunInfo/Run Number&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">ival</span><span class="p">,</span><span class="w"> </span><span class="n">ok</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">ok</span><span class="p">)</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;Run Number: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">ival</span><span class="p">;</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;Run Number: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">ival</span><span class="p">;</span>
<span class="k">else</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;**ERROR** Couldn&#39;t obtain the &#39;Run Number&#39;.&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;**ERROR** Couldn&#39;t obtain the &#39;Run Number&#39;.&quot;</span><span class="p">;</span>
</pre></div>
</div>
<p>Reading a <code class="docutils literal notranslate"><span class="pre">TMusrRunPhysicalQuantity</span></code> object, <em>e.g.</em> the sample temperature looks like this</p>
@@ -427,11 +551,11 @@ is derived which is extending the base class to the needs of the instrument.</p>
<span class="n">header</span><span class="o">-&gt;</span><span class="n">Get</span><span class="p">(</span><span class="s">&quot;RunInfo/Sample Temperature&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">prop</span><span class="p">,</span><span class="w"> </span><span class="n">ok</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">ok</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;Sample Temperature: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetValue</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot; +- &quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetError</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetUnit</span><span class="p">().</span><span class="n">Data</span><span class="p">();</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;; SP: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetDemand</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;; &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetDescription</span><span class="p">().</span><span class="n">Data</span><span class="p">();</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;Sample Temperature: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetValue</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot; +- &quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetError</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetUnit</span><span class="p">().</span><span class="n">Data</span><span class="p">();</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;; SP: &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetDemand</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;; &quot;</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">prop</span><span class="p">.</span><span class="n">GetDescription</span><span class="p">().</span><span class="n">Data</span><span class="p">();</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;**ERROR** Couldn&#39;t obtain the &#39;Sample Temperature&#39;.&quot;</span><span class="p">;</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">&quot;**ERROR** Couldn&#39;t obtain the &#39;Sample Temperature&#39;.&quot;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
@@ -887,8 +1011,8 @@ the entry has been added. The last token, <code class="docutils literal notransl
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2025, Andreas Suter.
<span class="lastupdated">Last updated on Jun 06, 2025.
<p>&#169; Copyright 2026, Andreas Suter.
<span class="lastupdated">Last updated on Feb 21, 2026.
</span></p>
</div>