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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI04-geosplat/trunk/pygss/common.py@6809
Revision 1660, 8.2 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"""
6common.py
7=========
8
9Holds common functions and classes used in the package.
10
11"""
12
13# Import python modules
14import os
15
16# Import package modules
17from serverConfig import *
18
19# Set up commmon variables. These are CAPITALISED to
20# improve visibility in other modules.
21
22STAGES=["DatasetPage", "VariablesPage", "RenderingOptionsPage", "PlotConfigPage", "ResultsPage"]
23
24DOMAIN_PARAMS=("start_time", "end_time", "time_interval", "horiz_domain", 
25                      "resolution", "vertical_units", "vertical_domain", 
26                       "outputFormat")
27
28GRAPHICAL_OUTPUT_TYPES_OR_STRING="PointValueAndMetadata|YvsXGraph|2DPlot|2DLatLonPlot|Animation|TrajectoriesOverMap|MultipleTrajectoriesOver2DLatLonPlot"
29GRAPHICAL_OUTPUT_TYPES=GRAPHICAL_OUTPUT_TYPES_OR_STRING.split("|")
30
31# Set up common functions
32
33def isUndefined(dict, item): 
34    """
35    Function that returns 1 if item is not a key in dict or
36    is defined as None in dict.
37    """
38    if dict.has_key(item):
39        if dict[item]!=None:
40            return 0
41    return 1
42   
43   
44def keyPatternMatch(dct, pattern):
45    """
46    Returns 1 if one or more keys in the dictionary 'dct' match the
47    pattern provided using string.find(). Returns 0 otherwise.
48    """
49    for key in dct.keys():
50        if key.find(pattern)>-1:
51            return 1
52    return 0
53   
54
55def getValuesInRange(start, end, array):
56    """
57    getValuesInRange function - takes a start and end value and returns the
58    values in the array that are between them.
59    """
60    # check all are floats
61    array=map(lambda x: float(x), list(array))
62    if array[0]>array[-1]: array.reverse()
63    if start>end:  (start, end)=(end, start)
64    (start, end)=(float(start), float(end))
65    rtarray=[]
66    for i in array:
67        if i>=start and i<=end:
68            rtarray.append(i)
69    return rtarray
70
71def normaliseXCoord(x):
72    """
73    Converts x values to somewhere in range (0,360)
74    """
75    if x<0:
76        return x+360
77    return x
78
79def getSpatialOverlap(bbox1, bbox2):
80    """
81    If no spatial overlap (i.e. < 2 deg of overlap in lat or lon)
82    then return None. Otherwise return the bounding box that covers
83    both in a way that will be useful to plot. This may shift a global
84    coverage to a new startX, endX.
85    """
86    threshold=2 # degrees
87    t=threshold # quicker to type
88    (ya,xa,yb,xb)=bbox1 # (south,west,north,east)
89    (yc,xc,yd,xd)=bbox2
90   
91    n=normaliseXCoord
92    xa=n(xa)
93    xb=n(xb)
94    xc=n(xc)
95    xd=n(xd)
96   
97    if xc>=(xb-t) or xd<=(xa+t): return None
98    if yd<=(ya+t) or yc>=(yb-2): return None
99   
100    ybot=max(ya,yc)
101    ytop=min(yb,yd)
102    xbot=min(xa,xc)
103    xtop=max(xb,xd)
104   
105    # Now create a slight buffer so not touching edges (unless 90N and 90S)
106    ytop=ytop+t
107    ybot=ybot-t
108    if ytop>90: ytop=90
109    if ybot<-90: ybot=-90
110
111    return (ybot,xbot,ytop,xtop) 
112
113
114def getattrNone(item, attr):
115    """
116    Returns the attr of item or None.
117    """
118    if not hasattr(item, attr):
119        return None
120    return getattr(item, attr)
121
122def identifyLatLonVarIDs(cdmsFile):
123    """
124    Returns list of latID and lonID in file or cdmsFile object.
125    Any not found are returned as "None" type.
126    """
127    if type(cdmsFile)==type("filename"):
128        import cdms
129        f=cdms.open(cdmsFile)
130    else:
131        f=cdmsFile
132    varIDs=f.listvariables()
133    latLon=[None, None]
134   
135    lonPoss=("longitude", "Longitude", "Lon", "lon", "Lng", "lng")
136    latPoss=("latitude", "Latitude", "Lat", "lat")
137   
138    for varID in varIDs:
139        var=f[varID]
140        if getattrNone(var, "standard_name")=="latitude": latLon[0]=varID
141        if getattrNone(var, "standard_name")=="longitude": latLon[1]=varID
142        if getattrNone(var, "long_name") in latPoss: latLon[0]=varID
143        if getattrNone(var, "long_name") in lonPoss: latLon[1]=varID
144        if varID in latPoss: latLon[0]=varID
145        if varID in lonPoss: latLon[1]=varID
146       
147    return latLon
148   
149def translateURI(uri):
150    """
151    Takes a URL and returns the location of the file on the local network
152    or takes a local path and returns the URL of the file/directory.
153    """
154    if uri.find("http")>-1:
155        newpath=uri.replace(OUTPUT_DIR_URL, OUTPUT_DIR)
156    else:
157        newpath=uri.replace(OUTPUT_DIR, OUTPUT_DIR_URL)
158    return newpath
159
160
161def getBestName(v):
162        """
163        Returns the most appropriate variable or axis name for a long name listing.
164        """       
165        if not hasattr(v, "standard_name"):
166            if not hasattr(v, "long_name"):
167                   if not hasattr(v, "title"):
168                       if not hasattr(v, "name"):
169                           if hasattr(v, "id"):
170                               name=v.id
171                           else:
172                               name="unnamed_variable"
173                       else:
174                           name=v.name
175                   else:
176                       name=v.title
177            else:
178                   name=v.long_name
179        else:
180               name=v.standard_name
181        # Fix name to remove leading asterisks and lower case surface start.
182        name=name.replace("_", " ")
183        if name[:2]=="**": name=(name[2:]).strip()
184        if name[:7]=="surface": name=(name[7:]).strip()
185        return name
186
187
188def minmax(array):
189    """
190    Returns the min and max of any 1-D array.
191    """
192    mn=min(array)
193    mx=max(array)
194    return (mn,mx)
195
196
197def deUnicodeObject(obj):
198    """
199    Returns the object identical except unicode strings are all
200    converted to normal strings.
201    """
202    tupleFound=None
203    if type(obj)==type((1,2)): 
204        tupleFound=1
205        obj=list(obj)
206
207    if type(obj)==type([]):
208        rtobj=[]
209        for i in obj:
210            if type(i) in (type([]), type((1,2))):
211                rtobj.append(deUnicodeObject(i)) 
212            elif type(i)==type(u""):
213                rtobj.append(str(i))
214            else:
215                rtobj.append(i)
216        if tupleFound==1: rtobj=tuple(rtobj)
217
218    elif type(obj)==type(u""):
219        rtobj=str(obj)
220    else: 
221        rtobj=obj
222    return rtobj
223
224def overlap(list1, list2):
225    """
226    overlap function - returns a list of overlapping items in list1 and list2.
227    Otherwise returns None.
228    """ 
229    rtlist=[]
230    for i in list1:
231       if i in list2: rtlist.append(i)
232
233    if len(rtlist)>0:
234        return rtlist
235    else:
236        return None
237
238def makeDirsAndPerms(basedir, dirs, permissions, owner, verbose="no"):
239    """
240    A function for making directories recursively and setting permissions/ownership.
241    """
242    if type(dirs)==str: dirs=[dirs]
243    dirs=[basedir]+list(dirs)
244    dir=None
245
246    while len(dirs)>0:
247
248        if dir:
249            dir=os.path.join(dir, dirs[0])
250        else:
251            dir=dirs[0]
252        dirs=dirs[1:]
253
254        if not os.path.exists(dir):
255            if verbose=="yes":   print "Making directory:", dir
256            os.mkdir(dir)
257            os.chmod(dir, permissions)
258            os.system('/bin/chown %s %s' % (owner, dir))
259
260    return
261   
262def checkSubDirectory(user=None):
263    """
264    checkSubDirectory method - checks if the required sub-directory exists
265    to write the output and if not it creates it.
266    """ 
267    if user==None or user=="None":   user="anonymous"
268    outputDir=os.path.join(OUTPUT_DIR, user, "dx_output")
269    if not os.path.isdir(outputDir):
270        makeDirsAndPerms(OUTPUT_DIR, (user, "dx_output"), OUTPUT_DIR_PERMISSION, "%s.%s" %
271                                           (OUTPUT_FILE_USER, OUTPUT_FILE_GROUP))
272    # Local rule follows
273    if LOCAL_RULES==1:  makeAccessControlFile(user)     
274    return outputDir
275   
276# Set up common classes
277class RedirectStdout:
278    """
279    RedirectStdout class - used to direct standard output away from
280    the screen in CGI scripts.
281    """
282
283    def write(self, item):
284        """
285        write method - allows dummy standard out to work.
286        """
287        pass
288
289    def flush(self):
290        """
291        Method to do nothing, again!
292        """
293        pass
Note: See TracBrowser for help on using the repository browser.