Scan Aggregation
================

When a measurement contains multiple scans (repetitions of the same spectrum),
they must be combined into a single spectrum before further analysis. The
:meth:`~daxs.measurements.Measurement1D.aggregate` method on 1D measurements
(i.e. :class:`~daxs.measurements.Xas` and :class:`~daxs.measurements.Xes`)
exposes two mathematically distinct strategies, controlled by the ``mode``
argument.

Background
----------

For each scan *i*, let :math:`S_i(E)` be the detector signal and
:math:`M_i(E)` be the monitor counts at energy point *E*.  The individual
normalized spectrum is the ratio :math:`S_i / M_i`.  The two aggregation modes
differ in *when* the monitor division is performed.

Fraction of sums (default)
--------------------------

.. math::

   y(E) = \frac{\displaystyle\sum_i S_i(E)}{\displaystyle\sum_i M_i(E)}

All signal channels and all monitor channels are accumulated first; only then
is the global ratio computed.

**When to use:** Preferred for most experiments. Because the division is
performed once on the *totals*, high-monitor scans naturally receive more
weight. This produces the cleanest final spectrum when beam intensity
fluctuates between scans, by giving more influence to the measurements with
the best signal-to-noise ratio::

    measurement.aggregate()                            # default
    measurement.aggregate(mode="fraction of sums")     # explicit

Mean of fractions
-----------------

.. math::

   y(E) = \frac{1}{N}\sum_i \frac{S_i(E)}{M_i(E)}

Each scan is normalized by its own monitor before averaging, giving every scan
*equal weight* regardless of how many counts were collected.

**When to use:** Useful when scans have been recorded under systematically
different monitor conditions (e.g. different integration times or attenuator
settings) and you want each repetition to contribute equally to the average.
Be aware that this mode amplifies noise in low-count scans::

    measurement.aggregate(mode="mean of fractions")

Monitor handling
----------------

Regardless of the aggregation mode, the stored monitor (``measurement.monitor``)
is always the **mean** of the monitors across all scans.  If no monitor
was recorded, the "fraction of sums" mode automatically divides the
summed signal by the number of scans to produce a simple mean.

API reference
-------------

See :meth:`~daxs.measurements.Measurement1D.aggregate`.
