Completed
Push — master ( 98c26c...9e9700 )
by Michael
15:43
created

GridNavRetriever.createPolar()   C

Complexity

Conditions 9

Size

Total Lines 54
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 54
rs 6.5626
c 0
b 0
f 0
cc 9
nop 9

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
import os
2
import math
3
from awips import ThriftClient
4
from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.gempak.request import GetGridNavRequest
5
from ctypes import *
6
7
EARTH_RADIUS = 6371200.0
8
DEG_TO_RAD = math.pi / 180.0
9
RAD_TO_DEG = 180.0 / math.pi
10
TWOPI = math.pi * 2.0
11
HALFPI = math.pi / 2.0
12
PI4TH = math.pi / 4.0
13
PI3RD = math.pi / 3.0
14
15
16
def createPolar(nsflag, clon, lat1, lon1, dx, dy, unit, nx, ny):
17
    clonr = clon * DEG_TO_RAD
18
    latr = lat1 * DEG_TO_RAD
19
    lonr = lon1 * DEG_TO_RAD
20
    if nsflag == 'N':
21
        x1 = EARTH_RADIUS * math.tan(PI4TH - latr/2.0) * math.sin(lonr-clonr)
22
        y1 = -1 * EARTH_RADIUS * math.tan(PI4TH - latr/2.0) * math.cos(lonr-clonr)
23
    else:
24
        x1 = EARTH_RADIUS * math.tan(PI4TH + latr/2.0) * math.sin(lonr-clonr)
25
        y1 = EARTH_RADIUS * math.tan(PI4TH + latr/2.0) * math.cos(lonr-clonr)
26
27
    if unit == 'm':
28
        tdx = dx / (1 + math.sin(PI3RD))
29
        tdy = dy / (1 + math.sin(PI3RD))
30
    else:
31
        tdx = (dx*1000.0) / (1 + math.sin(PI3RD))
32
        tdy = (dy*1000.0) / (1 + math.sin(PI3RD))
33
34
    x2 = x1 + tdx * (nx-1)
35
    y2 = y1 + tdy * (ny-1)
36
    xll = min(x1, x2)
37
    yll = min(y1, y2)
38
    xur = max(x1, x2)
39
    yur = max(y1, y2)
40
41
    if nsflag == 'N':
42
        latll = (HALFPI - 2*math.atan2(math.hypot(xll, yll), EARTH_RADIUS)) * RAD_TO_DEG
43
        rtemp = clonr + math.atan2(xll, -yll)
44
    else:
45
        latll = -1 * (HALFPI - 2*math.atan2(math.hypot(xll, yll), EARTH_RADIUS)) * RAD_TO_DEG
46
        rtemp = clonr + math.atan2(xll, yll)
47
48
    if rtemp > math.pi:
49
        lonll = (rtemp-TWOPI) * RAD_TO_DEG
50
    elif rtemp < -math.pi:
51
        lonll = (rtemp+TWOPI) * RAD_TO_DEG
52
    else:
53
        lonll = rtemp * RAD_TO_DEG
54
55
    if nsflag == 'N':
56
        latur = (HALFPI - 2*math.atan2(math.hypot(xur, yur), EARTH_RADIUS)) * RAD_TO_DEG
57
        rtemp = clonr + math.atan2(xur, -yur)
58
    else:
59
        latur = -1 * (HALFPI - 2*math.atan2(math.hypot(xur, yur), EARTH_RADIUS)) * RAD_TO_DEG
60
        rtemp = clonr + math.atan2(xur, yur)
61
62
    if rtemp > math.pi:
63
        lonur = (rtemp-TWOPI) * RAD_TO_DEG
64
    elif rtemp < -math.pi:
65
        lonur = (rtemp+TWOPI) * RAD_TO_DEG
66
    else:
67
        lonur = rtemp * RAD_TO_DEG
68
69
    return [latll, lonll, latur, lonur]
70
71
72
def createConic(nsflag, clon, lat1, lon1, dx, dy, unit, nx, ny, ang1, ang3):
73
    clonr = clon * DEG_TO_RAD
74
    latr = lat1 * DEG_TO_RAD
75
    lonr = lon1 * DEG_TO_RAD
76
77
    angle1 = HALFPI - (math.fabs(ang1) * DEG_TO_RAD)
78
    angle2 = HALFPI - (math.fabs(ang3) * DEG_TO_RAD)
79
80
    if ang1 == ang3:
81
        cc = math.cos(angle1)
82
    else:
83
        cc = (math.log(math.sin(angle2)) - math.log(math.sin(angle1))) \
84
             / (math.log(math.tan(angle2/2.0)) - math.log(math.tan(angle1/2.0)))
85
86
    er = EARTH_RADIUS / cc
87
88
    if nsflag == 'N':
89
        x1 = er * math.pow(math.tan((HALFPI-latr)/2.0), cc) * math.sin(cc*(lonr-clonr))
90
        y1 = -1.0 * er * math.pow(math.tan((HALFPI-latr)/2.0), cc) * math.cos(cc*(lonr-clonr))
91
    else:
92
        x1 = er * math.pow(math.tan((HALFPI+latr)/2.0), cc) * math.sin(cc*(lonr-clonr))
93
        y1 = er * math.pow(math.tan((HALFPI+latr)/2.0), cc) * math.cos(cc*(lonr-clonr))
94
95
    alpha = math.pow(math.tan(angle1/2.0), cc) / math.sin(angle1)
96
97
    if unit == 'm':
98
        x2 = x1 + (nx-1) * alpha * dx
99
        y2 = y1 + (ny-1) * alpha * dy
100
    else:
101
        x2 = x1 + (nx-1) * alpha * (dx*1000.0)
102
        y2 = y1 + (ny-1) * alpha * (dy*1000.0)
103
104
    xll = min(x1, x2)
105
    yll = min(y1, y2)
106
    xur = max(x1, x2)
107
    yur = max(y1, y2)
108
109
    if nsflag == 'N':
110
        latll = (HALFPI - 2.0 * math.atan(math.pow(math.hypot(xll, yll)/er, (1/cc)))) * RAD_TO_DEG
111
        rtemp = math.atan2(xll, -yll) * (1/cc) + clonr
112
    else:
113
        latll = (-1.0 * (HALFPI - 2.0 * math.atan(math.pow(math.hypot(xll, yll)/er, (1/cc))))) * RAD_TO_DEG
114
        rtemp = math.atan2(xll, yll) * (1/cc) + clonr
115
116
    if rtemp > math.pi:
117
        lonll = (rtemp-TWOPI) * RAD_TO_DEG
118
    elif rtemp < -math.pi:
119
        lonll = (rtemp+TWOPI) * RAD_TO_DEG
120
    else:
121
        lonll = rtemp * RAD_TO_DEG
122
123
    if nsflag == 'N':
124
        latur = (HALFPI - 2.0 * math.atan(math.pow(math.hypot(xur, yur)/er, (1/cc)))) * RAD_TO_DEG
125
        rtemp = math.atan2(xur, -yur) * (1/cc) + clonr
126
    else:
127
        latur = (-1.0 * (HALFPI - 2.0 * math.atan(math.pow(math.hypot(xur, yur)/er, (1/cc))))) * RAD_TO_DEG
128
        rtemp = math.atan2(xur, yur) * (1/cc) + clonr
129
130
    if rtemp > math.pi:
131
        lonur = (rtemp-TWOPI) * RAD_TO_DEG
132
    elif rtemp < -math.pi:
133
        lonur = (rtemp+TWOPI) * RAD_TO_DEG
134
    else:
135
        lonur = rtemp * RAD_TO_DEG
136
137
    return [latll, lonll, latur, lonur]
138
139
140
class StringConverter(Union):
141
    _fields_ = [("char", c_char*4), ("int", c_int), ("float", c_float)]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable c_int does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable c_float does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable c_char does not seem to be defined.
Loading history...
142
143
144
class GridNavRetriever:
145
146
    def __init__(self, server, pluginName, modelId, arrayLen):
147
        self.pluginName = pluginName
148
        self.modelId = modelId
149
        self.arrayLen = arrayLen
150
        self.host = os.getenv("DEFAULT_HOST", server)
151
        self.port = os.getenv("DEFAULT_PORT", "9581")
152
        self.client = ThriftClient.ThriftClient(self.host, self.port)
153
154
    def getNavBlk(self):
155
        """ Sends ThriftClient request and writes out received files."""
156
        req = GetGridNavRequest()
157
        req.setPluginName(self.pluginName)
158
        req.setModelId(self.modelId)
159
        resp = self.client.sendRequest(req)
160
161
        nav = []
162
163
        for record in resp:
164
            unit = record['spacingunit']
165
            sk = record['spatialkey']
166
            skarr = sk.split('/')
167
168
            nx = float(skarr[1])
169
            ny = float(skarr[2])
170
            dx = float(skarr[3])
171
            dy = float(skarr[4])
172
173
            sc = StringConverter()
174
            if record['projtype'] == 'LatLon':
175
                sc.char = 'CED '
176
                gemproj = 2.0
177
                ang1 = 0.0
178
                ang2 = 0.0
179
                ang3 = 0.0
180
181
                lllat = float(record['lowerleftlat'])
182
                lllon = float(record['lowerleftlon'])
183
                urlat = lllat + (dy * (ny-1))
184
                urlon = lllon + (dx * (nx-1))
185
                if lllon > 180:
186
                    lllon -= 360.0
187
                if urlon > 180:
188
                    urlon -= 360.0
189
190
            if record['projtype'] == 'Polar Stereographic':
191
                sc.char = 'STR '
192
                gemproj = 2.0
193
                if float(record['standard_parallel_1']) < 0.0:
194
                    ang1 = -90.0
195
                    nsflag = 'S'
196
                else:
197
                    ang1 = 90.0
198
                    nsflag = 'N'
199
                ang2 = float(record['central_meridian'])
200
                ang3 = 0.0
201
202
                lat1 = float(record['lowerleftlat'])
203
                lon1 = float(record['lowerleftlon'])
204
                coords = createPolar(nsflag, ang2, lat1, lon1, dx, dy, unit, nx, ny)
205
                lllat = coords[0]
206
                lllon = coords[1]
207
                urlat = coords[2]
208
                urlon = coords[3]
209
210
            if record['projtype'] == 'Lambert Conformal':
211
                sc.char = 'LCC '
212
                gemproj = 2.0
213
214
                ang1 = float(skarr[7])
215
                ang2 = float(record['central_meridian'])
216
                ang3 = float(skarr[8])
217
                if ang1 < 0.0:
218
                    nsflag = 'S'
219
                else:
220
                    nsflag = 'N'
221
222
                lat1 = float(record['lowerleftlat'])
223
                lon1 = float(record['lowerleftlon'])
224
                coords = createConic(nsflag, ang2, lat1, lon1, dx, dy, unit, nx, ny, ang1, ang3)
225
                lllat = coords[0]
226
                lllon = coords[1]
227
                urlat = coords[2]
228
                urlon = coords[3]
229
230
            # Fill up the output array of floats
231
            nav.append(gemproj)
0 ignored issues
show
introduced by
The variable gemproj does not seem to be defined for all execution paths.
Loading history...
232
            nav.append(sc.float)
233
            nav.append(1.0)
234
            nav.append(1.0)
235
            nav.append(nx)
236
            nav.append(ny)
237
            nav.append(lllat)
0 ignored issues
show
introduced by
The variable lllat does not seem to be defined for all execution paths.
Loading history...
238
            nav.append(lllon)
0 ignored issues
show
introduced by
The variable lllon does not seem to be defined for all execution paths.
Loading history...
239
            nav.append(urlat)
0 ignored issues
show
introduced by
The variable urlat does not seem to be defined for all execution paths.
Loading history...
240
            nav.append(urlon)
0 ignored issues
show
introduced by
The variable urlon does not seem to be defined for all execution paths.
Loading history...
241
            nav.append(ang1)
0 ignored issues
show
introduced by
The variable ang1 does not seem to be defined for all execution paths.
Loading history...
242
            nav.append(ang2)
0 ignored issues
show
introduced by
The variable ang2 does not seem to be defined for all execution paths.
Loading history...
243
            nav.append(ang3)
0 ignored issues
show
introduced by
The variable ang3 does not seem to be defined for all execution paths.
Loading history...
244
245
        for i in range(13, int(self.arrayLen)):
246
            nav.append(0.0)
247
        return nav
248
249
    def getAnlBlk(self):
250
        anl = []
251
        # Type
252
        anl.append(2.0)
253
        # Delta
254
        anl.append(1.0)
255
        # Extend area
256
        anl.append(0.0)
257
        anl.append(0.0)
258
        anl.append(0.0)
259
        anl.append(0.0)
260
        # Grid area
261
        anl.append(-90.0)
262
        anl.append(-180.0)
263
        anl.append(90.0)
264
        anl.append(180.0)
265
        # Data area
266
        anl.append(-90.0)
267
        anl.append(-180.0)
268
        anl.append(90.0)
269
        anl.append(180.0)
270
        for i in range(18, int(self.arrayLen)):
271
            anl.append(0.0)
272
        return anl
273
274
275
def getnavb(server, table, model, arrlen):
276
    gnr = GridNavRetriever(server, table, model, arrlen)
277
    return gnr.getNavBlk()
278
279
280
def getanlb(server, table, model, arrlen):
281
    gnr = GridNavRetriever(server, table, model, arrlen)
282
    return gnr.getAnlBlk()
283
284
285
# This is the standard boilerplate that runs this script as a main
286
if __name__ == '__main__':
287
    # Run Test
288
    srv = 'edex-cloud.unidata.ucar.edu'
289
    tbl = 'grid_info'
290
    mdl = 'NAM40'
291
    navlen = '256'
292
    print(getnavb(srv, tbl, mdl, navlen))
293
    anllen = '128'
294
    print(getanlb(srv, tbl, mdl, anllen))
295