-
Notifications
You must be signed in to change notification settings - Fork 21
/
sparse.py
126 lines (97 loc) · 3.82 KB
/
sparse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'''Sparse array class.
This file is a part of bdpy.
'''
__all__ = ['SparseArray', 'load_array', 'save_array', 'save_multiarrays']
import os
import numpy as np
import h5py
import hdf5storage
def load_array(fname, key='data'):
'''Load an array (dense or sparse).'''
with h5py.File(fname, 'r') as f:
methods = [attr for attr in dir(f[key]) if callable(getattr(f[key], str(attr)))]
if 'keys' in methods and '__bdpy_sparse_arrray' in f[key].keys():
# SparseArray
s_ary = SparseArray(fname, key=key)
return s_ary.dense
elif type(f[key][()]) == np.ndarray:
# Dense array
return hdf5storage.loadmat(fname)[key]
else:
raise RuntimeError('Unsupported data type: %s' % type(f[key][()]))
def save_array(fname, array, key='data', dtype=np.float64, sparse=False):
'''Save an array (dense or sparse).'''
if sparse:
# Save as a SparseArray
s_ary = SparseArray(array.astype(dtype))
s_ary.save(fname, key=key, dtype=dtype)
else:
# Save as a dense array
hdf5storage.savemat(fname,
{key: array.astype(dtype)},
format='7.3', oned_as='column',
store_python_metadata=True)
return None
def save_multiarrays(fname, arrays):
'''Save arrays (dense).'''
save_dict = {k: v for k, v in arrays.items()}
hdf5storage.savemat(fname,
save_dict,
format='7.3', oned_as='column',
store_python_metadata=True)
return None
class SparseArray(object):
'''Sparse array class.'''
def __init__(self, src=None, key='data', background=0):
self.__background = background
if type(src) == np.ndarray:
# Create sparse array from numpy.ndarray
self.__make_sparse(src)
elif os.path.isfile(src):
# Load data from src
self.__load(src, key=key)
else:
raise ValueError('Unsupported input')
@property
def dense(self):
return self.__make_dense()
def save(self, fname, key='data', dtype=np.float64):
hdf5storage.savemat(fname, {key: {u'__bdpy_sparse_arrray': True,
u'index': self.__index,
u'value': self.__value.astype(dtype),
u'shape': self.__shape,
u'background' : self.__background}},
format='7.3', oned_as='column', store_python_metadata=True)
return None
def __make_sparse(self, array):
self.__index = np.where(array != self.__background)
self.__value = array[self.__index]
self.__shape = array.shape
return None
def __make_dense(self):
dense = np.ones(self.__shape) * self.__background
dense[self.__index] = self.__value
return dense
def __load(self, fname, key='data'):
data = hdf5storage.loadmat(fname)[key]
index = data[u'index']
if isinstance(index, tuple):
self.__index = index
elif isinstance(index, np.ndarray):
self.__index = tuple(index[0])
else:
raise TypeError('Unsupported data type ("index").')
value = data[u'value']
if value.ndim == 1:
self.__value = value
else:
self.__value = value.flatten()
array_shape = data[u'shape']
if isinstance(array_shape, tuple):
self.__shape = array_shape
elif isinstance(array_shape, np.ndarray):
self.__shape = array_shape.flatten()
else:
raise TypeError('Unsupported data type ("shape").')
self.__background = data[u'background']
return None