Skip to content

Commit

Permalink
fixup! python: rewrite Python high level API in python
Browse files Browse the repository at this point in the history
  • Loading branch information
vicentebolea committed Dec 22, 2023
1 parent d39b56e commit 88af23d
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 55 deletions.
14 changes: 10 additions & 4 deletions docs/user_guide/source/api_high/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,17 @@ Python Read "step-by-step" example
When reading in stepping mode with the for-in directive, as in the example above, use the step handler (``fstep``) inside the loop rather than the global handler (``fh``)


File class API
High Level API
--------------

.. automodule:: adios2
:members: open
.. autoclass:: adios2::Stream
:members:

.. autoclass:: adios2::FileReader
:members:

.. autoclass:: adios2::Variable
:members:

.. autoclass:: adios2::File
.. autoclass:: adios2::Attribute
:members:
1 change: 1 addition & 0 deletions docs/user_guide/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import os

sys.path.insert(0, os.path.abspath('../../../../bindings/Python'))
sys.path.insert(0, os.path.abspath('../../../../python'))

extensions = [
'sphinx.ext.todo',
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,6 @@ ADIOS2_INSTALL_GENERATE_CONFIG = "OFF"
line-length = 99
target-version = ['py38', 'py39', 'py310']
include = 'python/adios2/.*.py|testing/adios2/python/.*.py'

[tool.pylint]
disable = ['E0401', 'W0102', 'R0904', 'R0913']
7 changes: 6 additions & 1 deletion python/adios2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#!/usr/bin/python3
""" ADIOS2 high-level API module
License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""

import adios2.bindings

Expand All @@ -12,4 +16,5 @@
from adios2.file_reader import *
from adios2.bindings import LocalValueDim

__license__ = "Apache-2.0"
__version__ = adios2.bindings.__version__
5 changes: 5 additions & 0 deletions python/adios2/adios.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""

from adios2.io import IO
from adios2.operator import Operator

Expand Down
50 changes: 44 additions & 6 deletions python/adios2/attribute.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,61 @@
import adios2.bindings
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""


class Attribute:
"""High level representation of the Attribute class in the adios2.bindings"""

def __init__(self, io, name, *args, **kwargs):
self._impl = io.DefineAttribute(name, *args, **kwargs)
self.impl = io.DefineAttribute(name, *args, **kwargs)

@property
def impl(self):
"""Bindings implementation of the class"""
return self._impl

@impl.setter
def impl(self, implementation):
self._impl = implementation

def __eq__(self, other):
if isinstance(other, Attribute):
return self.name() == other.name()
return False

def name(self):
return self._impl.Name()
"""
Name of the Attribute
Returns:
Name of the Attribute as a str.
"""
return self.impl.Name()

def type(self):
return self._impl.Type()
"""
Type of the Attribute
Returns:
Type of the Attribute as a str.
"""
return self.impl.Type()

def data(self):
return self._impl.Data()
"""
Content of the Attribute
Returns:
Content of the Attribute as a non string.
"""
return self.impl.Data()

def data_string(self):
return self._impl.DataString()
"""
Content of the Attribute
Returns:
Content of the Attribute as a str.
"""
return self.impl.DataString()
14 changes: 10 additions & 4 deletions python/adios2/file_reader.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""

from adios2.adios import Adios
from adios2.stream import Stream
import adios2.bindings as bindings

import numpy as np
from adios2 import bindings


class FileReader(Stream):
"""High level implementation of the FileReader class for read Random access mode"""

def __repr__(self):
return f"<adios.file named {self._name}>"
return f"<adios.file named {self._io_name}>"

def __init__(self, path, comm=None, engine_type="BPStream", config_file=None):
self._adios = Adios(comm)
Expand All @@ -17,4 +22,5 @@ def __init__(self, path, comm=None, engine_type="BPStream", config_file=None):
self._engine = self._io.open(path, self._mode)

def variables(self):
"""Returns the list of variables contained in the opened file"""
return [self._io.inquire_variable(var) for var in self.available_variables()]
15 changes: 13 additions & 2 deletions python/adios2/io.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""

import numpy as np
import adios2.bindings as bindings
from adios2.attribute import Attribute
Expand Down Expand Up @@ -59,10 +64,16 @@ def define_variable(
count=[],
isConstantDims=False,
):
var_impl = None
if isinstance(content, np.ndarray):
return Variable(self._impl, name, content, shape, start, count, isConstantDims)
var_impl = self._impl.DefineVariable(
name, content, shape, start, count, isConstantDims
)

else:
return Variable(self._impl, name)
var_impl = self._impl.DefineVariable(name)

return Variable(var_impl)

def inquire_variable(self, name):
var = None
Expand Down
38 changes: 33 additions & 5 deletions python/adios2/operator.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
import adios2.bindings
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""


class Operator:
def __init__(self, impl, name):
self._impl = impl
"""High level representation of the Attribute class in the adios2.bindings"""

def __init__(self, implementation, name):
self.impl = implementation
self._name = name

@property
def impl(self):
"""Bindings implementation of the class"""
return self._impl

@impl.setter
def impl(self, implementation):
self._impl = implementation

def __eq__(self, other):
if isinstance(other, Operator):
return self._name == other._name
return False

def get_parameters(self):
return self._impl.Parameters()
"""
Get parameters associated to this Operator
Returns:
dict: parameters
"""
return self.impl.Parameters()

def set_parameter(self, key, value):
self._impl.SetParameter(key, value)
"""
Set parameter associated to this Operator
Args:
str: key
str: value
"""
self.impl.SetParameter(key, value)
62 changes: 52 additions & 10 deletions python/adios2/stream.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""License:
Distributed under the OSI-approved Apache License, Version 2.0. See
accompanying file Copyright.txt for details.
"""

from adios2.adios import Adios
import adios2.bindings as bindings
from adios2 import bindings

import numpy as np


def open(name, mode, engine_type="BPStream", config_file=None):
"""Stream object open"""
return Stream(name, mode, engine_type)


def type_adios_to_numpy(name):
"""Translation between numpy and adios2 types"""
return {
"char": np.int8,
"int8_t": np.int8,
Expand All @@ -26,8 +27,21 @@ def type_adios_to_numpy(name):


class Stream:
"""High level implementation of the Stream class from the core API"""

def __init__(self, path, mode="r", comm=None, engine_type="BPStream", config_file=None):
self._adios = Adios(comm)
# pylint: disable=E1121
if config_file:
if comm:
self._adios = Adios(config_file, comm)
else:
self._adios = Adios(config_file)
else:
if comm:
self._adios = Adios(comm)
else:
self._adios = Adios()
# pylint: enable=E1121
self._io_name = f"stream:{path}:engine_type:{engine_type}"
self._io = self._adios.declare_io(self._io_name)

Expand All @@ -44,18 +58,22 @@ def __init__(self, path, mode="r", comm=None, engine_type="BPStream", config_fil

@property
def mode(self):
"""Selected open mode"""
return self._mode

@property
def adios(self):
"""Selected open mode"""
return self._adios

@property
def io(self):
"""Selected open mode"""
return self._io

@property
def engine(self):
"""Selected open mode"""
return self._engine

def __repr__(self):
Expand Down Expand Up @@ -153,6 +171,9 @@ def available_attributes(self):
return self._io.available_attributes()

def define_variable(self, name):
"""
Define new variable without specifying its type and content.
"""
return self._io.define_variable(name)

def write(self, name, content, shape=[], start=[], count=[], operations=None):
Expand Down Expand Up @@ -299,8 +320,8 @@ def read_attribute(self, name, variable_name="", separator="/"):

if attribute.type() == "string":
return attribute.data_string()
else:
return attribute.data()

return attribute.data()

def read_attribute_string(self, name, variable_name="", separator="/"):
"""
Expand Down Expand Up @@ -329,6 +350,14 @@ def read_attribute_string(self, name, variable_name="", separator="/"):
return attribute.data_string()

def begin_step(self):
"""
Write mode: advances to the next step. Convenient when declaring
variable attributes as advancing to the next step is not attached
to any variable.
Read mode: in streaming mode releases the current step (no effect
in file based engines)
"""
self._engine.begin_step()

def end_step(self):
Expand Down Expand Up @@ -365,6 +394,18 @@ def current_step(self):
return self._engine.current_step()

def steps(self, num_steps=0):
"""
Returns an interator that can be use to itererate throught the steps.
In each iteration begin_step() and end_step() will be internally called.
Write Mode: num_steps is a mandatory argument and should specify the number
of steps.
Read Mode: num_steps should not be used and there will be as much iterations
as steps exits.
IMPORTANT NOTE: Do not use with ReadRandomAccess mode.
"""
if num_steps > 0:
self.max_steps = num_steps
else:
Expand All @@ -373,5 +414,6 @@ def steps(self, num_steps=0):
self.index = 0
return self

def num_steps(self, num_steps=0):
def num_steps(self):
"""READ MODE ONLY. Return the number of steps available."""
return self._engine.steps()
Loading

0 comments on commit 88af23d

Please sign in to comment.