source: nappy/trunk/cdms2na.py @ 364

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/nappy/trunk/cdms2na.py@364
Revision 364, 26.1 KB checked in by astephen, 15 years ago (diff)

Latest changes.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/env python
2#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
3#   This software may be distributed under the terms of the
4#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5
6helpMessage="""
7
8cdms2na.py
9==========
10
11Converts a CdmsFile object into one a NASA Ames file.
12
13Usage
14=====
15
16    cdms2na.py [<options>] -i <infilename> -o <outfilename>
17
18Where
19-----
20
21    infilename  - name of input file (NetCDF).
22    outfilename - name of output file (NASA Ames).
23    options     - list of options [NOT YET IMPLEMENTED].
24   
25"""
26
27# Imports from python standard library
28import sys, os, time, string, fileinput, re
29if len(sys.argv)>0:
30    sys.path.append(os.path.join("..", ".."))
31    sys.path.append("..")
32
33# Import cdat modules
34if sys.platform.find("win")>-1:
35    pass
36else:
37    import cdms, cdtime, Numeric
38    # Define cdms variables
39    cdms.setAutoBounds("off")
40
41# Import nappy modules
42import cdmsMap
43import version
44import general
45import localRules
46from naCore import *
47from naError import *
48
49
50# Set up functions
51def compareAxes(ax1, ax2):
52    """
53    Takes 2 cmds axis objects returning 1 if they are essentially
54    the same and 0 if not.
55    """
56    for axtype in ("time", "level", "latitude", "longitude"):
57        if cdms.axisMatches(ax1, axtype) and not cdms.axisMatches(ax2, axtype):
58            return 0
59
60    # Check ids
61    if ax1.id!=ax2.id: return 0
62    # Check lengths
63    if len(ax1)!=len(ax2): return 0
64    # Check values
65    if ax1._data_!=ax2._data_: return 0
66    # Check units
67    if ax1.units!=ax2.units: return 0
68    # OK, I think they are the same axis!
69    return 1
70
71
72def compareVariables(var1, var2):
73    """
74    Compares two cdms variables to see if they are defined on identical
75    axes. Returns 1 if true, 0 if not.
76    """
77    try:
78        for i in range(len(var1.getAxisList())):
79            ax1=var1.getAxis(i)
80            ax2=var2.getAxis(i)       
81            if compareAxes(ax1, ax2)==0:
82                return 0
83    except:
84        return 0
85    return 1
86
87
88def isAuxAndVar(avar, var):
89    """
90    Compares two cdms variables and returns true if the first dimension of the
91    main variable is the only dimension the auxiliary variable is defined against.
92    """
93    if len(avar.shape)>1:
94        return 0
95    auxax=avar.getAxis(0)
96    varax=var.getAxis(0)
97    return compareAxes(auxax, varax)
98
99
100def arrayToList(array, inlist):
101    """
102    Takes an n-dimensional Numeric array and converts it to an
103    n-dimensional list object.
104    """
105    dimlist=array.shape
106    if len(dimlist[1:])>0:
107            for i in range(dimlist[0]):
108                arrayToList(inlist[i], array[i])
109    else:
110            for i in range(dimlist[0]):
111                inlist.append(array[i])
112    return inlist
113
114
115def listOfListsCreator(inlist, dimlist):
116    """
117    Creates a list of lists with dimensions defined in dimlist (a list of integers).
118    """
119    if len(dimlist[1:])>0:
120        for i in range(dimlist[0]):
121            inlist.append([])
122            listOfListsCreator(inlist[i], array, dimlist[1:])
123    return inlist
124
125
126def getBestName(var): 
127    """
128    Returns the most appropriate variable name for a NASA Ames header
129    """
130    name=None
131    if hasattr(var, "id"): name=var.id
132    if hasattr(var, "shortname"): name=var.short_name
133    if hasattr(var, "name"): name=var.name
134    if hasattr(var, "title"): name=var.title
135    if hasattr(var, "long_name"): name=var.long_name
136    if hasattr(var, "standard_name"): name=var.standard_name
137   
138    if hasattr(var, "has_key"):
139        if var.has_key("id"): name=var["id"]
140        if var.has_key("short_name"): name=var["short_name"]   
141        if var.has_key("name"): name=var["name"]
142        if var.has_key("title"): name=var["title"]     
143        if var.has_key("long_name"): name=var["long_name"]
144        if var.has_key("standard_name"): name=var["standard_name"]   
145   
146    if hasattr(var, "units") and not re.match("^\s+$", var.units): 
147        name="%s (%s)" % (name, var.units)   
148        # Do a check to see units are not duplicated
149        # [The regex below failed because it interpreted 'm**2' as
150        # regex characters]
151        #match=re.match("(.*\(%s\)\s*)\(%s\)(.*)$" % (var.units, var.units), name)
152        #if match:
153        #    name=match.groups()[0]+match.groups()[1]
154        if name.count("(%s)" % var.units)>1:
155            name=name.replace("(%s)" % var.units, "")
156            name="%s (%s)" % (name, var.units)
157       
158    if name[-2:]=="()": name=name[:-2]
159    return name
160
161
162def getMissingValue(var):
163    """
164    Returns the missing value or defaults to 1.E20.
165    """
166    miss=None
167    if hasattr(var, "missing_value"): miss=var.missing_value
168    # if hasattr(var, "fill_value"): miss=var.fill_value  # returns an array????
169    if hasattr(var, "_FillValue"): miss=var._FillValue
170    if miss==None:
171        return 1.E20
172    else:
173        return miss
174
175
176def fixHeaderLength(file):
177    """
178    Fixes length of header.
179    """
180    lines=open(file).readlines()[:200]
181    count=0
182    for line in lines:
183        count=count+1
184        if line=="###Data Section begins on the next line###\n":
185            break
186    # Now replace 1st line NLHEAD with count
187    firstline=lines[0]
188    newline="%s    %s" % (count, firstline.split()[-1])
189    for line in fileinput.input(file, inplace=1):
190        if line==firstline:
191          # write the changed line
192          sys.stdout.write(newline+"\n")
193        else:
194          # write the line unchanged
195          sys.stdout.write(line)
196
197
198def cdms2na(infilename, outfilename, naVars={}, variables=None, ffi="automatic", rules=None):
199    """
200    Main conversion function that calls the appropriate classes and functions
201    to write a NASA Ames file.
202    """
203    allowedOverwriteMetadata="DATE RDATE".split()
204   
205    print "Reading data from: %s" % infilename
206    cdmsfile=cdms.open(infilename)
207    globals=cdmsfile.attributes
208   
209    vars=[]
210    if not variables:
211        variables=cdmsfile.listvariables()
212        #for var in cdmsfile.listvariables():
213            #vars.append(cdmsfile(var))   
214           
215    for variable in variables:
216        varObj=cdmsfile(variable)
217        # Deal with singleton variables
218        if not hasattr(varObj, "rank"):
219                varMetadata=cdmsfile[variable].attributes
220                varValue=varObj
221                #print varMetadata, varValue, varMetadata.keys(), varMetadata._obj_.id
222                varObj=cdms.createVariable(Numeric.array(varObj), id=getBestName(varMetadata).replace(" ", "_"), attributes=varMetadata)
223                #varObj.rank=0
224               
225        #print varObj, varObj.attributes                         
226        vars.append(varObj)
227       
228    # Re-order variables if they have the attribute 'nasa_ames_var_number'
229    orderedVars=[None]*1000
230    otherVars=[]
231    for var in vars:
232        varMetadata=cdmsfile[var]
233        if hasattr(varMetadata, "nasa_ames_var_number"):
234            num=varMetadata.nasa_ames_var_number
235            orderedVars[num]=var
236        else:
237            otherVars.append(var)
238   
239    vars=[]
240    for var in orderedVars:
241        if var!=None:
242            vars.append(var)
243           
244    vars=vars+otherVars
245   
246    builder=CdmsToNABuilder(vars, globals)
247    #print builder.naDict["X"]
248    builtNADicts=[[builder.naDict, builder.varIDs]]
249    while len(builder.varBin)>0:
250        builder=CdmsToNABuilder(builder.varBin, globals)
251        builtNADicts.append([builder.naDict, builder.varIDs])
252       
253    print "%s files to write" % len(builtNADicts)
254
255    count=1
256    for i in builtNADicts:
257        if len(builtNADicts)==1:
258            suffix=""
259        else:
260            suffix="_%s" % count
261        nameparts=outfilename.split(".")   
262        newname=(".".join(nameparts[:-1]))+suffix+"."+nameparts[-1]
263        print "\nWriting output NASA Ames file: %s" % newname
264        builtNADict=i[0]
265        for key in naVars.keys():
266            if key in allowedOverwriteMetadata:
267                if type(builtNADict[key])==list:
268                    builtNADict[key]=naVars[key].split()
269                else:
270                    builtNADict[key]=naVars[key]
271                print "Key replace in: ", key, builtNADict[key]
272        general.openNAFile(newname, 'w', builtNADict)
273        nlhead=fixHeaderLength(newname) 
274        print "\nWrote the following variables to this file:"
275        print "\n\t"+("\n\t".join(i[1][0]))
276        if len(i[1][1])>0:
277            print "\nWrote the following auxiliary variables to this file:"
278            print "\n\t"+("\n\t".join(i[1][1])) 
279            print "\nNASA Ames file written successfully: %s" % newname
280        count=count+1
281             
282    print "\n%s files written." % (count-1)
283
284
285class CdmsToNABuilder(NACore):
286    """
287    Class to build a NASA Ames File object from a set of
288    CDMS variables and global attributes (optional).
289    """
290   
291    def __init__(self, vars, global_attributes={}):
292        """
293        Sets up instance variables and calls appropriate methods to
294        generate sections of NASA Ames file object.
295        """
296        self.naDict={}
297        self.vars=vars
298        self.globals=global_attributes
299        (self.orderedVars, auxVars)=self.analyseVariables()
300        if self.orderedVars==None:
301            print "All variables located."
302            self.varBin=[]
303        else:
304            #print "NAMELISTS:", [var.id for var in self.orderedVars],[var.id for var in auxVars]
305            self.varIDs=[[var.id for var in self.orderedVars],[var.id for var in auxVars]]
306       
307            self.naDict["NLHEAD"]="-999"
308       
309            #print [var.id for var in self.orderedVars]
310            #print [var.rank() for var in self.orderedVars]     
311            self.defineNAVars(self.orderedVars)
312            self.defineNAAuxVars(auxVars)
313            self.defineNAGlobals()
314            self.defineNAComments()
315            self.defineGeneralHeader()
316            # Quick fudge
317            if self.naDict["FFI"]==1001: self.naDict["X"]=self.naDict["X"][0]
318
319
320    def analyseVariables(self):
321        """
322        Method to examine the content of CDMS variables to return
323        a tuple of two lists containing variables and auxiliary variables
324        for the NASA Ames file object.
325        Variables not compatible with the first file are binned to be used next.
326        """
327        # Need to group the variables together in bins
328        self.varBin=[]
329        self.rankZeroVars=[]
330        self.rankZeroVarIDs=[]
331        # Get largest ranked variable as the one we use as standard
332        highrank=-1
333        count=0
334        for var in self.vars:
335            print "Analysing:", var.id
336            count=count+1
337            #print count
338            # Deal with singleton dimensions
339            #if callable(var.rank):
340            #    rank=var.rank()
341            #else:
342            #    rank=var.rank
343            #print var.id, var.rank()
344            rank=var.rank()
345            if rank==0: 
346                self.rankZeroVars.append(var)
347                self.rankZeroVarIDs.append(var.id)
348                continue
349           
350            if rank>highrank:
351                highrank=rank
352                bestVar=var
353                bestVarIndex=count
354            elif rank==highrank:
355                if len(var.flat)>len(bestVar.flat):
356                    bestVar=var
357                    bestVarIndex=count
358       
359        if len(self.rankZeroVars)==len(self.vars):  return (None, None)
360       
361        vars4NA=[bestVar]
362        auxVars4NA=[]
363        shape=bestVar.shape
364        ndims=len(shape)
365        self.naDict["NIV"]=ndims
366
367        # Work out which File Format Index is appropriate
368        if ndims in (2,3,4):
369            self.naDict["FFI"]=10+(ndims*1000)
370        elif ndims>4:
371            raise "Cannot write variables defined against greater than 4 axes in NASA Ames format."
372        else:
373            if len(auxVars4NA)>0 or (self.naDict.has_key("NAUXV") and self.naDict["NAUXV"]>0):
374                self.naDict["FFI"]=1010
375            else:
376                self.naDict["FFI"]=1001
377        #print self.naDict["FFI"]
378        axes=bestVar.getAxisList()
379       
380        # Get other variable info
381        #print [v.id for v in self.vars], bestVarIndex
382        #print [v.id for v in self.vars[:bestVarIndex-1]+self.vars[bestVarIndex:]]
383        for var in self.vars[:bestVarIndex-1]+self.vars[bestVarIndex:]:
384            #print self.rankZeroVars
385            #for rzv in self.rankZeroVars: 
386            #    if var.id==rzv.id and var[0]==rzv[0]: continue
387            #print [v.id for v in self.rankZeroVars]
388            if var.id in self.rankZeroVarIDs: continue
389            #print var.id, ndims, shape, len(var.shape), var.shape
390            if len(var.shape)!=ndims or var.shape!=shape: 
391                # Could it be an auxiliary variable
392                if len(var.shape)!=1: 
393                    self.varBin.append(var)
394                    continue
395                caxis=var.getAxis(0)
396                if compareAxes(axes[0], caxis)==0: 
397                    self.varBin.append(var)
398                    continue
399                # I think it is an auxiliary variable
400                auxVars4NA.append(var) 
401                # Also put it in var bin because auxiliary vars might be useful
402                self.varBin.append(var)
403            else:
404                caxes=var.getAxisList()
405                #print var.id, "here"
406                for i in range(ndims):           
407                    if compareAxes(axes[i], caxes[i])==0:
408                        self.varBin.append(var)
409                        continue
410                # OK, I think they are compatible
411                vars4NA.append(var)
412               
413        # Re-order if they previously came from NASA Ames files (i.e. including
414        # the attribute 'nasa_ames_var_number')
415        orderedVars=[None]*1000
416        otherVars=[]
417        for var in vars4NA:
418            if hasattr(var, "nasa_ames_var_number"):
419                orderedVars[var.nasa_ames_var_number[0]]=var
420            else:
421                otherVars.append(var)
422        # Remake vars4NA now in order
423        vars4NA=[]
424        for var in orderedVars:
425            if var!=None: vars4NA.append(var)
426        vars4NA=vars4NA+otherVars
427
428        # Now re-order the Auxiliary variables if they previously came from NASA
429        # Ames files (i.e. including the attribute 'nasa_ames_aux_var_number')
430
431        orderedAuxVars=[None]*1000
432        otherAuxVars=[]
433        for var in auxVars4NA:
434            if hasattr(var, "nasa_ames_aux_var_number"):
435                orderedAuxVars[var.nasa_ames_aux_var_number[0]]=var
436            else:
437                otherAuxVars.append(var)
438        # Remake auxVars4NA now in order
439        auxVars4NA=[]
440        for var in orderedAuxVars:
441            if var!=None: auxVars4NA.append(var)
442        auxVars4NA=auxVars4NA+otherAuxVars     
443        return (vars4NA, auxVars4NA)
444
445
446    def defineNAVars(self, vars):
447        """
448        Method to define NASA Ames file object variables and their
449        associated metadata.
450        """
451        self.naDict["NV"]=len(vars)
452        self.naDict["VNAME"]=[]
453        self.naDict["VMISS"]=[]
454        self.naDict["VSCAL"]=[]
455        self.naDict["V"]=[]
456        for var in vars:
457            name=getBestName(var)
458            self.naDict["VNAME"].append(name)
459            miss=getMissingValue(var)
460            if type(miss) not in (float, int, long):  miss=miss[0]
461            self.naDict["VMISS"].append(miss)
462            #print self.naDict["VMISS"]
463            self.naDict["VSCAL"].append(1)
464            # AND THE ARRAY
465            # Populate the variable list 
466            ######## NOTE - might not have to do this #####
467            ######## It  might handle writing from a Numeric array ########
468            self.naDict["V"].append(var._data)
469            #listOfListsCreator(inlist, var.shape)
470            #arrayToList(var, inlist)
471
472            if not self.naDict.has_key("X"):
473                self.naDict["NXDEF"]=[]
474                self.naDict["NX"]=[]
475                # Create independent variable information
476                #print var.id, var.getAxis(0)
477                self.ax0=var.getAxis(0)
478                self.naDict["X"]=[list(self.ax0._data_)]
479                self.naDict["XNAME"]=[getBestName(self.ax0)]
480                if len(self.ax0)==1:
481                    self.naDict["DX"]=[0]
482                else:
483                    incr=self.ax0[1]-self.ax0[0]
484                    for i in range(1, len(self.ax0)):
485                        if (self.ax0[i]-self.ax0[i-1])!=incr:
486                            self.naDict["DX"]=[0]
487                            break
488                    else:
489                        self.naDict["DX"]=[incr]
490                # Now sort the rest of the axes
491                for axis in var.getAxisList()[1:]:
492                    self.getAxisDefinition(axis)
493
494
495    def defineNAAuxVars(self, auxVars):
496        """
497        Method to define NASA Ames file object auxiliary variables and their
498        associated metadata.
499        """
500        self.naDict["NAUXV"]=len(auxVars)
501        self.naDict["ANAME"]=[]
502        self.naDict["AMISS"]=[]
503        self.naDict["ASCAL"]=[]
504        self.naDict["A"]=[]
505        for var in auxVars:
506            name=getBestName(var)
507            self.naDict["ANAME"].append(name)
508            miss=getMissingValue(var)
509            if type(miss)!=float:  miss=miss[0]
510            self.naDict["AMISS"].append(miss)
511            self.naDict["ASCAL"].append(1)
512            # AND THE ARRAY
513            # Populate the variable list 
514            ######## NOTE - might not have to do this #####
515            ######## It  might handle writing from a Numeric array ########
516            self.naDict["A"].append(var._data)
517            #listOfListsCreator(inlist, var.shape)
518            #arrayToList(var, inlist)     
519
520
521    def getAxisDefinition(self, axis):
522        """
523        Method to create the appropriate NASA Ames file object
524        items associated with an axis (independent variable in
525        NASA Ames).
526        """
527        self.naDict["NX"].append(len(axis))
528        self.naDict["XNAME"].append(getBestName(axis))
529        # If only one item in axis values
530        if len(axis)<3:
531            self.naDict["DX"].append(0)
532            self.naDict["NXDEF"].append(len(axis))
533            self.naDict["X"].append(list(axis._data_))       
534            return
535   
536        incr=axis[1]-axis[0]
537        for i in range(1, len(axis)):
538            if (axis[i]-axis[i-1])!=incr:
539                self.naDict["DX"].append(0)
540                self.naDict["NXDEF"].append(len(axis))
541                self.naDict["X"].append(list(axis._data_))
542                break
543        else:
544            self.naDict["DX"].append(incr)
545            self.naDict["NXDEF"].append(3)
546            self.naDict["X"].append(axis[:3])
547        return
548
549
550    def defineNAGlobals(self):
551        """
552        Maps CDMS (NetCDF) global attributes into NASA Ames Header fields.
553        """
554        # Get the global mapping dictionary
555        globalmap=cdmsMap.toNA
556        # Check if we should add to it with locally set rules
557        locGlobs=localRules.localGlobalAttributes
558        for att in locGlobs.keys():
559            if not globalmap.has_key(att):
560                globalmap[key]=locGlobs[key]
561
562        self.extra_comments=[[],[],[]]  # Normal comments, special comments, other comments
563        for key in self.globals.keys():
564            if key!="first_valid_date_of_data" and type(self.globals[key]) not in (str, float, int): continue
565            if key in globalmap.keys():
566                if key=="history":
567                    timestring=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
568                    self.history="History:\n\t%s - Converted to NASA Ames format using nappy-%s.\n\t%s" % (timestring, version.version, self.globals[key])
569                    self.history=self.history.split("\n") 
570                   
571                elif key=="institution":
572                    # If fields came from NA then extract appropriate fields.
573                    match=re.match(r"(.*)\s+\(ONAME from NASA Ames file\);\s+(.*)\s+\(ORG from NASA Ames file\)\.", self.globals[key])
574                    if match:
575                        self.naDict["ONAME"]=match.groups()[0]
576                        self.naDict["ORG"]=match.groups()[1]
577                    else:
578                        self.naDict["ONAME"]=self.globals[key]
579                        self.naDict["ORG"]=self.globals[key]               
580                   
581                    # NOte: should probably do the following search and replace on all string lines
582                    self.naDict["ONAME"]=self.naDict["ONAME"].replace("\n", "  ")
583                    self.naDict["ORG"]=self.naDict["ORG"].replace("\n", "  ")
584                                   
585                elif key=="comment":
586                    # Need to work out if they are actually comments from NASA Ames in the first place
587                    #self.ncom=[self.globals[key]]
588                    comLines=self.globals[key].split("\n")
589                    normComms=[]
590                    normCommFlag=None
591                    specComms=[]
592                    specCommFlag=None
593                    for line in comLines:
594                        if line.find("###NASA Ames Special Comments follow###")>-1:
595                            specCommFlag=1
596                        elif line.find("###NASA Ames Special Comments end###")>-1:
597                            specCommFlag=None
598                        elif line.find("###NASA Ames Normal Comments follow###")>-1:
599                            normCommFlag=1
600                        elif line.find("###NASA Ames Normal Comments end###")>-1:
601                            normCommFlag=None   
602                        elif specCommFlag==1:
603                            specComms.append(line)
604                        elif normCommFlag==1:
605                            normComms.append(line)
606                        elif line.find("###Data Section begins on the next line###")>-1:
607                            pass
608                        else:
609                            normComms.append(line)         
610                   
611                    self.extra_comments=[specComms, normComms, []]                 
612                                   
613                elif key=="first_valid_date_of_data":
614                    self.naDict["DATE"]=self.globals[key]
615               
616                elif key in ("Conventions", "references"):
617                    pass
618                else:
619                    self.naDict[globalmap[key]]=self.globals[key]
620            else:
621                self.extra_comments[2].append("%s:   %s" % (key, self.globals[key]))
622        return
623
624
625    def defineNAComments(self, normal_comments=[], special_comments=[]):
626        """
627        Defines the Special and Normal comments sections in the NASA Ames file
628        object - including information gathered from the defineNAGlobals method.
629        """
630       
631        if hasattr(self, "ncom"):  normal_comments=self.ncom+normal_comments
632        NCOM=[]
633        for ncom in normal_comments:
634            NCOM.append(ncom)
635        if len(NCOM)>0:   NCOM.append("")
636       
637        if len(self.extra_comments[2])>0:
638            for excom in self.extra_comments[2]:
639                NCOM.append(excom)
640       
641        if len(self.extra_comments[1])>0: 
642            NCOM.append("Additional Global Attributes defined in the source file and not translated elsewhere:")
643            for excom in self.extra_comments[1]:
644                NCOM.append(excom)
645
646        if hasattr(self, "history"):
647            for h in self.history:
648                NCOM.append(h)
649       
650        if len(NCOM)>0:
651            NCOM.insert(0, "###NASA Ames Normal Comments follow###")
652            NCOM.append("")
653            NCOM.append("###NASA Ames Normal Comments end###")
654        NCOM.append("###Data Section begins on the next line###")
655
656        specCommentsFlag=None
657        SCOM=[]
658        special_comments=self.extra_comments[0]
659        if len(special_comments)>0: 
660            SCOM=["###NASA Ames Special Comments follow###"]
661            specCommentsFlag=1
662        for scom in special_comments:
663            SCOM.append(scom)
664
665
666        used_var_atts=("name", "long_name", "standard_name", "id", 
667                "missing_value", "fill_value", "units", 
668                "nasa_ames_var_number", "nasa_ames_aux_var_number")
669        varCommentsFlag=None
670
671        # Create a string for the Special comments to hold rank-zero vars
672        rankZeroVarsString=[]
673        for var in self.rankZeroVars:
674            rankZeroVarsString.append("\tVariable (%s): %s" % (var.id, getBestName(var)))
675            for att in var.attributes.keys():
676                value=var.attributes[att]
677                if type(value) in (str, float, int):
678                    rankZeroVarsString.append("\t\t%s = %s" % (att, var.attributes[att]))
679            #print "VALUES", dir(var), var._data ; rankZeroVarsString.append("\t\tvalue = %s" % var._data)
680       
681        if len(rankZeroVarsString)>0:
682            rankZeroVarsString.insert(0, "###Singleton Variables defined in the source file follow###")
683            rankZeroVarsString.append("###Singleton Variables defined in the source file end###")
684
685        for var in self.orderedVars:
686            varflag="unused"
687            name=getBestName(var)
688            for scom in var.attributes.keys():
689                if type(scom) in (str, float, int) and scom not in used_var_atts:
690                    if varflag=="unused":
691                        if varCommentsFlag==None:
692                            varCommentsFlag=1
693                            if specCommentsFlag==None:
694                                SCOM=["###NASA Ames Special Comments follow###"]+rankZeroVarsString
695                            SCOM.append("Additional Variable Attributes defined in the source file and not translated elsewhere:")
696                            SCOM.append("###Variable attributes from source (NetCDF) file follow###")
697                        varflag="using" 
698                        SCOM.append("\tVariable (%s): %s" % (var.id, name))
699                    SCOM.append("\t\t%s = %s" % (scom, var.attributes[scom]))
700        if varCommentsFlag==1:  SCOM.append("###Variable attributes from source (NetCDF) file end###")
701        if specCommentsFlag==1:
702            SCOM.append("###NASA Ames Special Comments end###")
703
704        """used_var_atts=("name", "long_name", "standard_name", "id", "missing_value", "fill_value", "units")
705        for var in self.vars:
706            for scom in var.attributes.keys():
707                name=getBestName(var)
708                if type(scom) in (str, float, int) and scom not in used_var_atts:
709                    SCOM.append("\t%s: %s - %s" % (name, scom, var.attributes[scom]))"""
710
711        # Strip out empty lines (or returns)
712        NCOM_cleaned=[]
713        SCOM_cleaned=[]
714        for c in NCOM:
715            if c.strip() not in ("", " ", "  "): NCOM_cleaned.append(c)
716        for c in SCOM:
717            if c.strip() not in ("", " ", "  "): SCOM_cleaned.append(c)
718
719        self.naDict["NCOM"]=NCOM_cleaned
720        self.naDict["NNCOML"]=len(self.naDict["NCOM"])
721        self.naDict["SCOM"]=SCOM_cleaned
722        self.naDict["NSCOML"]=len(self.naDict["SCOM"])
723        return
724
725
726    def defineGeneralHeader(self, header_items={}):
727        """
728        Defines known header items and overwrites any with header_items
729        key/value pairs.
730        """
731        # Check if DATE field previously known in NASA Ames file
732        time_now=time.strftime("%Y %m %d", time.localtime(time.time())).split()
733        if not self.naDict.has_key("RDATE"):
734            self.naDict["RDATE"]=time_now
735       
736        if self.ax0.isTime():
737            # Get first date in list
738            try:
739                (unit, start_date)=re.match("(\w+)\s+?since\s+?(\d+-\d+-\d+)", self.ax0.units).groups()           
740                comptime=cdtime.s2c(start_date)
741                first_day=comptime.add(self.naDict["X"][0][0], getattr(cdtime, unit.capitalize()))
742                self.naDict["DATE"]=string.replace(str(first_day).split(" ")[0], "-", " ").split()
743            except:
744                print "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file."
745                self.naDict["DATE"]="<DATE_UNKNOWN>"
746        else: 
747            if not self.naDict.has_key("DATE"):
748                print "Nappy Warning: Could not get the first date in the file. You will need to manually edit the output file."
749                self.naDict["DATE"]="<DATE_UNKNOWN>"
750        self.naDict["IVOL"]=1
751        self.naDict["NVOL"]=1
752        for key in header_items.keys():
753             self.naDict[key]=header_items[key]
754        return
755               
756
757usenc2nainstead="""if __name__=="__main__":
758
759    args=sys.argv[1:]
760    if len(args)<4:
761        print helpMessage
762        print "Incorrect number of arguments used."
763        sys.exit()
764       
765    for arg in args:
766        if arg=="-i":
767            infile=args[args.index(arg)+1]
768        elif arg=="-o":
769            outfile=args[args.index(arg)+1]
770
771    cdms2na(infile, outfile) """
Note: See TracBrowser for help on using the repository browser.