Skip to content

Commit 0680786

Browse files
authored
Merge pull request #49 from BAMresearch/static_data_iosource
Static data iosource, in the shape of YAMLLoader
2 parents 2cc47c4 + 5e34526 commit 0680786

File tree

15 files changed

+661
-370
lines changed

15 files changed

+661
-370
lines changed

docs/Classes.drawio

Lines changed: 277 additions & 147 deletions
Large diffs are not rendered by default.

src/modacor/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from pint import UnitRegistry, set_application_registry
77

88
ureg = UnitRegistry(system="SI")
9+
# we need to define an arbitrary intensity unit for scaling of intensity data:
10+
ureg.define("AIU = [intensity] = arbitrary_intensity_unit")
911
Q_ = ureg.Quantity
1012
# recommended for pickling and unpickling:
1113
set_application_registry(ureg)

src/modacor/dataclasses/messagehandler.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import logging
55

6-
logger = logging.getLogger(__name__)
6+
# logger = logging.getLogger(__name__)
77

88

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

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

36-
if name is None:
37-
name = self.name
38-
39-
self.logger(message, level=level, name=name)
36+
# if name is None:
37+
# name = self.name
38+
# does not take a name: # self.logger = logging.getLogger(name)
39+
self.logger.log(msg=message, level=level)
4040

4141
def info(self, message: str):
42-
self.log(message, level=logging.INFO, name="MoDaCor")
42+
self.log(message, level=logging.INFO)
4343

4444
def warning(self, message: str):
45-
self.log(message, level=logging.WARNING, name="MoDaCor")
45+
self.log(message, level=logging.WARNING)
4646

4747
def error(self, message: str):
48-
self.log(message, level=logging.ERROR, name="MoDaCor")
48+
self.log(message, level=logging.ERROR)
4949

5050
def critical(self, message: str):
51-
self.log(message, level=logging.CRITICAL, name="MoDaCor")
51+
self.log(message, level=logging.CRITICAL)
5252

5353
def debug(self, message: str):
54-
self.log(message, level=logging.DEBUG, name="MoDaCor")
54+
self.log(message, level=logging.DEBUG)

src/modacor/dataclasses/source_data.py

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/modacor/io/io_source.py

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,24 @@
11
# SPDX-License-Identifier: BSD-3-Clause
2-
# Copyright 2025 MoDaCor Authors
3-
#
4-
# Redistribution and use in source and binary forms, with or without modification,
5-
# are permitted provided that the following conditions are met:
6-
# 1. Redistributions of source code must retain the above copyright notice, this
7-
# list of conditions and the following disclaimer.
8-
# 2. Redistributions in binary form must reproduce the above copyright notice,
9-
# this list of conditions and the following disclaimer in the documentation
10-
# and/or other materials provided with the distribution.
11-
# 3. Neither the name of the copyright holder nor the names of its contributors
12-
# may be used to endorse or promote products derived from this software without
13-
# specific prior written permission.
14-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
15-
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16-
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18-
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19-
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21-
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22-
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23-
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24-
25-
__license__ = "BSD-3-Clause"
26-
__copyright__ = "Copyright 2025 MoDaCor Authors"
27-
__status__ = "Alpha"
28-
__all__ = ["IoSource"]
29-
30-
31-
from typing import Any
2+
# /usr/bin/env python3
3+
# -*- coding: utf-8 -*-
324

5+
from __future__ import annotations
6+
7+
__coding__ = "utf-8"
8+
__authors__ = ["Malte Storm", "Brian R. Pauw"] # add names to the list as appropriate
9+
__copyright__ = "Copyright 2025, The MoDaCor team"
10+
__date__ = "14/06/2025"
11+
__status__ = "Development" # "Development", "Production"
12+
# end of header and standard imports
13+
14+
from typing import Any, Optional, Tuple, Union
15+
16+
import numpy as np
3317
from attrs import define, field
3418

35-
from modacor.dataclasses.source_data import SourceData
19+
# for type hinting of slicing:
20+
Index = Union[int, slice, type(Ellipsis)]
21+
ArraySlice = Union[Index, Tuple[Index, ...]]
3622

3723

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

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

81-
def get_data(self, index: int, data_key: str) -> SourceData:
67+
def get_data(self, data_key: str, load_slice: Optional[ArraySlice] = None) -> np.ndarray:
8268
"""
83-
Get data and metadata from the IO source using the provided data key.
69+
Get data from the IO source using the provided data key.
8470
8571
Parameters
8672
----------
87-
index : int
88-
The index to access the data.
8973
data_key : str
90-
The key to access the data.
74+
The key to access the data, e.g. '/entry1/instrument/detector00/data'.
75+
load_slice : Optional[ArraySlice]
76+
A slice or tuple of slices to apply to the data. If None, the entire data is returned.
77+
Slicing is not yet implemented, so this will raise NotImplementedError if used.
78+
Consider using the numpy.s_ or numpy.index_exp for simplifying the slicing syntax.
9179
9280
Returns
9381
-------
9482
np.ndarray :
95-
The data associated with the provided key.
83+
The data array associated with the provided key. For scalars, this is a 0-d array.
84+
"""
85+
if load_slice is not None:
86+
raise NotImplementedError("Slicing is not yet implemented.")
87+
raise NotImplementedError("This method should be implemented in subclasses.")
88+
89+
def get_data_shape(self, data_key: str) -> Tuple[int, ...]:
90+
"""
91+
Get the shape of the data from the IO source if the format supports it else empty tuple.
92+
93+
Parameters
94+
----------
95+
data_key : str
96+
The key to the data for which the shape is requested.
97+
98+
Returns
99+
-------
100+
Tuple[int, ...] :
101+
The shape of the data associated with the provided key.
102+
Returns an empty tuple if nothing available or unsupported.
103+
"""
104+
raise NotImplementedError("This method should be implemented in subclasses.")
105+
106+
def get_data_dtype(self, data_key: str) -> Optional[np.dtype]:
107+
"""
108+
Get the data type of the data from the IO source if the format supports it else None.
109+
110+
Parameters
111+
----------
112+
data_key : str
113+
The key to the data for which the dtype is requested.
114+
115+
Returns
116+
-------
117+
Optional[np.dtype] :
118+
The data type of the data associated with the provided key.
119+
Returns None if nothing available or unsupported.
120+
"""
121+
raise NotImplementedError("This method should be implemented in subclasses.")
122+
123+
def get_data_attributes(self, data_key: str) -> dict[str, Any]:
124+
"""
125+
Get data attributes from the IO source if the format supports it else empty dict.
126+
127+
Parameters
128+
----------
129+
data_key : str
130+
The key to the data for which attributes are requested.
131+
132+
Returns
133+
-------
134+
dict[str, Any] :
135+
The attributes associated with the data.
136+
Returns an empty dictionary if nothing available or unsupported.
96137
"""
97138
raise NotImplementedError("This method should be implemented in subclasses.")
98139

src/modacor/io/io_sources.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,75 @@ def get_data(self, data_reference: str, index: int) -> np.ndarray:
132132
_source = self.get_source(_source_ref)
133133
return _source.get_data(index, _data_key)
134134

135+
def get_data_shape(self, data_reference: str, index: int) -> np.ndarray:
136+
"""
137+
Get data from the specified source using the provided data key.
138+
139+
The data_reference is composed of the source reference and the internal
140+
data reference, separated by "::".
141+
142+
Parameters
143+
----------
144+
data_reference : str
145+
The reference name of the source to access.
146+
index : int
147+
The index to access the data.
148+
149+
Returns
150+
-------
151+
Any :
152+
The data associated with the provided key.
153+
"""
154+
_source_ref, _data_key = self.split_data_reference(data_reference)
155+
_source = self.get_source(_source_ref)
156+
return _source.get_data_shape(index, _data_key)
157+
158+
def get_data_dtype(self, data_reference: str, index: int) -> np.ndarray:
159+
"""
160+
Get data from the specified source using the provided data key.
161+
162+
The data_reference is composed of the source reference and the internal
163+
data reference, separated by "::".
164+
165+
Parameters
166+
----------
167+
data_reference : str
168+
The reference name of the source to access.
169+
index : int
170+
The index to access the data.
171+
172+
Returns
173+
-------
174+
Any :
175+
The data associated with the provided key.
176+
"""
177+
_source_ref, _data_key = self.split_data_reference(data_reference)
178+
_source = self.get_source(_source_ref)
179+
return _source.get_data_dtype(index, _data_key)
180+
181+
def get_data_attributes(self, data_reference: str, index: int) -> np.ndarray:
182+
"""
183+
Get data from the specified source using the provided data key.
184+
185+
The data_reference is composed of the source reference and the internal
186+
data reference, separated by "::".
187+
188+
Parameters
189+
----------
190+
data_reference : str
191+
The reference name of the source to access.
192+
index : int
193+
The index to access the data.
194+
195+
Returns
196+
-------
197+
Any :
198+
The data associated with the provided key.
199+
"""
200+
_source_ref, _data_key = self.split_data_reference(data_reference)
201+
_source = self.get_source(_source_ref)
202+
return _source.get_data_attributes(index, _data_key)
203+
135204
def get_static_metadata(self, data_reference: str) -> Any:
136205
"""
137206
Get static metadata from the specified source using the provided data key.
File renamed without changes.

0 commit comments

Comments
 (0)