source: TI04-geosplat/trunk/pygss/GSController.py @ 1660

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI04-geosplat/trunk/pygss/GSController.py@6809
Revision 1660, 12.8 KB checked in by astephen, 14 years ago (diff)

Version with overlay of trajectories on top of model fields draft version working before any rigourous testing.

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"""
6GSController.py
7===============
8
9The core class for controlling the package.
10
11"""
12
13# Import required modules
14import sys
15import os 
16import time 
17
18# Bring package into local scope
19#from serverConfig import BASEDIR
20#sys.path.insert(0, os.path.split(BASEDIR)[0])
21from pygss import *
22
23 
24# Add any other locally required directories in which you have modules.
25for path in LOCAL_PYTHONPATH:
26   sys.path.insert(0, path) 
27
28
29class GSController:
30    """
31    Controls the overall process flow of the a session.
32    This class is called through each stage of the interactive process
33    and responds according to the environment and arguments provided.
34    Note that this class is called by the WSInterface
35    class which then reads various instance variables. As a result, very
36    little is returned from the methods below. Instead the data is stored
37    in the instance object.
38    """
39   
40    def __init__(self, args):
41        """
42        Takes in a group of arguments and then calls the appropriate
43        methods to process the user request.
44        """
45        self.username="undefined" 
46        self.password="undefined"
47        self.userRoles=[]
48        self.sessionID=None
49        self.sessionObj=None
50        self.bag=self.sessionObj # alias       
51        self.secureToken="undefined"
52        self.error=None
53   
54        # Parse the arguments
55        try:
56            self._parseArgs(args)
57        except Exception, error:
58            raise Exception, error
59           
60        # If switched on check security       
61        if self.error==None:
62            if RESTRICTED_DATA==1:
63                try:
64                    self._checkSecurity()
65                except Exception, error:
66                    raise Exception, error   
67            else:
68                self.secureToken="undefined"
69                   
70        # Construct the session object
71        if self.error==None:   
72            try:   
73                self._constructSessionObject()   
74            except Exception, error:
75                raise Exception, error
76
77        # Generate the options object
78        if self.error==None:   
79            try:   
80                self._generateOptions()   
81            except Exception, error:
82                raise Exception, error         
83
84
85        # Write request to a file if it has some content
86        if self.error==None:
87          if overlap(["dataset_1", "variable_1", "sessionID", "numberOfDatasets"], 
88                      self.bag.keys()):                       
89            self.bag["accessTime"]=time.time()             
90            self.sessionObjectManager.writeSessionObject(self.bag) 
91   
92            # Validate the selection against known information
93            try:           
94                self._validate()                   
95            except Exception, error:
96                raise Exception, error
97           
98        # Estimate the cost of the extraction
99        creditChecked=None
100        if self.error==None:   
101          if self.bag.has_key("action") and self.bag["action"]=="checkCredit":     
102            # Check user has sufficient credit
103            try:           
104                self._checkCredit()   
105                creditChecked="yes"                 
106            except Exception, error:
107                raise Exception, error
108
109        # Estimate the cost of the extraction
110        if self.error==None:   
111          if self.bag.has_key("action") and self.bag["action"]=="requestCosts":
112           
113            try:
114                (self.estimatedDuration, self.estimatedVolume)=self._createOutput(costOnly=1)
115                sizeLimitInBytes=REQUEST_SIZE_LIMIT*2L**20
116                # If size is over limit then send a tidy error to the user
117                if self.estimatedVolume>sizeLimitInBytes:
118                    sizeInMB=self.estimatedVolume/(2L**20.)
119                    err="""Your request of %.1f MB is over the current %s MB size limit.       
120The Data Extractor cannot yet deal with such large requests.
121Consider mailing <A HREF="mailto:%s">%s</A> for advice or submit multiple smaller requests.""" % (sizeInMB, 
122                               REQUEST_SIZE_LIMIT, ADMIN_MAIL_ADDRESS, ADMIN_MAIL_ADDRESS)     
123                    errorCatcher=ErrorHandler(None, self.username, self.sessionID)
124                    self.error=errorCatcher.displayError(err)
125                    sys.exit() 
126            except Exception, error:
127                raise Exception, error
128
129        # Process the selections to generate some data
130        if self.error==None:   
131            if (self.bag.has_key("getOutput") or (self.bag.has_key("action") and self.bag["action"]=="createOutput")) and creditChecked==None:
132                # Check user has sufficient credit
133                try:       
134                    self._checkCredit()                     
135                except Exception, error:
136                    raise Exception, error
137                           
138                try:                   
139                    self._createOutput()           
140                    self.logger=LogManager(self.bag)       
141                    self.bag["status"]="complete"       
142                    self.logger.logCompletedRequest(self.bag["outputFilePath"])         
143                except Exception, error:
144                    raise Exception, error
145   
146        if self.error==None:
147            print "Saving session details:\n", self.bag, "\n\n" 
148            if self.bag.has_key("action") and self.bag["action"]=="clearRequest":
149                del self.bag["action"]
150            elif self.bag.has_key("action") and self.bag["action"]=="createOutput":
151                del self.bag["action"]
152            elif self.bag.has_key("getOutput"):
153                del self.bag["getOutput"]
154            self.sessionObjectManager.writeSessionObject(self.bag)
155        else:
156            self.logger=LogManager(self.bag) 
157            self.logger.logError(self.error)
158         
159           
160    def _parseArgs(self, args):
161        """
162        Parses the argument dictionary that are sent.
163        """                     
164        self.args={}
165        for key, value in args.items():
166            if type(key)==type(u""):
167                newkey=str(key)
168            else:
169                newkey=key
170                   
171            if type(value)==type(u""):
172                newvalue=str(value)
173            else:
174                newvalue=value
175               
176            self.args[newkey]=newvalue
177           
178   
179        for item in ("username", "password", "secureToken"):
180            if self.args.has_key(item):             
181                value=self.args[item]               
182                setattr(self, item, value)
183                del self.args[item]
184               
185        print "ARGS and SecureToken:", self.args, self.secureToken
186                             
187
188    def _checkSecurity(self):
189        """
190        Checks security by getting username and
191        allowed groups from whatever implementation you have put in place.
192        """
193        secChecker=SecurityManager(self.username, self.password, self.secureToken) 
194        # Do something about logout here as well
195     
196        secCheck=secChecker.validateUser() 
197        self.username=secChecker.username
198
199        if type(secCheck)==type(""):
200            raise secCheck
201        elif type(secCheck)==type([]):
202            (self.secureToken, self.userRoles)=secCheck 
203        else: 
204            raise str(secCheck)+str(type(secCheck))#"No response from Security class!"
205           
206
207    def _constructSessionObject(self):
208        """
209        Ensures that all appropriate arguments are being written
210        to the session object in the correct manner. Note that the
211        session object "sessionObj" is just a dictionary but is read
212        in from a shelve object (if it exists already).
213        """     
214        # self.args now holds the input arguments
215        if not self.args.has_key("sessionID"): 
216            self.sessionObjectManager=SessionObject()
217            self.bag=self.sessionObjectManager.dict
218            #self.sessionObj["targetPage"]=STAGES=[0]
219        else: 
220            self.sessionObjectManager=SessionObject(self.args["sessionID"]) 
221            self.bag=self.sessionObjectManager.readSessionObject() 
222            # Clear the session object if requested
223            if self.args.has_key("clearRequest") or self.args.has_key("newRequest"):
224                self.sessionObjectManager.clearSessionObject(self.bag) 
225               
226        if type(self.sessionID)==type(u""):
227            self.sessionID=str(self.sessionID) 
228               
229        # Update session object with allowed roles at each stage (this is checked every reload)
230        self.bag["userRoles"]=self.userRoles
231
232        # Say it is under construction at present
233        self.bag["status"]="constructing"
234       
235        # Add the rest of the arguments to the session object
236        for key in self.args.keys(): 
237            self.bag[key]=self.args[key] 
238
239        # Might need username later
240        if self.bag.has_key("username"):
241            self.username=self.bag["username"]
242        else:
243            self.bag["username"]=self.username
244   
245
246    def _generateOptions(self):
247        """
248        Method that examines the current status of the request to create an appropriate
249        list of options for the user. Made up of many if clauses to control a logical
250        response to the current request.
251        """
252       
253        if keyPatternMatch(self.bag, "fileURI")==0:
254            print self.bag
255            self.options={"AWAITING_FILEURIS":"AWAITING_FILEURIS"}
256            return
257           
258        optionHandler=OptionHandler(self.bag["userRoles"], self.username, self.bag)
259        self.options=optionHandler.options
260        if hasattr(optionHandler, "varDict"):
261            self.bag["varDict"]=optionHandler.varDict
262             
263        return
264       
265       
266    def _validate(self):
267        """
268        Validates the selections made by the user. Returns 1 if successful
269        and a string if failure.
270        """
271        validater=ValidateSelection(self.bag)
272        validResponse=validater.validate()
273        if validResponse!=1:
274            raise validResponse
275           
276     
277    def _checkCredit(self):
278        """
279        Checks if the user has the available credit to the selection task. Returns 1 if successful
280        and a string if failure.
281        """
282        creditChecker=CreditManager(self.username, self.bag)
283        creditResponse=creditChecker.creditCheck()
284        if creditResponse!=1:
285            raise creditResponse
286           
287           
288    def _createOutput(self, costOnly=None):
289        """
290        Creates either data file.
291        """   
292        if costOnly==1:
293            requestCoster=RequestCost(self.bag) 
294            return requestCoster.getDurationAndVolume()                     
295
296        # Now really get data...
297        outman=OutputManager(self.bag) 
298
299        if outman.textOnly:
300            print "FOUND POINT VALUE OUTPUT - send to client."
301            self.message=outman.textOnly
302            # Fill in some request values needed by logger
303            for key in ["outputFilePath", "fileFormat"]:
304                self.bag[key]="NOT_APPLICABLE"     
305            return
306       
307        print """Should really fork this process at this point so that we can return
308              something if likely to be large job."""
309        try:
310            outman.createOutputs() 
311        except:
312            raise Exception, "Problem generating requested output file."
313
314        self.bag["outputFilePath"]=outman.localPath       
315        self.bag["outputURLPath"]=outman.URLPath
316   
317if __name__=="__main__":
318    print "Trying to plot trajectory over model field...\n"
319    b=GSController({'getOutput':"getOutput", 'status': 'constructing', 'username': 'undefined', 'outputURLPath': 'http://localhost/gs/output/output_20061018074443.gif', 'graphicalOutputType': 'MultipleTrajectoriesOver2DLatLonPlot_1.5-2.1', 'projection': 'standard', 'proceed': 'Proceed', 'fileURIList': ['/data/traj.nc', '/data/var2.nc'], 'userRoles': [], 'fileVariable_1.5': 'temp', 'varDict': {'2.1': {'domain': {'latitude': ['latitude', 'latitude', [-90, 90]], 'grots': [['2DLatLonPlot', "2D Lat-Lon Plot for variable 'var2' from file: '/data/var2.nc'"]], 'ordered_axes': ['time', 'latitude', 'longitude'], 'longitude': ['longitude', 'longitude', [0, 355]], 'time': ['time', 'time', [0, 0]]}, 'id': 'var2'}, '1.1': {'domain': {'grots': [['TrajectoriesOverMap', "Trajectories plotted on map for variable 'lat' from file: '/data/traj.nc'"], ['2DPlot', "2D Plot for variable 'lat' from file: '/data/traj.nc'"]], 'bbox': (67.399993896484375, 22.500001907348633, 42.299999237060547, 126.36080169677734), 'parcel': ['parcel', 'unrecognised', [0.0, 1.0]], 'ordered_axes': ['time', 'parcel'], 'time': ['time', 'time', [0.0, 432000.0]]}, 'id': 'lat'}, '1.5-2.1': {'domain': {'grots': [['MultipleTrajectoriesOver2DLatLonPlot', "Multiple Trajectories for variable 'temp' plotted over 2D Plot for variable 'var2'"]], 'bbox': (90, 0, -90, 355)}}}, 'sessionID': 'session_20061018074431451', 'fileVariable_2.1': 'var2', 'plotType': 'MultipleTrajectoryOverBoxfillLinear', 'mapArea':'surroundingArea', 'outputFilePath': '/home/as56/apache/htdocs/gs/output/output_20061018074443.gif', 'fileFormat': 'gif', 'accessTime': 1161157483.026027, 'imageSize': '800x600'})
320   
321    #({'mapArea':"global", 'outputURLPath': 'http://localhost/gs/output/output_20061004002742.gif', 'graphicalOutputType': 'MultipleTrajectoriesOver2DLatLonPlot_1.1-2.1', 'projection': 'standard', 'getOutput':"getOutput", 'fileURIList': ['/data/traj.nc','/data/var2.nc'], 'fileVariable_1.1': 'temp', 'fileVariable_2.1':'var2', 'sessionID': 'session_20061004002735159', 'plotType': 'MultipleTrajectoryOverBoxfillLinear', 'outputFilePath': '/home/as56/apache/htdocs/gs/output/output_20061004002742.gif', 'fileFormat': 'gif', 'imageSize': '800x600'})
322    sys.exit()
323       
324       
325    GSController({'username': 'undefined', 'outputURLPath': 'http://localhost/gs/output/output_20061004002742.gif', 'graphicalOutputType': 'TrajectoriesOverMap_1.1', 'projection': 'standard', 'getOutput':"getOutput", 'fileURIList': ['/data/traj.nc'], 'userRoles': [], 'fileVariable_1.1': 'lat', 'sessionID': 'session_20061004002735159', 'plotType': 'MultipleTrajectory', 'outputFilePath': '/home/as56/apache/htdocs/gs/output/output_20061004002742.gif', 'fileFormat': 'gif', 'accessTime': 1159921662.625607, 'imageSize': '800x600'})
Note: See TracBrowser for help on using the repository browser.