Scan Selection
==============

When creating an :class:`~daxs.sources.Hdf5Source`, the ``selection`` parameter
controls which scans are loaded from the HDF5 file. You can specify scans in
several ways — from a simple number to flexible text-based expressions.

In all examples below, ``selection`` is the value passed as the second argument
to :class:`~daxs.sources.Hdf5Source`::

    from daxs.sources import Hdf5Source

    source = Hdf5Source(
        filename="data.h5",
        selection=selection, # see below
        data_mappings={"x": ".1/...", "signal": ".1/..."},
    )

Specifying individual scans
---------------------------

Pass a single scan number, or a list of scan numbers::

    selection = 42          # load only scan 42
    selection = [1, 5, 7]   # load scans 1, 5, and 7

You can also use a NumPy array of integers::

    import numpy as np
    selection = np.arange(1, 11)   # scans 1 through 10

Using a range
-------------

To load a consecutive sequence of scans, write ``start-end``::

    selection = "1-50"   # loads scans 1, 2, 3, ..., 50

The range is inclusive on both ends.  You can also take every *n*-th scan by
appending ``:n``::

    selection = "1-50:2"   # every other scan: 1, 3, 5, ..., 49
    selection = "1-50:3"   # every third scan: 1, 4, 7, ..., 49

Loading all scans
-----------------

Use the keyword ``"all"`` to load every scan present in the file::

    selection = "all"

Selecting by scan title
-----------------------

Each scan stored in the file has a short text label called a *title* (for
example ``"ascan sy 0 1 100 1"``).  You can select scans by writing part of
the title as the ``selection`` string::

    selection = "ascan"       # all scans whose title contains "ascan"
    selection = "loopscan"    # all scans whose title contains "loopscan"

The match is case-insensitive. To take every *n*-th match, append ``:n``::

    selection = "ascan:3"    # every third scan among those titled "ascan"

Excluding scans
---------------

Add ``NOT`` followed by a title fragment or range to remove unwanted scans from
the selection::

    # All scans 1-100, but skip those titled "dark":
    selection = "1-100 NOT dark"

    # All "loopscan" scans except those also labeled "reference":
    selection = "loopscan NOT reference"

Combining selections
--------------------

Use ``AND`` to add more scans to the current selection::

    # Scans 1-20 together with scans 50-70:
    selection = "1-20 AND 50-70"

    # All "ascan" scans plus all "loopscan" scans:
    selection = "ascan AND loopscan"

``AND`` and ``NOT`` can be combined freely in a single expression::

    selection = "1-200 NOT dark NOT reference"

.. note::
   Exclusions always take priority.  If a scan would be both included and
   excluded, it is excluded.  The final list is always sorted in ascending
   order.

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

See :class:`~daxs.sources.Hdf5Source`, and in particular the ``selection``
parameter, for the full specification.
