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.
This commit is contained in:
Martin Diehl 2019-11-26 22:53:46 +01:00
parent 5661f60552
commit 2d96136a0d
2 changed files with 66 additions and 31 deletions

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys
from io import StringIO
from optparse import OptionParser from optparse import OptionParser
import damask import damask
@ -34,9 +36,14 @@ parser.set_defaults(defgrad = 'f',
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
table = damask.Table(name) damask.util.report(scriptName,name)
table.add_array('Cauchy',damask.mechanics.Cauchy(table.get_array(options.defgrad).reshape(-1,3,3),
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), table.get_array(options.stress).reshape(-1,3,3)).reshape(-1,9),
scriptID) scriptID)
table.to_ASCII(name) table.to_ASCII(sys.stdout if name is None else name)

View File

@ -4,9 +4,42 @@ import pandas as pd
import numpy as np import numpy as np
class Table(): class Table():
"""Read and write to ASCII tables""" """Store spreadsheet-like data."""
def __init__(self,fname): 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: try:
f = open(fname) f = open(fname)
except TypeError: except TypeError:
@ -17,43 +50,38 @@ class Table():
header = int(header) header = int(header)
else: else:
raise Exception raise Exception
self.comments = [f.readline()[:-1] for i in range(header-1)] comments = [f.readline()[:-1] for i in range(header-1)]
labels_raw = f.readline().split() labels_raw = f.readline().split()
self.data = pd.read_csv(f,delim_whitespace=True,header=None) labels = [l.split('_',1)[1] if '_' in l else l for l in labels_raw]
labels_repeated = [l.split('_',1)[1] if '_' in l else l for l in labels_raw] headings = {}
self.data.rename(columns=dict(zip([l for l in self.data.columns],labels_repeated)),inplace=True)
self.shape = {}
for l in labels_raw: for l in labels_raw:
tensor_column = re.search(':.*?_',l) tensor_column = re.search(':.*?_',l)
if tensor_column: if tensor_column:
my_shape = tensor_column.group()[1:-1].split('x') 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: else:
vector_column = re.match('.*?_',l) vector_column = re.match('.*?_',l)
if vector_column: 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: 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): 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): 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)) self.comments.append('{}: {}'.format(label,info))
else: else:
self.comments.append('{} {}: {}'.format(label,array.shape[1:],info)) self.comments.append('{} {}: {}'.format(label,array.shape[1:],info))
self.shape[label] = array.shape[1:] self.headings[label] = array.shape[1:] if len(array.shape) > 1 else (1,)
self.labels.append(label) size = np.prod(array.shape[1:],dtype=int)
size = np.product(array.shape[1:])
new_data = pd.DataFrame(data=array.reshape(-1,size), new_data = pd.DataFrame(data=array.reshape(-1,size),
columns=[label for l in range(size)]) columns=[label for l in range(size)])
self.data = pd.concat([self.data,new_data],axis=1) self.data = pd.concat([self.data,new_data],axis=1)
@ -61,15 +89,15 @@ class Table():
def to_ASCII(self,fname): def to_ASCII(self,fname):
labels = [] labels = []
for l in self.labels: for l in self.headings:
if(self.shape[l] == (1,)): if(self.headings[l] == (1,)):
labels.append('{}'.format(l)) labels.append('{}'.format(l))
elif(len(self.shape[l]) == 1): elif(len(self.headings[l]) == 1):
labels+=['{}_{}'.format(i+1,l)\ labels+=['{}_{}'.format(i+1,l)\
for i in range(self.shape[l][0])] for i in range(self.headings[l][0])]
else: else:
labels+=['{}:{}_{}'.format(i+1,'x'.join([str(d) for d in self.shape[l]]),l)\ labels+=['{}:{}_{}'.format(i+1,'x'.join([str(d) for d in self.headings[l]]),l)\
for i in range(np.product(self.shape[l]))] for i in range(np.prod(self.headings[l],dtype=int))]
header = ['{} header'.format(len(self.comments)+1)]\ header = ['{} header'.format(len(self.comments)+1)]\
+ self.comments\ + self.comments\