Changeset 3347 for nappy


Ignore:
Timestamp:
09/02/08 19:43:49 (12 years ago)
Author:
astephen
Message:

Splitting up cdms to na stuff into more modules to make more readable.

Location:
nappy/trunk/nappy/nc_interface
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • nappy/trunk/nappy/nc_interface/cdms_to_na.py

    r3345 r3347  
    1 #!/usr/bin/env python 
    21#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ). 
    32#   This software may be distributed under the terms of the 
     
    2322import nappy.utils 
    2423import nappy.utils.common_utils 
     24import nappy.cdms_utils.var_utils 
    2525import nappy.na_file.na_core 
    26  
    2726 
    2827nc_to_na_map = utils.getConfigDict()["nc_to_na_map"] 
     
    3837cdms.setAutoBounds("off")  
    3938 
    40 compareAxes = nappy.cdms_utils.axis_utils.compareAxes 
    41 compareVariables = nappy.cdms_utils.var_utils.compareVariables 
    42 arrayToList = nappy.utils.list_manipulator.arrayToList 
    43 listOfListsCreator = nappy.utils.list_manipulator.listOfListsCreator 
    44 getBestName = nappy.cdms_utils.var_utils.getBestName 
    45 getMissingValue = nappy.cdms_utils.var_utils.getMissingValue 
    46 flatten2DTimeAxis = nappy.contrib.aircraft.aircraft_utils.flatten2DTimeAxis 
    47 modifyNADictCopy = nappy.utils.common_utils.modifyNADictCopy 
    48  
    49  
    5039cdms2na - 200 lines of code to do main conversion, needs to be split out into other stuff. 
    5140 * getVariableCollections(f and varlist) --> (ordered_vars, other_vars) 
     
    5342 * writeToOutputFiles() 
    5443 
    55 class CdmsToNABuilder --> NAContentCollector: (naDict, varIDs, varBin) 
    56 __init__ --> sets everything up and runs it move some to --> analyse() 
    57 analyseVariables 
    58 defineNAVars 
    59 defineNAAuxVars 
    60 getAxisDefinition 
    61 defineNAGlobals 
    62 defineNAComments 
    63 defineGeneralHeader 
     44 
    6445 
    6546def cdms2na(ncfile, na_file_names, naVars={}, variables=None, nFilesOnly="no",  
     
    7657    allowed_overwrite_metadata = ("DATE",  "RDATE", "ANAME", "MNAME", 
    7758           "ONAME", "ORG", "SNAME", "VNAME") 
    78     arrayArgs=["DATE", "RDATE", "ANAME", "VNAME"] 
    79     # ANAME[a] - array of 'a' x ANAME strings - aux var names 
    80     # DATE (array of three) - UT date at which the data within the file starts  
    81     # MNAME - mission name  
    82     # ONAME - name of originator(s)  
    83     # ORG - org or affiliation of originator(s)  
    84     # RDATE (array of three) - date of data reduction or revision  
    85     # SNAME - source of measurement or model output VNAME[n] - array of 'n' x  
    86     # VNAME strings - var names. 
    87     output_message=[] 
    88     msg="Reading data from: %s\n" % infilename 
     59    array_args = ["DATE", "RDATE", "ANAME", "VNAME"] 
     60    output_message = [] 
     61    msg = "Reading data from: %s\n" % infilename 
    8962    print msg 
    9063    output_message.append(msg) 
    91     cdms_file=cdms.open(infilename) 
    92     globals=cdms_file.attributes 
    93      
    94     vars=[] 
     64    cdms_file = cdms.open(infilename) 
     65    globals = cdms_file.attributes 
     66     
     67    vars = [] 
    9568    if not variables: 
    96         variables=cdms_file.listvariables() 
     69        variables = cdms_file.listvariables() 
    9770        #for var in cdms_file.listvariables(): 
    9871            #vars.append(cdms_file(var))     
    9972             
    10073    for variable in variables: 
    101         varObj=cdms_file(variable) 
     74        varObj = cdms_file(variable) 
    10275        # Deal with singleton variables 
    10376        if not hasattr(varObj, "rank"): 
    104                 varMetadata=cdms_file[variable].attributes 
    105                 varValue=varObj 
     77                varMetadata = cdms_file[variable].attributes 
     78                varValue = varObj 
    10679                #print varMetadata, varValue, varMetadata.keys(), varMetadata._obj_.id 
    107                 varObj=cdms.createVariable(Numeric.array(varObj), id=getBestName(varMetadata).replace(" ", "_"), attributes=varMetadata) 
     80                varObj = cdms.createVariable(Numeric.array(varObj), id=nappy.cdms_utils.var_utils.getBestName(varMetadata).replace(" ", "_"), attributes=varMetadata) 
    10881                #print varObj, dir(varObj); sys.exit() 
    109                 varObj.value=varObj._data[0] 
    110                 #varObj.rank=0 
     82                varObj.value = varObj._data[0] 
     83                #varObj.rank = 0 
    11184                 
    11285        #print varObj, varObj.attributes                          
     
    11487         
    11588    # Re-order variables if they have the attribute 'nasa_ames_var_number' 
    116     ordered_vars=[None]*1000 
    117     otherVars=[] 
     89    ordered_vars = [None] * 1000 
     90    other_vars = [] 
    11891    for var in vars: 
    119         varMetadata=cdms_file[var] 
     92        varMetadata = cdms_file[var] 
    12093        if hasattr(varMetadata, "nasa_ames_var_number"): 
    121             num=varMetadata.nasa_ames_var_number 
    122             ordered_vars[num]=var 
     94            num = varMetadata.nasa_ames_var_number 
     95            ordered_vars[num] = var 
    12396        else: 
    124             otherVars.append(var) 
    125      
    126     vars=[] 
     97            other_vars.append(var) 
     98     
     99    vars = [] 
    127100    for var in ordered_vars: 
    128         if var!=None: 
     101        if var != None: 
    129102            vars.append(var) 
    130103             
    131     vars=vars+otherVars 
    132      
    133     builder=NAContentCollector(vars, globals, rule=rule, cdms_file=cdms_file) 
     104    vars = vars + other_vars 
     105     
     106    builder = NAContentCollector(vars, globals, rule=rule, cdms_file=cdms_file) 
    134107    #print builder.naDict["X"] 
    135     builtNADicts=[[builder.naDict, builder.varIDs]] 
    136     if builder.varIDs==None: 
    137         msg="\nNo files created after variables parsed." 
     108    builtNADicts = [[builder.naDict, builder.varIDs]] 
     109    if builder.varIDs == None: 
     110        msg = "\nNo files created after variables parsed." 
    138111        print msg 
    139112        output_message.append(msg) 
    140113        return output_message 
    141114 
    142     while len(builder.varBin)>0: 
    143         builder=NAContentCollector(builder.varBin, globals, rule=rule, cdms_file=cdms_file) 
    144         output_message=output_message+builder.output_message 
    145         if builder.varIDs!=None:  builtNADicts.append([builder.naDict, builder.varIDs]) 
     115    while len(builder.varBin) > 0: 
     116        builder = NAContentCollector(builder.varBin, globals, rule=rule, cdms_file=cdms_file) 
     117        output_message = output_message + builder.output_message 
     118        if builder.varIDs != None:  builtNADicts.append([builder.naDict, builder.varIDs]) 
    146119 
    147120    # Return only filenames if only want to know them now. 
    148     ncount=1 
    149     fileNames=[] 
    150     if nFilesOnly=="yes":  
     121    ncount = 1 
     122    fileNames = [] 
     123    if nFilesOnly == "yes":  
    151124        for i in builtNADicts: 
    152             if len(builtNADicts)==1: 
    153                 suffix="" 
     125            if len(builtNADicts) == 1: 
     126                suffix = "" 
    154127            else: 
    155                 suffix="_%s" % ncount 
    156             nameparts=outfilenames[0].split(".")     
    157             newname=(".".join(nameparts[:-1]))+suffix+"."+nameparts[-1] 
     128                suffix = "_%s" % ncount 
     129            nameparts = outfilenames[0].split(".")     
     130            newname = (".".join(nameparts[:-1])) + suffix + "." + nameparts[-1] 
    158131            fileNames.append(newname) 
    159         ncount=ncount+1 
     132        ncount = ncount + 1 
    160133             
    161134        return fileNames 
    162135                 
    163     msg="\n%s files to write" % len(builtNADicts) 
     136    msg = "\n%s files to write" % len(builtNADicts) 
    164137    print msg 
    165138    output_message.append(msg) 
    166139 
    167     count=1 
    168     ncount=1 
     140    count = 1 
     141    ncount = 1 
    169142    for i in builtNADicts: 
    170         if len(outfilenames)==1: 
    171             if len(builtNADicts)==1: 
    172                 suffix="" 
     143        if len(outfilenames) == 1: 
     144            if len(builtNADicts) == 1: 
     145                suffix = "" 
    173146            else: 
    174                 suffix="_%s" % ncount 
    175             nameparts=outfilenames[0].split(".")     
    176             newname=(".".join(nameparts[:-1]))+suffix+"."+nameparts[-1] 
     147                suffix = "_%s" % ncount 
     148            nameparts = outfilenames[0].split(".")     
     149            newname = (".".join(nameparts[:-1])) + suffix + "." + nameparts[-1] 
    177150        else: 
    178             newname=outfilenames[count-1] 
     151            newname = outfilenames[count - 1] 
    179152  
    180         msg="\nWriting output NASA Ames file: %s" % newname 
     153        msg = "\nWriting output NASA Ames file: %s" % newname 
    181154        print msg 
    182155        output_message.append(msg) 
    183156         
    184         builtNADict=i[0] 
     157        builtNADict = i[0] 
    185158        for key in naVars.keys(): 
    186159            if key in allowed_overwrite_metadata: 
    187160             
    188                 if key in arrayArgs: 
    189                     newItem=naVars[key].split()             
     161                if key in array_args: 
     162                    newItem = naVars[key].split()                   
    190163                else: 
    191                     newItem=naVars[key] 
     164                    newItem = naVars[key] 
    192165                                     
    193                 if newItem!=builtNADict[key]: 
    194                     builtNADict[key]=newItem 
    195                     msg="Metadata overwritten in output file: '%s' is now '%s'" % (key, builtNADict[key]) 
     166                if newItem != builtNADict[key]: 
     167                    builtNADict[key] = newItem 
     168                    msg = "Metadata overwritten in output file: '%s' is now '%s'" % (key, builtNADict[key]) 
    196169                    print msg 
    197170                    output_message.append(msg) 
    198171         
    199         fileList=[] 
     172        fileList = [] 
    200173        # Cope with size limits if specified and FFI is 1001 
    201         if size_limit and (builtNADict["FFI"]==1001 and len(builtNADict["V"][0])>size_limit): 
    202             varList=builtNADict["V"] 
    203             arrayLength=len(varList[0]) 
    204             nvolInfo=divmod(arrayLength, size_limit) 
    205             nvol=nvolInfo[0] 
    206             if nvolInfo[1]>0: nvol=nvol+1 
    207             start=0 
    208             letterCount=0 
    209             ivol=0 
    210             while start<arrayLength: 
    211                 ivol=ivol+1 
    212                 end=start+size_limit 
    213                 if end>arrayLength: 
    214                     end=arrayLength 
    215                 currentBlock=[] 
     174        if size_limit and (builtNADict["FFI"] == 1001 and len(builtNADict["V"][0]) > size_limit): 
     175            varList = builtNADict["V"] 
     176            arrayLength = len(varList[0]) 
     177            nvolInfo = divmod(arrayLength, size_limit) 
     178            nvol = nvolInfo[0] 
     179            if nvolInfo[1] > 0: nvol = nvol + 1 
     180            start = 0 
     181            letterCount = 0 
     182            ivol = 0 
     183            while start < arrayLength: 
     184                ivol = ivol + 1 
     185                end = start + size_limit 
     186                if end > arrayLength: 
     187                    end = arrayLength 
     188                currentBlock = [] 
    216189                # Write new V array 
    217190                for v in varList: 
     
    219192 
    220193                # Adjust X accordingly 
    221                 NADictCopy=modifyNADictCopy(builtNADict, currentBlock, start, end, ivol, nvol) 
     194                NADictCopy = nappy.utils.common_utils.modifyNADictCopy(builtNADict, currentBlock, start, end, ivol, nvol) 
    222195                 
    223196                # Write data to output file 
    224                 newnamePlusLetter="%s-%.3d.na" % (newname[:-3], ivol) 
     197                newnamePlusLetter = "%s-%.3d.na" % (newname[:-3], ivol) 
    225198                fileList.append(newnamePlusLetter) 
    226199                general.openNAFile(newnamePlusLetter, 'w', NADictCopy, spacer=spacer, floatFormat=floatFormat) 
    227                 msg="\nOutput files split on size limit: %s\nFilename used: %s" % (size_limit, newnamePlusLetter) 
     200                msg = "\nOutput files split on size limit: %s\nFilename used: %s" % (size_limit, newnamePlusLetter) 
    228201                print msg 
    229202                output_message.append(msg) 
    230                 letterCount=letterCount+1 
    231                 start=end 
     203                letterCount = letterCount + 1 
     204                start = end 
    232205 
    233206 
     
    235208            general.openNAFile(newname, 'w', builtNADict, spacer=spacer, floatFormat=floatFormat) 
    236209 
    237         msg="\nWrote the following variables:"+"\n\t"+("\n\t".join(i[1][0])) 
     210        msg = "\nWrote the following variables:" + "\n\t" + ("\n\t".join(i[1][0])) 
    238211        print msg 
    239212        output_message.append(msg) 
    240213         
    241         if len(i[1][1])>0: 
    242             msg="\nWrote the following auxiliary variables:" 
    243             msg=msg+"\n\t"+("\n\t".join(i[1][1]))        
    244              
    245         if len(i[1][2])>0: 
    246             msg="\nWrote the following Singleton variables:" 
    247             msg=msg+"\n\t"+("\n\t".join(i[1][2])) 
    248  
    249         if len(fileList)>0: 
    250             msg=msg+("\n\nNASA Ames files written successfully: \n%s" % "\n".join(fileList)) 
    251             count=count+len(fileList) 
     214        if len(i[1][1]) > 0: 
     215            msg = "\nWrote the following auxiliary variables:" 
     216            msg = msg + "\n\t" + ("\n\t".join(i[1][1]))  
     217             
     218        if len(i[1][2]) > 0: 
     219            msg = "\nWrote the following Singleton variables:" 
     220            msg = msg + "\n\t" + ("\n\t".join(i[1][2])) 
     221 
     222        if len(fileList) > 0: 
     223            msg = msg + ("\n\nNASA Ames files written successfully: \n%s" % "\n".join(fileList)) 
     224            count = count + len(fileList) 
    252225        else: 
    253             msg=msg+"\n\nNASA Ames file written successfully: %s" % newname 
    254             count=count+1 
    255         ncount=ncount+1 
     226            msg = msg + "\n\nNASA Ames file written successfully: %s" % newname 
     227            count = count + 1 
     228        ncount = ncount + 1 
    256229 
    257230        print msg 
    258231        output_message.append(msg) 
    259232             
    260     if (count-1)==1: 
    261         plural="" 
     233    if (count - 1) == 1: 
     234        plural = "" 
    262235    else: 
    263         plural="s"             
    264     msg="\n%s file%s written." % ((count-1), plural) 
     236        plural = "s"           
     237    msg = "\n%s file%s written." % ((count - 1), plural) 
    265238    print msg 
    266239    output_message.append(msg) 
    267240    return output_message 
    268241 
    269  
    270 class NAContentCollector(NACore): 
    271     """ 
    272     Class to build a NASA Ames File object from a set of  
    273     CDMS variables and global attributes (optional). 
    274     """ 
    275      
    276     def __init__(self, vars, global_attributes={}, cdms_file=None): 
    277         """ 
    278         Sets up instance variables and calls appropriate methods to 
    279         generate sections of NASA Ames file object. 
    280         """ 
    281         self.cdms_file=cdms_file 
    282         self.output_message=[] 
    283         self.na_dict={} 
    284         self.vars=vars 
    285         self.var_ids=None 
    286         self.globals=global_attributes   
    287         self.rank_zero_vars=[] 
    288         self.rank_zero_var_ids=[] 
    289         (self.ordered_vars, auxVars)=self.analyseVariables() 
    290         if self.ordered_vars==None: 
    291             self.var_bin=[] 
    292         else: 
    293  
    294             self.var_ids=[[var.id for var in self.ordered_vars],[var.id for var in auxVars], self.rank_zero_var_ids] 
    295          
    296             self.na_dict["NLHEAD"]="-999" 
    297          
    298             #print [var.id for var in self.ordered_vars] 
    299             #print [var.rank() for var in self.ordered_vars]     
    300             self.defineNAVars(self.ordered_vars) 
    301             self.defineNAAuxVars(auxVars) 
    302             self.defineNAGlobals() 
    303             self.defineNAComments() 
    304             self.defineGeneralHeader() 
    305             # Quick fudge 
    306             if self.na_dict["FFI"]==1001: self.na_dict["X"]=self.na_dict["X"][0] 
    307  
    308  
    309     def analyseVariables(self): 
    310         """ 
    311         Method to examine the content of CDMS variables to return 
    312         a tuple of two lists containing variables and auxiliary variables 
    313         for the NASA Ames file object. 
    314         Variables not compatible with the first file are binned to be used next. 
    315         """ 
    316         # Need to group the variables together in bins 
    317         self.var_bin=[] 
    318         # Get largest ranked variable as the one we use as standard 
    319         highrank=-1 
    320         best_var=None 
    321         count=0 
    322         for var in self.vars: 
    323             msg="Analysing: %s" % var.id 
    324             print msg 
    325             self.output_message.append(msg) 
    326             count=count+1 
    327  
    328             # get rank 
    329             rank=var.rank() 
    330  
    331             # Deal with singleton variables 
    332             if rank==0:  
    333                 self.rank_zero_vars.append(var) 
    334                 self.rank_zero_var_ids.append(var.id) 
    335                 continue 
    336              
    337             if rank>highrank: 
    338                 highrank=rank 
    339                 best_var=var 
    340                 best_var_index=count 
    341             elif rank==highrank: 
    342                 if len(var.flat)>len(best_var.flat): 
    343                     best_var=var 
    344                     best_var_index=count 
    345          
    346         if len(self.rank_zero_vars)==len(self.vars):  return (None, None) 
    347         if not best_var:   
    348             print "No variables produced" 
    349             return (None, None) 
    350  
    351         vars4NA=[best_var] 
    352         auxVars4NA=[] 
    353         shape=best_var.shape 
    354         ndims=len(shape) 
    355         self.na_dict["NIV"]=ndims 
    356  
    357         # Work out which File Format Index is appropriate  
    358         if ndims in (2,3,4): 
    359             self.na_dict["FFI"]=10+(ndims*1000) 
    360         elif ndims>4: 
    361             raise "Cannot write variables defined against greater than 4 axes in NASA Ames format." 
    362         else: 
    363             if len(auxVars4NA)>0 or (self.na_dict.has_key("NAUXV") and self.na_dict["NAUXV"]>0): 
    364                 self.na_dict["FFI"]=1010 
    365             else: 
    366                 self.na_dict["FFI"]=1001 
    367         #print self.na_dict["FFI"] 
    368         axes=best_var.getAxisList() 
    369          
    370         # Get other variable info 
    371         #print [v.id for v in self.vars], best_var_index 
    372         #print [v.id for v in self.vars[:best_var_index-1]+self.vars[best_var_index:]] 
    373         for var in self.vars[:best_var_index-1]+self.vars[best_var_index:]: 
    374  
    375             #print self.rank_zero_vars 
    376             #for rzv in self.rank_zero_vars:   
    377             #    if var.id==rzv.id and var[0]==rzv[0]: continue 
    378             #print [v.id for v in self.rank_zero_vars] 
    379             if var.id in self.rank_zero_var_ids: continue 
    380             #print var.id, ndims, shape, len(var.shape), var.shape 
    381             if len(var.shape)!=ndims or var.shape!=shape:  
    382                 # Could it be an auxiliary variable  
    383                 if len(var.shape)!=1:  
    384                     self.var_bin.append(var) 
    385                     continue 
    386                 caxis=var.getAxis(0) 
    387                 if compareAxes(axes[0], caxis)==0:  
    388                     self.var_bin.append(var) 
    389                     continue 
    390                 # I think it is an auxiliary variable 
    391                 auxVars4NA.append(var)  
    392                 # Also put it in var bin because auxiliary vars might be useful 
    393                 self.var_bin.append(var) 
    394             else: 
    395                 caxes=var.getAxisList() 
    396                 #print var.id, "here" 
    397                 for i in range(ndims):             
    398                     if compareAxes(axes[i], caxes[i])==0: 
    399                         self.var_bin.append(var) 
    400                         continue 
    401                 # OK, I think they are compatible 
    402                 vars4NA.append(var) 
    403                  
    404         # Re-order if they previously came from NASA Ames files (i.e. including  
    405         # the attribute 'nasa_ames_var_number') 
    406         ordered_vars=[None]*1000 
    407         otherVars=[] 
    408         for var in vars4NA: 
    409             if hasattr(var, "nasa_ames_var_number"): 
    410                 ordered_vars[var.nasa_ames_var_number[0]]=var 
    411             else: 
    412                 otherVars.append(var) 
    413         # Remake vars4NA now in order 
    414         vars4NA=[] 
    415         for var in ordered_vars: 
    416             if var!=None: vars4NA.append(var) 
    417         vars4NA=vars4NA+otherVars 
    418  
    419         # Now re-order the Auxiliary variables if they previously came from NASA  
    420         # Ames files (i.e. including the attribute 'nasa_ames_aux_var_number') 
    421  
    422         orderedAuxVars=[None]*1000 
    423         otherAuxVars=[] 
    424         for var in auxVars4NA: 
    425             if hasattr(var, "nasa_ames_aux_var_number"): 
    426                 orderedAuxVars[var.nasa_ames_aux_var_number[0]]=var 
    427             else: 
    428                 otherAuxVars.append(var) 
    429         # Remake auxVars4NA now in order 
    430         auxVars4NA=[] 
    431         for var in orderedAuxVars: 
    432             if var!=None: auxVars4NA.append(var) 
    433         auxVars4NA=auxVars4NA+otherAuxVars       
    434         return (vars4NA, auxVars4NA) 
    435  
    436  
    437     def defineNAVars(self, vars): 
    438         """ 
    439         Method to define NASA Ames file object variables and their 
    440         associated metadata. 
    441         """ 
    442         self.na_dict["NV"]=len(vars) 
    443         self.na_dict["VNAME"]=[] 
    444         self.na_dict["VMISS"]=[] 
    445         self.na_dict["VSCAL"]=[] 
    446         self.na_dict["V"]=[] 
    447         for var in vars: 
    448             name=getBestName(var) 
    449             self.na_dict["VNAME"].append(name) 
    450             miss=getMissingValue(var) 
    451             if type(miss) not in (float, int, long):  miss=miss[0] 
    452             self.na_dict["VMISS"].append(miss) 
    453             #print self.na_dict["VMISS"] 
    454             self.na_dict["VSCAL"].append(1) 
    455             # AND THE ARRAY 
    456             # Populate the variable list   
    457             ######## NOTE - might not have to do this ##### 
    458             ######## It  might handle writing from a Numeric array ######## 
    459             self.na_dict["V"].append(var._data) 
    460             #listOfListsCreator(inlist, var.shape) 
    461             #arrayToList(var, inlist) 
    462  
    463             if not self.na_dict.has_key("X"): 
    464                 self.na_dict["NXDEF"]=[] 
    465                 self.na_dict["NX"]=[] 
    466                 # Create independent variable information 
    467                 #print var.id, var.getAxis(0) 
    468                 self.ax0=var.getAxis(0) 
    469                 self.na_dict["X"]=[list(self.ax0._data_)] 
    470                 self.na_dict["XNAME"]=[getBestName(self.ax0)] 
    471                 if len(self.ax0)==1: 
    472                     self.na_dict["DX"]=[0] 
    473                 else: 
    474                     incr=self.ax0[1]-self.ax0[0] 
    475                     # Set default increment as gap between first two 
    476                     self.na_dict["DX"]=[incr] 
    477                     # Now overwrite it as zero if non-uniform interval in axis 
    478                     for i in range(1, len(self.ax0)): 
    479                         if (self.ax0[i]-self.ax0[i-1])!=incr: 
    480                             self.na_dict["DX"]=[0] 
    481                             break 
    482  
    483                 # Now sort the rest of the axes 
    484                 for axis in var.getAxisList()[1:]: 
    485                     self.getAxisDefinition(axis) 
    486  
    487  
    488     def defineNAAuxVars(self, auxVars): 
    489         """ 
    490         Method to define NASA Ames file object auxiliary variables and their 
    491         associated metadata. 
    492         """ 
    493         self.na_dict["NAUXV"]=len(auxVars) 
    494         self.na_dict["ANAME"]=[] 
    495         self.na_dict["AMISS"]=[] 
    496         self.na_dict["ASCAL"]=[] 
    497         self.na_dict["A"]=[] 
    498         for var in auxVars: 
    499             name=getBestName(var) 
    500             self.na_dict["ANAME"].append(name) 
    501             miss=getMissingValue(var) 
    502             if type(miss)!=float:  miss=miss[0] 
    503             self.na_dict["AMISS"].append(miss) 
    504             self.na_dict["ASCAL"].append(1) 
    505             # AND THE ARRAY 
    506             # Populate the variable list   
    507             ######## NOTE - might not have to do this ##### 
    508             ######## It  might handle writing from a Numeric array ######## 
    509             self.na_dict["A"].append(var._data) 
    510             #listOfListsCreator(inlist, var.shape) 
    511             #arrayToList(var, inlist)      
    512  
    513  
    514     def getAxisDefinition(self, axis): 
    515         """ 
    516         Method to create the appropriate NASA Ames file object  
    517         items associated with an axis (independent variable in  
    518         NASA Ames). 
    519         """ 
    520         length=len(axis) 
    521         self.na_dict["NX"].append(length) 
    522         self.na_dict["XNAME"].append(getBestName(axis)) 
    523         # If only one item in axis values 
    524         if length<2: 
    525             self.na_dict["DX"].append(0) 
    526             self.na_dict["NXDEF"].append(length) 
    527             self.na_dict["X"].append(list(axis._data_))         
    528             return 
    529     
    530         incr=axis[1]-axis[0] 
    531         for i in range(1, length): 
    532             if (axis[i]-axis[i-1])!=incr: 
    533                 self.na_dict["DX"].append(0) 
    534                 self.na_dict["NXDEF"].append(length) 
    535                 self.na_dict["X"].append(list(axis._data_)) 
    536                 break 
    537         else: 
    538             maxLength=length 
    539             if length>3: maxLength=3 
    540             self.na_dict["DX"].append(incr) 
    541             self.na_dict["NXDEF"].append(maxLength) 
    542             self.na_dict["X"].append(axis[:maxLength]) 
    543         return 
    544  
    545  
    546     def defineNAGlobals(self): 
    547         """ 
    548         Maps CDMS (NetCDF) global attributes into NASA Ames Header fields. 
    549         """ 
    550         # Get the global mapping dictionary 
    551         globalmap=cdmsMap.toNA 
    552         # Check if we should add to it with locally set rules 
    553         locGlobs=localRules.localGlobalAttributes 
    554         for att in locGlobs.keys(): 
    555             if not globalmap.has_key(att): 
    556                 globalmap[key]=locGlobs[key] 
    557  
    558         self.extra_comments=[[],[],[]]  # Normal comments, special comments, other comments 
    559         conventionOrReferenceComments=[] 
    560         for key in self.globals.keys(): 
    561             if key!="first_valid_date_of_data" and type(self.globals[key]) not in (str, float, int): continue 
    562             if key in globalmap.keys(): 
    563                 if key=="history": 
    564                     timestring=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) 
    565                     history="History:\t%s - Converted to NASA Ames format using nappy-%s.\n\t%s" % (timestring, version.version, self.globals[key]) 
    566                     history=history.split("\n")  
    567                     self.history=[] 
    568                     for h in history: 
    569                         if h[:8]!="History:" and h[:1]!="\t": h="\t"+h 
    570                         self.history.append(h)  
    571                      
    572                 elif key=="institution": 
    573                     # If fields came from NA then extract appropriate fields. 
    574                     match=re.match(r"(.*)\s+\(ONAME from NASA Ames file\);\s+(.*)\s+\(ORG from NASA Ames file\)\.", self.globals[key]) 
    575                     if match: 
    576                         self.na_dict["ONAME"]=match.groups()[0] 
    577                         self.na_dict["ORG"]=match.groups()[1] 
    578                     else: 
    579                         self.na_dict["ONAME"]=self.globals[key] 
    580                         self.na_dict["ORG"]=self.globals[key]                
    581                      
    582                     # NOte: should probably do the following search and replace on all string lines 
    583                     self.na_dict["ONAME"]=self.na_dict["ONAME"].replace("\n", "  ") 
    584                     self.na_dict["ORG"]=self.na_dict["ORG"].replace("\n", "  ") 
    585                                      
    586                 elif key=="comment": 
    587                     # Need to work out if they are actually comments from NASA Ames in the first place 
    588                     #self.ncom=[self.globals[key]] 
    589                     comLines=self.globals[key].split("\n") 
    590                     normComms=[] 
    591                     normCommFlag=None 
    592                     specComms=[] 
    593                     specCommFlag=None 
    594                     for line in comLines: 
    595                         if line.find("###NASA Ames Special Comments follow###")>-1: 
    596                             specCommFlag=1 
    597                         elif line.find("###NASA Ames Special Comments end###")>-1: 
    598                             specCommFlag=None 
    599                         elif line.find("###NASA Ames Normal Comments follow###")>-1: 
    600                             normCommFlag=1 
    601                         elif line.find("###NASA Ames Normal Comments end###")>-1: 
    602                             normCommFlag=None    
    603                         elif specCommFlag==1: 
    604                             specComms.append(line) 
    605                         elif normCommFlag==1: 
    606                             normComms.append(line) 
    607                         elif line.find("###Data Section begins on the next line###")>-1: 
    608                             pass 
    609                         else: 
    610                             normComms.append(line)           
    611                      
    612                     self.extra_comments=[specComms, normComms, []]                   
    613                                      
    614                 elif key=="first_valid_date_of_data": 
    615                     self.na_dict["DATE"]=self.globals[key] 
    616                  
    617                 elif key in ("Conventions", "references"): 
    618                     #conventionOrReferenceComments.append("%s:   %s" % (key, self.globals[key])) 
    619                     self.extra_comments[2].append("%s:   %s" % (key, self.globals[key])) 
    620                 else: 
    621                     self.na_dict[globalmap[key]]=self.globals[key] 
    622             else: 
    623                 self.extra_comments[2].append("%s:   %s" % (key, self.globals[key])) 
    624         #self.extra_comments 
    625         return 
    626  
    627  
    628     def defineNAComments(self, normal_comments=[], special_comments=[]): 
    629         """ 
    630         Defines the Special and Normal comments sections in the NASA Ames file  
    631         object - including information gathered from the defineNAGlobals method. 
    632         """ 
    633          
    634         if hasattr(self, "ncom"):  normal_comments=self.ncom+normal_comments 
    635         NCOM=[] 
    636         for ncom in normal_comments: 
    637             NCOM.append(ncom) 
    638         if len(NCOM)>0:   NCOM.append("") 
    639          
    640         if len(self.extra_comments[2])>0: 
    641             for excom in self.extra_comments[2]: 
    642                 NCOM.append(excom) 
    643          
    644         if len(self.extra_comments[1])>0:   
    645             NCOM.append("Additional Global Attributes defined in the source file and not translated elsewhere:") 
    646             for excom in self.extra_comments[1]: 
    647                 NCOM.append(excom) 
    648  
    649         if hasattr(self, "history"): 
    650             for h in self.history: 
    651                 NCOM.append(h) 
    652          
    653         if len(NCOM)>0: 
    654             NCOM.insert(0, "###NASA Ames Normal Comments follow###") 
    655             NCOM.append("") 
    656             NCOM.append("###NASA Ames Normal Comments end###") 
    657         NCOM.append("###Data Section begins on the next line###") 
    658  
    659         specCommentsFlag=None 
    660         SCOM=[] 
    661         special_comments=self.extra_comments[0] 
    662         if len(special_comments)>0:  
    663             SCOM=["###NASA Ames Special Comments follow###"] 
    664             specCommentsFlag=1 
    665         for scom in special_comments: 
    666             SCOM.append(scom) 
    667  
    668  
    669         #used_var_atts=("name", "long_name", "standard_name", "id",  
    670             #    "missing_value", "fill_value", "units",  
    671                 #"nasa_ames_var_number", "nasa_ames_aux_var_number") 
    672         used_var_atts=("id",  "missing_value", "fill_value", "units",  
    673                    "nasa_ames_var_number", "nasa_ames_aux_var_number") 
    674         varCommentsFlag=None 
    675  
    676         # Create a string for the Special comments to hold rank-zero vars 
    677         rank_zero_varsString=[] 
    678         for var in self.rank_zero_vars: 
    679             rank_zero_varsString.append("\tVariable %s: %s" % (var.id, getBestName(var))) 
    680             for att in var.attributes.keys(): 
    681                 value=var.attributes[att] 
    682                 if type(value) in (str, float, int): 
    683                     rank_zero_varsString.append("\t\t%s = %s" % (att, var.attributes[att])) 
    684             #print "VALUES", dir(var), var._data ; rank_zero_varsString.append("\t\tvalue = %s" % var._data) 
    685          
    686         if len(rank_zero_varsString)>0: 
    687             rank_zero_varsString.insert(0, "###Singleton Variables defined in the source file follow###") 
    688             rank_zero_varsString.append("###Singleton Variables defined in the source file end###") 
    689  
    690         for var in self.ordered_vars: 
    691             varflag="unused" 
    692             name=getBestName(var) 
    693             for scom,value in var.attributes.items(): 
    694                 if type(value) in (type([]), type(Numeric.array([0]))) and len(value)==1: 
    695                     value=value[0] 
    696                 if type(value) in (str, float, int) and scom not in used_var_atts: 
    697                     if varflag=="unused": 
    698                         if varCommentsFlag==None: 
    699                             varCommentsFlag=1 
    700                             if specCommentsFlag==None: 
    701                                 SCOM=["###NASA Ames Special Comments follow###"]+rank_zero_varsString 
    702                             SCOM.append("Additional Variable Attributes defined in the source file and not translated elsewhere:") 
    703                             SCOM.append("###Variable attributes from source (NetCDF) file follow###") 
    704                         varflag="using"  
    705                         SCOM.append("\tVariable %s: %s" % (var.id, name)) 
    706                     SCOM.append("\t\t%s = %s" % (scom, value)) 
    707  
    708         if varCommentsFlag==1:  SCOM.append("###Variable attributes from source (NetCDF) file end###") 
    709         if specCommentsFlag==1: 
    710             SCOM.append("###NASA Ames Special Comments end###") 
    711  
    712         """used_var_atts=("name", "long_name", "standard_name", "id", "missing_value", "fill_value", "units") 
    713         for var in self.vars: 
    714             for scom,value in var.attributes.items(): 
    715                 name=getBestName(var) 
    716                 if type(value) in (str, float, int) and scom not in used_var_atts: 
    717                     SCOM.append("\t%s: %s - %s" % (name, scom, value))""" 
    718  
    719         # Strip out empty lines (or returns) 
    720         NCOM_cleaned=[] 
    721         SCOM_cleaned=[] 
    722         #hiddenNewLineCount1=0 
    723         for c in NCOM: 
    724             if c.strip() not in ("", " ", "  "): 
    725                 #hiddenNewLineCount1=hiddenNewLineCount1+c.count("\n") 
    726                 # Replace new lines within one attribute with a newline and tab so easier to read 
    727                 lines=c.split("\n") 
    728                 for line in lines: 
    729                     if line!=lines[0]: line="\t"+line 
    730                     NCOM_cleaned.append(line) 
    731                  
    732         #hiddenNewLineCount2=0   
    733         for c in SCOM: 
    734             if c.strip() not in ("", " ", "  "):                 
    735                 #hiddenNewLineCount2=hiddenNewLineCount2+c.count("\n") 
    736                 # Replace new lines within one attribute with a newline and tab so easier to read 
    737                 #c=c.replace("\n", "\n\t") 
    738                 #SCOM_cleaned.append(c) 
    739                 lines=c.split("\n") 
    740                 for line in lines: 
    741                     if line!=lines[0]: line="\t"+line 
    742                     SCOM_cleaned.append(line) 
    743                      
    744         self.na_dict["NCOM"]=NCOM_cleaned 
    745         self.na_dict["NNCOML"]=len(self.na_dict["NCOM"])#+hiddenNewLineCount1 
    746         self.na_dict["SCOM"]=SCOM_cleaned 
    747         self.na_dict["NSCOML"]=len(self.na_dict["SCOM"])#+hiddenNewLineCount2 
    748         return 
    749  
    750  
    751     def defineGeneralHeader(self, header_items={}): 
    752         """ 
    753         Defines known header items and overwrites any with header_items  
    754         key/value pairs. 
    755         """ 
    756         # Check if DATE field previously known in NASA Ames file 
    757         time_now=time.strftime("%Y %m %d", time.localtime(time.time())).split() 
    758         if not self.na_dict.has_key("RDATE"): 
    759             self.na_dict["RDATE"]=time_now 
    760          
    761         if self.ax0.isTime(): 
    762             # Get first date in list 
    763             try: 
    764                 (unit, start_date)=re.match("(\w+)\s+?since\s+?(\d+-\d+-\d+)", self.ax0.units).groups()             
    765                 comptime=cdtime.s2c(start_date) 
    766                 first_day=comptime.add(self.na_dict["X"][0][0], getattr(cdtime, unit.capitalize())) 
    767                 self.na_dict["DATE"]=string.replace(str(first_day).split(" ")[0], "-", " ").split() 
    768             except: 
    769                 msg="Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
    770                 print msg 
    771                 self.output_message.append(msg) 
    772                 self.na_dict["DATE"]=("DATE", "NOT", "KNOWN") 
    773         else:  
    774             if not self.na_dict.has_key("DATE"): 
    775                 msg="Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file." 
    776                 print msg 
    777                 self.output_message.append(msg) 
    778                 self.na_dict["DATE"]=("DATE", "NOT", "KNOWN") 
    779         self.na_dict["IVOL"]=1 
    780         self.na_dict["NVOL"]=1 
    781         for key in header_items.keys(): 
    782              self.na_dict[key]=header_items[key] 
    783         return 
    784  
Note: See TracChangeset for help on using the changeset viewer.