Merge branch 'new-ASCII' into grid-filters
This commit is contained in:
commit
b1ff178109
|
@ -1,4 +1,3 @@
|
||||||
import random
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -21,26 +20,35 @@ class Table():
|
||||||
Additional, human-readable information.
|
Additional, human-readable information.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
self.comments = [] if comments is None else [c for c in comments]
|
||||||
self.data = pd.DataFrame(data=data)
|
self.data = pd.DataFrame(data=data)
|
||||||
|
|
||||||
labels = {}
|
|
||||||
i = 0
|
|
||||||
for label in shapes.keys():
|
|
||||||
for components in range(np.prod(shapes[label])):
|
|
||||||
labels[i] = label
|
|
||||||
i+=1
|
|
||||||
|
|
||||||
if i != self.data.shape[1]:
|
|
||||||
raise IndexError('Shape mismatch between shapes and data')
|
|
||||||
|
|
||||||
self.data.rename(columns=labels,inplace=True)
|
|
||||||
|
|
||||||
if comments is None:
|
|
||||||
self.comments = []
|
|
||||||
else:
|
|
||||||
self.comments = [c for c in comments]
|
|
||||||
|
|
||||||
self.shapes = shapes
|
self.shapes = shapes
|
||||||
|
self.__label_condensed()
|
||||||
|
|
||||||
|
|
||||||
|
def __label_flat(self):
|
||||||
|
"""Label data individually, e.g. v v v ==> 1_v 2_v 3_v."""
|
||||||
|
labels = []
|
||||||
|
for label,shape in self.shapes.items():
|
||||||
|
size = np.prod(shape)
|
||||||
|
labels += ['{}{}'.format('' if size == 1 else '{}_'.format(i+1),label) for i in range(size)]
|
||||||
|
self.data.columns = labels
|
||||||
|
|
||||||
|
|
||||||
|
def __label_condensed(self):
|
||||||
|
"""Label data condensed, e.g. 1_v 2_v 3_v ==> v v v."""
|
||||||
|
labels = []
|
||||||
|
for label,shape in self.shapes.items():
|
||||||
|
labels += [label] * np.prod(shape)
|
||||||
|
self.data.columns = labels
|
||||||
|
|
||||||
|
|
||||||
|
def __add_comment(self,label,shape,info):
|
||||||
|
if info is not None:
|
||||||
|
self.comments.append('{}{}: {}'.format(label,
|
||||||
|
' '+str(shape) if np.prod(shape,dtype=int) > 1 else '',
|
||||||
|
info))
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_ASCII(fname):
|
def from_ASCII(fname):
|
||||||
|
@ -67,7 +75,7 @@ class Table():
|
||||||
header = int(header)
|
header = int(header)
|
||||||
else:
|
else:
|
||||||
raise Exception
|
raise Exception
|
||||||
comments = [f.readline()[:-1] for i in range(header-1)]
|
comments = [f.readline()[:-1] for i in range(1,header)]
|
||||||
labels = f.readline().split()
|
labels = f.readline().split()
|
||||||
|
|
||||||
shapes = {}
|
shapes = {}
|
||||||
|
@ -81,13 +89,13 @@ class Table():
|
||||||
if vector_column:
|
if vector_column:
|
||||||
shapes[label.split('_',1)[1]] = (int(label.split('_',1)[0]),)
|
shapes[label.split('_',1)[1]] = (int(label.split('_',1)[0]),)
|
||||||
else:
|
else:
|
||||||
shapes[label]=(1,)
|
shapes[label] = (1,)
|
||||||
|
|
||||||
data = pd.read_csv(f,names=[i for i in range(len(labels))],sep=r'\s+').to_numpy()
|
data = pd.read_csv(f,names=list(range(len(labels))),sep=r'\s+').to_numpy()
|
||||||
|
|
||||||
return Table(data,shapes,comments)
|
return Table(data,shapes,comments)
|
||||||
|
|
||||||
|
@property
|
||||||
def labels(self):
|
def labels(self):
|
||||||
"""Return the labels of all columns."""
|
"""Return the labels of all columns."""
|
||||||
return list(self.shapes.keys())
|
return list(self.shapes.keys())
|
||||||
|
@ -105,9 +113,12 @@ class Table():
|
||||||
"""
|
"""
|
||||||
if re.match(r'[0-9]*?_',label):
|
if re.match(r'[0-9]*?_',label):
|
||||||
idx,key = label.split('_',1)
|
idx,key = label.split('_',1)
|
||||||
return self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1))
|
data = self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1))
|
||||||
else:
|
else:
|
||||||
return self.data[label].to_numpy().reshape((-1,)+self.shapes[label])
|
data = self.data[label].to_numpy().reshape((-1,)+self.shapes[label])
|
||||||
|
|
||||||
|
return data.astype(type(data.flatten()[0]))
|
||||||
|
|
||||||
|
|
||||||
def set(self,label,data,info=None):
|
def set(self,label,data,info=None):
|
||||||
"""
|
"""
|
||||||
|
@ -123,11 +134,7 @@ class Table():
|
||||||
Human-readable information about the new data.
|
Human-readable information about the new data.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if info is not None:
|
self.__add_comment(label,data.shape[1:],info)
|
||||||
if np.prod(data.shape[1:],dtype=int) == 1:
|
|
||||||
self.comments.append('{}: {}'.format(label,info))
|
|
||||||
else:
|
|
||||||
self.comments.append('{} {}: {}'.format(label,data.shape[1:],info))
|
|
||||||
|
|
||||||
if re.match(r'[0-9]*?_',label):
|
if re.match(r'[0-9]*?_',label):
|
||||||
idx,key = label.split('_',1)
|
idx,key = label.split('_',1)
|
||||||
|
@ -136,6 +143,7 @@ class Table():
|
||||||
else:
|
else:
|
||||||
self.data[label] = data.reshape(self.data[label].shape)
|
self.data[label] = data.reshape(self.data[label].shape)
|
||||||
|
|
||||||
|
|
||||||
def add(self,label,data,info=None):
|
def add(self,label,data,info=None):
|
||||||
"""
|
"""
|
||||||
Add column data.
|
Add column data.
|
||||||
|
@ -150,17 +158,16 @@ class Table():
|
||||||
Human-readable information about the modified data.
|
Human-readable information about the modified data.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if info is not None:
|
self.__add_comment(label,data.shape[1:],info)
|
||||||
if np.prod(data.shape[1:],dtype=int) == 1:
|
|
||||||
self.comments.append('{}: {}'.format(label,info))
|
|
||||||
else:
|
|
||||||
self.comments.append('{} {}: {}'.format(label,data.shape[1:],info))
|
|
||||||
|
|
||||||
self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,)
|
self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,)
|
||||||
size = np.prod(data.shape[1:],dtype=int)
|
size = np.prod(data.shape[1:],dtype=int)
|
||||||
new_data = pd.DataFrame(data=data.reshape(-1,size),
|
new = pd.DataFrame(data=data.reshape(-1,size),
|
||||||
columns=[label for l in range(size)])
|
columns=[label]*size,
|
||||||
self.data = pd.concat([self.data,new_data],axis=1)
|
)
|
||||||
|
new.index = self.data.index
|
||||||
|
self.data = pd.concat([self.data,new],axis=1)
|
||||||
|
|
||||||
|
|
||||||
def delete(self,label):
|
def delete(self,label):
|
||||||
"""
|
"""
|
||||||
|
@ -176,6 +183,7 @@ class Table():
|
||||||
|
|
||||||
del self.shapes[label]
|
del self.shapes[label]
|
||||||
|
|
||||||
|
|
||||||
def rename(self,label_old,label_new,info=None):
|
def rename(self,label_old,label_new,info=None):
|
||||||
"""
|
"""
|
||||||
Rename column data.
|
Rename column data.
|
||||||
|
@ -190,9 +198,10 @@ class Table():
|
||||||
"""
|
"""
|
||||||
self.data.rename(columns={label_old:label_new},inplace=True)
|
self.data.rename(columns={label_old:label_new},inplace=True)
|
||||||
|
|
||||||
comments = '{} => {}'.format(label_old,label_new)
|
self.comments.append('{} => {}{}'.format(label_old,
|
||||||
comments += ': {}'.format(info) if info is not None else ''
|
label_new,
|
||||||
self.comments.append(comments)
|
'' if info is None else ': {}'.format(info),
|
||||||
|
))
|
||||||
|
|
||||||
self.shapes[label_new] = self.shapes.pop(label_old)
|
self.shapes[label_new] = self.shapes.pop(label_old)
|
||||||
|
|
||||||
|
@ -203,26 +212,18 @@ class Table():
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
label : list of str or str
|
label : str or list
|
||||||
Column labels.
|
Column labels.
|
||||||
ascending : bool, optional
|
ascending : bool or list, optional
|
||||||
Set sort order.
|
Set sort order.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_temp = []
|
self.__label_flat()
|
||||||
_labels = []
|
self.data.sort_values(labels,axis=0,inplace=True,ascending=ascending)
|
||||||
for label in labels if isinstance(labels,list) else [labels]:
|
self.__label_condensed()
|
||||||
if re.match(r'[0-9]*?_',label):
|
|
||||||
_temp.append(str(random.getrandbits(128)))
|
|
||||||
self.add(_temp[-1],self.get(label))
|
|
||||||
_labels.append(_temp[-1])
|
|
||||||
else:
|
|
||||||
_labels.append(label)
|
|
||||||
|
|
||||||
self.data.sort_values(_labels,axis=0,inplace=True,ascending=ascending)
|
|
||||||
for t in _temp: self.delete(t)
|
|
||||||
self.comments.append('sorted by [{}]'.format(', '.join(labels)))
|
self.comments.append('sorted by [{}]'.format(', '.join(labels)))
|
||||||
|
|
||||||
|
|
||||||
def to_ASCII(self,fname):
|
def to_ASCII(self,fname):
|
||||||
"""
|
"""
|
||||||
Store as plain text file.
|
Store as plain text file.
|
||||||
|
@ -238,14 +239,14 @@ class Table():
|
||||||
if(self.shapes[l] == (1,)):
|
if(self.shapes[l] == (1,)):
|
||||||
labels.append('{}'.format(l))
|
labels.append('{}'.format(l))
|
||||||
elif(len(self.shapes[l]) == 1):
|
elif(len(self.shapes[l]) == 1):
|
||||||
labels+=['{}_{}'.format(i+1,l)\
|
labels += ['{}_{}'.format(i+1,l) \
|
||||||
for i in range(self.shapes[l][0])]
|
for i in range(self.shapes[l][0])]
|
||||||
else:
|
else:
|
||||||
labels+=['{}:{}_{}'.format('x'.join([str(d) for d in self.shapes[l]]),i+1,l)\
|
labels += ['{}:{}_{}'.format('x'.join([str(d) for d in self.shapes[l]]),i+1,l) \
|
||||||
for i in range(np.prod(self.shapes[l],dtype=int))]
|
for i in range(np.prod(self.shapes[l],dtype=int))]
|
||||||
|
|
||||||
header = ['{} header'.format(len(self.comments)+1)]\
|
header = ['{} header'.format(len(self.comments)+1)] \
|
||||||
+ self.comments\
|
+ self.comments \
|
||||||
+ [' '.join(labels)]
|
+ [' '.join(labels)]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -9,7 +9,7 @@ from damask import Table
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def default():
|
def default():
|
||||||
"""Simple Table."""
|
"""Simple Table."""
|
||||||
x = np.ones((5,13))
|
x = np.ones((5,13),dtype=float)
|
||||||
return Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['test data','contains only ones'])
|
return Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['test data','contains only ones'])
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -58,7 +58,7 @@ class TestTable:
|
||||||
assert np.allclose(d,0.0) and d.shape[1:] == (3,3)
|
assert np.allclose(d,0.0) and d.shape[1:] == (3,3)
|
||||||
|
|
||||||
def test_labels(self,default):
|
def test_labels(self,default):
|
||||||
assert default.labels() == ['F','v','s']
|
assert default.labels == ['F','v','s']
|
||||||
|
|
||||||
def test_add(self,default):
|
def test_add(self,default):
|
||||||
d = np.random.random((5,9))
|
d = np.random.random((5,9))
|
||||||
|
@ -82,9 +82,9 @@ class TestTable:
|
||||||
default.get('v')
|
default.get('v')
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_initialization(self,default):
|
def test_invalid_initialization(self):
|
||||||
x = default.get('v')
|
x = np.random.random((5,10))
|
||||||
with pytest.raises(IndexError):
|
with pytest.raises(ValueError):
|
||||||
Table(x,{'F':(3,3)})
|
Table(x,{'F':(3,3)})
|
||||||
|
|
||||||
def test_invalid_set(self,default):
|
def test_invalid_set(self,default):
|
||||||
|
@ -115,7 +115,14 @@ class TestTable:
|
||||||
def test_sort_revert(self):
|
def test_sort_revert(self):
|
||||||
x = np.random.random((5,12))
|
x = np.random.random((5,12))
|
||||||
t = Table(x,{'F':(3,3),'v':(3,)},['random test data'])
|
t = Table(x,{'F':(3,3),'v':(3,)},['random test data'])
|
||||||
t.sort_by('4_F',False)
|
t.sort_by('4_F',ascending=False)
|
||||||
sort = t.get('4_F')
|
sort = t.get('4_F')
|
||||||
assert np.all(np.sort(sort,0)==sort[::-1,:])
|
assert np.all(np.sort(sort,0)==sort[::-1,:])
|
||||||
|
|
||||||
|
def test_sort(self):
|
||||||
|
t = Table(np.array([[0,1,],[2,1,]]),
|
||||||
|
{'v':(2,)},
|
||||||
|
['test data'])
|
||||||
|
t.add('s',np.array(['b','a']))
|
||||||
|
t.sort_by('s')
|
||||||
|
assert np.all(t.get('1_v') == np.array([2,0]).reshape((2,1)))
|
||||||
|
|
Loading…
Reference in New Issue