source: TI03-DataExtractor/trunk/pydxs/NumericalOperations.py @ 1109

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxs/NumericalOperations.py@1109
Revision 1109, 4.3 KB checked in by astephen, 13 years ago (diff)

Stable-ish version with fully-ish working dxc client.

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"""
6NumericalOperations.py
7======================
8
9Holds the NumericalOperations class used to perform various
10mathematical operations involving one or more variables.
11
12Some notes on what is to come...
13
14currently we support:
15
16MA.log
17log10
18maximum
19minimum
20pi
21sin
22tan
23sqrt
24cos
25arccos
26arctan
27arcsin
28exp
29absolute
30+
31-
32()
33/
34*
35**
36
37and variables must be represented
38as (variableXXX)
39
40start by parsing out all the
41
42start with
43(variableXXX)-(variableXXX)
44
45"###########################"
46
47replace any whitespace with nothing.
48
49"##########################"
50
51search for "(variable\d+)"
52
53"###(variable1)#(variable2)"
54
55search for "+-*/"
56
57"##+(variable1)*(variable2)"
58
59search for "pi,exp,cos, arctan, ...etc"
60
61"pi+(variable1)*(variable2)"
62
63
64"""
65
66# Import library modules
67import os, sys, re
68
69# Import external modules
70import cdms
71
72# Import package modules
73from serverConfig import *
74from common import *
75from DXErrors import *
76
77
78class NumericalOperations:
79    """
80    Class used to perform various mathematical operations involving one or
81    more variables.
82    """
83   
84    def __init__(self, opstring):
85        """
86        Method to take in the operation string and map it to an operation using
87        variables provided.
88        """         
89        operation=self._parseOperation(opstring)
90       
91       
92    def _parseOperation(self, opstring):
93        """
94        Parses the operation string.
95        """
96        matchedIndices=re.findall(r"\(var(\d+)\)", opstring)
97        self.variableIndices=[int(i)-1 for i in matchedIndices]
98        if opstring=="(var2)-(var1)":
99            self.opMethod=self.var2_minus_var1
100        elif opstring=="(var1)-(var2)":
101            self.opMethod=self.var1_minus_var2
102        else:
103            raise DXOptionHandlingError, "Operation '%s' is not supported." % opstring
104       
105           
106    def performOperation(self, varList):
107        """
108        Calls appropriate method to actually perform operation.
109        """
110        try: 
111            rtVar=apply(self.opMethod, (varList,))
112            return rtVar
113        except:
114            raise DXProcessingError, "Could not complete '%s' operation requested." % self.opMethod.__name__
115       
116       
117    def var2_minus_var1(self, varList):
118        """
119        Method to subtract var1 from var2. Returns the resulting array
120        as a transient variable.
121        """
122        varList.reverse()
123        return self.var1_minus_var2(varList)   
124       
125       
126    def var1_minus_var2(self, varList):
127        """
128        Method to subtract var2 from var1. Returns the resulting array
129        as a transient variable.
130        """
131        (var1, var2)=varList
132
133        if var1.getGrid()==None and var2.getGrid()==None:
134            pass
135        elif compareGrids(var1.getGrid(), var2.getGrid())==0:
136            # Use the standard CDAT regridder to interpolate variable 2 to variable 1 grid.
137            # This might be replaced by the SCRIP regridder (or other) in future.
138            if var1.rank()!=var2.rank():
139                var1=var1(squeeze=1)
140                var2=var2(squeeze=1)
141            #print var1, var2
142            try:
143                var1Grid=var1.getGrid()
144                var2Grid=var2.getGrid()         
145                v1Size=var1Grid.size()
146                v2Size=var2Grid.size()         
147                if v1Size>=v2Size:
148                    var1=var1.regrid(var2Grid)
149                else: # v2Size>v1Size
150                    var2=var2.regrid(var1Grid)
151                   
152            except Exception, error:
153                raise DXProcessingError, "An error occurred whilst trying to interpolate variables to same grid."
154               
155        print "Differencing datasets..."
156
157        # Subtract var2 from var1
158        array=var1-var2
159       
160        # Create some metadata for the new variable name
161        rtVar=cdms.createVariable(array, grid=var1.getGrid())
162        rtVar.name="Differenced dataset: %s - %s" % (var1.id, var2.id)
163        rtVar.long_name=rtVar.name
164        rtVar.title=rtVar.name     
165        rtVar.id="%s_minus_%s" % (var1.id, var2.id)
166        if hasattr(rtVar, "units"):   del rtVar.units
167
168        return rtVar
169
170
171if __name__=="__main__":
172    x=NumericalOperations("(var1)-(var2)")
173    print x.variableIndices
174    print x.opMethod.__name__
175    print x.performOperation([cdms.open("/usr/local/dx/testdata/testdata1.xml")("pqn", time=slice(0,1)), cdms.open("/usr/local/dx/testdata/testdata2.xml")("var2")])
176    x=NumericalOperations("(var1)-(var2)")
177    print x.performOperation([cdms.open("/dxd/zeros.nc")("t"), cdms.open("/dxd/200plus.nc")("t")])
178    x=NumericalOperations("(var2)-(var1)")
179    print x.performOperation([cdms.open("/dxd/zeros.nc")("t"), cdms.open("/dxd/200plus.nc")("t")])
180   
Note: See TracBrowser for help on using the repository browser.