.. _basic-concepts:

Basic Concepts
==============

Basic pyXSIM Concepts
---------------------

In this section we will describe some basic concepts of pyXSIM that one should
familiarize themselves with.

"Photon" Lists vs. "Event" Lists
++++++++++++++++++++++++++++++++

If one is attempting to create synthetic observations for use with instrument
models, this is done by first creating a "photon list", which is then used to
create an "event list". The first is a sample of photons with cosmologically
redshifted energies that are distributed in 3D, associated with their original
cells or particles. This is a large sample that is then used to create the
event list, at which point a line-of-sight observation direction is chosen,
which projects the photons to the sky plane and shifts the photon energies
via Doppler shifting from the line-of-sight velocity of the originating cell.

These concepts are described in more detail in :ref:`phlist_overview`.

SIMPUT Catalogs
+++++++++++++++

The `SIMPUT <https://www.sternwarte.uni-erlangen.de/sixte/sources/>`_ standard
is a FITS file format used by pyXSIM to convert event lists (mentioned above)
to a format that can be read in by instrument simulation software such as
`SOXS <https://hea-www.cfa.harvard.edu/soxs>`_,
`SIXTE <https://www.sternwarte.uni-erlangen.de/research/sixte/>`_,
`MARX <https://space.mit.edu/ASC/MARX/>`_, or
`SIMX <https://hea-www.cfa.harvard.edu/simx/>`_. See :ref:`instruments` for
more details.

pyXSIM Limitations
++++++++++++++++++

pyXSIM currently has the following limitations, which may or may not be
lifted in the future:

* pyXSIM is currently unable to simulate any sources with any optical
  thickness, self-absorption, or self-scattering.
* pyXSIM is currently unable to simulate any sources with explicit time
  dependence.
* pyXSIM is currently limited to datasets in Cartesian coordinates.

Basic yt Concepts
-----------------

In this section we will outline some basic yt concepts that you will need to
familiarize yourself with in order to use pyXSIM effectively. If you are
familiar with how yt works, you can safely skip this section.

Datasets
++++++++

Most commonly, one will be working with a dataset that was generated by some
simulation code, i.e. FLASH, Enzo, Athena, etc. These datasets are loaded
using ``yt.load``:

.. code-block:: python

    ds = yt.load("sloshing_nomag2_hdf5_plt_cnt_0150")

Alternatively, if you have data from a non-supported dataset format or some
3D arrays that were generated from scratch, there are a number of ways to
create in-memory datasets in yt.

Data Objects
++++++++++++

Once you have a dataset object, it can be used to create geometrical
"data objects" in three dimensions in yt. For example, to create a sphere,
one would use:

.. code-block:: python

    sp = ds.sphere("c", (1.0, "Mpc"))

where the first argument is the center of the sphere (here ``"c"`` means the
center of the simulation domain) and the second is the radius, which is given
as a (value, unit) tuple. One could also have supplied a particular coordinate
value such as ``[0.1, 0.3, 0.5]`` for the center.

As another example, to create an object containing all of the data in the
simulation domain, use:

.. code-block:: python

    dd = ds.all_data()

Other data objects can be created--for more information about the various data
objects and the options to use to create them, check out
`the yt documentation on data objects <http://yt-project.org/doc/analyzing/objects.html>`_.

Unitful Quantities
++++++++++++++++++

yt employs a symbolic unit system when dealing with physical quantities with
units. pyXSIM uses yt's unit system to keep track of the units of various
quantities such as exposure times, effective areas, distances, energies, etc.
You can read more about the yt unit system and how it works
`here <http://yt-project.org/doc/analyzing/units/index.html>`_.

Most routines in pyXSIM which ask for unitful quantities will accept them in
one of three forms:

* A :class:`~yt.units.yt_array.YTArray` or :class:`~yt.units.yt_array.YTQuantity`
  with the correct dimensions, i.e. ``YTArray([30., 45.], "deg")``
* A ``(value, unit)`` tuple with the correct dimensions, i.e. ``(3.0, "keV")``
* A floating-point number, in which case default units will be assumed

In the latter case, the default units for various dimensionful quantities are:

* Length (for distances to sources): :math:`\rm{Mpc}`
* Time: :math:`\rm{s}`
* Velocity: :math:`\rm{km/s}`
* Area: :math:`\rm{cm^2}`
* Energy: :math:`\rm{keV}`
* Angle: :math:`\rm{degree}`

To be on the safe side, it's always recommended to provide some unit
information, since the units will be checked for correct dimensionality and will
be converted if necessary.

Field Specifications
++++++++++++++++++++

This means that whenever pyXSIM accepts a field specification as an argument, it
will need to be in one of the following two forms:

* A string (yt will look up the field by its name). Examples are: ``"density"``,
  ``"particle_velocity_x"``, ``"temperature"``, ``"emission_measure"``, etc.
* A tuple of two strings, the first string specifying the field type and the
  second specifying the field name. Examples are: ``("gas", "density")``,
  ``("PartType0", "Temperature")``, etc.

Either way of specifying fields is acceptable, but if you want to make
absolutely sure you get the correct field, it is better to specify in the second
form, since this will correspond to a unique field.
