Changeset 2452 for TI02-CSML


Ignore:
Timestamp:
02/05/07 15:05:35 (12 years ago)
Author:
mggr
Message:

initial version of PML methods (will need testing) - mggr checking in for mhen

Location:
TI02-CSML/branches/csml-pml
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • TI02-CSML/branches/csml-pml/csmllibs/csmldataiface.py

    r2444 r2452  
    2525MA.set_print_limit(0) 
    2626 
     27# Generic mathematical expression solver, required by the raw and image 
     28# interfaces 
     29import NumericTransform 
     30# Part of the PIL. Required for ImageFileInterface: 
     31import Image 
    2732 
    2833class DataInterface(object): 
     
    4045                elif self.iface == 'cdunif': 
    4146                        return cdunifInterface() 
     47                elif self.iface == 'raw': 
     48                        return RawFileInterface() 
     49                elif self.iface == 'image': 
     50                        return ImageFileInterface() 
    4251                 
    4352                 
     
    4857                if fileExtension == '.nc': 
    4958                        return cdunifInterface() 
    50                 if fileExtension == '.qxf': 
     59                if fileExtension == '.qxf': 
    5160                        return cdunifInterface() 
    5261                elif fileExtension == '.pp': 
     
    5463                elif fileExtension == 'ctl': 
    5564                        return cdunifInterface() 
    56                 elif fileExtension == 'xml': 
     65                elif fileExtension == 'xml': 
    5766                        return cdmlInterface() 
     67                elif fileExtensions == 'png' or fileExtension == 'gif': 
     68                        return ImageFileInterface() 
    5869                else: 
    5970                        try: 
     
    504515        axisSize=self.file.axes[axis].length 
    505516        return axisSize 
     517 
     518 
     519class RawFileInterface(AbstractDI): 
     520 
     521   def __init__(self): 
     522      self.extractType   = 'rawExtract' 
     523      self.extractPrefix = '_rawextract_' 
     524 
     525 
     526   def openFile(self, filename): 
     527      self.file = open(filename, "rb") 
     528 
     529 
     530   def closeFile(self): 
     531      self.file.close() 
     532 
     533 
     534   def readFile(self, **kwargs): 
     535       # index into an array that determines the type based on various 
     536       # combinations of settings in the CSML.  This is very clever, but 
     537       # rather obscure.. blame mhen :p 
     538      format_index = 0 
     539       
     540      if kwargs['type'] == 'float': 
     541         format_index |= 12 # Float: Set bit 2 (float) and bit 3 (signed) 
     542      elif kwargs['signedness'] != 'unsigned': 
     543         format_index |= 8  # Signed Int: set bit 3 (signed) 
     544          
     545      # Set bits 0 and 1 depending on whether the data are 8, 16, 32 or 64  
     546      # bits wide. 
     547      if kwargs['depth'] in [8,16,32,64]: 
     548         format_index |= [8,16,32,64].index(kwargs['depth']) 
     549          
     550      # Set the endianness of the format string. (Set to Host-Endian if not 
     551      # defined 
     552      if kwargs['endianness'] == 'big': 
     553         format_str = '>' 
     554      elif kwargs['endianness'] == 'little': 
     555         format_str = '<' 
     556      else: 
     557         format_str = '=' 
     558          
     559      # Set the size of the data to read (product of dimensions) 
     560      format_str += str(reduce(lambda a,b:a*b, kwargs['dimensions'])) 
     561       
     562      # Lookup the type character 
     563      format_str += "bhiq----BHIQ--fd"[format_index] 
     564 
     565      self.data = list(struct.unpack(format_str, self.file.read())) 
     566      self.dimensions = kwargs['dimensions'] 
     567 
     568      if 'numericTransform' in kwargs: 
     569         self.numericTransform = NumericTransform.infixExpression(kwargs['numericTransform']) 
     570      if 'fillValue' in kwargs: 
     571         self.fillValue = kwargs['fillValue'] 
     572 
     573 
     574   # Allows data to be indexed as if it were a multidimensional array: 
     575   def index(self, *indices): 
     576      index1d = 0 
     577      factor  = 1 
     578      for n in range(len(indices)): 
     579         index1d += factor * indices[n] 
     580         factor  *= self.dimensions[n] 
     581      return self.data[index1d] 
     582 
     583 
     584   # Return the (transformed) fill value. 
     585   def getFillValue(self): 
     586      if(self.fillValue): 
     587         return numericTransform.solve( n = self.fillValue ) 
     588      else: 
     589         return None 
     590 
     591 
     592   def getDataForVar(self): 
     593      if not self.data: 
     594         self.readFile() 
     595      if self.numericTransform: 
     596         # Solve the numeric transform and return the resulting array of floats 
     597         return map(lambda val: numericTransform.solve( n = val ), self.data)  
     598      else: 
     599         return self.data 
     600 
     601 
     602   def getSubsetOfDataForVar(self, **kwargs): 
     603      # Assume subset parameters are passed as: lower=(0,0) upper=(512,512) 
     604      if 'lower' not in kwargs or 'upper' not in kwargs: 
     605         raise NotImplementedError("Only supports subsetting with lower+upper array indices") 
     606      elif len(kwargs['lower']) != len(self.dimensions) or len(kwargs['upper']) != len(self.dimensions): 
     607         raise NotImplementedError("Only supports subsets of same dimensionality as full dataset") 
     608      else: 
     609         if not self.data: 
     610            self.readFile() 
     611         subset = [] 
     612 
     613         # Recursive function for the purpose of iterating over an array of 
     614         # arbitrary dimensionality. (Iterate over the desired subset, and 
     615         # append each data item encountered to the subset array) 
     616         ptr = [None] * len(self.dimensions) 
     617         def iterate(n = 0): 
     618            for ptr[n] in range(kwargs['lower'][n], kwargs['upper'][n] + 1): 
     619               if n < len(self.dimensions) - 1: 
     620                  iterate(n + 1) 
     621               else: 
     622                  subset.insert(0, self.index(*ptr)) 
     623         iterate() 
     624 
     625         if self.numericTransform: 
     626            # Solve the numeric transform and return the resulting array of floats 
     627            return map(lambda val: numericTransform.solve( n = val ), subset) 
     628         else: 
     629            return subset 
     630 
     631 
     632# Interface from reading data from image files. Requires PIL Image module 
     633class ImageFileInterface(RawFileInterface): 
     634   def __init__(self): 
     635      self.extractType   = 'imageExtract' 
     636      self.extractPrefix = '_imageextract_' 
     637 
     638   def openFile(self, filename): 
     639      self.file = Image.open(filename) 
     640 
     641   def closeFile(self): 
     642      self.file = None 
     643 
     644   def readFile(self, **kwargs): 
     645      self.data = im.getdata() 
     646      self.dimensions = list(im.size) 
     647 
     648      if 'numericTransform' in kwargs: 
     649         self.numericTransform = NumericTransform.infixExpression(kwargs['numericTransform']) 
     650      if 'fillValue' in kwargs: 
     651         self.fillValue = kwargs['fillValue'] 
  • TI02-CSML/branches/csml-pml/parser.py

    r2444 r2452  
    10261026        csElement.__init__(self,**kwargs) 
    10271027 
     1028class RawFileExtract(FileExtract, csElement): 
     1029 
     1030   # Note: Unlike the other file extracts, this sets a self.dataInterface 
     1031   # attribute, which is used by the overridden getData to determine which 
     1032   # Data Interface is used to read the file. This is necessary because the 
     1033   # getUnknownDataInterface() method determines which DI to use based on 
     1034   # filename suffix (raw files could be called anything) or by inspecting 
     1035   # the file (raw files have no magic numbers or other markers that could 
     1036   # be used to unequivocally determine the file type). 
     1037   def __init__(self,**kwargs): 
     1038      FileExtract.__init__(self, **kwargs) 
     1039      elems=['endianness', 'fillValue'] 
     1040      addelems(self,elems) 
     1041      children={elems[0]:[CSML('endianness'), 'csString'],elems[1]:[CSML('fillValue'), 'csString']} 
     1042      addchildren(self,children) 
     1043      csElement.__init__(self,**kwargs) 
     1044      self.dataInterface = csml.csmllibs.csmldataiface.RawFileInterface 
     1045 
     1046 
     1047   # raw and image extracts need access to metadata defined in the CSML to 
     1048   # correctly read the file. This method overrides the FileExtract getData() 
     1049   # method making use of the readFile() DI method to pass this metadata to 
     1050   # the data interface. 
     1051   # TODO: This should probably be moved outside parser.py, possibly into 
     1052   # API/ops_FileExtract 
     1053   def getData(self,  fileposition=None,**kwargs): 
     1054       #file position defines the position of the filename if a list of filenames exists 
     1055       #**kwargs can hold subsetting request. 
     1056        
     1057       if fileposition is not None: 
     1058           file = self.fileList.fileNames.CONTENT.split()[fileposition] 
     1059       else: 
     1060           file = self.fileName.CONTENT 
     1061       
     1062       # Determine metadata required to correctly read and process the 
     1063       # raw file: 
     1064       meta = {} 
     1065       meta['dimensions'] = self.arraySize.CONTENT.split() 
     1066       if self.numericTransform: 
     1067          meta['numericTransform'] = self.numericTransform.CONTENT.strip() 
     1068       if self.endianness: 
     1069          meta['endianness'] = self.endianness.CONTENT.strip() 
     1070       if self.fillValue: 
     1071          meta['fillValue'] = self.fillValue.CONTENT.strip() 
     1072       if self.numericType: 
     1073          type = self.numericType.CONTENT.strip() 
     1074          if type == 'float': 
     1075             meta['signedness'] = 'signed' 
     1076             meta['type']       = 'float' 
     1077             meta['depth']      = 32 
     1078          elif type == 'double': 
     1079             meta['signedness'] = 'signed' 
     1080             meta['type']       = 'float' 
     1081             meta['depth']      = 64 
     1082          elif type == 'uint': 
     1083             meta['signedness'] = 'unsigned' 
     1084             meta['type']       = 'int' 
     1085             meta['depth']      = int(type[4:]) 
     1086          elif type == 'int': 
     1087             meta['signedness'] = 'signed' 
     1088             meta['type']       = 'int' 
     1089             meta['depth']      = int(type[3:]) 
     1090 
     1091       if self.dataInterface: 
     1092          DI = self.dataInterface() 
     1093       else: 
     1094          DI = csml.csmllibs.csmldataiface.DataInterface() 
     1095          DI = DI.getUnknownInterfaceType(file) 
     1096 
     1097       DI.openFile(file) 
     1098       DI.readFile(**meta) 
     1099       if kwargs: 
     1100          print 'subsetting' 
     1101          data = DI.getSubsetOfDataForVar(**kwargs) 
     1102       else: 
     1103          print 'non subsetting' 
     1104          data = DI.getDataForVar() 
     1105       fillValue = DI.getFillValue() 
     1106       DC=DataContainer(data) 
     1107       dataArray=DC.dataArray 
     1108       DI.closeFile() 
     1109       return dataArray, fillValue, None, None 
     1110 
     1111 
     1112# Note: This is derived from RawFileExtract, because it requires the overriden 
     1113# getData(). 
     1114class ImageFileExtract(RawFileExtract, csElement): 
     1115 
     1116   def __init__(self,**kwargs): 
     1117      FileExtract.__init__(self, **kwargs) 
     1118      elems=['fillValue'] 
     1119      addelems(self,elems) 
     1120      children={elems[0]:[CSML('fillValue'), 'csString']} 
     1121      addchildren(self,children) 
     1122      csElement.__init__(self,**kwargs) 
     1123      self.dataInterface = csml.csmllibs.csmldataiface.ImageFileInterface 
    10281124 
    10291125class SimpleCondition(csElement):  
Note: See TracChangeset for help on using the changeset viewer.