source: nappy/trunk/naToCdms.py @ 351

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

* empty log message *

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