neuralib.persistence.persistence
Cache class's exported field. |
|
make a field as auto increment, which can be used to save and distinguish between same source data but different random/shuffle persistence result. |
|
A class decorator. |
|
ensure data is a persistence class. |
|
transform persistence data into dictionary, which field as key. |
|
transform dictionary |
|
Load data as data_cls from path. |
|
save persistence data under path. |
|
Get data persistence filename. |
|
Raised when a persistence's autoinc field is not resolved, and it is unable to do following operations. |
|
It is used to mark the function which its function body is auto generated. |
|
The handler for loading and saving persistence instance. |
|
Support field type: all python objects. |
|
Support field type: all python objects. |
Persistence Class
- author:
Ta-Shun Su
Define a persistence class
Import
>>> import numpy as np
>>> from neuralib import persistence
Define class
>>> @persistence.persistence_class
... class Example:
... # key. use filename keyword to display key in filename.
... use_animal: str = persistence.field(validator=True, filename=True)
... use_session: str = persistence.field(validator=True)
... use_date: str = persistence.field(validator=True, filename=True)
... # data
... channels: list[int]
... data: np.ndarray
Load/Save
>>> example = Example(use_animal='A00', use_session='', use_date='1234')
>>> save(example, 'example.pkl')
>>> example_2 = load(Example, 'example.pkl') # example and example_2 should be content identical
Cooperate with PersistenceOptions
>>> from neuralib.persistence.cli_persistence import PersistenceOptions
>>> class ExampleHandle(PersistenceOptions[Example]):
... def empty_cache(self) -> Example:
... return Example(use_animal='A00', use_session='', use_date='1234') # with attribute initialization
... def compute_cache(self, result: Example) -> Example:
... result.channels = [0, 1, 2]
... result.riglog = np.array(result.channels)
... return result
Dynamic generated methods for persistence class
__init__({foreach persistence.field})
>>> class Example: ... ... # as same as above ... def __init__(self, use_animal:str, use_session: str, use_date: str): # auto generated ... ...
__str__ return filename
>>> class Example: ... ... # as same as above ... def __str__(self): # auto generated ... return filename(self)
__repr__
>>> class Example: ... ... # as same as above ... def __repr__(self): # auto generated ... return 'Example{' + f'use_animal={self.use_animal}, use_session={self.use_session}, use_date={self.use_date}' + "}"
_replace when persistence define empty _replace methods. It is NamedTuple._replace like function.
>>> class Example: ... ... # as same as above ... def _replace(self, **kwargs): pass # empty method ... def _replace(self, *, # replaced by generated ... use_animal=missing, ... use_session=missing, ... use_date=missing, ... channels=missing, ... data=missing) -> Example: ... ...
Auto increment field
For some reason you want to save a persistence result that came from same data source but different
contents, which are usualy generated by random or suffle process. To save them all separately, you may
need a field value that keep track that it is n-th persistence result. autoinc_field() is proposed
to help this case.
>>> @persistence_class
... class Result:
... a: str = field(validator=True, filename=T)
... b: int = autoinc_field()
... c: str
... def __init__(self, a: str, b: int = None): # auto generated signature
... def _replace(self, *, a: str, c:str): # auto generated signature
There are some rule when a persistence class has an autoinc_field.
only one autoinc_field in a persistence class allowed.
field type only int is allowed.
raise error when load a result without autoinc field resolved.
autoinc field is auto resolved when saving. Its value is max(found) + 1
Pickle format
Persistence class is transformed into a dict by as_dict, which as a root instance to be saved into a pickle file.
IMPORTANT
If a persistance class has a custom __init__ function which signature is differed from auto generated, you need to define a classmethod from_dict for creating that persistance class.
>>> @persistence.persistence_class
... class Example:
... a: int = persistence.field(validator=True, filename=True)
... b: int = persistence.field(validator=True, filename=True)
... c: int
... def __init__(self): ... # custom __init__
... @classmethod
... def from_dict(cls, data:dict[str, Any]) -> 'Example':
... # data = {'a', 'b', 'c'}