Changeset 3324


Ignore:
Timestamp:
08/02/08 09:31:46 (12 years ago)
Author:
astephen
Message:
 
Location:
nappy/trunk/nappy
Files:
4 edited
3 moved

Legend:

Unmodified
Added
Removed
  • nappy/trunk/nappy/Plans for re-factoring 2008.txt

    r3321 r3324  
    137137Need to do a lot of grepping for inconsistencies. 
    138138 
    139  * _normalizedX should be True|False not "yes","no" 
     139The following need to be set to True or False (not yes,no): 
     140 * _normalizedX  
     141 * time_warning 
    140142 
    141143Global find and replace: 
     
    143145floatFormat 
    144146naDict 
     147===================== 
     148 
     149In naToCdms.py.NAToCdms.toCdmsAxis() there is a line naming the id (if too long) as: 
     150 
     151naAuxVariable.... 
     152 
     153 - need to find where else this string is used and replace all with "naIndVariable" with map-back! 
     154 
     155=================== 
     156 
     157Should we leave in the interactive time units checker in na_to_cdms.py - ask Charles 
     158 
     159===== 
     160cdms_map is not all done in the config file dict. 
     161 
     162 
  • nappy/trunk/nappy/bin/na2nc.py

    r3321 r3324  
    55 
    66""" 
    7 na2nc 
    8 ===== 
     7na2nc.py 
     8======== 
    99 
    1010Converts a NASA Ames file to a NetCDF file. 
     
    1313===== 
    1414 
    15    na2nc.py [<options>] -i <infilename> -o <outfilename>  
     15   na2nc.py [-m <mode>] [-v <var_list>] [-a <aux_var_list>] [-g <global_atts_list>] 
     16            [-r <rename_vars_list>] [-t <time_units>] [-n] -i <na_file> [-o <nc_file>]  
    1617 
    1718Where 
    1819----- 
    1920 
    20     infilename  - name of input file (NASA Ames). 
    21     outfilename - name of output file (NetCDF). 
    22     options     - list of options: 
    23                     -t <time_units_string>  (such as "hours since 2003-04-30 10:00:00") 
     21    <mode>                              is the file mode, either "w" for write or "a" for append 
     22    <var_list>                  is a comma-separated list of variable names to include 
     23    <aux_var_list>              is a comma-separated list of auxiliary variables names to include 
     24    <global_atts_list>  is a comma-separated list of global attributes to add 
     25    <rename_vars_list>  is a comma-separated list of <old_name>,<new_name> pairs to rename variables 
     26    <time_units>                is a valid time units string such as "hours since 2003-04-30 10:00:00" 
     27    -n                                  suppresses the time units warning if invalid 
     28    <na_file>                   is the input NASA Ames file path 
     29    <nc_file>                   is the output NetCDF file path 
    2430     
    2531""" 
     
    2733# Imports from python standard library 
    2834import sys 
    29 sys.path.append(r"..") 
    30 import os 
    3135import re 
    32 import time 
    3336 
    3437# Import from nappy package 
    35 import general 
    36 import cdmsMap 
     38import nappy.nc_convertor.na_to_nc 
    3739 
    38 def na2cdms(nafile, ncfile, time_units=None, time_warning="yes", rename_variables={}, rules=None): 
    39     print "Reading data from: %s" % nafile 
    40     file=general.openNAFile(nafile) 
    41     if file.FFI in (2110, 2160, 2310):  
    42         print """\nERROR: Cannot convert NASA Ames File Format Index (FFI) %s to NetCDF.  
    43 No mapping implemented yet.""" % file.FFI 
    44         return 0 
     40def makeDictFromCommaSepString(s): 
     41    """ 
     42    Reads in comma-separated list and converts to dictionary of successive 
     43    keyword,value pairs. 
     44    """ 
     45    if s.count(",") % 2 == 0: 
     46        raise Exception("Must provide even number of items in argument of commas-separated pairs of values: " + s) 
    4547 
    46     print "Writing output NetCDF file: %s\n" % ncfile 
    47     file.toCdmsFile(ncfile, time_units=time_units, time_warning=time_warning, rename_variables=rename_variables) 
     48    d = {} 
     49    items = value.split(",") 
     50    while len(items) > 0: 
     51        d[items[0]] = items[1] 
     52        items = items[2:]  
     53    return d 
     54 
     55def parseArgs(args): 
     56    """ 
     57    Parses arguments and returns dictionary. 
     58    """ 
     59    arg_dict = {} 
     60    a = arg_dict 
     61 
     62    # Set up defaults 
     63    a["na_file"] = None 
     64    a["mode"] = "w" 
     65    a["variables"] = "all" 
     66    a["aux_variables"]  = "all" 
     67    a["global_attributes"] = {} 
     68    a["rename_variables"] = {} 
     69    a["time_units"] = None 
     70    a["time_warning"] = True 
     71    a["nc_file"] = None 
     72 
     73    (arg_list, dummy) = getopt.getopt("i:o:m:v:a:g:t:nr:", args) 
    4874     
    49     print "\nNetCDF file written successfully: %s" % ncfile 
     75    for arg, value in arg_list: 
     76        if arg == "-i": 
     77            a["na_file"] = value 
     78        elif arg == "-o": 
     79            a["nc_file"] = value 
     80        elif arg == "-m": 
     81            a["mode"] = value 
     82        elif arg == "-v": 
     83            a["variables"] = value.split(",") 
     84        elif arg == "-a": 
     85            a["aux_variables"] = value.split(",") 
     86        elif arg == "-g": 
     87            a["global_attributes"] = makeDictFromCommaSepString(value) 
     88        elif arg == "-t": 
     89            a["time_units"] = value 
     90        elif arg == "-n": 
     91            a["time_warning"] = False 
     92        elif arg == "-r": 
     93            a["rename_variables"] = makeDictFromCommaSepString(value) 
    5094 
    51     return 1 
     95    if not a["na_file"]: 
     96        raise Exception("Please provide argument '-i <na_file>'") 
    5297 
    53 if __name__=="__main__": 
     98    if not a["nc_file"]: 
     99        fn = a["na_file"] 
     100        if fn[-3:] == ".na": fn = fn[:-3] 
     101        nc_file = fn + ".nc" 
     102        print "Auto-generating output file name:", nc_file 
     103        a["nc_file"] = nc_file 
     104 
     105    return a 
     106 
     107 
     108def na2nc(args): 
     109    """ 
     110    Controller for conversion of NASA Ames file to NetCDF file. 
     111    """ 
     112    arg_dict = parseArgs(args) 
     113    nc_file = arg_dict["nc_file"] 
     114    del arg_dict["nc_file"] 
     115    mode = arg_dict["mode"] 
     116    del arg_dict["mode"] 
     117 
     118    convertor = apply(nappy.nc_convertor.na_to_nc.NAToNC, [], arg_dict) 
     119    convertor.convert() 
     120    convertor.writeFile(nc_file, mode)     
     121 
     122 
     123if __name__ == "__main__": 
    54124 
    55125    args=sys.argv[1:] 
    56     if len(args)<4: 
    57         print helpMessage 
    58         print "Incorrect number of arguments used." 
    59         sys.exit() 
    60          
    61     time_units=None 
    62     time_warning="yes" 
    63     rename_variables={} 
    64      
    65     for arg in args: 
    66         if arg=="-i": 
    67             infile=args[args.index(arg)+1] 
    68         elif arg=="-o": 
    69             outfile=args[args.index(arg)+1] 
    70         elif arg=="-t": 
    71             time_units=args[args.index(arg)+1] 
    72         elif arg=="-n": 
    73             time_warning="no" 
    74         elif arg=="-r": 
    75             renamer=args[args.index(arg)+1].split("=")       
    76             rename_variables[renamer[0]]=renamer[1] 
    77  
    78     na2cdms(infile, outfile, time_units=time_units, time_warning=time_warning, rename_variables=rename_variables)  
    79  
     126    na2nc(args) 
  • nappy/trunk/nappy/nappy.ini

    r3321 r3324  
    44[local_attributes] 
    55institution = Data held at British Atmospheric Data Centre (BADC), Rutherford Appleton Laboratory, UK. 
     6 
     7[na_to_nc_map] 
     8NLHEAD = no_of_nasa_ames_header_lines 
     9FFI = file_format_index 
     10ONAME&ORG = institution 
     11SNAME = source 
     12MNAME = title 
     13IVOL = file_number_in_set 
     14NVOL = total_files_in_set 
     15RDATE = history 
     16DATE = first_valid_date_of_data 
     17SCOM&NCOM = comment 
     18 
     19[nc_to_na_map] 
     20Conventions = None 
     21source = SNAME 
     22title = MNAME 
     23institution = ONAME&ORG 
     24references = None 
     25comment = SCOM&NCOM 
     26history = RDATE 
     27file_format_index = FFI 
     28no_of_nasa_ames_header_lines = NLHEAD 
     29total_files_in_set = NVOL 
     30file_number_in_set = IVOL 
     31first_valid_date_of_data = DATE 
  • nappy/trunk/nappy/nc_interface/na_to_cdms.py

    r3321 r3324  
    44 
    55""" 
    6 naToCdms.py 
    7 =========== 
     6na_to_cdms.py 
     7============= 
    88 
    99Container module for mixin class NAToCdms that is sub-classed 
     
    1818 
    1919# Import from nappy package 
    20 import cdms_map 
    21 from na_error import na_error 
     20import utils 
     21from nappy.na_error import na_error 
     22import nappy.utils 
     23 
     24na_to_nc_map = utils.getConfigDict()["na_to_nc_map"] 
    2225 
    2326# Import external packages (if available) 
    24 if sys.platform.find("win")>-1: 
    25     pass 
    26 else: 
    27     try: 
    28         import cdms, Numeric 
    29         cdms.setAutoBounds("off")  
    30     except: 
    31         print "Cannot import cdms package, CDAT-dependent features will not work." 
     27if sys.platform.find("win") > -1: 
     28    raise na_error.NAPlatformError("Windows does not support CDMS. CDMS is required to convert to CDMS objects and NetCDF.") 
     29try: 
     30    import cdms, Numeric 
     31except: 
     32    raise Exception("Could not import third-party software. Nappy requires the CDMS and Numeric packages to be installed to convert to CDMS and NetCDF.") 
     33cdms.setAutoBounds("off")  
    3234 
    3335# Define global variables 
    34 safe_nc_id=re.compile("[\/\s\[\(\)\]\=\+\-\?\#\~\@\&\$\%\!\*\{\}\^]+") 
    35  
    36 time_units_pattn=re.compile("\w+\s+since\s+\d{4}-\d{1,2}-\d{1,2}\s+\d+:\d+:\d+") 
    37  
    38 class NAToCdms: 
    39     """ 
    40     Abstract class inherited by standard NAFile classes for mapping of 
    41     NASA Ames to CDMS-type files. 
    42     """ 
    43      
    44     def toCdmsFile(self, filename, time_units=None, time_warning="yes", variables="all", \ 
    45                    aux_variables="all", global_attributes={"Conventions":"CF-1.0"}, \ 
    46                    rename_variables={}, ffi=None): 
    47         """ 
    48         Main method for writing the existing NASA Ames dictionary out 
    49         to a CDMS (NetCDF) file. 
    50         """ 
    51         self.outputMessage=[]  # for output printing message 
    52         if self.FFI in (2110, 2160, 2310):  
    53             msg="""ERROR: Cannot convert NASA Ames File Format Index (FFI) %s to NetCDF.  
    54 No mapping implemented yet.""" % self.FFI 
    55             print msg 
    56             self.outputMessage.append(msg) 
    57             sys.exit() 
    58              
    59         print "V:", variables 
    60         #print "A:", aux_variables 
    61         #print "TW:", time_warning 
    62         self.variables=variables 
    63         self.aux_variables=aux_variables 
    64         self.time_warning=time_warning 
    65         self.rename_variables=rename_variables 
    66         # Modify self.rename_variables to give users a chance 
    67         #for key in self.rename_variables.keys(): 
    68         #    value=self.rename_variables[key] 
    69         #    match=re.search(r"^(.*)\s+\([^\)]+\)$", value) 
    70         #    if match: 
    71         #        self.rename_variables[key]=match.groups()[0] 
    72         # 
    73          
    74         if sys.platform.find("win")>-1: 
    75             raise NAPlatformError 
    76  
    77         self.time_units=time_units 
    78         # Read the data section of the NASA Ames file 
    79         self.readData() 
    80         print "Reading in data..." 
    81         self.cdmsFilename=filename 
    82         self.cdmsFile=cdms.open(self.cdmsFilename, 'w') 
    83          
    84         # at file level: write global attributes 
    85         for key in global_attributes.keys(): 
    86             setattr(self.cdmsFile, key, global_attributes[key]) 
    87  
    88         for key in cdms_map.fromNA.keys(): 
    89             if type(key)==tuple: 
    90                 if key==("SCOM", "NCOM"): 
    91                     # Map special and normal comments into the global comments section 
    92                      
    93                     commentline="" 
    94                     if self.NSCOML>0: 
    95                         commentline=commentline+"###NASA Ames Special Comments follow###\n" 
    96                         for i in self.SCOM:  
    97                             if i.strip() not in ("###NASA Ames Special Comments follow###", "###NASA Ames Special Comments end###", 
    98                                     "Additional Variable Attributes defined in the source file and not translated elsewhere:", 
    99                                     "Additional Global Attributes defined in the source file and not translated elsewhere:", "\n"): 
    100                                 commentline=commentline+"\n"+i 
    101                         commentline=commentline+"\n###NASA Ames Special Comments end###\n" 
    102                     if self.NNCOML>0: 
    103                         commentline=commentline+"###NASA Ames Normal Comments follow###\n" 
    104                         for i in self.NCOM:  
    105                             if i.strip() not in ("###NASA Ames Normal Comments follow###", "###NASA Ames Normal Comments end###", "###Data Section begins on the next line###", 
    106                                     "Additional Variable Attributes defined in the source file and not translated elsewhere:", 
    107                                     "Additional Global Attributes defined in the source file and not translated elsewhere:", "\n"): 
    108                                 commentline=commentline+"\n"+i 
    109                         commentline=commentline+"\n###NASA Ames Normal Comments end###" 
    110                         commentline=commentline.replace("\n\n", "\n") 
    111                     self.cdmsFile.comment=commentline 
    112                 elif key==("ONAME", "ORG"): 
    113                     # Map the two organisation NA files to the institution field in CDMS (NetCDF) 
    114                     self.cdmsFile.institution="%s (ONAME from NASA Ames file); %s (ORG from NASA Ames file)." % (self.ONAME, self.ORG) 
    115                 else: 
    116                     item=(getattr(self, key[0]))+"\n"+(getattr(self, key[1])) 
    117                     setattr(self.cdmsFile, cdms_map.fromNA[key], item) 
    118             elif key=="RDATE": 
    119                 dateparts=getattr(self, "RDATE") 
    120                 datestring="%.4d-%.2d-%.2d" % tuple(dateparts) 
    121                 item=datestring+" - NASA Ames File created/revised.\n" 
    122                 timestring=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) 
    123                 item=item+"\n"+timestring+" - Converted to CDMS (NetCDF) format using nappy-%s." % version.version 
    124             else: 
    125                 setattr(self.cdmsFile, cdms_map.fromNA[key], getattr(self, key)) 
    126  
    127         # Then do dimensions 
    128         if not hasattr(self, 'cdmsAxes'):  self.createCdmsAxes() 
    129  
    130         # Then do variables 
    131         if not hasattr(self, 'cdmsVariables'):  self.createCdmsVariables() 
    132         for var in self.cdmsVariables: 
    133             self.cdmsFile.write(var) 
    134  
    135         # Then do auxiliary variables 
    136         if hasattr(self, "NAUXV") and (type(self.NAUXV)==type(1) and self.NAUXV>0):   # Are there any auxiliary variables? 
    137             if not hasattr(self, 'cdmsAuxVariables'):  self.createCdmsAuxVariables() 
    138             for avar in self.cdmsAuxVariables: 
    139                 self.cdmsFile.write(avar) 
    140  
    141         self.cdmsFile.close() 
    142         return "Cdmsfile '%s' written successfully." % self.cdmsFilename 
    143  
    144     def createCdmsVariables(self): 
    145         """ 
    146         Creates cdms variable list for writing out. 
    147         """ 
    148         self.cdmsVariables=[] 
    149         if self.variables=="all":     
    150             for var_number in range(self.NV): 
    151                 self.cdmsVariables.append(self.toCdmsVariable(var_number)) 
    152         else: 
    153             if type(self.variables[0])==type(1): # They are integers = indices 
    154                 for var_number in self.variables: 
    155                     self.cdmsVariables.append(self.toCdmsVariable(var_number))    
    156             elif type(self.variables[0])==type(""): 
    157                 for var_name in self.variables: 
    158                     if var_name in self.VNAME: 
    159                         var_number=self.VNAME.index(var_name) 
    160                         self.cdmsVariables.append(self.toCdmsVariable(var_number)) 
    161                     else: 
    162                         raise "Variable name not known: "+var_name 
    163  
    164  
    165     def toCdmsVariable(self, var_number, attributes={}): 
    166         """ 
    167         Creates a single cdms variable from the variable number provided in the list. 
    168         """ 
    169         if sys.platform.find("win")>-1: 
    170             raise NAPlatformError 
    171         (varname, units, miss, scal)=self.getVariable(var_number) 
    172         #print self.V 
    173         msg="\nAdding variable: %s" % self.VNAME[var_number] 
    174         print msg 
    175         self.outputMessage.append(msg) 
    176         array=Numeric.array(self.V[var_number]) 
    177         array=array*scal 
    178         # Set up axes 
    179         if not hasattr(self, 'cdmsAxes'): 
    180             self.createCdmsAxes() 
    181  
    182         # Set up variable 
    183         var=cdms.createVariable(array, axes=self.cdmsAxes, fill_value=miss, attributes=attributes) 
    184  
    185         # Sort units etc 
    186         if units:   var.units=units 
    187          
    188         # Add the best variable name 
    189         if len(varname)<40: 
    190             var.id=safe_nc_id.sub("_", varname).lower() 
    191         else: 
    192             var.id="naVariable_%s" % (var_number) 
    193          
    194         # Check if user wants to rename this variable 
    195         #print self.rename_variables, "3"*200 
    196         #if varname in self.rename_variables.keys(): 
    197         #    varname=self.rename_variables[varname] 
    198              
    199         var.long_name=var.name=var.title=varname 
    200  
    201         # If we have a standard name list then compare to it 
    202         if varname in ("standard_name_list",) or varname in ("badc_list",): 
    203             var.standard_name="name from the list###**" 
    204  
    205         # Add a NASA Ames variable number (for mapping correctly back to NASA Ames) 
    206         var.nasa_ames_var_number=var_number 
    207  
    208         return var 
    209  
    210     def createCdmsAuxVariables(self): 
    211         """ 
    212         Creates a cdms variable from an auxiliary variable 
    213         """ 
    214         self.cdmsAuxVariables=[] 
    215  
    216         if self.aux_variables=="all":     
    217             for avar_number in range(self.NAUXV): 
    218                 self.cdmsAuxVariables.append(self.auxToCdmsVariable(avar_number)) 
    219         else: 
    220             if type(self.aux_variables[0])==type(1): # They are integers = indices 
    221                 for avar_number in self.aux_variables: 
    222                     self.cdmsAuxVariables.append(self.auxToCdmsVariable(avar_number))    
    223             elif type(self.aux_variables[0])==type(""): 
    224                 for avar_name in self.aux_variables: 
    225                     if avar_name in self.ANAME: 
    226                         avar_number=self.ANAME.index(avar_name) 
    227                         self.cdmsAuxVariables.append(self.auxToCdmsVariable(avar_number))  
    228                     else: 
    229                         raise "Auxiliary variable name not known: "+avar_name        
    230  
    231     def auxToCdmsVariable(self, avar_number, attributes={}): 
    232         """ 
    233         Converts an auxiliary variable to a cdms variable. 
    234         """ 
    235         if sys.platform.find("win")>-1: 
    236             raise NAPlatformError 
    237         (varname, units, miss, scal)=self.getAuxVariable(avar_number) 
    238         array=Numeric.array(self.A[avar_number]) 
    239         array=array*scal 
    240  
    241         msg="\nAdding auxiliary variable: %s" % self.ANAME[avar_number] 
    242         print msg 
    243         self.outputMessage.append(msg) 
    244         # Set up axes 
    245         if not hasattr(self, 'cdmsAxes'): 
    246             self.createCdmsAxes() 
    247  
    248         # Set up variable 
    249         var=cdms.createVariable(array, axes=[self.cdmsAxes[0]], fill_value=miss, attributes=attributes) 
    250  
    251         # Sort units etc 
    252         if units:   var.units=units 
    253         if len(varname)<20: 
    254             var.id=safe_nc_id.sub("_", varname).lower() 
    255         else: 
    256             var.id="naAuxVariable_%s" % (avar_number) 
    257  
    258         var.long_name=var.name=varname 
    259         if varname in ("standard_name_list",) or varname in ("badc_list",): 
    260             var.standard_name="name from the list***" 
    261  
    262  
    263         # Add a NASA Ames auxiliary variable number (for mapping correctly back to NASA Ames) 
    264         var.nasa_ames_aux_var_number=avar_number 
    265  
    266         return var         
    267  
    268     def createCdmsAxes(self):  
    269         """ 
    270         Creates cdms axes from information provided in the NASA Ames dictionary. 
    271         """ 
    272         if sys.platform.find("win")>-1: 
    273             raise NAPlatformError 
    274         if not hasattr(self, 'cdmsAxes'):         
    275             self.cdmsAxes=[] 
    276         for ivar_number in range(self.NIV): 
    277             self.cdmsAxes.append(self.toCdmsAxis(ivar_number)) 
    278  
    279     def toCdmsAxis(self, ivar_number): 
    280         """ 
    281         Creates a cdms axis from a NASA Ames independent variable. 
    282         """ 
    283         if sys.platform.find("win")>-1: 
    284             raise NAPlatformError 
    285  
    286         if self._normalizedX=="no": self._normalizeIndVars() 
    287  
    288         if self.NIV==1: 
    289             array=self.X 
    290         else: 
    291             array=self.X[ivar_number] 
    292         axis=cdms.createAxis(array) 
    293         axis.id=axis.name=axis.long_name=self.XNAME[ivar_number] 
    294         (varname, units)=self.getIndependentVariable(ivar_number) 
    295          
    296         # Sort units etc 
    297         if units:   axis.units=units 
    298         if len(varname)<20: 
    299             axis.id=safe_nc_id.sub("_", varname).lower() 
    300         else: 
    301             axis.id="naAuxVariable_%s" % (ivar_number) 
    302  
    303         if units: axis.units=units 
    304         axis_types=("longitude", "latitude", "level", "time") 
    305         designators={"longitude":axis.designateLongitude, "latitude":axis.designateLatitude, 
    306                      "level":axis.designateLevel, "time":axis.designateTime} 
    307         for axis_type in axis_types: 
    308             if re.search(axis_type, varname, re.IGNORECASE): 
    309                 axis.standard_name=axis.id=axis_type 
    310                 apply(designators[axis_type.lower()]) 
    311                 # Check warning for time units pattern 
    312                 if axis.isTime() and (not hasattr(axis, "units") or not time_units_pattn.match(axis.units)): 
    313                     if self.time_units==None: 
    314                      
    315                         timeUnitsInput="I WON'T MATCH" 
    316                         while timeUnitsInput!="" and not time_units_pattn.match(timeUnitsInput): 
    317                             message="""\nWARNING: Could not recognise time units. For true NetCDF compability 
     36safe_nc_id = re.compile("[\/\s\[\(\)\]\=\+\-\?\#\~\@\&\$\%\!\*\{\}\^]+") 
     37time_units_pattn = re.compile("\w+\s+since\s+\d{4}-\d{1,2}-\d{1,2}\s+\d+:\d+:\d+") 
     38max_id_length = 40 
     39special_comment_known_strings = ("###NASA Ames Special Comments follow###",  
     40                                     "###NASA Ames Special Comments end###",   
     41                                  "Additional Variable Attributes defined in the source file and not translated elsewhere:", 
     42                                  "Additional Global Attributes defined in the source file and not translated elsewhere:", "\n") 
     43 
     44normal_comment_known_strings = ("###NASA Ames Normal Comments follow###",  
     45                                "###NASA Ames Normal Comments end###",  
     46                                "###Data Section begins on the next line###", 
     47                                            "Additional Variable Attributes defined in the source file and not translated elsewhere:", 
     48                                                "Additional Global Attributes defined in the source file and not translated elsewhere:",  
     49                                "\n") 
     50 
     51time_units_warning_message = """\nWARNING: Could not recognise time units. For true NetCDF compability 
    31852please insert the correct time unit string below in the format: 
    31953     
     
    32458    <YYYY> is the year, <MM> is the month, <DD> is the day, 
    32559    <hh> is the hour, <mm> is minutes, <ss> is seconds. 
    326 """                          
    327                             if self.time_warning=="yes": 
    328                                 print message 
    329                                 timeUnitsInput=raw_input("Please insert your time unit string here (or leave blank):").strip() 
    330                             else:  
    331                                 timeUnitsInput="" 
    332                                 self.outputMessage.append(message) 
    333                         if timeUnitsInput!="": 
    334                             self.time_units=timeUnitsInput 
    335  
    336                     axis.units=self.time_units 
    337                     axis.long_name=axis.name="time (%s)" % self.time_units 
    338                     if axis.units==None:   
    339                         if units: 
    340                             axis.units=units     
    341                         else: 
    342                             axis.units="Not known" 
     60""" 
     61 
     62class NADictToCdmsObjects: 
     63    """ 
     64    Converts a NA File instance to a tuple of CDMS objects. 
     65    """ 
     66     
     67    def __init__(self, na_file_obj, variables="all", aux_variables="all", 
     68                 global_attributes={"Conventions":"CF-1.0"}, 
     69                 time_units=None, time_warning=True,  
     70                 rename_variables={}): 
     71        """ 
     72        Sets up instance variables. 
     73        """ 
     74        self.na_file_obj = na_file_obj      
     75        self.variables = variables 
     76        self.aux_variables = aux_variables 
     77        self.global_attributes = global_attributes 
     78        self.time_units = time_units 
     79        self.time_warning = time_warning 
     80        self.rename_variables = rename_variables 
     81 
     82        # Check if we have capability to convert this FFI 
     83        if self.na_file_obj.ffi in (2110, 2160, 2310):  
     84                raise Exception("Cannot convert NASA Ames File Format Index (FFI) " + `self.na_file_obj.ffi` + " to CDMS objects. No mapping implemented yet.") 
     85 
     86        self.output_message = []  # for output printing message 
     87        self.converted = False 
     88 
     89    def convert(self): 
     90        """ 
     91        Reads the NASA Ames file object and converts to CDMS objects. 
     92        Returns (variable_list, aux_variable_list, global_attribute_dict). 
     93        All these can be readily written to a CDMS File object. 
     94        """ 
     95        if self.converted == True: 
     96            print "Already converted to CDMS objects." 
     97            return (self.cdms_variables, self.cdms_aux_variables, self.global_attributes) 
     98 
     99        self.na_file_obj.readData() 
     100        #self.cdms_filename = filename 
     101        #self.cdms_file = cdms.open(self.cdms_filename, 'w') 
     102         
     103        # at file level: write global attributes 
     104        #for key in global_attributes.keys(): 
     105        #    setattr(self.cdms_file, key, global_attributes[key]) 
     106 
     107        # Convert global attribute 
     108        self._mapNACommentsToGlobalAttributes() 
     109 
     110        # Convert axes 
     111        if not hasattr(self, 'cdms_axes'):  self._convertCdmsAxes() 
     112 
     113        # Convert main variables 
     114        if not hasattr(self, 'cdms_variables'):  self._convertCdmsVariables() 
     115        #for var in self.cdms_variables: 
     116        #    self.cdms_file.write(var) 
     117 
     118        # Then do auxiliary variables 
     119        if hasattr(self, "NAUXV") and (type(self.NAUXV) == type(1) and self.NAUXV > 0):   # Are there any auxiliary variables? 
     120            if not hasattr(self, 'cdms_aux_variables'):   
     121                self._convertCdmsAuxVariables() 
     122             
     123            #for avar in self.cdms_aux_variables: 
     124            #    self.cdms_file.write(avar) 
     125 
     126        #self.cdms_file.close() 
     127        #rt = "cdms_file '%s' written successfully." % self.cdms_filename 
     128        self.converted = True 
     129        return (self.cdms_variables, self.cdms_aux_variables, self.global_attributes) 
     130 
     131 
     132    def _mapNACommentsToGlobalAttributes(self): 
     133        """ 
     134        Maps the NASA Ames comments section to global attributes and append them to the  
     135        self.global_attributes dictionary. 
     136        """ 
     137         
     138        for key in na_to_nc_map.keys(): 
     139 
     140            if type(key) == type((1,2)): 
     141 
     142                if key == ("SCOM", "NCOM"): 
     143                    # Map special and normal comments into the global comments section 
     144                    comment_line = "" 
     145 
     146                    # Add Special comments first 
     147                    if self.na_file_obj.NSCOML > 0: 
     148                        comment_line += "###NASA Ames Special Comments follow###\n" 
     149 
     150                        for i in self.na_file_obj.SCOM:  
     151                             
     152                            if i.strip() not in special_comment_known_strings: 
     153                                comment_line += ("\n" + i) 
     154                             
     155                        comment_line += "\n###NASA Ames Special Comments end###\n" 
     156 
     157                    # Now add normal comments 
     158                    if self.na_file_obj.NNCOML > 0: 
     159                        comment_line += "###NASA Ames Normal Comments follow###\n" 
     160 
     161                        for i in self.na_file_obj.NCOM:  
     162                            if i.strip() not in normal_comment_known_strings: 
     163                                comment_line += ("\n" + i) 
     164 
     165                        comment_line += "\n###NASA Ames Normal Comments end###" 
     166 
     167                    # Tidy comment line then write to global atts dict 
     168                    comment_line = comment_line.replace("\n\n", "\n") 
     169                    #self.cdms_file.comment = comment_line 
     170                    self.global_attributes["comment"] = comment_line 
     171 
     172                elif key == ("ONAME", "ORG"): 
     173                    # Map the two organisation NA files to the institution field in CDMS (NetCDF) 
     174                    institution = "%s (ONAME from NASA Ames file); %s (ORG from NASA Ames file)." % \ 
     175                                         (self.na_file_obj.ONAME, self.na_file_obj.ORG) 
     176                    self.global_attributes["institution"] = institution 
     177                    #self.cdms_file.institution = "%s (ONAME from NASA Ames file); %s (ORG from NASA Ames file)." % (self.na_file_obj.ONAME, self.na_file_obj.ORG) 
     178 
     179                else: 
     180                    # Any other strange tuple just gets merged into a string 
     181                        item = (getattr(self.na_file_obj, key[0])) + "\n" + (getattr(self.na_file_obj, key[1])) 
     182                    # setattr(self.cdms_file, cdms_map.fromNA[key], item) 
     183                    self.global_attributes[na_to_nc_map[key]] = item 
     184 
     185            elif key == "RDATE": 
     186                # RDATE = Revision date - update this and put in history global attribute 
     187                date_parts = getattr(self.na_file_obj, "RDATE") 
     188                date_string = "%.4d-%.2d-%.2d" % tuple(date_parts) 
     189                hist = date_string + " - NASA Ames File created/revised.\n" 
     190                time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) 
     191                version = nappy.utils.getVersion() 
     192                hist = "%s\n%s - Converted to CDMS (NetCDF) format using nappy-%s." % (hist, time_string, version) 
     193                # self.cdms_file.history = hist 
     194                print "DIDNT HAVE MAPPING SO PUT HISTORY IN LINE 160 IN na_to_cdms.py" 
     195                self.global_attributes["history"] = hist 
     196            else: 
     197                # Anything else just needs to be stored as a global attribute 
     198                # setattr(self.cdms_file, cdms_map.fromNA[key], getattr(self, key)) 
     199                self.global_attributes[na_to_nc_map[key]] = getattr(self.na_file_obj, key) 
     200 
     201 
     202    def _convertCdmsVariables(self): 
     203        """ 
     204        Creates cdms variable list for writing out. 
     205        """ 
     206        self.cdms_variables = [] 
     207 
     208        if self.variables == "all":     
     209            for var_number in range(self.NV): 
     210            self.cdms_variables.append(self._convertNAToCdmsVariable(var_number)) 
     211        else: 
     212            if type(self.variables[0]) == type(1): # They are integers = indices 
     213                for var_number in self.variables: 
     214                    self.cdms_variables.append(self._convertNAToCdmsVariable(var_number))    
     215            elif type(self.variables[0]) == type("string"):  # Vars are strings 
     216                for var_name in self.variables: 
     217                    if var_name in self.VNAME: 
     218                        var_number = self.VNAME.index(var_name) 
     219                        self.cdms_variables.append(self._convertNAToCdmsVariable(var_number)) 
     220                    else: 
     221                        raise Exception("Variable name not known: " + var_name) 
     222 
     223 
     224    def _convertNAToCdmsVariable(self, var_number, attributes={}): 
     225        """ 
     226        Creates a single cdms variable from the variable number provided in the list. 
     227        """ 
     228        (var_name, units, miss, scal) = self.na_file_obj.getVariable(var_number) 
     229        msg = "\nAdding variable: %s" % self.na_file_obj.VNAME[var_number] 
     230        print msg 
     231        self.output_message.append(msg) 
     232        array = Numeric.array(self.na_file_obj.V[var_number]) 
     233        array = array * scal 
     234        # Set up axes 
     235        if not hasattr(self, 'cdms_axes'): 
     236            self._convertCdmsAxes() 
     237 
     238        # Set up variable 
     239        var=cdms.createVariable(array, axes=self.cdms_axes, fill_value=miss, attributes=attributes) 
     240 
     241        # Sort units etc 
     242        if units:   var.units=units 
     243         
     244        # Add the best variable name 
     245        if len(var_name) < max_id_length: 
     246            var.id=safe_nc_id.sub("_", var_name).lower() 
     247        else: 
     248            var.id="naVariable_%s" % (var_number) 
     249         
     250             # Check if mapping provided for renaming this variable 
     251        if var_name in self.rename_variables.keys(): 
     252            var_name = self.rename_variables[var_name] 
     253             
     254        var.long_name = var.name = var.title = var_name 
     255 
     256        # Add a NASA Ames variable number (for mapping correctly back to NASA Ames) 
     257        var.nasa_ames_var_number = var_number 
     258        return var 
     259 
     260    def _convertCdmsAuxVariables(self): 
     261        """ 
     262        Creates a cdms variable from an auxiliary variable 
     263        """ 
     264        self.cdms_aux_variables = [] 
     265 
     266        if self.aux_variables == "all":     
     267            for avar_number in range(self.NAUXV): 
     268                self.cdms_aux_variables.append(self._convertNAAuxToCdmsVariable(avar_number)) 
     269        else: 
     270            if type(self.aux_variables[0]) == type(1): # They are integers = indices 
     271                for avar_number in self.aux_variables: 
     272                    self.cdms_aux_variables.append(self._convertNAAuxToCdmsVariable(avar_number))    
     273 
     274            elif type(self.aux_variables[0]) == type("string"): # They are strings 
     275                for avar_name in self.aux_variables: 
     276                    if avar_name in self.ANAME: 
     277                        avar_number = self.ANAME.index(avar_name) 
     278                        self.cdms_aux_variables.append(self._convertNAAuxToCdmsVariable(avar_number))  
     279            else: 
     280                raise Exception("Auxiliary variable name not known: " + avar_name)           
     281 
     282    def _convertNAAuxToCdmsVariable(self, avar_number, attributes={}): 
     283        """ 
     284        Converts an auxiliary variable to a cdms variable. 
     285        """ 
     286        (var_name, units, miss, scal) = self.na_file_obj(avar_number) 
     287        array = Numeric.array(self.na_file_obj.A[avar_number]) 
     288        array = array * scal 
     289 
     290        msg="\nAdding auxiliary variable: %s" % self.na_file_obj.ANAME[avar_number] 
     291        print msg 
     292        self.output_message.append(msg) 
     293 
     294        # Set up axes 
     295        if not hasattr(self, 'cdms_axes'): 
     296            self._convertCdmsAxes() 
     297 
     298        # Set up variable 
     299        var = cdms.createVariable(array, axes=[self.cdms_axes[0]], fill_value=miss,  
     300                                  attributes=attributes) 
     301 
     302        # Sort units etc 
     303        if units:   var.units = units 
     304        if len(var_name) < max_id_length: 
     305            var.id = safe_nc_id.sub("_", var_name).lower() 
     306        else: 
     307            var.id = "naAuxVariable_%s" % (avar_number) 
     308 
     309            # Check if mapping provided for renaming this variable 
     310        if var_name in self.rename_variables.keys(): 
     311            var_name = self.rename_variables[var_name] 
     312 
     313        var.long_name = var.name = var.title = var_name 
     314 
     315        # Add a NASA Ames auxiliary variable number (for mapping correctly back to NASA Ames) 
     316        var.nasa_ames_aux_var_number = avar_number 
     317        return var         
     318 
     319    def _convertCdmsAxes(self):  
     320        """ 
     321        Creates cdms axes from information provided in the NASA Ames dictionary. 
     322        """ 
     323        if not hasattr(self, 'cdms_axes'):         
     324            self.cdms_axes = [] 
     325 
     326        for ivar_number in range(self.na_file_obj.NIV): 
     327            self.cdms_axes.append(self._convertNAIndVarToCdmsAxis(ivar_number)) 
     328 
     329    def _convertNAIndVarToCdmsAxis(self, ivar_number): 
     330        """ 
     331        Creates a cdms axis from a NASA Ames independent variable. 
     332        """ 
     333        if self._normalizedX == "no": self.na_file_obj._normalizeIndVars() 
     334 
     335        if self.na_file_obj.NIV == 1: 
     336            array = self.na_file_obj.X 
     337        else: 
     338            array = self.na_file_obj.X[ivar_number] 
     339 
     340        axis = cdms.createAxis(array) 
     341        axis.id = axis.name = axis.long_name = self.na_file_obj.XNAME[ivar_number] 
     342        (var_name, units) = self.getIndependentVariable(ivar_number) 
     343         
     344        # Sort units etc 
     345        if units:   axis.units = units 
     346        if len(var_name) < max_id_length: 
     347            axis.id = safe_nc_id.sub("_", var_name).lower() 
     348        else: 
     349            axis.id = "naAuxVariable_%s" % (ivar_number) 
     350 
     351        if units: axis.units = units 
     352 
     353        axis_types = ("longitude", "latitude", "level", "time") 
     354 
     355        for axis_type in axis_types: 
     356            if re.search(axis_type, var_name, re.IGNORECASE): 
     357                axis.standard_name = axis.id = axis_type 
     358                # Designate it CF-style if known axis type (e.g. axis.designateTime() etc..) 
     359                exec "axis.designate%s()" % axis_type.title() 
     360                print "CHECK AXIS GOT DESIGNATED PROPERLY - RE-FACTORED" * 5 
     361 
     362        # Check warning for time units pattern 
     363        if axis.isTime() and (not hasattr(axis, "units") or not time_units_pattn.match(axis.units)): 
     364            if self.time_units == None: 
     365                time_units_input = "I WON'T MATCH" 
     366 
     367                while time_units_input != "" and not time_units_pattn.match(time_units_input): 
     368                    message = time_units_warning_message                             
     369                    if self.time_warning == True: 
     370                        print message 
     371                        time_units_input = raw_input("Please insert your time unit string here (or leave blank):").strip() 
     372                    else:  
     373                        time_units_input = "" 
     374                    self.output_message.append(message) 
     375 
     376                        self.time_units = time_units_input 
     377 
     378                    axis.units = self.time_units 
     379            axis.long_name = axis.name = "time (%s)" % self.time_units 
     380 
     381        if axis.units == None:   
     382            if units: 
     383                axis.units = units       
     384            else: 
     385                axis.units = "Not known" 
     386 
    343387        return axis 
    344  
    345  
    346 class NA2Cdms(NAToCdms): 
    347     """ 
    348     Pseudonym for NAToCdms class. 
    349     """ 
    350     pass 
  • nappy/trunk/nappy/utils/parse_config.py

    r3321 r3324  
    1212 
    1313# Global variables 
    14 config_file = os.environ["NAPPY_INI"] 
    15 wps_config_dict = None 
     14config_file = ".." + os.path.sep + "nappy.ini" 
     15config_dict = None 
    1616 
     17class MyCasePreservingConfigParser(ConfigParser.ConfigParser): 
     18    optionxform = str 
    1719 
    1820def makeConfigDict(cf=config_file): 
     
    2224    """ 
    2325    d = {} 
    24     conf = ConfigParser.ConfigParser() 
     26    conf = MyCasePreservingConfigParser() 
    2527    conf.read(cf) 
    2628 
     
    3335    for section in conf.sections(): 
    3436        d[section] = {} 
    35         for item in d.options(section): 
    36             d[section][item] = conf.get(section, item) 
     37        for item in conf.options(section): 
     38            value = conf.get(section, item) 
     39            if item.find("&") > -1: 
     40                item = tuple(item.split("&")) 
     41            if value.find("&") > -1: 
     42                value = tuple(value.split("&")) 
     43            d[section][item] = value 
    3744 
    3845    return d 
     
    4148def getConfigDict(cf=config_file): 
    4249    "Checks if already made and only makes if required." 
    43     global wps_config_dict 
    44     if wps_config_dict == None: 
    45         wps_config_dict = makeConfigDict(cf) 
    46     return wps_config_dict 
     50    global config_dict 
     51    if config_dict == None: 
     52        config_dict = makeConfigDict(cf) 
     53    return config_dict 
    4754 
    4855 
Note: See TracChangeset for help on using the changeset viewer.