Coverage for gamdpy/configuration/colarray.py: 97%
37 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1import numpy as np
3# Can be doctested: https://docs.python.org/3/library/doctest.html
4# python3 -m doctest colarray.py # No output == No problem!
5# python3 -m doctest -v colarray.py # The verbose version
7class colarray():
8 """ The Column array Class
10 A class storing several sets ('columns') of lengths with identical dimensions in a single numpy array. Strings are used as indices along the zeroth dimension corresponding to different columns of lengths.
12 Examples
13 --------
15 Storage for positions, velocities, and forces, for 1000 particles in 2 dimensions:
17 >>> ca = colarray(('r', 'v', 'f'), size=(1000,2))
18 >>> ca.shape
19 (3, 1000, 2)
20 >>> ca.column_names
21 ('r', 'v', 'f')
22 >>> # Data is accessed via string indices (similar to dataframes in pandas):
23 >>> ca['r'] = np.ones((1000,2))
24 >>> ca['v'] = 2 # Broadcast by numpy to correct shape
25 >>> print(ca['r'] + 0.01*ca['v'])
26 [[1.02 1.02]
27 [1.02 1.02]
28 [1.02 1.02]
29 ...
30 [1.02 1.02]
31 [1.02 1.02]
32 [1.02 1.02]]
33 """
35 # Most error handling is left to be handled by numpy, as it gives usefull error messages
36 # (illustrated in the documentation string above).
38 def __init__(self, column_names, size, dtype=np.float32, array=None):
39 self.column_names = column_names
40 self.dtype = dtype
41 self.indices = {key:index for index,key in enumerate(column_names)}
42 if type(array)==np.ndarray: # Used, e.g., when loading from file
43 self.array = array
44 else:
45 self.array = np.zeros((len(column_names), *size), dtype=dtype)
47 self.shape = self.array.shape
49 def __setitem__(self, key, data):
50 self.array[self.indices[key]] = data
52 def __getitem__(self, key):
53 return self.array[self.indices[key]]
55 def __repr__(self):
56 return 'colarray('+str(tuple(self.indices.keys()))+', '+self.array.shape[1:].__repr__()+')\n'+self.array.__repr__()
58 def copy(self):
59 return colarray(self.column_names, self.shape, self.dtype, self.array.copy())
62 def save(self, filename):
63 """
64 Save a colarray to disk.
65 >>> ca = colarray(('r', 'v', 'f'), size=(1000,2))
66 >>> ca.save('my_colarray')
67 >>> # Remove the files used for storage of the colarray:
68 >>> colarray.remove_files('my_colarray')
69 """
70 np.save(f'{filename}.npy', self.array)
71 with open(f'{filename}.col', 'w') as f: # Use pickle / json
72 f.write(str(len(self.column_names)) + '\n')
73 for key in self.column_names:
74 f.write(key + '\n')
75 return
78 def load(filename):
79 """
80 Load a colarray from disk.
81 >>> ca = colarray(('r', 'v', 'f'), size=(1000,2))
82 >>> ca['f'] = np.random.uniform(size=(1000,2))
83 >>> ca.save('my_colarray')
84 >>> ca2 = colarray.load('my_colarray')
85 >>> for col in ca.column_names:
86 ... print(np.all(ca2[col]==ca[col]))
87 True
88 True
89 True
91 Remove the files used for storage of the colarray:
92 >>> colarray.remove_files('my_colarray')
94 The file(s) needs to be present:
95 >>> ca2 = colarray.load('my_colarray')
96 Traceback (most recent call last):
97 ...
98 FileNotFoundError: [Errno 2] No such file or directory: 'my_colarray.col'
99 """
101 with open(f'{filename}.col', 'r') as f:
102 num_columns = int(f.readline())
103 column_names = []
104 for i in range(num_columns):
105 column_names.append(f.readline()[:-1]) # removing '\n'
106 array = np.load(f'{filename}.npy')
107 return colarray(column_names, array.shape[1:], array=array)
109 def remove_files(filename):
110 """
111 Remove files storing a colarray
112 >>> ca = colarray(('r', 'v', 'f'), size=(1000,2))
113 >>> ca.save('my_colarray')
114 >>> colarray.remove_files('my_colarray')
115 """
117 import os
118 os.remove(f'{filename}.col')
119 os.remove(f'{filename}.npy')