diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 266c3fe0..f1af21ea 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,4 +1,8 @@ template: | - ## What’s Changed + ## What’s Changed since $PREVIOUS_TAG $CHANGES + + ## Contributors + + $CONTRIBUTORS \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e90073d9..5cfc2962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,10 +3,12 @@ name: CI # by not building all branches on push, we avoid the duplicated builds in PRs on: push: - branches: - - main - tags: - - '**' + # TODO + # Remove comment: just a test to force CI on push + # branches: + # - main + # tags: + # - '**' pull_request: env: @@ -111,3 +113,27 @@ jobs: pytest -n auto --dist loadscope --cov=nectarchain --cov-report=xml - uses: codecov/codecov-action@v4 + + docs: + needs: lint + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.9 + + - name: Install doc dependencies + run: | + pip install -e .[docs] + # git describe --tags + python -c 'import nectarchain; print(nectarchain.__version__)' + + - name: Build docs + run: make -C docs html diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 340cea3e..9760b1c6 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -2,6 +2,7 @@ name: Release Drafter on: push: + # branches to consider in the event; optional, defaults to all branches: - main @@ -9,6 +10,7 @@ jobs: update_release_draft: runs-on: ubuntu-latest steps: + # Drafts your next Release notes as Pull Requests are merged into "master" - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 93112cd3..43202e4b 100644 --- a/.gitignore +++ b/.gitignore @@ -92,7 +92,6 @@ src/nectarchain/user_scripts/**/test **.log **.pdf **.csv -**.png #VScode .vscode/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..246ca4af --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,35 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # You can also specify other tool versions: + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +# formats: +# - pdf +# - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - method: pip + path: . + extra_requirements: + - docs \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..3f474726 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,24 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= -W --keep-going -n --color -j auto +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +clean: + rm -rf api + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_static/nectarcam.png b/docs/_static/nectarcam.png new file mode 100644 index 00000000..8f28b617 Binary files /dev/null and b/docs/_static/nectarcam.png differ diff --git a/docs/api-reference/data/index.rst b/docs/api-reference/data/index.rst new file mode 100644 index 00000000..74e2ce05 --- /dev/null +++ b/docs/api-reference/data/index.rst @@ -0,0 +1,11 @@ +.. _data: + +Data (`data`) +============= +Module containing functions and classes holding NectarCAM data structure, and interaction with DIRAC. + +Reference/API +============= +.. automodule:: nectarchain.data + :members: + :undoc-members: \ No newline at end of file diff --git a/docs/api-reference/display/index.rst b/docs/api-reference/display/index.rst new file mode 100644 index 00000000..2420ad5e --- /dev/null +++ b/docs/api-reference/display/index.rst @@ -0,0 +1,10 @@ +.. _display: + +Display (`display`) +=================== + +Reference/API +============= +.. automodule:: nectarchain.display + :members: + :undoc-members: diff --git a/docs/api-reference/dqm/index.rst b/docs/api-reference/dqm/index.rst new file mode 100644 index 00000000..ac61a127 --- /dev/null +++ b/docs/api-reference/dqm/index.rst @@ -0,0 +1,12 @@ +.. _dqm: + +Data Quality Monitoring (`dqm`) +=============================== + +Module for the NectarCAM data quality monitoring. + +Reference/API +============= +.. automodule:: nectarchain.dqm + :members: + :undoc-members: \ No newline at end of file diff --git a/docs/api-reference/index.rst b/docs/api-reference/index.rst new file mode 100644 index 00000000..2303e42c --- /dev/null +++ b/docs/api-reference/index.rst @@ -0,0 +1,8 @@ +API Docs +======== + +.. toctree:: + :maxdepth: 1 + :glob: + + */index diff --git a/docs/api-reference/tools/index.rst b/docs/api-reference/tools/index.rst new file mode 100644 index 00000000..0cf536e7 --- /dev/null +++ b/docs/api-reference/tools/index.rst @@ -0,0 +1,12 @@ +.. _tools: + +Tools (`tools`) +=============== + +Tools submodule. + +Reference/API +============= +.. automodule:: nectarchain.tools + :members: + :undoc-members: \ No newline at end of file diff --git a/docs/api-reference/utils/index.rst b/docs/api-reference/utils/index.rst new file mode 100644 index 00000000..d115fbce --- /dev/null +++ b/docs/api-reference/utils/index.rst @@ -0,0 +1,12 @@ +.. _utils: + +Utilities (`utils`) +=================== + +Utilities submodule. + +Reference/API +============= +.. automodule:: nectarchain.utils + :members: + :undoc-members: \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..486b563a --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,138 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import datetime +import sys +from pathlib import Path + +import nectarchain + +if sys.version_info < (3, 11): + import tomli as tomllib +else: + import tomllib + +pyproject_path = Path(__file__).parent.parent / "pyproject.toml" +pyproject = tomllib.loads(pyproject_path.read_text()) + +project = pyproject["project"]["name"] +author = pyproject["project"]["authors"][0]["name"] +copyright = "{}. Last updated {}".format( + author, datetime.datetime.now().strftime("%d %b %Y %H:%M") +) +python_requires = pyproject["project"]["requires-python"] + +# make some variables available to each page +rst_epilog = f""" +.. |python_requires| replace:: {python_requires} +""" + +version = nectarchain.__version__ +# The full version, including alpha/beta/rc tags. +release = version + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.githubpages", + "sphinx.ext.intersphinx", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.viewcode", + "sphinx_automodapi.automodapi", + "sphinx_automodapi.smart_resolver", + "numpydoc", +] + +numpydoc_show_class_members = False +autosummary_generate = True + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +templates_path = [] # ["_templates"] + +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# intersphinx allows referencing other packages sphinx docs +intersphinx_mapping = { + "python": ("https://docs.python.org/3.9", None), + "astropy": ("https://docs.astropy.org/en/latest/", None), + "ctapipe": ("https://ctapipe.readthedocs.io/en/v0.19.3/", None), + "matplotlib": ("https://matplotlib.org/", None), + "traitlets": ("https://traitlets.readthedocs.io/en/stable/", None), +} + +# These links are ignored in the checks, necessary due to broken intersphinx for these +nitpick_ignore = [ + ("py:obj", "enum.auto"), + ("py:obj", "enum.IntFlag"), + ("py:obj", "enum.unique"), + # coming from inherited traitlets docs + ("py:class", "t.Union"), + ("py:class", "t.Dict"), + ("py:class", "t.Tuple"), + ("py:class", "t.List"), + ("py:class", "t.Any"), + ("py:class", "t.Type"), + ("py:class", "Config"), + ("py:class", "Unicode"), + ("py:class", "StrDict"), + ("py:class", "ClassesType"), +] + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "pydata_sphinx_theme" +# html_theme = "alabaster" + +# Output file base name for HTML help builder. +htmlhelp_basename = f"{project}doc" + +html_logo = "_static/nectarcam.png" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] +html_context = { + "default_mode": "light", + "github_user": "cta-observatory", + "github_repo": f"{project}", + "github_version": "main", + "doc_path": "docs", +} +html_file_suffix = ".html" + +html_theme_options = { + "navigation_with_keys": False, + "github_url": f"https://github.com/cta-observatory/{project}", + "navbar_start": ["navbar-logo", "version-switcher"], + "announcement": """ +

nectarchain is not stable yet, so expect large and rapid + changes to structure and functionality as we explore various + design choices before the 1.0 release.

+ """, +} + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = f"{project} v{release}" diff --git a/docs/developer-guide/getting-started.rst b/docs/developer-guide/getting-started.rst new file mode 100644 index 00000000..88b17ebb --- /dev/null +++ b/docs/developer-guide/getting-started.rst @@ -0,0 +1,19 @@ +.. _getting_started_dev: + +Getting Started For Developers +============================== + +Building the documentation +-------------------------- + +To locally build the documentation, optional dependencies should be installed with: + +.. code-block:: + + $ pip install -e ".[docs]" + +The documentation can then be compiled with: + +.. code-block:: + + $ make -C docs html \ No newline at end of file diff --git a/docs/developer-guide/index.rst b/docs/developer-guide/index.rst new file mode 100644 index 00000000..42c13e8d --- /dev/null +++ b/docs/developer-guide/index.rst @@ -0,0 +1,9 @@ +.. _developer-guide: + +Developer Guide +=============== + +.. toctree:: + :maxdepth: 2 + + getting-started diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..82d05db6 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,25 @@ +.. _nectarchain: + +Welcome to nectarchain's documentation! +======================================= + +.. currentmodule:: nectarchain + +**version**: |version| **Date**: |today| + +.. _nectarchain_docs: + +.. toctree:: + :maxdepth: 1 + :hidden: + + developer-guide/index + api-reference/index + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` \ No newline at end of file diff --git a/environment.yml b/environment.yml index f99de826..3e01867c 100644 --- a/environment.yml +++ b/environment.yml @@ -14,6 +14,9 @@ dependencies: - pip - pandas - scipy=1.11 + - sphinx + - sphinx-automodapi + - pydata-sphinx-theme - pip: - zeo - zodb diff --git a/pyproject.toml b/pyproject.toml index f4d196ad..cb56c3b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" name = "nectarchain" description = "Analysis chain for the CTA MSTN NectarCAM prototype" readme = "README.md" -authors = [{name = "NectarCAM collaboration"}] +authors = [{name = "CTAO NectarCAM collaboration"}] license = {text = "BSD-3-Clause"} classifiers = [ "Development Status :: 3 - Alpha", @@ -46,9 +46,17 @@ dev = [ "setuptools_scm", ] +docs = [ + "sphinx", + "sphinx-automodapi", + "pydata_sphinx_theme", + "numpydoc", + "tomli; python_version < '3.11'" +] + # we can use self-references to simplify all all = [ - "nectarchain[test,dev]", + "nectarchain[test,docs,dev]", ] [tool.setuptools.packages.find] diff --git a/src/nectarchain/data/container/core.py b/src/nectarchain/data/container/core.py index 87e41c0d..0f7aa4e7 100644 --- a/src/nectarchain/data/container/core.py +++ b/src/nectarchain/data/container/core.py @@ -105,6 +105,7 @@ def from_hdf5(cls, path): class ArrayDataContainer(NectarCAMContainer): """ A container that holds information about waveforms from a specific run. + Attributes: run_number (int): The run number associated with the waveforms. nevents (int): The number of events. diff --git a/src/nectarchain/data/container/pedestalContainer.py b/src/nectarchain/data/container/pedestalContainer.py index 5a1c1b2f..77959b95 100644 --- a/src/nectarchain/data/container/pedestalContainer.py +++ b/src/nectarchain/data/container/pedestalContainer.py @@ -1,28 +1,29 @@ import logging - -logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s %(message)s") -log = logging.getLogger(__name__) -log.handlers = logging.getLogger("__main__").handlers +from enum import IntFlag, auto, unique import numpy as np from ctapipe.containers import Field from .core import NectarCAMContainer -from enum import IntFlag, auto, unique +logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s %(message)s") +log = logging.getLogger(__name__) +log.handlers = logging.getLogger("__main__").handlers @unique class PedestalFlagBits(IntFlag): - ''' + """ Define the bits corresponding to pedestal-related flags + NEVENTS: Number of events below the acceptable minimum value MEAN_PEDESTAL: Mean pedestal outside acceptable range - STD_SAMPLE: Pedestal standard deviation for all samples in channel/pixel below the - minimum acceptable value + STD_SAMPLE: Pedestal standard deviation for all samples in channel/pixel below + the minimum acceptable value STD_PIXEL: Pedestal standard deviation in a channel/pixel above the maximum - acceptable value - ''' + acceptable value + """ + NEVENTS = auto() MEAN_PEDESTAL = auto() STD_SAMPLE = auto() @@ -35,14 +36,17 @@ class NectarCAMPedestalContainer(NectarCAMContainer): Fields: nsamples (int): The number of samples in the waveforms. - nevents (np.ndarray): The number of events used to estimate the pedestals for each pixel. + nevents (np.ndarray): The number of events used to estimate the pedestals for + each pixel. pixels_id (np.ndarray): An array of pixel IDs. ucts_timestamp_min (int): The minimum of the input events UCTS timestamps. ucts_timestamp_max (int): The maximum of the input events UCTS timestamps. pedestal_mean_hg (np.ndarray): An array of high gain mean pedestals. pedestal_mean_lg (np.ndarray): An array of low gain mean pedestals. - pedestal_std_hg (np.ndarray): An array of standard deviations of high gain pedestals. - pedestal_std_lg (np.ndarray): An array of standard deviations of low gain pedestals. + pedestal_std_hg (np.ndarray): An array of standard deviations of high gain + pedestals. + pedestal_std_lg (np.ndarray): An array of standard deviations of low gain + pedestals. """ nsamples = Field( @@ -51,7 +55,9 @@ class NectarCAMPedestalContainer(NectarCAMContainer): ) nevents = Field( - type=np.ndarray, dtype=np.float64, ndim=1, + type=np.ndarray, + dtype=np.float64, + ndim=1, description="number of events used to estimate the pedestals for each pixel", ) @@ -68,7 +74,10 @@ class NectarCAMPedestalContainer(NectarCAMContainer): ) pedestal_mean_hg = Field( - type=np.ndarray, dtype=np.float64, ndim=2, description="high gain mean pedestals" + type=np.ndarray, + dtype=np.float64, + ndim=2, + description="high gain mean pedestals", ) pedestal_mean_lg = Field( @@ -76,17 +85,23 @@ class NectarCAMPedestalContainer(NectarCAMContainer): ) pedestal_std_hg = Field( - type=np.ndarray, dtype=np.float64, ndim=2, - description="high gain pedestals standard deviations" + type=np.ndarray, + dtype=np.float64, + ndim=2, + description="high gain pedestals standard deviations", ) pedestal_std_lg = Field( - type=np.ndarray, dtype=np.float64, ndim=2, - description="low gain pedestals standard deviations" + type=np.ndarray, + dtype=np.float64, + ndim=2, + description="low gain pedestals standard deviations", ) pixel_mask = Field( - type=np.ndarray, dtype=np.int8, ndim=2, + type=np.ndarray, + dtype=np.int8, + ndim=2, description="Flag that identifies bad pixels. The flag is a binary mask. \ The meaning of the mask bits is defined in the class\ - ~nectarchain.data.container.PedestalFlagBits" + ~nectarchain.data.container.PedestalFlagBits", ) diff --git a/src/nectarchain/data/management.py b/src/nectarchain/data/management.py index a8ebf5d5..e438c292 100644 --- a/src/nectarchain/data/management.py +++ b/src/nectarchain/data/management.py @@ -33,14 +33,14 @@ class DataManagement: @staticmethod def findrun(run_number: int, search_on_GRID=True) -> Tuple[Path, List[Path]]: - """method to find in NECTARCAMDATA the list of *.fits.fz files associated to + """method to find in NECTARCAMDATA the list of `*.fits.fz` files associated to run_number Args: run_number (int): the run number Returns: - (PosixPath,list): the path list of *fits.fz files + (PosixPath,list): the path list of `*fits.fz` files """ basepath = f"{os.environ['NECTARCAMDATA']}/runs/" list = glob.glob( @@ -108,16 +108,14 @@ def get_GRID_location( username=None, password=None, ): - """method to get run location on GRID from Elog (work in progress!) + """ + Method to get run location on GRID from Elog (work in progress!) Args: run_number (int): run number - output_lfns (bool, optional): if True, return lfns path of fits.gz files, - else return parent directory of run location. Defaults to True. - basepath (str) : the path on GRID where nectarCAM data are stored. - Default to /vo.cta.in2p3.fr/nectarcam/. - fromElog (bool,optionnl): To force to use the method which read the Elog. - Default to False. To use the method with DIRAC API. + output_lfns (bool, optional): if True, return lfns path of fits.gz files, else return parent directory of run location. Defaults to True. + basepath (str) : the path on GRID where nectarCAM data are stored. Default to /vo.cta.in2p3.fr/nectarcam/. + fromElog (bool,optional): To force to use the method which read the Elog. Default to False. To use the method with DIRAC API. username (_type_, optional): username for Elog login. Defaults to None. password (_type_, optional): password for Elog login. Defaults to None. diff --git a/src/nectarchain/makers/component/PedestalComponent.py b/src/nectarchain/makers/component/PedestalComponent.py index 36c63e0c..d01bad7e 100644 --- a/src/nectarchain/makers/component/PedestalComponent.py +++ b/src/nectarchain/makers/component/PedestalComponent.py @@ -26,7 +26,7 @@ class PedestalEstimationComponent(NectarCAMComponent): """ Component that computes calibration pedestal coefficients from raw data. - Waveforms can be filtered based on time, stanndard deviation of the waveforms + Waveforms can be filtered based on time, standard deviation of the waveforms or charge distribution within the sample. Use the `events_per_slice' parameter of `NectarCAMComponent' to reduce memory load. @@ -38,7 +38,7 @@ class PedestalEstimationComponent(NectarCAMComponent): Maximum UCTS timestamp for events used in pedestal estimation filter_method : str The waveforms filter method to be used. - Inplemented methods: WaveformsStdFilter (standard deviation of waveforms), + Implemented methods: WaveformsStdFilter (standard deviation of waveforms), ChargeDistributionFilter (charge distribution). wfs_std_threshold : float Threshold of waveforms standard deviation in ADC counts above which a @@ -75,9 +75,9 @@ class PedestalEstimationComponent(NectarCAMComponent): filter_method = Unicode( None, - help="The waveforms filter method to be used.\n" - "Inplemented methods: WaveformsStdFilter (standard deviation of waveforms),\n" - " ChargeDistributionFilter (charge distribution).", + help="""The waveforms filter method to be used. +Implemented methods: WaveformsStdFilter (standard deviation of waveforms), + ChargeDistributionFilter (charge distribution).""", read_only=False, allow_none=True, ).tag(config=True) @@ -106,12 +106,12 @@ class PedestalEstimationComponent(NectarCAMComponent): ).tag(config=True) pixel_mask_mean_min = Float( - 200., + 200.0, help="Minimum value of pedestal mean below which the pixel is flagged as bad", ).tag(config=True) pixel_mask_mean_max = Float( - 300., + 300.0, help="Maximum value of pedestal mean above which the pixel is flagged as bad", ).tag(config=True) @@ -159,8 +159,8 @@ def __init__(self, subarray, config=None, parent=None, *args, **kwargs): Maximum UCTS timestamp for events used in pedestal estimation filter_method : str The waveforms filter method to be used. - Inplemented methods: WaveformsStdFilter (standard deviation of waveforms), - ChargeDistributionFilter (charge distribution). + Implemented methods: WaveformsStdFilter (standard deviation of + waveforms), ChargeDistributionFilter (charge distribution). wfs_std_threshold : float Threshold of waveforms standard deviation in ADC counts above which a waveform is excluded from pedestal computation. @@ -213,7 +213,7 @@ def calculate_stats(waveformsContainers, wfs_mask, statistics): Names of the statistics (numpy.ma attributes) to compute Returns - ---------- + ------- ped_stats : `dict` A dictionary containing 3D (n_chan,n_pixels,n_samples) arrays for each statistic. @@ -254,18 +254,19 @@ def flag_bad_pixels(self, ped_stats, nevents): for each pixel Returns + ------- pixel_mask : `np.ndarray` An array that contains the binary mask of shape (nchannels,npixels) to flag bad pixels - ---------- """ # Initialize mask to False (all pixels are good) - pixel_mask = np.int8(np.zeros(np.shape(ped_stats['mean'])[:2])) + pixel_mask = np.int8(np.zeros(np.shape(ped_stats["mean"])[:2])) # Flag on number of events log.info( - f"Flag pixels with number of events below the acceptable minimum value {self.pixel_mask_nevents_min}") + f"Flag pixels with number of events below the acceptable minimum value {self.pixel_mask_nevents_min}" + ) flag_nevents = np.int8(nevents < self.pixel_mask_nevents_min) # Bitwise OR pixel_mask = pixel_mask | flag_nevents[np.newaxis, :] * PedestalFlagBits.NEVENTS @@ -273,29 +274,37 @@ def flag_bad_pixels(self, ped_stats, nevents): # Flag on mean pedestal value # Average over all samples for each channel/pixel log.info( - f"Flag pixels with mean pedestal outside acceptable range {self.pixel_mask_mean_min}-{self.pixel_mask_mean_max}") - ped_mean = np.mean(ped_stats['mean'], axis=2) + f"Flag pixels with mean pedestal outside acceptable range {self.pixel_mask_mean_min}-{self.pixel_mask_mean_max}" + ) + ped_mean = np.mean(ped_stats["mean"], axis=2) # Apply thresholds - flag_mean = np.int8(np.logical_or(ped_mean < self.pixel_mask_mean_min, - ped_mean > self.pixel_mask_mean_max)) + flag_mean = np.int8( + np.logical_or( + ped_mean < self.pixel_mask_mean_min, ped_mean > self.pixel_mask_mean_max + ) + ) # Bitwise OR pixel_mask = pixel_mask | flag_mean * PedestalFlagBits.MEAN_PEDESTAL # Flag on standard deviation per sample # all samples in channel/pixel below threshold log.info( - f"Flag pixels with pedestal standard deviation for all samples in channel/pixel below the minimum acceptable value {self.pixel_mask_std_sample_min}") - flag_sample_std = np.int8(np.all(ped_stats['std'] < self.pixel_mask_std_sample_min, - axis=2)) + f"Flag pixels with pedestal standard deviation for all samples in channel/pixel below the minimum acceptable value {self.pixel_mask_std_sample_min}" + ) + flag_sample_std = np.int8( + np.all(ped_stats["std"] < self.pixel_mask_std_sample_min, axis=2) + ) # Bitwise OR pixel_mask = pixel_mask | flag_sample_std * PedestalFlagBits.STD_SAMPLE # Flag on standard deviation per pixel # Standard deviation of pedestal in channel/pixel above threshold log.info( - f"Flag pixels with pedestal standard deviation in a chennel/pixel above the maximum acceptable value {self.pixel_mask_std_pixel_max}") + f"Flag pixels with pedestal standard deviation in a chennel/pixel above the maximum acceptable value {self.pixel_mask_std_pixel_max}" + ) flag_pixel_std = np.int8( - np.std(ped_stats['mean'], axis=2) > self.pixel_mask_std_pixel_max) + np.std(ped_stats["mean"], axis=2) > self.pixel_mask_std_pixel_max + ) # Bitwise OR pixel_mask = pixel_mask | flag_pixel_std * PedestalFlagBits.STD_PIXEL @@ -324,7 +333,7 @@ def timestamp_mask(self, tmin, tmax): Maximum time of the required interval Returns - ---------- + ------- mask : `~numpy.ndarray` A boolean array of shape (n_events,n_pixels,n_samples) that identifies waveforms to be masked. @@ -372,7 +381,7 @@ def waveformsStdFilter_mask(self, threshold): filtered out Returns - ---------- + ------- mask : `~numpy.ndarray` A boolean array of shape (n_events,n_pixels,n_samples) that identifies waveforms to be masked @@ -420,7 +429,7 @@ def chargeDistributionFilter_mask(self, sigma_low, sigma_high): filtered out Returns - ---------- + ------- mask : `~numpy.ndarray` A boolean array of shape (n_events,n_pixels,n_samples) that identifies waveforms to be masked @@ -589,10 +598,10 @@ def finish(self, *args, **kwargs): pixels_id=self._waveformsContainers.pixels_id, ucts_timestamp_min=np.uint64(tmin), ucts_timestamp_max=np.uint64(tmax), - pedestal_mean_hg=self._ped_stats['mean'][HIGH_GAIN], - pedestal_mean_lg=self._ped_stats['mean'][LOW_GAIN], - pedestal_std_hg=self._ped_stats['std'][HIGH_GAIN], - pedestal_std_lg=self._ped_stats['std'][LOW_GAIN], + pedestal_mean_hg=self._ped_stats["mean"][HIGH_GAIN], + pedestal_mean_lg=self._ped_stats["mean"][LOW_GAIN], + pedestal_std_hg=self._ped_stats["std"][HIGH_GAIN], + pedestal_std_lg=self._ped_stats["std"][LOW_GAIN], pixel_mask=pixel_mask, ) diff --git a/src/nectarchain/makers/component/chargesComponent.py b/src/nectarchain/makers/component/chargesComponent.py index c35dc026..c699a789 100644 --- a/src/nectarchain/makers/component/chargesComponent.py +++ b/src/nectarchain/makers/component/chargesComponent.py @@ -235,6 +235,7 @@ def _get_imageExtractor(method: str, subarray: SubarrayDescription, **kwargs): def finish(self, *args, **kwargs): """ Create an output container for the specified trigger type and method. + Args: trigger_type (EventType): The type of trigger. method (str): The name of the charge extraction method. @@ -276,6 +277,7 @@ def finish(self, *args, **kwargs): def sort(chargesContainer: ChargesContainer, method: str = "event_id"): """ Sorts the charges in a ChargesContainer object based on the specified method. + Args: chargesContainer (ChargesContainer): The ChargesContainer object to be sorted. method (str, optional): The sorting method. Defaults to 'event_id'. @@ -316,6 +318,7 @@ def sort(chargesContainer: ChargesContainer, method: str = "event_id"): def select_charges_hg(chargesContainer: ChargesContainer, pixel_id: np.ndarray): """ Selects the charges from the ChargesContainer object for the given pixel_id and returns the result transposed. + Args: chargesContainer (ChargesContainer): The ChargesContainer object. pixel_id (np.ndarray): An array of pixel IDs. @@ -332,6 +335,7 @@ def select_charges_hg(chargesContainer: ChargesContainer, pixel_id: np.ndarray): def select_charges_lg(chargesContainer: ChargesContainer, pixel_id: np.ndarray): """ Selects the charges from the ChargesContainer object for the given pixel_id and returns the result transposed. + Args: chargesContainer (ChargesContainer): The ChargesContainer object. pixel_id (np.ndarray): An array of pixel IDs. @@ -347,6 +351,7 @@ def select_charges_lg(chargesContainer: ChargesContainer, pixel_id: np.ndarray): def charges_hg(self, trigger: EventType): """ Returns the charges for a specific trigger type as a NumPy array of unsigned 16-bit integers. + Args: trigger (EventType): The specific trigger type. Returns: @@ -360,6 +365,7 @@ def charges_hg(self, trigger: EventType): def charges_lg(self, trigger: EventType): """ Returns the charges for a specific trigger type as a NumPy array of unsigned 16-bit integers. + Args: trigger (EventType): The specific trigger type. Returns: @@ -373,6 +379,7 @@ def charges_lg(self, trigger: EventType): def peak_hg(self, trigger: EventType): """ Returns the peak charges for a specific trigger type as a NumPy array of unsigned 16-bit integers. + Args: trigger (EventType): The specific trigger type. Returns: @@ -386,6 +393,7 @@ def peak_hg(self, trigger: EventType): def peak_lg(self, trigger: EventType): """ Returns the peak charges for a specific trigger type as a NumPy array of unsigned 16-bit integers. + Args: trigger (EventType): The specific trigger type. Returns: @@ -416,6 +424,7 @@ def create_from_waveforms( ) -> ChargesContainer: """ Create a ChargesContainer object from waveforms using the specified charge extraction method. + Args: waveformsContainer (WaveformsContainer): The waveforms container object. method (str, optional): The charge extraction method to use (default is "FullWaveformSum"). @@ -461,6 +470,7 @@ def compute_charges( ): """ Compute charge from waveforms. + Args: waveformContainer (WaveformsContainer): The waveforms container object. channel (int): The channel to compute charges for.