diff --git a/processing/post/sortTable.py b/processing/post/sortTable.py index 53a357226..3a3738d18 100755 --- a/processing/post/sortTable.py +++ b/processing/post/sortTable.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -26,7 +25,7 @@ With coordinates in columns "x", "y", and "z"; sorting with x slowest and z fast parser.add_option('-l','--label', - dest = 'keys', + dest = 'labels', action = 'extend', metavar = '', help = 'list of column labels (a,b,c,...)') parser.add_option('-r','--reverse', @@ -38,42 +37,14 @@ parser.set_defaults(reverse = False, ) (options,filenames) = parser.parse_args() - - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.labels is None: + parser.error('no labels specified.') for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ assemble header --------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.sort_by(options.labels,not options.reverse) - table.head_read() - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data --------------------------------------- - - table.data_readArray() - - keys = table.labels(raw = True)[::-1] if options.keys is None else options.keys[::-1] # numpy sorts with most significant column as last - - cols = [] - remarks = [] - for i,column in enumerate(table.label_index(keys)): - if column < 0: remarks.append('label "{}" not present...'.format(keys[i])) - else: cols += [table.data[:,column]] - if remarks != []: damask.util.croak(remarks) - - ind = np.lexsort(cols) if cols != [] else np.arange(table.data.shape[0]) - if options.reverse: ind = ind[::-1] - -# ------------------------------------------ output result --------------------------------------- - - table.data = table.data[ind] - table.data_writeArray() - table.close() # close ASCII table + table.to_ASCII(sys.stdout if name is None else name) diff --git a/python/damask/table.py b/python/damask/table.py index b2be3ae20..3c867fcf5 100644 --- a/python/damask/table.py +++ b/python/damask/table.py @@ -1,3 +1,4 @@ +import random import re import pandas as pd @@ -104,7 +105,7 @@ class Table(): """ if re.match(r'[0-9]*?_',label): idx,key = label.split('_',1) - return self.data[key].to_numpy()[:,int(idx)-1] + return self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1)) else: return self.data[label].to_numpy().reshape((-1,)+self.shapes[label]) @@ -196,6 +197,32 @@ class Table(): self.shapes[label_new] = self.shapes.pop(label_old) + def sort_by(self,labels,ascending=True): + """ + Get column data. + + Parameters + ---------- + label : list of str or str + Column labels. + ascending : bool, optional + Set sort order. + + """ + _temp = [] + _labels = [] + for label in labels if isinstance(labels,list) else [labels]: + 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))) + def to_ASCII(self,fname): """ Store as plain text file. diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index 67bcab557..b17348881 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -19,13 +19,21 @@ def reference_dir(reference_dir_base): class TestTable: - def test_get_tensor(self,default): - d = default.get('F') - assert np.allclose(d,1.0) and d.shape[1:] == (3,3) + def test_get_scalar(self,default): + d = default.get('s') + assert np.allclose(d,1.0) and d.shape[1:] == (1,) def test_get_vector(self,default): d = default.get('v') assert np.allclose(d,1.0) and d.shape[1:] == (3,) + + def test_get_tensor(self,default): + d = default.get('F') + assert np.allclose(d,1.0) and d.shape[1:] == (3,3) + + def test_get_component(self,default): + d = default.get('5_F') + assert np.allclose(d,1.0) and d.shape[1:] == (1,) def test_write_read_str(self,default,tmpdir): default.to_ASCII(str(tmpdir.join('default.txt'))) @@ -87,3 +95,27 @@ class TestTable: def test_invalid_get(self,default): with pytest.raises(KeyError): default.get('n') + + def test_sort_scalar(self): + x = np.random.random((5,13)) + t = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) + unsort = t.get('s') + t.sort_by('s') + sort = t.get('s') + assert np.all(np.sort(unsort,0)==sort) + + def test_sort_component(self): + x = np.random.random((5,12)) + t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) + unsort = t.get('4_F') + t.sort_by('4_F') + sort = t.get('4_F') + assert np.all(np.sort(unsort,0)==sort) + + def test_sort_revert(self): + x = np.random.random((5,12)) + t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) + t.sort_by('4_F',False) + sort = t.get('4_F') + assert np.all(np.sort(sort,0)==sort[::-1,:]) +