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

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

Unstable but latest version with multi-variable support and split hooks
for CDML and CSML.

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
12"""
13
14# Import library modules
15import os, sys, re
16
17# Import external modules
18import cdms
19
20# Import package modules
21from serverConfig import *
22from common import *
23
24class NumericalOperations:
25    """
26    Class used to perform various mathematical operations involving one or
27    more variables.
28    """
29   
30    def __init__(self, opstring):
31        """
32        Method to take in the operation string and map it to an operation using
33        variables provided.
34        """         
35        operation=self._parseOperation(opstring)
36       
37       
38    def _parseOperation(self, opstring):
39        """
40        Parses the operation string.
41        """
42        matchedIndices=re.findall(r"\(variable(\d+)\)", opstring)
43        self.variableIndices=[int(i)-1 for i in matchedIndices]
44        if opstring=="(variable2)-(variable1)":
45            self.opMethod=self.var2_minus_var1
46        elif opstring=="(variable1)-(variable2)":
47            self.opMethod=self.var1_minus_var2
48       
49           
50    def performOperation(self, varList):
51        """
52        Calls appropriate method to actually perform operation.
53        """
54        apply(self.opMethod, (varList,))
55
56       
57    def _chooseOperation(self, opstring):
58        """
59        Method to map operation string to a known method.
60        """
61        if opstring=="var1 - var2":
62            method=self.v1minusv2
63        elif opstring=="var2 - var1":
64            method=self.v2minusv1
65        elif opstring=="var1 + var2":
66            method=self.v1addv2
67        elif opstring=="var1 * var2":
68            method=self.v1timesv2
69        elif opstring=="var1 / var2":
70            method=self.v1dividedbyv2
71        elif opstring=="var2 / var1":
72            method=self.v2dividedbyv1
73        elif opstring=="((var1**2) + (var2**2))**0.5":
74            method=self.magv1v2
75        elif opstring=="var1, var2 (as they come)":
76            method=self.v1andv2
77        return method
78
79       
80    def processOperation(self, variables):
81        """
82        Method to actually process the operation.
83        """
84        vars=self.operation()
85        return vars
86       
87       
88    def var2_minus_var1(self, varList):
89        """
90        Method to subtract var1 from var2. Returns the resulting array
91        as a transient variable.
92        """
93        varList.reverse()
94        return self.var1_minus_var2(varList)   
95       
96       
97    def var1_minus_var2(self, varList):
98        """
99        Method to subtract var2 from var1. Returns the resulting array
100        as a transient variable.
101        """
102        (var1, var2)=varList
103
104        if compareGrids(var1.getGrid(), var2.getGrid())==0:
105            # Use the standard CDAT regridder to interpolate variable 2 to variable 1 grid.
106            # This might be replaced by the SCRIP regridder (or other) in future.
107            if var1.rank()!=var2.rank():
108                var1=var1(squeeze=1)
109                var2=var2(squeeze=1)
110            #print var1, var2
111            try:
112                var1Grid=var1.getGrid()
113                var2Grid=var2.getGrid()         
114                v1Size=var1Grid.size()
115                v2Size=var2Grid.size()         
116                if v1Size>=v2Size:
117                    var1=var1.regrid(var2Grid)
118                else: # v2Size>v1Size
119                    var2=var2.regrid(var1Grid)
120                   
121            except Exception, error:
122                raise DXProcessingError, "An error occurred whilst trying to interpolate variables to same grid."
123               
124        print "Differencing datasets..."
125
126        # Subtract var2 from var1
127        array=var1-var2
128       
129        # Create some metadata for the new variable name
130        rtVar=cdms.createVariable(array, grid=var1.getGrid())
131        rtVar.name="Differenced dataset: %s - %s" % (var1.id, var2.id)
132        rtVar.long_name=rtVar.name
133        rtVar.title=rtVar.name     
134        rtVar.id="%s_minus_%s" % (var1.id, var2.id)
135        if hasattr(rtVar, "units"):   del rtVar.units
136
137        return rtVar
138
139
140if __name__=="__main__":
141    x=NumericalOperations("(variable1)-(variable2)")
142    print x.variableIndices
143    print x.opMethod
144    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")])
145   
Note: See TracBrowser for help on using the repository browser.