source: nappy/trunk/naToCdms.py @ 347

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/nappy/trunk/naToCdms.py@347
Revision 347, 9.4 KB checked in by selatham, 15 years ago (diff)

Incorporates changes by selatham and Ag Stephens. as of 5/11/04.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""
2naToCdms.py
3===========
4
5Container module for mixin class NAToCdms that is sub-classed
6by NAFile classes.
7
8"""
9
10# Imports from python standard library
11import sys
12sys.path.append(r"..")
13import os
14import re
15import time
16
17# Import from nappy package
18import cdmsMap
19from naError import *
20import version
21
22# Import external packages (if available)
23if sys.platform.find("win")>-1:
24    pass
25else:
26    try:
27        import cdms, Numeric
28        cdms.setAutoBounds("off") 
29    except:
30        print "Cannot import cdms package, CDAT-dependent features will not work."
31
32# Define global variables
33safe_nc_id=re.compile("[\s\[()\]=+-?#~@&$%!*{}\^]+")
34time_units_pattn=re.compile("\w+\s+since\s+\d{4}-\d{1,2}-\d{1,2}\s+\d+:\d+:\d+")
35
36class NAToCdms:
37
38    def toCdmsFile(self, filename, time_units=None, variables="all", aux_variable="all", global_attributes={"Conventions":"CF-1.0"}, ffi=None):
39        if sys.platform.find("win")>-1:
40            raise NAPlatformError
41
42        self.time_units=time_units
43        # Read the data section of the NASA Ames file
44        self.readData()
45        self.cdmsFilename=filename
46        self.cdmsFile=cdms.open(self.cdmsFilename, 'w')
47       
48        # at file level: write global attributes
49        for key in global_attributes.keys():
50            setattr(self.cdmsFile, key, global_attributes[key])
51
52        for key in cdmsMap.fromNA.keys():
53            if type(key)==tuple:
54                if key==("SCOM", "NCOM"):
55                    # Map special and normal comments into the global comments section
56                   
57                    commentline=""
58                    if self.NSCOML>0:
59                        commentline=commentline+"###NASA Ames Special Comments follow###\n"
60                        for i in self.SCOM: 
61                            if i.strip() not in ("###NASA Ames Special Comments follow###", "###NASA Ames Special Comments end###",
62                                    "Additional Variable Attributes defined in the source file and not translated elsewhere:",
63                                    "Additional Global Attributes defined in the source file and not translated elsewhere:", "\n"):
64                                commentline=commentline+"\n"+i
65                        commentline=commentline+"\n###NASA Ames Special Comments end###\n"
66                    if self.NNCOML>0:
67                        commentline=commentline+"###NASA Ames Normal Comments follow###\n"
68                        for i in self.NCOM: 
69                            if i.strip() not in ("###NASA Ames Normal Comments follow###", "###NASA Ames Normal Comments end###", "###Data Section begins on the next line###",
70                                    "Additional Variable Attributes defined in the source file and not translated elsewhere:",
71                                    "Additional Global Attributes defined in the source file and not translated elsewhere:", "\n"):
72                                commentline=commentline+"\n"+i
73                        commentline=commentline+"\n###NASA Ames Normal Comments end###"
74                        commentline=commentline.replace("\n\n", "\n")
75                    self.cdmsFile.comment=commentline
76                elif key==("ONAME", "ORG"):
77                    # Map the two organisation NA files to the institution field in CDMS (NetCDF)
78                    self.cdmsFile.institution="%s (ONAME from NASA Ames file); %s (ORG from NASA Ames file)." % (self.ONAME, self.ORG)
79                else:
80                    item=(getattr(self, key[0]))+"\n"+(getattr(self, key[1]))
81                    setattr(self.cdmsFile, cdmsMap.fromNA[key], item)
82            elif key=="RDATE":
83                dateparts=getattr(self, "RDATE")
84                datestring="%.4d-%.2d-%.2d" % tuple(dateparts)
85                item=datestring+" - NASA Ames File created/revised.\n"
86                timestring=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
87                item=item+"\n"+timestring+" - Converted to CDMS (NetCDF) format using nappy-%s." % version.version
88            else:
89                setattr(self.cdmsFile, cdmsMap.fromNA[key], getattr(self, key))
90
91        # Then do dimensions
92        if not hasattr(self, 'cdmsAxes'):  self.createCdmsAxes()
93
94        # Then do variables
95        if not hasattr(self, 'cdmsVariables'):  self.createCdmsVariables()
96        for var in self.cdmsVariables:
97            self.cdmsFile.write(var)
98
99        # Then do auxiliary variables
100        if hasattr(self, "NAUXV") and type(self.NAUXV)==int:   # Are there any auxiliary variables?
101            if not hasattr(self, 'cdmsAuxVariables'):  self.createCdmsAuxVariables()
102            for avar in self.cdmsAuxVariables:
103                self.cdmsFile.write(avar)
104
105        self.cdmsFile.close()
106        return "Cdmsfile '%s' written successfully." % self.cdmsFilename
107
108    def createCdmsVariables(self):
109        self.cdmsVariables=[]
110        for var_number in range(self.NV):
111            self.cdmsVariables.append(self.toCdmsVariable(var_number))
112
113
114    def toCdmsVariable(self, var_number, attributes={}):
115        if sys.platform.find("win")>-1:
116            raise NAPlatformError
117        (varname, units, miss, scal)=self.getVariable(var_number)
118        print self.V
119        array=Numeric.array(self.V[var_number])
120        array=array*scal
121        # Set up axes
122        if not hasattr(self, 'cdmsAxes'):
123            self.createCdmsAxes()
124
125        # Set up variable
126        var=cdms.createVariable(array, axes=self.cdmsAxes, fill_value=miss, attributes=attributes)
127
128        # Sort units etc
129        if units:   var.units=units
130       
131        # Add the best variable name
132        if len(varname)<20:
133            var.id=safe_nc_id.sub("_", varname).lower()
134        else:
135            var.id="naVariable_%s" % (var_number)
136
137        var.long_name=var.name=varname
138
139        # If we have a standard name list then compare to it
140        if varname in ("standard_name_list",) or varname in ("badc_list",):
141            var.standard_name="name from the list###**"
142
143        # Add a NASA Ames variable number (for mapping correctly back to NASA Ames)
144        var.nasa_ames_var_number=var_number
145
146        return var
147
148    def createCdmsAuxVariables(self):
149        self.cdmsAuxVariables=[]
150        for avar_number in range(self.NAUXV):
151            self.cdmsAuxVariables.append(self.auxToCdmsVariable(avar_number))
152
153    def auxToCdmsVariable(self, avar_number, attributes={}):
154        if sys.platform.find("win")>-1:
155            raise NAPlatformError
156        (varname, units, miss, scal)=self.getAuxVariable(avar_number)
157        array=Numeric.array(self.A[avar_number])
158        array=array*scal
159
160        # Set up axes
161        if not hasattr(self, 'cdmsAxes'):
162            self.createCdmsAxes()
163
164        # Set up variable
165        var=cdms.createVariable(array, axes=[self.cdmsAxes[0]], fill_value=miss, attributes=attributes)
166
167        # Sort units etc
168        if units:   var.units=units
169        if len(varname)<20:
170            var.id=safe_nc_id.sub("_", varname).lower()
171        else:
172            var.id="naAuxVariable_%s" % (avar_number)
173
174        var.long_name=var.name=varname
175        if varname in ("standard_name_list",) or varname in ("badc_list",):
176            var.standard_name="name from the list***"
177
178
179        # Add a NASA Ames auxiliary variable number (for mapping correctly back to NASA Ames)
180        var.nasa_ames_aux_var_number=avar_number
181
182        return var       
183
184    def createCdmsAxes(self):
185        if sys.platform.find("win")>-1:
186            raise NAPlatformError
187        if not hasattr(self, 'cdmsAxes'):       
188            self.cdmsAxes=[]
189        for ivar_number in range(self.NIV):
190            self.cdmsAxes.append(self.toCdmsAxis(ivar_number))
191
192    def toCdmsAxis(self, ivar_number):
193        if sys.platform.find("win")>-1:
194            raise NAPlatformError
195
196        if self._normalizedX=="no": self._normalizeIndVars()
197
198        if self.NIV==1:
199            array=self.X
200        else:
201            array=self.X[ivar_number]
202        axis=cdms.createAxis(array)
203        axis.id=axis.name=axis.long_name=self.XNAME[ivar_number]
204        (varname, units)=self.getIndependentVariable(ivar_number)
205        # Sort units etc
206        if units:   axis.units=units
207        if len(varname)<20:
208            axis.id=safe_nc_id.sub("_", varname).lower()
209        else:
210            axis.id="naAuxVariable_%s" % (ivar_number)
211
212        if units: axis.units=units
213        axis_types=("longitude", "latitude", "level", "time")
214        designators={"longitude":axis.designateLongitude, "latitude":axis.designateLatitude,
215                     "level":axis.designateLevel, "time":axis.designateTime}
216        for axis_type in axis_types:
217            if re.search(axis_type, varname, re.IGNORECASE):
218                axis.standard_name=axis.id=axis_type
219                apply(designators[axis_type.lower()])
220                # Check warning for time units pattern
221                if axis.isTime() and (not hasattr(axis, "units") or not time_units_pattn.match(axis.units)):
222                    if self.time_units==None:
223                        print """\nWARNING: Could not recognise time units. For true NetCDF compability
224please insert the correct time unit string below in the format:
225   
226    <units> since <YYYY>-<MM>-<DD> <hh>-<mm>-<ss>
227   
228Where:
229    <units> is a known time interval such as years, months, days, etc.
230    <YYYY> is the year, <MM> is the month, <DD> is the day,
231    <hh> is the hour, <mm> is minutes, <ss> is seconds.
232"""
233                        timeUnitsInput="I WON'T MATCH"
234                        while timeUnitsInput!="" and not time_units_pattn.match(timeUnitsInput):
235                            timeUnitsInput=raw_input("Please insert your time unit string here (or leave blank):").strip()
236                        if timeUnitsInput!="":
237                            self.time_units=timeUnitsInput
238                    axis.units=self.time_units
239                    axis.long_name=axis.name="time (%s)" % self.time_units
240               
241        return axis
242
243
244class NA2Cdms(NAToCdms):
245    """
246    Pseudonym for NAToCdms class.
247    """
248    pass
Note: See TracBrowser for help on using the repository browser.