source: nappy/tags/NDG0-1/naFile.py @ 349

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/nappy/tags/NDG0-1/naFile.py@3005
Revision 349, 9.8 KB checked in by selatham, 15 years ago (diff)

Inserted license information.

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