"""Array printing function $Id: arrayprint.py,v 1.2 2002/01/31 15:14:34 jaytmiller Exp $ """ # # Written by Konrad Hinsen # last revision: 1996-3-13 # modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details) # and by Perry Greenfield 2000-4-1 for numarray import sys #from umath import * #import Numeric import numarray # The following 3 functions are temporary replacemnts for numeric functions # not yet implemented. This file only uses them for 1-d data. def product(x, y): return x*y def maximum_reduce(arr): maximum = arr[0] for i in xrange(1, arr.nelements()): if arr[i] > maximum: maximum = arr[i] return maximum def minimum_reduce(arr): minimum = arr[0] for i in xrange(1, arr.nelements()): if arr[i] < minimum: minimum = arr[i] return minimum def numeric_compress(arr): nonzero = 0 for i in xrange(arr.nelements()): if arr[i] != 0: nonzero += 1 retarr = numarray.zeros((nonzero,)) nonzero = 0 for i in xrange(arr.nelements()): if arr[i] != 0: retarr[nonzero] = abs(arr[i]) nonzero += 1 return retarr def array2string(a, max_line_width = None, precision = None, suppress_small = None, separator=' ', array_output=0): """array2string(a, max_line_width = None, precision = None, suppress_small = None, separator=' ', array_output=0)""" if len(a._shape) == 0: return str(a[0]) # treat as a null array if any of shape elements == 0 if reduce(product, a._shape) == 0: return "array([], type=%s)" % (a._type.name,) if max_line_width is None: try: max_line_width = sys.output_line_width except AttributeError: max_line_width = 70 if precision is None: try: precision = sys.float_output_precision except AttributeError: precision = 8 if suppress_small is None: try: suppress_small = sys.float_output_suppress_small except AttributeError: suppress_small = 0 data = numarray.ravel(a) type = a._type items_per_line = a._shape[-1] if isinstance(type, numarray.IntegralType) or isinstance(type, numarray.BooleanType): max_str_len = max(len(str(numarray.maximum.reduce(data))), len(str(numarray.minimum.reduce(data)))) ##max_str_len = max(len(str(maximum_reduce(data))), ## ## len(str(minimum_reduce(data)))) ## format = '%' + str(max_str_len) + 'd' item_length = max_str_len format_function = lambda x, f = format: _formatInteger(x, f) elif isinstance(type, numarray.FloatingType): format, item_length = _floatFormat(data, precision, suppress_small) format_function = lambda x, f = format: _formatFloat(x, f) elif isinstance(type, numarray.ComplexType): real_format, real_item_length = _floatFormat(data.getreal(), precision, suppress_small, sign=0) imag_format, imag_item_length = _floatFormat(data.getimag(), precision, suppress_small, sign=1) item_length = real_item_length + imag_item_length + 3 format_function = lambda x, f1 = real_format, f2 = imag_format: \ _formatComplex(x, f1, f2) ## elif type in [numarray.Int8, numarray.UInt8, numarray.Bool]: ## item_length = 1 ## format_function = lambda x: x ## elif type == 'O': ## item_length = max(map(lambda x: len(str(x)), data)) ## format_function = _formatGeneral else: ## return str(a) raise ValueError("Can only print numeric arrays") final_spaces = ((type != numarray.Int8) or (type != numarray.UInt8) or (type != numarray.Bool)) final_spaces = 1 item_length = item_length+len(separator) line_width = item_length*items_per_line - final_spaces if line_width > max_line_width: indent = 6 if indent == item_length: indent = 8 ## items_first = (max_line_width+final_spaces)/item_length items_first = (max_line_width+final_spaces-indent)/item_length if items_first < 1: items_first = 1 items_continuation = (max_line_width+final_spaces-indent)/item_length if items_continuation < 1: items_continuation = 1 line_width = max(item_length*items_first, item_length*items_continuation+indent) - final_spaces number_of_lines = 1 + (items_per_line-items_first + items_continuation-1)/items_continuation line_format = (number_of_lines, items_first, items_continuation, indent, line_width, separator) else: line_format = (1, items_per_line, 0, 0, line_width, separator) lst = _arrayToString(a, format_function, len(a._shape), line_format, array_output, 0)[:-1] if array_output: if a._type in [numarray.Int32, numarray.Float64, numarray.Complex64]: ## return "array(%s)" % lst else: return "array(%s, type=%s)" % (lst, a._type.name) else: return lst def _floatFormat(data, precision, suppress_small, sign = 0): exp_format = 0 non_zero = numarray.abs(numarray.compress(numarray.not_equal(data, 0), data)) ##non_zero = numeric_compress(data) ## if len(non_zero) == 0: max_val = 0. min_val = 0. else: max_val = numarray.maximum.reduce(non_zero) min_val = numarray.minimum.reduce(non_zero) ##max_val = maximum_reduce(non_zero) ##min_val = minimum_reduce(non_zero) if max_val >= 1.e8: exp_format = 1 if not suppress_small and (min_val < 0.0001 or max_val/min_val > 1000.): exp_format = 1 if exp_format: large_exponent = 0 < min_val < 1e-99 or max_val >= 1e100 max_str_len = 8 + precision + large_exponent if sign: format = '%+' else: format = '%' format = format + str(max_str_len) + '.' + str(precision) + 'e' if large_exponent: format = format + '3' item_length = max_str_len else: format = '%.' + str(precision) + 'f' precision = min(precision, max(tuple(map(lambda x, p=precision, f=format: _digits(x,p,f), data)))) max_str_len = len(str(int(max_val))) + precision + 2 if sign: format = '%#+' else: format = '%#' format = format + str(max_str_len) + '.' + str(precision) + 'f' item_length = max_str_len return (format, item_length) def _digits(x, precision, format): s = format % x zeros = len(s) while s[zeros-1] == '0': zeros = zeros-1 return precision-len(s)+zeros def _arrayToString(a, format_function, rank, line_format, base_indent=0, indent_first=1): if rank == 0: return str(a[0]) elif rank == 1: s = '' s0 = '[' items = line_format[1] if indent_first: indent = base_indent else: indent = 0 index = 0 for j in range(line_format[0]): s = s + indent * ' '+s0 for i in range(items): s = s + format_function(a[index])+line_format[-1] index = index + 1 if index == a._shape[0]: break if s[-1] == ' ': s = s[:-1] s = s + '\n' items = line_format[2] indent = line_format[3]+base_indent s0 = '' s = s[:-len(line_format[-1])]+']\n' else: if indent_first: s = ' '*base_indent+'[' else: s = '[' for i in range(a._shape[-rank]-1): s = s + _arrayToString(a[i], format_function, rank-1, line_format, base_indent+1, indent_first=i!=0) s = s[:-1]+line_format[-1][:-1]+'\n'*max(rank-1,1) s = s + _arrayToString(a[a._shape[-rank]-1], format_function, rank-1, line_format, base_indent+1) s = s[:-1]+']\n' return s def _formatInteger(x, format): return format % x def _formatFloat(x, format, strip_zeros = 1): if format[-1] == '3': # 3-digit exponent format = format[:-1] s = format % x third = s[-3] if third == '+' or third == '-': s = s[1:-2] + '0' + s[-2:] elif format[-1] == 'e': # 2-digit exponent s = format % x if s[-3] == '0': s = ' ' + s[:-3] + s[-2:] elif format[-1] == 'f': s = format % x if strip_zeros: zeros = len(s) while s[zeros-1] == '0': zeros = zeros-1 s = s[:zeros] + (len(s)-zeros)*' ' else: s = format % x return s def _formatComplex(x, real_format, imag_format): r = _formatFloat(x.real, real_format) i = _formatFloat(x.imag, imag_format, 0) if imag_format[-1] == 'f': zeros = len(i) while zeros > 2 and i[zeros-1] == '0': zeros = zeros-1 i = i[:zeros] + 'j' + (len(i)-zeros)*' ' else: i = i + 'j' return r + i def _formatGeneral(x): return str(x) + ' ' if __name__ == '__main__': a = Numeric.arange(10) ## b = Numeric.array([a, a+10, a+20]) ## c = Numeric.array([b,b+100, b+200]) print array2string(a) ## print array2string(b) ## print array2string(sin(c), separator=', ', array_output=1) ## print array2string(sin(c)+1j*cos(c), separator=', ', array_output=1) print array2string(Numeric.array([[],[]]))