From 2d96136a0d9fb305a0bd43ce11e00077c9d900d1 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 26 Nov 2019 22:53:46 +0100 Subject: [PATCH] more general constructor for Table reading from file is just one case (now handled by static method). General constructor needs data and header information as dictionary. Works only with python 3.7 where dict keeps the insertion order. Earlier python versions/other implementations might fail. --- processing/post/addCauchy.py | 15 +++++-- python/damask/table.py | 82 ++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/processing/post/addCauchy.py b/processing/post/addCauchy.py index 3a0e14da7..788f1b580 100755 --- a/processing/post/addCauchy.py +++ b/processing/post/addCauchy.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import os +import sys +from io import StringIO from optparse import OptionParser import damask @@ -34,9 +36,14 @@ parser.set_defaults(defgrad = 'f', (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] + for name in filenames: - table = damask.Table(name) - table.add_array('Cauchy',damask.mechanics.Cauchy(table.get_array(options.defgrad).reshape(-1,3,3), - table.get_array(options.stress).reshape(-1,3,3)).reshape(-1,9), + damask.util.report(scriptName,name) + + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.add_array('Cauchy', + damask.mechanics.Cauchy(table.get_array(options.defgrad).reshape(-1,3,3), + table.get_array(options.stress).reshape(-1,3,3)).reshape(-1,9), scriptID) - table.to_ASCII(name) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/python/damask/table.py b/python/damask/table.py index e77ae2b9c..6c5103bc9 100644 --- a/python/damask/table.py +++ b/python/damask/table.py @@ -4,9 +4,42 @@ import pandas as pd import numpy as np class Table(): - """Read and write to ASCII tables""" - - def __init__(self,fname): + """Store spreadsheet-like data.""" + + def __init__(self,array,headings,comments=None): + """ + New spreadsheet data. + + Parameters + ---------- + array : numpy.ndarray + Data. + headings : dict + Column headings. Labels as keys and shape as tuple. Example 'F':(3,3) for a deformation gradient. + comments : iterable of str, optional + Additional, human-readable information + + """ + self.data = pd.DataFrame(data=array) + + d = {} + i = 0 + for label in headings: + for components in range(np.prod(headings[label])): + d[i] = label + i+=1 + + self.data.rename(columns=d,inplace=True) + + if comments is None: + self.comments = [] + else: + self.comments = [c for c in comments] + + self.headings = headings + + @staticmethod + def from_ASCII(fname): try: f = open(fname) except TypeError: @@ -17,43 +50,38 @@ class Table(): header = int(header) else: raise Exception - self.comments = [f.readline()[:-1] for i in range(header-1)] - labels_raw = f.readline().split() - self.data = pd.read_csv(f,delim_whitespace=True,header=None) - - labels_repeated = [l.split('_',1)[1] if '_' in l else l for l in labels_raw] - self.data.rename(columns=dict(zip([l for l in self.data.columns],labels_repeated)),inplace=True) - - self.shape = {} + comments = [f.readline()[:-1] for i in range(header-1)] + labels_raw = f.readline().split() + labels = [l.split('_',1)[1] if '_' in l else l for l in labels_raw] + + headings = {} for l in labels_raw: tensor_column = re.search(':.*?_',l) if tensor_column: my_shape = tensor_column.group()[1:-1].split('x') - self.shape[l.split('_',1)[1]] = tuple([int(d) for d in my_shape]) + headings[l.split('_',1)[1]] = tuple([int(d) for d in my_shape]) else: vector_column = re.match('.*?_',l) if vector_column: - self.shape[l.split('_',1)[1]] = (int(l.split('_',1)[0]),) + headings[l.split('_',1)[1]] = (int(l.split('_',1)[0]),) else: - self.shape[l]=(1,) + headings[l]=(1,) - self.labels = list(dict.fromkeys(labels_repeated)) + return Table(np.loadtxt(f),headings,comments) def get_array(self,label): - return self.data[label].to_numpy().reshape((-1,)+self.shape[label]) + return self.data[label].to_numpy().reshape((-1,)+self.headings[label]) def add_array(self,label,array,info): - if np.product(array.shape[1:],dtype=int) == 1: + if np.prod(array.shape[1:],dtype=int) == 1: self.comments.append('{}: {}'.format(label,info)) - else: self.comments.append('{} {}: {}'.format(label,array.shape[1:],info)) - self.shape[label] = array.shape[1:] - self.labels.append(label) - size = np.product(array.shape[1:]) + self.headings[label] = array.shape[1:] if len(array.shape) > 1 else (1,) + size = np.prod(array.shape[1:],dtype=int) new_data = pd.DataFrame(data=array.reshape(-1,size), columns=[label for l in range(size)]) self.data = pd.concat([self.data,new_data],axis=1) @@ -61,15 +89,15 @@ class Table(): def to_ASCII(self,fname): labels = [] - for l in self.labels: - if(self.shape[l] == (1,)): + for l in self.headings: + if(self.headings[l] == (1,)): labels.append('{}'.format(l)) - elif(len(self.shape[l]) == 1): + elif(len(self.headings[l]) == 1): labels+=['{}_{}'.format(i+1,l)\ - for i in range(self.shape[l][0])] + for i in range(self.headings[l][0])] else: - labels+=['{}:{}_{}'.format(i+1,'x'.join([str(d) for d in self.shape[l]]),l)\ - for i in range(np.product(self.shape[l]))] + labels+=['{}:{}_{}'.format(i+1,'x'.join([str(d) for d in self.headings[l]]),l)\ + for i in range(np.prod(self.headings[l],dtype=int))] header = ['{} header'.format(len(self.comments)+1)]\ + self.comments\