source: nappy/tags/ver_0-9-7/naFile.py @ 339

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/nappy/tags/ver_0-9-7/naFile.py@8769
Revision 339, 28.7 KB checked in by astephen, 16 years ago (diff)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""
2naFile.py
3=========
4
5A module to hold the mixin base class NAFile that is subclassed
6for individual FFIs. Further classes are the subclasses for other FFIs.
7
8"""
9
10# Imports from Python standard library
11import sys
12import time
13import re
14
15# Imports from local package
16from naCore import *
17from textParser import *
18from cdmsMap import cdmsMap
19
20# Import external packages (if available)
21if sys.platform.find("win")>-1:
22    pass
23else:
24    try:
25        import cdms, Numeric 
26    except:
27        print "Cannot import cdms package, CDAT-dependent features will not work."
28
29# Define global variables
30NAPlatformError="Platform error: You cannot use the CDAT-dependent features on a Windows Platform."
31safe_nc_id=re.compile(r"[\s\^%$£\"'\[\]\(\)\{\}=+!/]+")
32cdms.setAutoBounds("off")
33
34
35class NAFile(NACore):
36
37    def __init__(self, filename, mode="r", naDict=None):
38        NACore.__init__(self)
39        self.naDict=naDict
40        self.filename=filename
41        self.open(mode)
42        if mode=="r":
43            self.normalizedX="yes"
44            self.readHeader()
45            self.readData()
46        elif mode=="w":
47            self.parseDictionary()
48            self.writeHeader()
49            self.writeData()
50        else:
51            raise "Unknown file mode '%s'." % mode
52        self.close()
53       
54    def open(self, mode):
55        self.file=open(self.filename, mode)
56
57    def close(self):
58        self.file.close()
59
60    def parseDictionary(self):
61        for i in self.naDict.keys():
62            setattr(self, i, self.naDict[i])
63
64    def readTopLine(self):
65        """
66        Reads number of header lines and File Format Index from top line.
67        Also assigns a value to NIV for the number of indepndent variables
68        based on the first character in the FFI.
69        """
70        (self.NLHEAD, self.FFI)=readItemsFromLine(self.file.readline(), 2, int)
71        self.NIV=int(self.FFI/1000)
72        return (self.NLHEAD, self.FFI)
73
74    def readLines(self, nlines):
75        lines=[]
76        for i in range(nlines):
77            lines.append(self.file.readline().strip())
78        return lines
79
80    def checkForBlankLines(self, datalines):
81        """
82        Searches for empty lines in the middle of the data section and raises
83        as error if found. It ignores empty lines at the end of the file but
84        strips them out before returning a list of lines for reading.
85        """
86        empties=None
87        count=0
88        rtlines=[]
89        for line in datalines:
90            if re.match(r"^[\s\n\t\r]*$", line):
91                empties=1
92            else:
93                if empties==1:   # If data line found after empty line then raise
94                    raise "Empty line found in data section at line: %s" % count
95                else:
96                    rtlines.append(line)
97            count=count+1
98        return rtlines
99
100    def readCommonHeader(self):
101        self.readTopLine()
102        self.ONAME=readItemFromLine(self.file.readline(), str)
103        self.ORG=readItemFromLine(self.file.readline(), str)
104        self.SNAME=readItemFromLine(self.file.readline(), str)
105        self.MNAME=readItemFromLine(self.file.readline(), str)
106        (self.IVOL, self.NVOL)=readItemsFromLine(self.file.readline(), 2, int)
107        dates=readItemsFromLine(self.file.readline(), 6, int)
108        (self.DATE, self.RDATE)=(dates[:3], dates[3:])
109
110    def writeCommonHeader(self):
111        self.file.write("%s    %s\n" % (self.NLHEAD, self.FFI))
112        self.file.write("%s\n" % self.ONAME)
113        self.file.write("%s\n" % self.ORG)
114        self.file.write("%s\n" % self.SNAME)
115        self.file.write("%s\n" % self.MNAME)
116        self.file.write("%s    %s\n" % (self.IVOL, self.NVOL))
117        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]))
118
119    def readVariablesHeaderSection(self):
120        """Assumes we are at the right point in the file"""
121        self.NV=readItemFromLine(self.file.readline(), int)
122        self.VSCAL=readItemsFromUnknownLines(self.file, self.NV, float)
123        self.VMISS=readItemsFromUnknownLines(self.file, self.NV, float)
124        self.VNAME=readItemsFromLines(self.readLines(self.NV), self.NV, str)
125
126    def writeVariablesHeaderSection(self):
127        self.file.write("%s\n" % self.NV)
128        self.file.write(("%s "*self.NV+"\n") % tuple(self.VSCAL))
129        self.file.write(("%s "*self.NV+"\n")  % tuple(self.VMISS))
130        self.file.write("%s\n"*self.NV % tuple(self.VNAME))
131
132    def readAuxVariablesHeaderSection(self):
133        """Assumes we are at the right point in the file"""
134        self.NAUXV=readItemFromLine(self.file.readline(), int)
135        if self.NAUXV>0:       
136            self.ASCAL=readItemsFromUnknownLines(self.file, self.NAUXV, float)
137            self.AMISS=readItemsFromUnknownLines(self.file, self.NAUXV, float)
138            self.ANAME=readItemsFromLines(self.readLines(self.NAUXV), self.NAUXV, str)
139
140    def writeAuxVariablesHeaderSection(self):
141        self.file.write("%s\n" % self.NAUXV)
142        if self.NAUXV>0:
143            self.file.write(("%s "*self.NAUXV+"\n")  % tuple(self.ASCAL))
144            self.file.write(("%s "*self.NAUXV+"\n")  % tuple(self.AMISS))
145            self.file.write("%s\n"*self.NV % tuple(self.ANAME))
146
147    def readCharAuxVariablesHeaderSection(self):
148        """Assumes we are at the right point in the file"""
149        self.NAUXV=readItemFromLine(self.file.readline(), int)
150        self.NAUXC=readItemFromLine(self.file.readline(), int)
151        nonCharAuxVars=self.NAUXV-self.NAUXC
152        if self.NAUXV>0:
153            self.ASCAL=readItemsFromUnknownLines(self.file, nonCharAuxVars, float)
154            self.AMISS=readItemsFromUnknownLines(self.file, nonCharAuxVars, float)
155            self.LENA=readItemsFromUnknownLines(self.file, self.NAUXC, int)
156            for i in range(nonCharAuxVars):
157                self.LENA.insert(0, None)
158            self.AMISS=self.AMISS+readItemsFromUnknownLines(self.file, self.NAUXC, str)   
159            self.ANAME=readItemsFromLines(self.readLines(self.NAUXV), self.NAUXV, str)       
160           
161    def readComments(self):
162        """Assumes we are at the right point in the file"""       
163        self.NSCOML=readItemFromLine(self.file.readline(), int)
164        self.readSpecialComments()
165        self.NNCOML=readItemFromLine(self.file.readline(), int)
166        self.readNormalComments()
167
168    def writeComments(self):
169        self.file.write("%s\n" % self.NSCOML)
170        self.file.write("%s\n"*self.NSCOML % tuple(self.SCOM))
171        self.file.write("%s\n" % self.NNCOML)
172        self.file.write("%s\n"*self.NNCOML % tuple(self.NCOM))
173
174    def readSpecialComments(self):
175        """Assumes that we are at the right point in the
176        file and that NSCOML variable is known."""
177        self.SCOM=self.readLines(self.NSCOML)
178        return self.SCOM
179
180    def readNormalComments(self):
181        """Assumes that we are at the right point in the
182        file and requires NNCOML variable."""
183        self.NCOM=self.readLines(self.NNCOML)
184        return self.NCOM
185
186    def _recursiveListPopulator(self, inlist, array, dimlist):
187        """
188        Populates the list object 'inlist' (e.g. []) with sublists of
189        dimensionality defined in the 'dimlist' list of dimensions (e.g [181, 360]).
190        At the deepest level it then inserts values from the long list
191        'array'.
192        """
193        if not hasattr(self, "_counter"):
194            self._counter=0
195        if len(dimlist[1:])>0:
196            for i in range(dimlist[0]):
197                inlist.append([])
198                self._recursiveListPopulator(inlist[i], array, dimlist[1:])
199        else:
200            count=self._counter
201            self._counter=self._counter+dimlist[0]
202            endcount=self._counter
203            for i in range(count, endcount):
204                inlist.append(array[i])
205        return inlist
206
207    def _recursiveListWriter(self, inlist, dimlist):
208        """
209        Goes through all the levels of the multi-level list object 'inlist' and
210        writes out appropriate values to lines of the output file 'self.file'.
211        'dimlist' is a list of the dimensions within 'inlist'.
212        """
213        if len(dimlist[1:])>0:
214            for i in range(dimlist[0]):
215                self._recursiveListWriter(inlist[i], dimlist[1:])
216        else:
217            var_string=""
218            for i in range(dimlist[0]):
219                var_string=var_string+("%s    " % inlist[i])
220            self.file.write("%s\n" % var_string.rstrip())
221
222
223    def toCdmsFile(self, filename, variables="all", aux_variable="all", global_attributes={"Conventions":"CF-1.0"}, ffi=None):
224        if sys.platform.find("win")>-1:
225            raise NAPlatformError
226
227        self.cdmsFilename=filename
228        self.cdmsFile=cdms.open(self.cdmsFilename, 'w')
229       
230        # at file level: write global attributes
231        for key in global_attributes.keys():
232            setattr(self.cdmsFile, key, global_attributes[key])
233
234        for key in cdmsMap["fromNA"].keys():
235            if type(key)==tuple:
236                if key==("SCOM", "NCOM"):
237                    commentline="NASA Ames Special Comments:\n"
238                    for i in self.SCOM: commentline=commentline+"\n"+i
239                    commentline=commentline+"NASA Ames Normal Comments:\n"
240                    for i in self.NCOM: commentline=commentline+"\n"+i
241                    self.cdmsFile.comment=commentline
242                else:
243                    item=(getattr(self, key[0]))+"\n"+(getattr(self, key[1]))
244                    setattr(self.cdmsFile, cdmsMap["fromNA"][key], item)
245            elif key=="RDATE":
246                dateparts=getattr(self, "RDATE")
247                datestring="%.4d-%.2d-%.2d" % tuple(dateparts)
248                item=datestring+" - NASA Ames File created/revised.\n"
249                timestring=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
250                item=item+"\n"+timestring+" - Data written to NetCDF file."
251            else:
252                setattr(self.cdmsFile, cdmsMap["fromNA"][key], getattr(self, key))
253
254        # Then do dimensions
255        if not hasattr(self, 'cdmsAxes'):  self.createCdmsAxes()
256
257        # Then do variables
258        if not hasattr(self, 'cdmsVariables'):  self.createCdmsVariables()
259        for var in self.cdmsVariables:
260            self.cdmsFile.write(var)
261
262        # Then do auxiliary variables
263        if hasattr(self, "NAUXV") and type(self.NAUXV)==int:   # Are there any auxiliary variables?
264            if not hasattr(self, 'cdmsAuxVariables'):  self.createCdmsAuxVariables()
265            for avar in self.cdmsAuxVariables:
266                self.cdmsFile.write(avar)
267
268        self.cdmsFile.close()
269        return "Cdmsfile '%s' written successfully." % self.cdmsFilename
270
271    def createCdmsVariables(self):
272        self.cdmsVariables=[]
273        for var_number in range(self.NV):
274            self.cdmsVariables.append(self.toCdmsVariable(var_number))
275
276
277    def toCdmsVariable(self, var_number, attributes={}):
278        if sys.platform.find("win")>-1:
279            raise NAPlatformError
280        (varname, units, miss, scal)=self.getVariable(var_number)
281
282        array=Numeric.array(self.V[var_number])
283        array=array*scal
284        # Set up axes
285        if not hasattr(self, 'cdmsAxes'):
286            self.createCdmsAxes()
287
288        # Set up variable
289        var=cdms.createVariable(array, axes=self.cdmsAxes, fill_value=miss, attributes=attributes)
290
291        # Sort units etc
292        if units:   var.units=units
293        if len(varname)<20:
294            var.id=safe_nc_id.sub("_", varname).lower()
295        else:
296            var.id="naVariable_%s" % (var_number)
297
298        var.long_name=var.name=varname
299        if varname in ("standard_name_list",) or varname in ("badc_list",):
300            var.standard_name="name from the list*****"
301
302        return var
303
304    def createCdmsAuxVariables(self):
305        self.cdmsAuxVariables=[]
306        for avar_number in range(self.NAUXV):
307            self.cdmsAuxVariables.append(self.auxToCdmsVariable(avar_number))
308
309    def auxToCdmsVariable(self, avar_number, attributes={}):
310        if sys.platform.find("win")>-1:
311            raise NAPlatformError
312        (varname, units, miss, scal)=self.getAuxVariable(avar_number)
313        array=Numeric.array(self.A[avar_number])
314        array=array*scal
315
316        # Set up axes
317        if not hasattr(self, 'cdmsAxes'):
318            self.createCdmsAxes()
319
320        # Set up variable
321        var=cdms.createVariable(array, axes=[self.cdmsAxes[0]], fill_value=miss, attributes=attributes)
322
323        # Sort units etc
324        if units:   var.units=units
325        if len(varname)<20:
326            var.id=safe_nc_id.sub("_", varname).lower()
327        else:
328            var.id="naAuxVariable_%s" % (avar_number)
329
330        var.long_name=var.name=varname
331        if varname in ("standard_name_list",) or varname in ("badc_list",):
332            var.standard_name="name from the list*****"
333
334        return var       
335
336    def createCdmsAxes(self):
337        if sys.platform.find("win")>-1:
338            raise NAPlatformError
339        if not hasattr(self, 'cdmsAxes'):       
340            self.cdmsAxes=[]
341        for ivar_number in range(self.NIV):
342            self.cdmsAxes.append(self.toCdmsAxis(ivar_number))
343
344    def toCdmsAxis(self, ivar_number):
345        if sys.platform.find("win")>-1:
346            raise NAPlatformError
347
348        if self.normalizedX=="no": self._normalizeIndVars()
349
350        if self.NIV==1:
351            array=self.X
352        else:
353            array=self.X[ivar_number]
354        axis=cdms.createAxis(array)
355        axis.id=axis.name=axis.long_name=self.XNAME[ivar_number]
356        (varname, units)=self.getIndependentVariable(ivar_number)
357        # Sort units etc
358        if units:   axis.units=units
359        if len(varname)<20:
360            axis.id=safe_nc_id.sub("_", varname).lower()
361        else:
362            axis.id="naAuxVariable_%s" % (ivar_number)
363
364        if units: axis.units=units
365        axis_types=("longitude", "latitude", "level", "time")
366        designators={"longitude":axis.designateLongitude, "latitude":axis.designateLatitude,
367                     "level":axis.designateLevel, "time":axis.designateTime}
368        for axis_type in axis_types:
369            if re.search(axis_type, varname, re.IGNORECASE):
370                axis.standard_name=axis.id=axis_type
371                apply(designators[axis_type.lower()])
372        return axis
373
374
375class NAFile1001(NAFile):
376
377    def readHeader(self):
378        self.readCommonHeader()
379        self.DX=readItemsFromLine(self.file.readline(), self.NIV, float)
380        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
381        self.readVariablesHeaderSection()
382        self.readComments()
383
384    def writeHeader(self):
385        self.writeCommonHeader()
386        self.file.write(("%s "*self.NIV+"\n") % tuple(self.DX))
387        self.file.write("%s\n"*self.NIV % tuple(self.XNAME))
388        self.writeVariablesHeaderSection()
389        self.writeComments()
390
391    def readData(self):
392        self._setupArrays()
393        datalines=open(self.filename).readlines()[self.NLHEAD:]
394        datalines=self.checkForBlankLines(datalines)
395
396        # Set up loop over unbounded indpendent variable
397        m=0   # Unbounded independent variable mark       
398        while len(datalines)>0:
399            datalines=self._readData1(datalines, m)
400            datalines=self._readData2(datalines, m)
401            m=m+1   
402
403    def _setupArrays(self):
404        self.X=[]
405        self.V=[]
406        # Set up the variables list
407        for n in range(self.NV):
408            self.V.append([])
409           
410    def _readData1(self, datalines, ivar_count): 
411        # Start with independent and Auxilliary vars
412        (x2_and_a, rtlines)=readItemsFromUnknownLines(datalines, 1+self.NAUXV, float)
413        (x, aux)=(x2_and_a[0], x2_and_a[1:])
414        self.X[0].append(x)
415        count=0
416        for a in range(self.NAUXV):
417            self.A[a].append(aux[count])
418            count=count+1
419        return rtlines
420
421    def _readData1(self, datalines, ivar_count): 
422        (x_and_v, rtlines)=readItemsFromUnknownLines(datalines, 1+self.NV, float)
423        (x, v)=(x_and_v[0], x_and_v[1:])
424        self.X.append(x)
425        count=0
426        # Set up mth list in self.V
427        for n in range(self.NV):
428            self.V[n].append(v[count])
429            count=count+1
430        return rtlines   
431
432    def _readData2(self, datalines, ivar_count):                 
433        return datalines 
434
435    def writeData(self):
436        for i in range(len(self.X)):
437            var_string=""
438            for n in range(self.NV):
439                var_string=var_string+("%s    " % self.V[n][i])
440            self.file.write("%s    %s\n" % (self.X[i], var_string))
441               
442       
443class NAFile1010(NAFile1001):
444
445    def readHeader(self):
446        self.readCommonHeader()
447        self.DX=readItemsFromLine(self.file.readline(), self.NIV, float)
448        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
449        self.readVariablesHeaderSection()
450        self.readAuxVariablesHeaderSection()
451        self.readComments()
452
453    def _setupArrays(self):
454        self.X=[]
455        self.V=[]
456        self.A=[]
457        for n in range(self.NV):
458            self.V.append([])
459        for a in range(self.NAUXV):
460            self.A.append([])
461
462    def _readData1(self, datalines, ivar_count): 
463        # Start with independent and Auxilliary vars
464        (x2_and_a, rtlines)=readItemsFromUnknownLines(datalines, 1+self.NAUXV, float)
465        (x, aux)=(x2_and_a[0], x2_and_a[1:])
466        self.X.append(x)
467        count=0
468        for a in range(self.NAUXV):
469            self.A[a].append(aux[count])
470            count=count+1
471        return rtlines
472   
473    def _readData2(self, datalines, ivar_count): 
474        # Now get the dependent variables
475        (v, rtlines)=readItemsFromUnknownLines(datalines, self.NV, float)             
476        # Set up mth list in self.V           
477        self.V.append([])
478        count=0
479        for n in range(self.NV):
480            self.V[n].append([])
481            self.V[ivar_count].append(v[count])
482            count=count+1
483        return rtlines
484           
485
486class NAFile1020(NAFile1010):
487
488    def readHeader(self):
489        self.normalizedX="no"
490        self.readCommonHeader()
491        self.DX=readItemsFromLine(self.file.readline(), self.NIV, float)
492        if self.DX==0:
493            raise "DX found to be zero (0). Not allowed for FFI 1020."
494
495        self.NVPM=readItemFromLine(self.file.readline(), int)
496        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
497        self.readVariablesHeaderSection()
498        self.readAuxVariablesHeaderSection()
499        self.readComments()
500 
501    def _readData2(self, datalines, ivar_count): 
502        # Now get the dependent variables
503        (v, rtlines)=readItemsFromUnknownLines(datalines, self.NV*self.NVPM, float)             
504        count=0
505        for n in range(self.NV):
506            self.V[n].append([])
507            for i in range(self.NVPM):   # Number of steps where independent variable is implied
508                self.V[n][ivar_count].append(v[count])
509            count=count+1
510        return rtlines
511
512    def _normalizeIndVars(self):
513        """
514        Normalizes the values in the unbounded independent variable for FFIs
515        that store an abbreviated version of this axis.
516        """
517        newX=[]
518        for x in self.X[0]:
519            for i in range(self.NVPM):
520                newX.append(x+(i*self.DX))
521        self.X[0]=newX
522        self.normalizedX="yes"
523
524
525class NAFile2010(NAFile):
526
527    def readHeader(self):
528        self.normalizedX="no"
529        self.readCommonHeader()
530        self.DX=readItemsFromLine(self.file.readline(), self.NIV, float)
531        self.DX.reverse()  # Reverse because C-type array is least-changing first
532        self.NX=readItemsFromLine(self.file.readline(), self.NIV-1, int)
533        self.NX.reverse()  # Reverse because C-type array is least-changing first
534        self.NXDEF=readItemsFromLine(self.file.readline(), self.NIV-1, int)
535        self.NXDEF.reverse()  # Reverse because C-type array is least-changing first
536        self.X=[]
537        for i in range(self.NIV-1):
538            self.X.append(readItemsFromUnknownLines(self.file, self.NXDEF[i], float))
539        # Unbounded Independent variable should be first so insert empty list at start
540        self.X.insert(0, [])
541        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
542        self.XNAME.reverse()  # Reverse because C-type array is least-changing first
543        self.readVariablesHeaderSection()
544        self.readAuxVariablesHeaderSection()
545        self.readComments()
546
547    def writeHeader(self):
548        self.writeCommonHeader()
549        self.DX.reverse()
550        self.file.write(("%s "*self.NIV+"\n") % tuple(self.DX))
551        self.NX.reverse()
552        self.file.write(("%s "*(self.NIV-1)+"\n") % tuple(self.NX))
553        self.NXDEF.reverse()
554        self.file.write(("%s "*(self.NIV-1)+"\n") % tuple(self.NXDEF))
555        for i in range(self.NIV-1):
556            self.file.write(("%s "*self.NXDEF[i]+"\n") % tuple(self.X[i+1][0:self.NXDEF[i]]))           
557        self.XNAME.reverse()
558        self.file.write("%s\n"*self.NIV % tuple(self.XNAME))
559        self.writeVariablesHeaderSection()
560        self.writeAuxVariablesHeaderSection()
561        self.writeComments()       
562
563    def readData(self):
564        self._setupArrays()
565        datalines=open(self.filename).readlines()[self.NLHEAD:]
566        datalines=self.checkForBlankLines(datalines)
567
568        # Set up loop over unbounded indpendent variable
569        m=0   # Unbounded independent variable mark       
570        while len(datalines)>0:
571            datalines=self._readData1(datalines, m)
572            datalines=self._readData2(datalines, m)
573            m=m+1   
574
575    def _setupArrays(self):
576        self.V=[]
577        self.A=[]
578        # Create an array size to request using read routines
579        self.arraySize=1
580        for i in self.NX:
581            self.arraySize=self.arraySize*i       
582        for n in range(self.NV):
583            self.V.append([])
584        for a in range(self.NAUXV):
585            self.A.append([])
586           
587    def _readData1(self, datalines, ivar_count): 
588        # Start with independent and Auxilliary vars
589        (x2_and_a, rtlines)=readItemsFromUnknownLines(datalines, 1+self.NAUXV, float)
590        (x, aux)=(x2_and_a[0], x2_and_a[1:])
591        self.X[0].append(x)
592        count=0
593        for a in range(self.NAUXV):
594            self.A[a].append(aux[count])
595            count=count+1
596        return rtlines
597
598    def _readData2(self, datalines, ivar_count):
599        # Now get the dependent variables         
600        (v, rtlines)=readItemsFromUnknownLines(datalines, self.arraySize, float)
601        for n in range(self.NV):
602            self.V[n].append([])
603            self._recursiveListPopulator(self.V[n][ivar_count], v, self.NX)
604            del self._counter
605        return rtlines   
606
607    def writeData(self):
608        # Set up unbounded IV loop
609        self.NX.reverse()
610        for m in range(len(self.X[0])):
611            # Write Independent variable mark and auxiliary variables
612            var_string="%s    " % self.X[0][m]
613            for a in range(self.NAUXV):
614                var_string=var_string+("%s    " % self.A[a][m])
615            self.file.write("%s\n" % var_string.rstrip())
616            # Write Variables
617            for n in range(self.NV):
618                self._recursiveListWriter(self.V[n][m], self.NX)
619
620    def _normalizeIndVars(self):
621        """
622        Normalizes the values in the unbounded independent variable for FFIs
623        that store an abbreviated version of this axis.
624        """
625        for i in range(self.NIV-1):
626            if self.NXDEF[i]==self.NX[i]:
627                pass
628            else:
629                del self.X[i+1][1:]
630                count=0
631                while len(self.X[i+1])<self.NX[i]:
632                    nextx=self.X[i+1][count]+self.DX[i+1]
633                    self.X[i+1].append(nextx)
634                    count=count+1
635        self.normalizedX="yes"
636
637
638class NAFile2110(NAFile2010):
639
640    def readHeader(self):
641        self.readCommonHeader()
642        self.DX=readItemsFromLine(self.file.readline(), self.NIV, float)
643        self.DX.reverse()  # Reverse because C-type array is least-changing first       
644        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
645        self.XNAME.reverse()  # Reverse because C-type array is least-changing first       
646        self.readVariablesHeaderSection()
647        self.readAuxVariablesHeaderSection()
648        self.readComments()
649
650    def _setupArrays(self):
651        self.V=[]
652        self.A=[]
653        self.X=[]  # Needs to be a list of sublists each containing [x0n, [x1n, x1n+1, x1n+2....]]
654        self.NX=[]
655 
656        for n in range(self.NV):
657            self.V.append([])
658        for i in range(self.NAUXV):
659            self.A.append([])
660
661    def _readData1(self, datalines, ivar_count): 
662        # Start with independent and Auxilliary vars
663        (x_and_a, rtlines)=readItemsFromUnknownLines(datalines, self.NAUXV+1, float)
664        (x, aux)=(x_and_a[0], x_and_a[1:])
665        for a in range(self.NAUXV):
666            self.A.append(aux[a])
667        self.X.append([])
668        self.X[ivar_count].append(x)
669        # Set up list to take second changing independent variable
670        self.X[ivar_count].append([]) 
671        self.NX.append(int(aux[0]))
672        return rtlines
673   
674    def _readData2(self, datalines, ivar_count): 
675        # Now get the dependent variables
676        for n in range(self.NV):
677            self.V[n].append([])
678        for c in range(self.NX[ivar_count]):
679            (x_and_v, datalines)=readItemsFromUnknownLines(datalines, self.NV+1, float)
680            (x, v)=(x_and_v[0], x_and_v[1:])
681            self.X[ivar_count][1].append(x)
682            count=0
683            for n in range(self.NV):
684                self.V[n][ivar_count].append(v[count])
685                count=count+1
686        rtlines=datalines
687        return rtlines
688
689
690class NAFile2160(NAFile2110):
691
692    def readHeader(self):
693        self.normalizedX="no"
694        self.readCommonHeader()
695        self.DX=readItemsFromLine(self.file.readline(), 1, float)
696        self.LENX=readItemFromLine(self.file.readline(), float)
697        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
698        self.XNAME.reverse()  # Reverse because C-type array is least-changing first         
699        self.readVariablesHeaderSection()
700        self.readCharAuxVariablesHeaderSection()
701        self.readComments()
702
703    def _setupArrays(self):
704        self.V=[]
705        self.A=[]
706        self.X=[]
707        self.NX=[]
708       
709        for n in range(self.NV):
710            self.V.append([])
711        for i in range(self.NAUXV):
712            self.A.append([])
713
714    def _readData1(self, datalines, ivar_count): 
715        # Start with independent and Auxilliary vars
716        # Get character string independent variable
717        (x1, datalines)=readItemsFromUnknownLines(datalines, 1, str)
718        self.X.append([])
719        self.X[ivar_count].append(x1)
720        # Set up list to take second changing independent variable
721        self.X[ivar_count].append([]) 
722        # Get NX and Non-character AUX vars
723        (aux, datalines)=readItemsFromUnknownLines(datalines, (self.NAUXV-self.NAUXC), float)
724        self.NX.append(int(aux[0]))
725        for a in range(self.NAUXV-self.NAUXC):
726            self.A.append(aux[a])
727        # Get character AUX vars
728        (auxc)=readItemsFromLines(datalines[:self.NAUXC], self.NAUXC, str)
729        rtlines=datalines[self.NAUXC:]
730        for a in range(self.NAUXC):
731            self.A.append(auxc[a])
732        return rtlines
733   
734
735class NAFile2310(NAFile2110):
736
737    def readHeader(self):
738        self.normalizedX="no"
739        self.readCommonHeader()
740        self.DX=readItemsFromLine(self.file.readline(), 1, float)
741        self.XNAME=readItemsFromLines(self.readLines(self.NIV), self.NIV, str)
742        self.XNAME.reverse()  # Reverse because C-type array is least-changing first         
743        self.readVariablesHeaderSection()
744        self.readAuxVariablesHeaderSection()
745        self.readComments()
746   
747    def _readData1(self, datalines, ivar_count): 
748        # Start with independent and Auxilliary vars
749        (x_and_a, rtlines)=readItemsFromUnknownLines(datalines, self.NAUXV+1, float)
750        (x, aux)=(x_and_a[0], x_and_a[1:])
751        for a in range(self.NAUXV):
752            self.A.append(aux[a])
753        self.X.append([])
754        self.X[ivar_count].append(x)
755        # Set up list to take second changing independent variable
756        self.X[ivar_count].append([aux[1]]) 
757        self.NX.append(int(aux[0]))
758        self.DX.append(int(aux[2]))
759        return rtlines
760   
761    def _readData2(self, datalines, ivar_count): 
762        # Now get the dependent variables
763        (v, rtlines)=readItemsFromUnknownLines(datalines, self.NV*self.NX[ivar_count], float)
764        count=0
765        for n in range(self.NV):
766            self.V[n].append([])
767            for i in range(self.NX[ivar_count]):
768                self.V[n][ivar_count].append(v[count])
769                count=count+1
770        return rtlines
771
772
773class NAFile3010(NAFile2010):
774    """
775    Identical class rules to FFI 3010.
776    """
777    pass
778
779class NAFile4010(NAFile2010):
780    """
781    Identical class rules to FFI 4040.
782    """
783    pass
Note: See TracBrowser for help on using the repository browser.