Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
eef3aac
fixed flake8 error
toqduj Jun 4, 2025
d156e4d
Merge branch 'BaseData-modification' of https://github.com/BAMresearc…
toqduj Jun 4, 2025
db0523c
fixed poisson_uncertainties test
toqduj Jun 4, 2025
885b6db
better poisson uncertainties test
toqduj Jun 4, 2025
010fe41
Merge branch 'BaseData-modification' of https://github.com/BAMresearc…
toqduj Jun 5, 2025
81c2daf
slowly figuring out how to realise operations
toqduj Jun 5, 2025
99b837f
static_data IoSource now loads defaults from yaml with path-like inte…
toqduj Jun 5, 2025
2afcad7
renaming to match hdf_loader naming
toqduj Jun 6, 2025
c46fe7b
header update
toqduj Jun 6, 2025
f2a5596
header update
toqduj Jun 6, 2025
38b8b14
header update
toqduj Jun 6, 2025
2dccf03
updated iosource with results from 20250613 discussion
toqduj Jun 13, 2025
c179688
updated iosource header
toqduj Jun 14, 2025
7f992ef
extending IoSources to match IoSource for getting data attributes, sh…
toqduj Jun 14, 2025
5d3daa7
updated classes diagram
toqduj Jun 14, 2025
0a4516b
merge with the updated tests.
toqduj Jun 18, 2025
34a88ed
applying the modifications, but in the wrong branch. will redo.
toqduj Jun 18, 2025
ff35051
merged updated baseData branch
toqduj Jun 18, 2025
d6aa36b
updated poisson uncertainty module tests.
toqduj Jun 18, 2025
fbc22e5
Merge branch 'BaseData-modification' into static_data_iosource
toqduj Oct 14, 2025
019a7e4
define an arbitrary intensity unit
toqduj Oct 14, 2025
17d3bd6
slight cleanup of now-simplified BaseData
toqduj Oct 14, 2025
9df7fb2
Merge branch 'BaseData-modification' into static_data_iosource
toqduj Oct 14, 2025
0236508
Merge branch 'main' into static_data_iosource
toqduj Oct 22, 2025
537f311
final changes to YAMLLoader
toqduj Oct 22, 2025
5e34526
added __all__ to YAMLLoader
toqduj Oct 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
424 changes: 277 additions & 147 deletions docs/Classes.drawio

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/modacor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pint import UnitRegistry, set_application_registry

ureg = UnitRegistry(system="SI")
# we need to define an arbitrary intensity unit for scaling of intensity data:
ureg.define("AIU = [intensity] = arbitrary_intensity_unit")
Q_ = ureg.Quantity
# recommended for pickling and unpickling:
set_application_registry(ureg)
Expand Down
22 changes: 11 additions & 11 deletions src/modacor/dataclasses/messagehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import logging

logger = logging.getLogger(__name__)
# logger = logging.getLogger(__name__)


class MessageHandler:
Expand All @@ -29,26 +29,26 @@ def __init__(self, level: int = logging.INFO, name: str = "MoDaCor", **kwargs):
self.consoleLogHandler.setFormatter(formatter)
self.logger.addHandler(self.consoleLogHandler)

def log(self, message: str, level: int = None, name: str = None):
def log(self, message: str, level: int = None) -> None: # , name: str = None):
if level is None:
level = self.level

if name is None:
name = self.name

self.logger(message, level=level, name=name)
# if name is None:
# name = self.name
# does not take a name: # self.logger = logging.getLogger(name)
self.logger.log(msg=message, level=level)

def info(self, message: str):
self.log(message, level=logging.INFO, name="MoDaCor")
self.log(message, level=logging.INFO)

def warning(self, message: str):
self.log(message, level=logging.WARNING, name="MoDaCor")
self.log(message, level=logging.WARNING)

def error(self, message: str):
self.log(message, level=logging.ERROR, name="MoDaCor")
self.log(message, level=logging.ERROR)

def critical(self, message: str):
self.log(message, level=logging.CRITICAL, name="MoDaCor")
self.log(message, level=logging.CRITICAL)

def debug(self, message: str):
self.log(message, level=logging.DEBUG, name="MoDaCor")
self.log(message, level=logging.DEBUG)
43 changes: 0 additions & 43 deletions src/modacor/dataclasses/source_data.py

This file was deleted.

115 changes: 78 additions & 37 deletions src/modacor/io/io_source.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2025 MoDaCor Authors
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

__license__ = "BSD-3-Clause"
__copyright__ = "Copyright 2025 MoDaCor Authors"
__status__ = "Alpha"
__all__ = ["IoSource"]


from typing import Any
# /usr/bin/env python3
# -*- coding: utf-8 -*-

from __future__ import annotations

__coding__ = "utf-8"
__authors__ = ["Malte Storm", "Brian R. Pauw"] # add names to the list as appropriate
__copyright__ = "Copyright 2025, The MoDaCor team"
__date__ = "14/06/2025"
__status__ = "Development" # "Development", "Production"
# end of header and standard imports

from typing import Any, Optional, Tuple, Union

import numpy as np
from attrs import define, field

from modacor.dataclasses.source_data import SourceData
# for type hinting of slicing:
Index = Union[int, slice, type(Ellipsis)]
ArraySlice = Union[Index, Tuple[Index, ...]]


def default_config() -> dict[str, Any]:
Expand Down Expand Up @@ -78,21 +64,76 @@ class IoSource:

configuration: dict[str, Any] = field(factory=default_config)

def get_data(self, index: int, data_key: str) -> SourceData:
def get_data(self, data_key: str, load_slice: Optional[ArraySlice] = None) -> np.ndarray:
"""
Get data and metadata from the IO source using the provided data key.
Get data from the IO source using the provided data key.

Parameters
----------
index : int
The index to access the data.
data_key : str
The key to access the data.
The key to access the data, e.g. '/entry1/instrument/detector00/data'.
load_slice : Optional[ArraySlice]
A slice or tuple of slices to apply to the data. If None, the entire data is returned.
Slicing is not yet implemented, so this will raise NotImplementedError if used.
Consider using the numpy.s_ or numpy.index_exp for simplifying the slicing syntax.

Returns
-------
np.ndarray :
The data associated with the provided key.
The data array associated with the provided key. For scalars, this is a 0-d array.
"""
if load_slice is not None:
raise NotImplementedError("Slicing is not yet implemented.")
raise NotImplementedError("This method should be implemented in subclasses.")

def get_data_shape(self, data_key: str) -> Tuple[int, ...]:
"""
Get the shape of the data from the IO source if the format supports it else empty tuple.

Parameters
----------
data_key : str
The key to the data for which the shape is requested.

Returns
-------
Tuple[int, ...] :
The shape of the data associated with the provided key.
Returns an empty tuple if nothing available or unsupported.
"""
raise NotImplementedError("This method should be implemented in subclasses.")

def get_data_dtype(self, data_key: str) -> Optional[np.dtype]:
"""
Get the data type of the data from the IO source if the format supports it else None.

Parameters
----------
data_key : str
The key to the data for which the dtype is requested.

Returns
-------
Optional[np.dtype] :
The data type of the data associated with the provided key.
Returns None if nothing available or unsupported.
"""
raise NotImplementedError("This method should be implemented in subclasses.")

def get_data_attributes(self, data_key: str) -> dict[str, Any]:
"""
Get data attributes from the IO source if the format supports it else empty dict.

Parameters
----------
data_key : str
The key to the data for which attributes are requested.

Returns
-------
dict[str, Any] :
The attributes associated with the data.
Returns an empty dictionary if nothing available or unsupported.
"""
raise NotImplementedError("This method should be implemented in subclasses.")

Expand Down
69 changes: 69 additions & 0 deletions src/modacor/io/io_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,75 @@ def get_data(self, data_reference: str, index: int) -> np.ndarray:
_source = self.get_source(_source_ref)
return _source.get_data(index, _data_key)

def get_data_shape(self, data_reference: str, index: int) -> np.ndarray:
"""
Get data from the specified source using the provided data key.

The data_reference is composed of the source reference and the internal
data reference, separated by "::".

Parameters
----------
data_reference : str
The reference name of the source to access.
index : int
The index to access the data.

Returns
-------
Any :
The data associated with the provided key.
"""
_source_ref, _data_key = self.split_data_reference(data_reference)
_source = self.get_source(_source_ref)
return _source.get_data_shape(index, _data_key)

def get_data_dtype(self, data_reference: str, index: int) -> np.ndarray:
"""
Get data from the specified source using the provided data key.

The data_reference is composed of the source reference and the internal
data reference, separated by "::".

Parameters
----------
data_reference : str
The reference name of the source to access.
index : int
The index to access the data.

Returns
-------
Any :
The data associated with the provided key.
"""
_source_ref, _data_key = self.split_data_reference(data_reference)
_source = self.get_source(_source_ref)
return _source.get_data_dtype(index, _data_key)

def get_data_attributes(self, data_reference: str, index: int) -> np.ndarray:
"""
Get data from the specified source using the provided data key.

The data_reference is composed of the source reference and the internal
data reference, separated by "::".

Parameters
----------
data_reference : str
The reference name of the source to access.
index : int
The index to access the data.

Returns
-------
Any :
The data associated with the provided key.
"""
_source_ref, _data_key = self.split_data_reference(data_reference)
_source = self.get_source(_source_ref)
return _source.get_data_attributes(index, _data_key)

def get_static_metadata(self, data_reference: str) -> Any:
"""
Get static metadata from the specified source using the provided data key.
Expand Down
Loading