@@ -207,16 +207,38 @@ class GeostationaryFixedGridSystem(CoordinateSystem):
207
207
208
208
def __init__ (self , subsat_lon = 0.0 , subsat_lat = 0.0 , sweep_axis = 'y' ,
209
209
sat_ecef_height = 35785831.0 ,
210
- ellipse = 'WGS84' , datum = 'WGS84' ):
210
+ ellipse = 'WGS84' ):
211
211
"""
212
- Satellite height is with respect to the ellipsoid. Fixed grid
213
- coordinates are in radians.
212
+ Coordinate system representing a grid of scan angles from the perspective of a
213
+ geostationary satellite above an arbitrary ellipsoid. Fixed grid coordinates are
214
+ in radians.
215
+
216
+ Parameters
217
+ ----------
218
+ subsat_lon : float
219
+ Longitude of the subsatellite point in degrees.
220
+ subsat_lat : float
221
+ Latitude of the subsatellite point in degrees.
222
+ sweep_axis : str
223
+ Axis along which the satellite sweeps. 'x' or 'y'. Use 'x' for GOES
224
+ and 'y' (default) for EUMETSAT.
225
+ sat_ecef_height : float
226
+ Height of the satellite in meters from the center of the Earth.
227
+ ellipse : str or list
228
+ A string representing a known ellipse to pyproj, or a list of [a, b] (semi-major
229
+ and semi-minor axes) of the ellipse. Default is 'WGS84'.
214
230
"""
215
- # self.ECEFxyz = proj4.Proj(proj='cart', ellps=ellipse)#, datum=datum)
216
- self .ECEFxyz = proj4 .Proj (proj = 'geocent' , ellps = ellipse )#, datum=datum)
231
+ if type (ellipse ) == list and len (ellipse ) == 2 :
232
+ rf = semiaxes_to_invflattening (ellipse [0 ], ellipse [1 ])
233
+ ellipse_args = {'a' : ellipse [0 ], 'rf' : rf }
234
+ elif type (ellipse ) == str :
235
+ ellipse_args = {'ellps' : ellipse }
236
+ else :
237
+ raise ValueError ("Ellipse must be a string or list of [a, b]." )
238
+ self .ECEFxyz = proj4 .Proj (proj = 'geocent' , ** ellipse_args )
217
239
self .fixedgrid = proj4 .Proj (proj = 'geos' , lon_0 = subsat_lon ,
218
240
lat_0 = subsat_lat , h = sat_ecef_height , x_0 = 0.0 , y_0 = 0.0 ,
219
- units = 'm' , sweep = sweep_axis , ellps = ellipse )
241
+ units = 'm' , sweep = sweep_axis , ** ellipse_args )
220
242
self .h = sat_ecef_height
221
243
222
244
def toECEF (self , x , y , z ):
@@ -473,3 +495,95 @@ def fromLocal(self, data):
473
495
return array ( [ (dot (self .TransformToLocal .transpose (), v ) + self .centerECEF )
474
496
for v in data [0 :3 ,:].transpose ()]
475
497
).squeeze ().transpose ()
498
+
499
+
500
+ def semiaxes_to_invflattening (semimajor , semiminor ):
501
+ """ Calculate the inverse flattening from the semi-major
502
+ and semi-minor axes of an ellipse"""
503
+ rf = semimajor / (semimajor - semiminor )
504
+ return rf
505
+
506
+
507
+ def centers_to_edges (x ):
508
+ """
509
+ Create an array of length N+1 edge locations from an
510
+ array of lenght N grid center locations.
511
+
512
+ In the interior, the edge positions set to the midpoints
513
+ of the values in x. For the outermost edges, half the
514
+ closest dx is assumed to apply.
515
+
516
+ Parameters
517
+ ----------
518
+ x : array, shape (N)
519
+ Locations of the centers
520
+
521
+ Returns
522
+ -------
523
+ xedge : array, shape (N+1,M+1)
524
+
525
+ """
526
+ xedge = zeros (x .shape [0 ]+ 1 )
527
+ xedge [1 :- 1 ] = (x [:- 1 ] + x [1 :])/ 2.0
528
+ xedge [0 ] = x [0 ] - (x [1 ] - x [0 ])/ 2.0
529
+ xedge [- 1 ] = x [- 1 ] + (x [- 1 ] - x [- 2 ])/ 2.0
530
+ return xedge
531
+
532
+
533
+ def centers_to_edges_2d (x ):
534
+ """
535
+ Create a (N+1, M+1) array of edge locations from a
536
+ (N, M) array of grid center locations.
537
+
538
+ In the interior, the edge positions set to the midpoints
539
+ of the values in x. For the outermost edges, half the
540
+ closest dx is assumed to apply. This matters for polar
541
+ meshes, where one edge of the grid becomes a point at the
542
+ polar coordinate origin; dx/2 is a half-hearted way of
543
+ trying to prevent negative ranges.
544
+
545
+ Parameters
546
+ ----------
547
+ x : array, shape (N,M)
548
+ Locations of the centers
549
+
550
+ Returns
551
+ -------
552
+ xedge : array, shape (N+1,M+1)
553
+
554
+ """
555
+ xedge = zeros ((x .shape [0 ]+ 1 ,x .shape [1 ]+ 1 ))
556
+ # interior is a simple average of four adjacent centers
557
+ xedge [1 :- 1 ,1 :- 1 ] = (x [:- 1 ,:- 1 ] + x [:- 1 ,1 :] + x [1 :,:- 1 ] + x [1 :,1 :])/ 4.0
558
+
559
+ # /\
560
+ # /\/\
561
+ # / /\ \
562
+ # /\/ \/\
563
+ # / /\ /\ \
564
+ # /\/ \/ \/\
565
+ # / /\ /\ /\ \
566
+ # /\/ \/ \/ \/\
567
+ #4 \/\ /\ /\ /\/ 4
568
+ # 3 \ \/ \/ \/ / 3
569
+ # \/\ /\ /\/
570
+ # 2 \ \/ \/ / 2
571
+ # \/\ /\/
572
+ # 1 \ \/ / 1
573
+ # \/\/
574
+ # 0 \/ 0 = center ID of 0th dimension
575
+ #
576
+
577
+ # calculate the deltas along each edge, excluding corners
578
+ xedge [1 :- 1 ,0 ] = xedge [1 :- 1 , 1 ] - (xedge [1 :- 1 , 2 ] - xedge [1 :- 1 , 1 ])/ 2.0
579
+ xedge [1 :- 1 ,- 1 ]= xedge [1 :- 1 ,- 2 ] - (xedge [1 :- 1 ,- 3 ] - xedge [1 :- 1 ,- 2 ])/ 2.0
580
+ xedge [0 ,1 :- 1 ] = xedge [1 ,1 :- 1 ] - (xedge [2 ,1 :- 1 ] - xedge [1 ,1 :- 1 ])/ 2.0
581
+ xedge [- 1 ,1 :- 1 ]= xedge [- 2 ,1 :- 1 ] - (xedge [- 3 ,1 :- 1 ] - xedge [- 2 ,1 :- 1 ])/ 2.0
582
+
583
+ # now do the corners
584
+ xedge [0 ,0 ] = xedge [1 , 1 ] - (xedge [2 , 2 ] - xedge [1 , 1 ])/ 2.0
585
+ xedge [0 ,- 1 ] = xedge [1 ,- 2 ] - (xedge [2 ,- 3 ] - xedge [1 ,- 2 ])/ 2.0
586
+ xedge [- 1 ,0 ] = xedge [- 2 ,1 ] - (xedge [- 3 ,2 ] - xedge [- 2 ,1 ])/ 2.0
587
+ xedge [- 1 ,- 1 ]= xedge [- 2 ,- 2 ]- (xedge [- 3 ,- 3 ]- xedge [- 2 ,- 2 ])/ 2.0
588
+
589
+ return xedge
0 commit comments