source: nappy/trunk/naFile.py @ 345

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

updated by selatham for bug fixes and new write methods

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""
2naFile.py
3=========
4
5A containter module for the mixin base class NAFile that is subclassed
6for individual FFIs. Each FFI class is held in an individual file.
7
8"""
9#$Log$
10#Revision 1.3  2004/11/03 16:23:41  selatham
11#updated by selatham for bug fixes and new write methods
12#
13
14# Imports from python standard library
15import sys
16import time
17import re
18
19# Imports from nappy package
20import naCore
21from textParser import *
22from naError import *
23import naToCdms
24
25class NAFile(naCore.NACore, naToCdms.NAToCdms):
26
27    """
28    NAFile class is a sub-class of NACore and NAToCdms mixin classes.
29    NAFile is also a mixin class and should not be called directly.
30   
31    NAFile holds all the methods are common to either all or more than
32    one NASA Ames FFI class. These methods set up the main read and write
33    functionality for the NASA Ames format.
34
35    When a sub-class of NAFile is called with a read ('r' - default) or
36    write ('w') mode the header in the file is automatically read or written.
37    However, the user must explicitly read or write the data section with a
38    call to the 'readData' or 'writeData' methods.
39
40    """
41
42    def __init__(self, filename, mode="r", naDict={}, spacer="    ", floatFormat="%8.3f"):
43        """
44        Initialization of class, decides if user wishes to read or write
45        NASA Ames file.
46        """
47        naCore.NACore.__init__(self)
48        self.naDict=naDict
49        self.filename=filename
50        self._open(mode)
51        self.spacer=spacer
52        self.floatFormat=floatFormat
53
54        if mode=="r":
55            self._normalizedX="yes"
56            self.readHeader()
57        elif mode=="w":
58            self._parseDictionary()
59            self.writeHeader()
60            self.writeData()
61        else:
62            raise "Unknown file mode '%s'." % mode
63        self.close()
64       
65    def _open(self, mode):
66        "Wrapper to builtin open file function."
67        self.file=open(self.filename, mode)
68
69    def close(self):
70        "Wrapper to builtin close file function."
71        self.file.close()
72
73    def _parseDictionary(self):
74        """
75        Parser for the optional naDict argument containing a dictionary
76        of NASA Ames internal variables. These are saved as instance attributes
77        with the name used in the NASA Ames documentation.
78        """
79        for i in self.naDict.keys():
80            setattr(self, i, self.naDict[i])
81
82    def _readTopLine(self):
83        """
84        Reads number of header lines and File Format Index from top line.
85        Also assigns a value to NIV for the number of independent variables
86        based on the first character in the FFI.
87
88        Returns NLHEAD and FFI in a tuple.
89        """
90        (self.NLHEAD, self.FFI)=readItemsFromLine(self.file.readline(), 2, int)
91        self.NIV=int(self.FFI/1000)
92        return (self.NLHEAD, self.FFI)
93
94    def _readLines(self, nlines):
95        "Reads nlines lines from a file and returns them in a list."
96        lines=[]
97        for i in range(nlines):
98            lines.append(self.file.readline().strip())
99        return lines
100
101    def _checkForBlankLines(self, datalines):
102        """
103        Searches for empty lines in the middle of the data section and raises
104        as error if found. It ignores empty lines at the end of the file but
105        strips them out before returning a list of lines for reading.
106        """
107        empties=None
108        count=0
109        rtlines=[]
110        for line in datalines:
111            if re.match(r"^[\s\n\t\r]*$", line):
112                empties=1
113            else:
114                if empties==1:   # If data line found after empty line then raise
115                    raise "Empty line found in data section at line: %s" % count
116                else:
117                    rtlines.append(line)
118            count=count+1
119        return rtlines
120
121    def _readCommonHeader(self):
122        """
123        Reads the header section common to all NASA Ames files.
124        """
125        self._readTopLine()
126        self.ONAME=readItemFromLine(self.file.readline(), str)
127        self.ORG=readItemFromLine(self.file.readline(), str)
128        self.SNAME=readItemFromLine(self.file.readline(), str)
129        self.MNAME=readItemFromLine(self.file.readline(), str)
130        (self.IVOL, self.NVOL)=readItemsFromLine(self.file.readline(), 2, int)
131        dates=readItemsFromLine(self.file.readline(), 6, int)
132        (self.DATE, self.RDATE)=(dates[:3], dates[3:])
133
134    def _writeCommonHeader(self):
135        """
136        Writes the header section common to all NASA Ames files.
137        """
138        self.file.write("%s    %s\n" % (self.NLHEAD, self.FFI))
139        self.file.write("%s\n" % self.ONAME)
140        self.file.write("%s\n" % self.ORG)
141        self.file.write("%s\n" % self.SNAME)
142        self.file.write("%s\n" % self.MNAME)
143        self.file.write("%s    %s\n" % (self.IVOL, self.NVOL))
144        self.file.write("%s %s %s    %s %s %s\n" % (self.DATE[0], self.DATE[1], self.DATE[2], self.RDATE[0], self.RDATE[1], self.RDATE[2]))
145
146    def _readVariablesHeaderSection(self):
147        """
148        Reads the variables section of the header.
149        Assumes we are at the right point in the file.
150        """
151        self.NV=readItemFromLine(self.file.readline(), int)
152        self.VSCAL=readItemsFromUnknownLines(self.file, self.NV, float)
153        self.VMISS=readItemsFromUnknownLines(self.file, self.NV, float)
154        self.VNAME=readItemsFromLines(self._readLines(self.NV), self.NV, str)
155
156    def _writeVariablesHeaderSection(self):
157        """
158        Writes the variables section of the header.
159        Assumes we are at the right point in the file.
160        """       
161        self.file.write("%s\n" % self.NV)
162        self.file.write(("%s "*self.NV+"\n") % tuple(self.VSCAL))
163        self.file.write(("%s "*self.NV+"\n")  % tuple(self.VMISS))
164        self.file.write("%s\n"*self.NV % tuple(self.VNAME))
165
166    def _readAuxVariablesHeaderSection(self):
167        """
168        Reads the auxiliary variables section of the header.
169        Assumes we are at the right point in the file.
170        """
171        self.NAUXV=readItemFromLine(self.file.readline(), int)
172        if self.NAUXV>0:       
173            self.ASCAL=readItemsFromUnknownLines(self.file, self.NAUXV, float)
174            self.AMISS=readItemsFromUnknownLines(self.file, self.NAUXV, float)
175            self.ANAME=readItemsFromLines(self._readLines(self.NAUXV), self.NAUXV, str)
176
177    def _writeAuxVariablesHeaderSection(self):
178        """
179        Writes the auxiliary variables section of the header.
180        Assumes we are at the right point in the file.
181        """       
182        self.file.write("%s\n" % self.NAUXV)
183        if self.NAUXV>0:
184            self.file.write(("%s "*self.NAUXV+"\n")  % tuple(self.ASCAL))
185            self.file.write(("%s "*self.NAUXV+"\n")  % tuple(self.AMISS))
186            self.file.write("%s\n"*self.NAUXV % tuple(self.ANAME))
187
188    def _readCharAuxVariablesHeaderSection(self):
189        """
190        Reads the character-encoded auxiliary variables section of the header.
191        Assumes we are at the right point in the file.
192        """
193        self.NAUXV=readItemFromLine(self.file.readline(), int)
194        self.NAUXC=readItemFromLine(self.file.readline(), int)
195        nonCharAuxVars=self.NAUXV-self.NAUXC
196        if self.NAUXV>0:
197            self.ASCAL=readItemsFromUnknownLines(self.file, nonCharAuxVars, float)
198            self.AMISS=readItemsFromUnknownLines(self.file, nonCharAuxVars, float)
199            self.LENA=readItemsFromUnknownLines(self.file, self.NAUXC, int)
200            for i in range(nonCharAuxVars):
201                self.LENA.insert(0, None)
202            self.AMISS=self.AMISS+readItemsFromUnknownLines(self.file, self.NAUXC, str)   
203            self.ANAME=readItemsFromLines(self._readLines(self.NAUXV), self.NAUXV, str)       
204           
205    def _readComments(self):
206        """
207        Reads the special and normal comments sections.
208        Assumes we are at the right point in the file.
209        """       
210        self.NSCOML=readItemFromLine(self.file.readline(), int)
211        self._readSpecialComments()
212        self.NNCOML=readItemFromLine(self.file.readline(), int)
213        self._readNormalComments()
214
215    def _writeComments(self):
216        """
217        Writes the special and normal comments sections.
218        Assumes we are at the right point in the file.
219        """ 
220        self.file.write("%s\n" % self.NSCOML)
221        self.file.write("%s\n"*self.NSCOML % tuple(self.SCOM))
222        self.file.write("%s\n" % self.NNCOML)
223        self.file.write("%s\n"*self.NNCOML % tuple(self.NCOM))
224
225    def _readSpecialComments(self):
226        """
227        Reads the special comments section.       
228        Assumes that we are at the right point in the file and that NSCOML
229        variable is known.
230        """
231        self.SCOM=self._readLines(self.NSCOML)
232        return self.SCOM
233
234    def _readNormalComments(self):
235        """
236        Reads the normal comments section.       
237        Assumes that we are at the right point in the file and that NNCOML
238        variable is known.
239        """
240        self.NCOM=self._readLines(self.NNCOML)
241        return self.NCOM
242
243    def readData(self):
244        """
245        Reads the data section of the file. This method actually calls a number
246        of FFI specific methods to setup the data arrays (lists of lists) and
247        read the various data sections.
248
249        This method can be called directly by the user.
250        """
251        self._setupArrays()
252        datalines=open(self.filename).readlines()[self.NLHEAD:]
253        datalines=self._checkForBlankLines(datalines)
254
255        # Set up loop over unbounded indpendent variable
256        m=0   # Unbounded independent variable mark       
257        while len(datalines)>0:
258            datalines=self._readData1(datalines, m)
259            datalines=self._readData2(datalines, m)
260            m=m+1   
261
Note: See TracBrowser for help on using the repository browser.