Commit 41f48908 authored by Theo Steininger's avatar Theo Steininger
Browse files

Merge branch 'versioning' into 'master'

Versioning capability for all NIFTy classes



See merge request !38
parents 6146b0ce 5221b105
from __future__ import division
import numpy as np
from keepers import Versionable,\
Loggable
from d2o import distributed_data_object,\
STRATEGIES as DISTRIBUTION_STRATEGIES
......@@ -14,10 +17,8 @@ from nifty.spaces.power_space import PowerSpace
import nifty.nifty_utilities as utilities
from nifty.random import Random
from keepers import Loggable
class Field(Loggable, object):
class Field(Loggable, Versionable, object):
# ---Initialization methods---
def __init__(self, domain=None, val=None, dtype=None, field_type=None,
......@@ -887,6 +888,53 @@ class Field(Loggable, object):
"\n - min.,max. = " + str(minmax) + \
"\n - mean = " + str(mean)
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group.attrs['dtype'] = self.dtype.name
hdf5_group.attrs['distribution_strategy'] = self.distribution_strategy
hdf5_group.attrs['field_type_axes'] = str(self.field_type_axes)
hdf5_group.attrs['domain_axes'] = str(self.domain_axes)
hdf5_group['num_domain'] = len(self.domain)
hdf5_group['num_ft'] = len(self.field_type)
ret_dict = {'val': self.val}
for i in range(len(self.domain)):
ret_dict['s_' + str(i)] = self.domain[i]
for i in range(len(self.field_type)):
ret_dict['ft_' + str(i)] = self.field_type[i]
return ret_dict
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
# create empty field
new_field = EmptyField()
# reset class
new_field.__class__ = cls
# set values
temp_domain = []
for i in range(hdf5_group['num_domain'][()]):
temp_domain.append(repository.get('s_' + str(i), hdf5_group))
new_field.domain = tuple(temp_domain)
temp_ft = []
for i in range(hdf5_group['num_ft'][()]):
temp_domain.append(repository.get('ft_' + str(i), hdf5_group))
new_field.field_type = tuple(temp_ft)
exec('new_field.domain_axes = ' + hdf5_group.attrs['domain_axes'])
exec('new_field.field_type_axes = ' +
hdf5_group.attrs['field_type_axes'])
new_field._val = repository.get('val', hdf5_group)
new_field.dtype = np.dtype(hdf5_group.attrs['dtype'])
new_field.distribution_strategy =\
hdf5_group.attrs['distribution_strategy']
return new_field
class EmptyField(Field):
def __init__(self):
......
# -*- coding: utf-8 -*-
import pickle
import numpy as np
from keepers import Versionable
class FieldType(object):
class FieldType(Versionable, object):
def __init__(self, shape, dtype):
try:
new_shape = tuple([int(i) for i in shape])
......@@ -56,3 +58,19 @@ class FieldType(object):
def post_cast(self, x, axes=None):
return x
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['shape'] = self.shape
hdf5_group['dtype'] = pickle.dumps(self.dtype)
return None
@classmethod
def _from_hdf5(cls, hdf5_group, loopback_get):
result = cls(
hdf5_group['shape'][:],
pickle.loads(hdf5_group['dtype'][()])
)
return result
......@@ -208,3 +208,22 @@ class GLSpace(Space):
self.logger.warn("nlon was set to an unrecommended value: "
"nlon <> 2*nlat-1.")
return nlon
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['nlat'] = self.nlat
hdf5_group['nlon'] = self.nlon
hdf5_group['dtype'] = self.dtype.name
return None
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
result = cls(
nlat=hdf5_group['nlat'][()],
nlon=hdf5_group['nlon'][()],
dtype=np.dtype(hdf5_group['dtype'][()])
)
return result
......@@ -203,3 +203,18 @@ class HPSpace(Space):
raise ValueError(
"nside must be positive and a multiple of 2.")
return nside
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['nside'] = self.nside
hdf5_group['dtype'] = self.dtype.name
return None
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
result = cls(
nside=hdf5_group['nside'][()],
dtype=np.dtype(hdf5_group['dtype'][()])
)
return result
......@@ -180,3 +180,18 @@ class LMSpace(Space):
if (lmax % 2 == 0) and (lmax > 2):
self.logger.warn("Unrecommended parameter (lmax <> 2*n+1).")
return lmax
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['lmax'] = self.lmax
hdf5_group['dtype'] = self.dtype.name
return None
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
result = cls(
lmax=hdf5_group['lmax'][()],
dtype=np.dtype(hdf5_group['dtype'][()])
)
return result
......@@ -154,3 +154,47 @@ class PowerSpace(Space):
@property
def k_array(self):
return self._k_array
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['kindex'] = self.kindex
hdf5_group['rho'] = self.rho
hdf5_group['pundex'] = self.pundex
hdf5_group.attrs['dtype'] = self.dtype.name
hdf5_group['log'] = self.log
# Store nbin as string, since it can be None
hdf5_group.attrs['nbin'] = str(self.nbin)
hdf5_group.attrs['binbounds'] = str(self.binbounds)
return {
'harmonic_domain': self.harmonic_domain,
'pindex': self.pindex,
'k_array': self.k_array
}
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
# make an empty PowerSpace object
new_ps = EmptyPowerSpace()
# reset class
new_ps.__class__ = cls
# set all values
new_ps.dtype = np.dtype(hdf5_group.attrs['dtype'])
new_ps._harmonic_domain = repository.get('harmonic_domain', hdf5_group)
new_ps._log = hdf5_group['log'][()]
exec('new_ps._nbin = ' + hdf5_group.attrs['nbin'])
exec('new_ps._binbounds = ' + hdf5_group.attrs['binbounds'])
new_ps._pindex = repository.get('pindex', hdf5_group)
new_ps._kindex = hdf5_group['kindex'][:]
new_ps._rho = hdf5_group['rho'][:]
new_ps._pundex = hdf5_group['pundex'][:]
new_ps._k_array = repository.get('k_array', hdf5_group)
return new_ps
class EmptyPowerSpace(PowerSpace):
def __init__(self):
pass
......@@ -241,7 +241,6 @@ class RGSpace(Space):
# prepare the distributed_data_object
nkdict = distributed_data_object(
global_shape=shape,
dtype=np.float128,
distribution_strategy=distribution_strategy)
if distribution_strategy in DISTRIBUTION_STRATEGIES['slicing']:
......@@ -320,3 +319,25 @@ class RGSpace(Space):
temp = np.empty(len(self.shape), dtype=bool)
temp[:] = zerocenter
return tuple(temp)
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group['shape'] = self.shape
hdf5_group['zerocenter'] = self.zerocenter
hdf5_group['distances'] = self.distances
hdf5_group['harmonic'] = self.harmonic
hdf5_group.attrs['dtype'] = self.dtype.name
return None
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
result = cls(
shape=hdf5_group['shape'][:],
zerocenter=hdf5_group['zerocenter'][:],
distances=hdf5_group['distances'][:],
harmonic=hdf5_group['harmonic'][()],
dtype=np.dtype(hdf5_group.attrs['dtype'])
)
return result
......@@ -146,10 +146,11 @@ import abc
import numpy as np
from keepers import Loggable
from keepers import Loggable,\
Versionable
class Space(Loggable, object):
class Space(Versionable, Loggable, object):
"""
.. __ __
.. /__/ / /_
......@@ -205,12 +206,13 @@ class Space(Loggable, object):
# parse dtype
self.dtype = np.dtype(dtype)
self._ignore_for_hash = []
self._ignore_for_hash = ['_global_id']
def __hash__(self):
# Extract the identifying parts from the vars(self) dict.
result_hash = 0
for (key, item) in vars(self).items():
for key in sorted(vars(self).keys()):
item = vars(self)[key]
if key in self._ignore_for_hash or key == '_ignore_for_hash':
continue
result_hash ^= item.__hash__() ^ int(hash(key)/117)
......@@ -290,3 +292,15 @@ class Space(Loggable, object):
string += str(type(self)) + "\n"
string += "dtype: " + str(self.dtype) + "\n"
return string
# ---Serialization---
def _to_hdf5(self, hdf5_group):
hdf5_group.attrs['dtype'] = self.dtype.name
return None
@classmethod
def _from_hdf5(cls, hdf5_group, repository):
result = cls(dtype=np.dtype(hdf5_group.attrs['dtype']))
return result
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment