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 | """ |
---|
6 | VariableAnalyser.py |
---|
7 | =================== |
---|
8 | |
---|
9 | Contains the VariableAnalyser class that is used to determine the |
---|
10 | type of feature present and any other useful information related |
---|
11 | to plotting options. |
---|
12 | |
---|
13 | It analyses the dimensionality, type of axes and the name of the |
---|
14 | variable to do this. |
---|
15 | |
---|
16 | """ |
---|
17 | |
---|
18 | # Import library modules |
---|
19 | import os, sys |
---|
20 | |
---|
21 | # Import package modules |
---|
22 | from serverConfig import * |
---|
23 | from common import * |
---|
24 | from FeatureTypes import * |
---|
25 | from GSErrors import * |
---|
26 | |
---|
27 | # Import external modules |
---|
28 | import cdms |
---|
29 | |
---|
30 | class VariableAnalyser: |
---|
31 | """ |
---|
32 | Class for analysing the nature of each variable. |
---|
33 | """ |
---|
34 | |
---|
35 | def __init__(self, filename, varID, graphicalOutputType=None, animationAxes=None): |
---|
36 | """ |
---|
37 | Takes a variable and analyses it to return a known Feature type. |
---|
38 | The Feature types can then be mapped to known plotting operations. |
---|
39 | """ |
---|
40 | self.filename=filename |
---|
41 | self.varID=varID |
---|
42 | cdmsfile=cdms.open(self.filename) |
---|
43 | self.var=cdmsfile[varID] |
---|
44 | self._analyse(graphicalOutputType, animationAxes) |
---|
45 | cdmsfile.close() |
---|
46 | |
---|
47 | |
---|
48 | def _analyse(self, graphicalOutputType, animationAxes): |
---|
49 | """ |
---|
50 | Calls various analysing methods. |
---|
51 | """ |
---|
52 | if graphicalOutputType==None: |
---|
53 | ft=self._getFeatureType() |
---|
54 | self.plotOpts=self._getGraphicalOutputTypes(ft) |
---|
55 | else: |
---|
56 | print graphicalOutputType*10 |
---|
57 | self.plotConfigurationDict=self._getPlotConfigurationDetails(graphicalOutputType, animationAxes) |
---|
58 | |
---|
59 | |
---|
60 | def _getFeatureType(self): |
---|
61 | """ |
---|
62 | Return Feature Type if can be identified, otherwise returns None. |
---|
63 | """ |
---|
64 | |
---|
65 | axes=self.var.getAxisList() |
---|
66 | shape=self.var.shape |
---|
67 | size=self.var.size() |
---|
68 | |
---|
69 | # Begin by squeezing out singleton axes |
---|
70 | if size==1: |
---|
71 | return "PointFeature" |
---|
72 | |
---|
73 | usefulAxes=[] |
---|
74 | for axis in axes: |
---|
75 | if len(axis)>1: usefulAxes.append(axis) |
---|
76 | |
---|
77 | ndims=len(usefulAxes) |
---|
78 | if ndims==1: |
---|
79 | return "ProfileFeature" |
---|
80 | elif ndims==2: |
---|
81 | return "2DGridFeature" |
---|
82 | elif ndims>2: |
---|
83 | return "%sDGridFeature" % ndims |
---|
84 | |
---|
85 | |
---|
86 | def _getGraphicalOutputTypes(self, featureType): |
---|
87 | """ |
---|
88 | Returns broad graphical output types available for a given |
---|
89 | feature type. |
---|
90 | """ |
---|
91 | ft=featureType |
---|
92 | |
---|
93 | if ft=="PointFeature": |
---|
94 | return [["PointValueAndMetadata", "Display single value for variable '%s' from file: '%s'" % (self.varID, self.filename)]] |
---|
95 | |
---|
96 | elif ft=="ProfileFeature": |
---|
97 | return [["YvsXGraph", "Y-vs-X Graph for variable '%s' from file: '%s'" % (self.varID, self.filename)]] |
---|
98 | |
---|
99 | elif ft=="2DGridFeature": |
---|
100 | return [["2DPlot", "2D Plot for variable '%s' from file: '%s'" % (self.varID, self.filename)]] |
---|
101 | |
---|
102 | else: |
---|
103 | return [["Animation", "Animated series if 2D plots for variable '%s' from file: '%s'" % (self.varID, self.filename)]] |
---|
104 | |
---|
105 | |
---|
106 | def _getPlotConfigurationDetails(self, graphicalOutputType, animationAxes=None): |
---|
107 | """ |
---|
108 | Returns plot configuration details in a dictionary of options |
---|
109 | where each value is a list of lists holding the short name and long name |
---|
110 | of the available options. |
---|
111 | """ |
---|
112 | plotConfigDict={} |
---|
113 | grot=graphicalOutputType |
---|
114 | print grot |
---|
115 | if grot=="YvsXGraph": |
---|
116 | plotConfigDict["plotType"]=[["YvsXGraph", "Y-vs-X Graph"]] |
---|
117 | |
---|
118 | |
---|
119 | elif grot in ("2DPlot", "Animation"): |
---|
120 | |
---|
121 | if animationAxes!=None: |
---|
122 | |
---|
123 | (loopID, yID, xID)=animationAxes |
---|
124 | axisList=[] |
---|
125 | |
---|
126 | for axID in (loopID, yID, xID): |
---|
127 | axis=self.var.getAxis(self.var.getAxisIds().index(axID)) |
---|
128 | axisList.append(axis) |
---|
129 | |
---|
130 | else: |
---|
131 | axisList=[] |
---|
132 | for axis in self.var.getAxisList(): |
---|
133 | if len(axis)>1: |
---|
134 | axisList.append(axis) |
---|
135 | |
---|
136 | latLonAxesTest=self._testLatLon(axisList[-2:]) |
---|
137 | |
---|
138 | if latLonAxesTest: |
---|
139 | plotConfigDict["continentsSwitch"]=[["on", "Show continents"], ["off", "Do not show continents"]] |
---|
140 | |
---|
141 | [[south, north], [west, east]]=latLonAxesTest |
---|
142 | |
---|
143 | projections=[["standard", "Standard"]] |
---|
144 | if (east-west)>200: # Need 200+ degrees west-east to use projections safely |
---|
145 | projections.append(["mollweide", "Mollweide"]) |
---|
146 | projections.append(["robinson", "Robinson"]) |
---|
147 | |
---|
148 | if north>80 and south<10: |
---|
149 | projections.append(["northPolar", "Polar (Northern Hemisphere)"]) |
---|
150 | if north>-10 and south<-80: |
---|
151 | projections.append(["southPolar", "Polar (Southern Hemisphere)"]) |
---|
152 | |
---|
153 | plotConfigDict["projection"]=projections |
---|
154 | |
---|
155 | if grot=="2DPlot": |
---|
156 | plotTypes=[["boxfill", "Boxfill"],["isofill", "Isofill"], |
---|
157 | ["isoline", "Isoline"],["isolineAndFill", "Isoline and Isofill"]] |
---|
158 | elif grot=="Animation": |
---|
159 | plotTypes=[["boxfill", "Boxfill"],["isofill", "Isofill"], |
---|
160 | ["isoline", "Isoline"]] |
---|
161 | |
---|
162 | plotConfigDict["plotType"]=plotTypes |
---|
163 | |
---|
164 | |
---|
165 | # Start with the easy one, image sizes |
---|
166 | imageSizes=["800 x 600", "300 x 200", "600 x 400", "792 x 612", "1000 x 800"] |
---|
167 | imageSizesLists=[[i.replace(" ",""), i] for i in imageSizes] |
---|
168 | |
---|
169 | plotConfigDict["imageSize"]=imageSizesLists |
---|
170 | |
---|
171 | # Then file format, also straightforward |
---|
172 | if grot=="Animation": |
---|
173 | fileFormats=["GIF"] |
---|
174 | else: |
---|
175 | fileFormats=["GIF", "Postscript"] |
---|
176 | fileFormatsLists=[[i.lower(), i] for i in fileFormats] |
---|
177 | plotConfigDict["fileFormat"]=fileFormatsLists |
---|
178 | |
---|
179 | return plotConfigDict |
---|
180 | |
---|
181 | |
---|
182 | def _testLatLon(self, axes): |
---|
183 | """ |
---|
184 | Returns ([northernExtent, southernExtent], westernExtent, easternExtent]) |
---|
185 | if axes are lat and lon. |
---|
186 | """ |
---|
187 | latFound=None |
---|
188 | lonFound=None |
---|
189 | for ax in axes: |
---|
190 | if len(ax)>1: |
---|
191 | if ax.isLatitude(): latFound=minmax(ax) |
---|
192 | if ax.isLongitude(): lonFound=minmax(ax) |
---|
193 | if latFound and lonFound: |
---|
194 | return (latFound, lonFound) |
---|
195 | |
---|
196 | |
---|
197 | if __name__=="__main__": |
---|
198 | v=VariableAnalyser("/tmp/tmp.nc", "var1") |
---|
199 | print v.plotOpts |
---|
200 | a=VariableAnalyser("/tmp/tmp.nc", "var1", "2DPlot") |
---|
201 | print a.plotConfigurationDict |
---|