Changeset 2461 for TI02CSML/branches
 Timestamp:
 04/05/07 18:09:38 (13 years ago)
 Location:
 TI02CSML/branches/csmlpml
 Files:

 3 edited
Legend:
 Unmodified
 Added
 Removed

TI02CSML/branches/csmlpml/csmllibs/NumericTransform.py
r2460 r2461 7 7 # TODO: Currently quite intolerent of incorrect syntax. 8 8 # TODO: Implementation of shunting yard too opaque. Possibly rewrite. 9 # 10 # Change History 11 # 20070504 mhen Modified to handle Numeric arrays 9 12 10 13 from math import * … … 63 66 elif(t == '(' or (t in _symbols and 'prec' not in _symbols[t])): 64 67 s.append(t) # Function, constant or left parenthesis token. 65 elif(t == ')' or t == ','): 68 elif(t == ')' or t == ','): # right paren or func separator token. 66 69 while(len(s)>0 and s[len(s)1] != '('): 67 70 q.append(s.pop()) … … 87 90 def isNumericString(candidate): 88 91 try: float(candidate) 89 except : return False92 except ValueError: return False 90 93 return True 91 94 … … 95 98 self.tokens = expression.split() 96 99 97 # Solve the tokenised postfix expression stored in self.tokens listand100 # Solve the tokenised postfix expression stored in self.tokens and 98 101 # return the solution (or None if no solution could be found) 99 102 def solve(self, **variables): … … 124 127 125 128 126 # Test:129 # Regression Test: 127 130 if __name__ == "__main__": 128 131 expression_str = " (10* (sqrt(16) + 3)  20)*x/10^2+0.42 " 
TI02CSML/branches/csmlpml/csmllibs/csmldataiface.py
r2460 r2461 535 535 536 536 537 # Read the data from the raw file into a multidimensional Numeric array 537 538 def readFile(self, **kwargs): 538 # index into an array that determines the type based on various 539 # combinations of settings in the CSML. This is very clever, but 540 # rather obscure.. blame mhen :p 541 format_index = 0 542 543 if kwargs['type'] == 'float': 544 format_index = 12 # Float: Set bit 2 (float) and bit 3 (signed) 545 elif kwargs['signedness'] != 'unsigned': 546 format_index = 8 # Signed Int: set bit 3 (signed) 547 548 # Set bits 0 and 1 depending on whether the data are 8, 16, 32 or 64 549 # bits wide. 550 if kwargs['depth'] in [8,16,32,64]: 551 format_index = [8,16,32,64].index(kwargs['depth']) 552 553 # Set the endianness of the format string. (Set to HostEndian if not 554 # defined 555 if kwargs['endianness'] == 'big': 556 format_str = '>' 557 elif kwargs['endianness'] == 'little': 558 format_str = '<' 559 else: 560 format_str = '=' 561 562 # Set the size of the data to read (product of dimensions) 563 format_str += str(reduce(lambda a,b:a*b, kwargs['dimensions'])) 564 565 # Lookup the type character 566 format_str += "BHIQbhiqfd"[format_index] 567 539 # Valid values for numericType and their associated struct format 540 # character: 541 numericLookup = { 542 'uint8':'B', 'uint16':'H', 'uint32':'I', 'uint64':'Q', 543 'int8':'b', 'int16':'h', 'int32':'i', 'int64':'q', 544 'float':'f', 'double':'d' 545 } 546 547 # Valid values for endianness and their associated struct format 548 # character: 549 endiannessLookup = { 550 'big':'>', 'little':'<', 'host':'=' 551 } 552 553 # Build the desired format string: 554 try: 555 format_str = endiannessLookup[kwargs['endianness']] 556 format_str += str(reduce(lambda a,b:a*b, kwargs['dimensions'])) 557 format_str += numericLookup[kwargs['numericType']] 558 except KeyError, TypeError: 559 raise TypeError("Missing or invalid parameters. Required: endianness=str, dimensions=list and numericType=str") 560 561 # Read and unpack data into a Numeric array. 568 562 self.data = Numeric.array(struct.unpack(format_str, self.file.read())) 569 563 self.data.shape = tuple(map(int, kwargs['dimensions'])) 570 564 565 # If numericTransform or fillValue were provided, store them as 566 # attributes. 571 567 if 'numericTransform' in kwargs: 572 # if a numericTransform was supplied, then compile it:573 568 self.numericTransform = NumericTransform.infixExpression(kwargs['numericTransform']) 574 575 569 if 'fillValue' in kwargs: 576 570 self.fillValue = kwargs['fillValue'] 577 571 578 572 579 580 # Allows data to be indexed as if it were a multidimensional array:581 def index(self, *indices):582 index1d = 0583 factor = 1584 for n in range(len(indices)):585 index1d += factor * indices[n]586 factor *= self.dimensions[n]587 return self.data[index1d]588 589 590 573 # Return the fill value, if set, and transform if necessary: 591 574 def getFillValue(self): 592 if(self.fillValue): 593 if(self.numericTransform): 594 return self.numericTransform.solve( n = float(self.fillValue) ) 595 else: 575 # Both fillValue and numericTransform attributes may or may 576 # not exist... 577 try: 578 return self.numericTransform.solve( n = float(self.fillValue) ) 579 except AttributeError: 580 try: 596 581 return self.fillValue 597 else: 598 return None 599 600 582 except AttributeError: 583 return None 584 585 586 # This is a just a special case of getSubsetOfDataForVar. To avoid 587 # duplication of code, just subset the entire array. (getSubset.. is 588 # optimised for this case) 601 589 def getDataForVar(self): 602 if self.numericTransform: 603 # Solve the numeric transform and return the resulting array of floats 604 return self.numericTransform.solve( n = self.data ) 605 else: 606 return self.data 607 608 590 return self.getSubsetOfDataForVar(lower = (0,)*len(self.data.shape), 591 upper = self.data.shape) 592 593 594 # Subset the ndimensional file based on array indices. Accepts parameters 595 # in the form of e.g. 596 # 597 # getSubsetOfDataForVar( lower=(0,0), upper=(1,2) ) 598 # 599 # Note: The rank of the required subset, must exactly match the 600 # rank of the original data: len(lower) == len(upper) == rank of file 601 # 609 602 def getSubsetOfDataForVar(self, **kwargs): 610 603 # Assume subset parameters are passed as: lower=(0,0) upper=(512,512) 611 604 if 'lower' not in kwargs or 'upper' not in kwargs: 605 # Have not specified any subset parameters that we recognise, so raise 606 # an exception: 612 607 raise NotImplementedError("Only supports subsetting with lower+upper array indices") 613 elif len(kwargs['lower']) != len(self.data.shape) or len(kwargs['upper']) != len(self.data.shape): 614 raise NotImplementedError("Only supports subsets of same dimensionality as full dataset") 608 elif not len(kwargs['lower']) == len(kwargs['upper']) == len(self.data.shape): 609 # Rank of subset is not the same as rank of full data array. so raise 610 # an exception: 611 raise NotImplementedError("Only supports subsets of same rank as full dataset") 612 elif Numeric.sometrue(Numeric.greater(kwargs['upper'], self.data.shape)): 613 # Requested upper bound of subset is beyond the size of the the full 614 # data array, so raise an exception 615 raise IndexException("Subset out of range") 616 elif Numeric.sometrue(Numeric.less( kwargs['upper'], Numeric.zeros(len(self.data.shape)))): 617 # Requested lower bound of subset is beyond the size of the the full 618 # data array, so raise an exception 619 raise IndexException("Subset out of range") 620 elif Numeric.sometrue(Numeric.less_equal(kwargs['upper', kwargs['lower'])): 621 # lower bound <= upper_bound for at least one dimension, so raise an 622 # exception 623 raise IndexException("Upper bound less than lower bound") 624 elif tuple(kwargs['lower']) == (0,)*len(self.data.shape) and tuple(kwargs['upper']) == self.data.shape: 625 # Special case of requested subset == entire data file. 626 subset = self.data 615 627 else: 616 if not self.data: 617 self.readFile() 618 subset = [] 619 620 # Recursive function for the purpose of iterating over an array of 621 # arbitrary dimensionality. (Iterate over the desired subset, and 622 # append each data item encountered to the subset array) 623 ptr = [None] * len(self.data.shape) 624 def iterate(n = 0): 625 for ptr[n] in range(kwargs['lower'][n], kwargs['upper'][n] + 1): 626 if n < len(self.data.shape)  1: 627 iterate(n + 1) 628 else: 629 subset.insert(0, self.index(*ptr)) 630 iterate() 631 632 if self.numericTransform: 633 # Solve the numeric transform and return the resulting array of floats 634 return self.numericTransform.solve( n = subset ) 635 else: 636 return subset 637 638 639 # Interface from reading data from image files. Requires PIL Image module 628 # We are okay to subset. 629 630 # I cant see any nice (and speedy) way of subsetting a Numeric 631 # array of arbitrary rank without the use of eval. By doing it 632 # this way, we can make use of the (possible) acceleration provided 633 # by Numeric/NumPy. 634 slices = [] 635 for i in range(len(self.data.shape)): 636 lower = int(kwargs['lower'][i]) 637 upper = int(kwargs['upper'][i]) 638 slices.append(str(lower)+':'+str(upper)) 639 subset = eval("self.data["+','.join(slices)+"]") 640 641 # Attempt to perform the numericTransform on the data array, if we get 642 # AttributeError, it most likely means that numericTransform was not 643 # specified, so return the data asis 644 try: 645 return self.numericTransform.solve( n = subset ) 646 except AttributeError: 647 return subset.copy() 648 649 650 # Interface for reading data from image files. Requires PIL Image module. 640 651 class ImageFileInterface(RawFileInterface): 641 652 def __init__(self): … … 647 658 648 659 def closeFile(self): 649 self.file = None 660 self.file = None #...Image does not seem to have a close() method. 650 661 651 662 def readFile(self, **kwargs): 652 663 # Convert the image to a Numeric array 653 self.data = Numeric.array(im.getdata()) 654 self.data.shape = tuple(map(int, im.size)) 664 self.data = Numeric.array(self.file.getdata()) 665 666 # The order of dimensions in Numeric arrays do not correspond with 667 # the order of dimensions in traditional image files, so we need to 668 # reverse the dimensions before shaping the array. 669 dimensions = map(int,self.file.size) 670 dimensions.reverse() 671 self.data.shape = tuple(dimensions) # self.data.shape = (Y,X) 655 672 656 673 if 'numericTransform' in kwargs: 
TI02CSML/branches/csmlpml/parser.py
r2460 r2461 1065 1065 meta = {} 1066 1066 meta['dimensions'] = map(int, self.arraySize.CONTENT.split()) 1067 if self.numericTransform: 1067 1068 try: 1068 1069 meta['numericTransform'] = self.numericTransform.CONTENT.strip() 1069 if self.endianness: 1070 except AttributeError: pass 1071 try: 1070 1072 meta['endianness'] = self.endianness.CONTENT.strip() 1071 if self.fillValue: 1073 except AttributeError: pass 1074 try: 1072 1075 meta['fillValue'] = self.fillValue.CONTENT.strip() 1073 if self.numericType: 1074 type = self.numericType.CONTENT.strip() 1075 if type == 'float': 1076 meta['signedness'] = 'signed' 1077 meta['type'] = 'float' 1078 meta['depth'] = 32 1079 elif type == 'double': 1080 meta['signedness'] = 'signed' 1081 meta['type'] = 'float' 1082 meta['depth'] = 64 1083 elif type[0:4] == 'uint': 1084 meta['signedness'] = 'unsigned' 1085 meta['type'] = 'int' 1086 meta['depth'] = int(type[4:]) 1087 elif type[0:3] == 'int': 1088 meta['signedness'] = 'signed' 1089 meta['type'] = 'int' 1090 meta['depth'] = int(type[3:]) 1091 1092 if self.dataInterface: 1076 except AttributeError: pass 1077 try: 1078 meta['numericType'] = self.numericType.CONTENT.strip() 1079 except AttributeError: pass 1080 1081 try: 1093 1082 DI = self.dataInterface() 1094 e lse:1083 except AttributeError: 1095 1084 DI = csml.csmllibs.csmldataiface.DataInterface() 1096 1085 DI = DI.getUnknownInterfaceType(file) … … 1109 1098 1110 1099 1111 class ImageFileExtract( FileExtract, csElement):1100 class ImageFileExtract(RawFileExtract, csElement): 1112 1101 def __init__(self,**kwargs): 1113 1102 FileExtract.__init__(self, **kwargs) … … 1118 1107 csElement.__init__(self,**kwargs) 1119 1108 self.dataInterface = csml.csmllibs.csmldataiface.ImageFileInterface 1120 self.getData = RawFileExtract.getData1109 1121 1110 1122 1111 class SimpleCondition(csElement):
Note: See TracChangeset
for help on using the changeset viewer.