How do I extract information by pressure level? - cfgrib

I am a complete novice with cfgrib, so please excuse what is probably a straight forward question..
I have a heterogeneous grib file that represents weather information at points on a grid and at atmospheric pressure levels.
For the life of me I cannot work out how to extract the information I need in a usable way.
I want to get, for example, the temperature information (Data variable=t), for each point in the grid at each of the available pressure levels. Or, if that isnt possible get the temperatures for each lat,lon for a specific pressure level.
My grib file looks like this:
Dimensions: (isobaricInhPa: 17, latitude: 145, longitude: 288)
Coordinates:
time datetime64[ns] 2020-10-16T12:00:00
step timedelta64[ns] 06:00:00
* isobaricInhPa (isobaricInhPa) int64 850 750 700 600 500 ... 175 150 125 100
* latitude (latitude) float64 -90.0 -88.75 -87.5 ... 87.5 88.75 90.0
* longitude (longitude) float64 0.0 1.25 2.5 3.75 ... 356.2 357.5 358.8
valid_time datetime64[ns] 2020-10-16T18:00:00
Data variables:
t (isobaricInhPa, latitude, longitude) float32 ...
u (isobaricInhPa, latitude, longitude) float32 ...
v (isobaricInhPa, latitude, longitude) float32 ...
gh (isobaricInhPa, latitude, longitude) float32 ...
Attributes:
GRIB_edition: 2
GRIB_centre: egrr
GRIB_centreDescription: U.K. Met Office - Exeter
GRIB_subCentre: 5
Conventions: CF-1.7
institution: U.K. Met Office - Exeter, <xarray.Dataset>
Dimensions: (isobaricInhPa: 5, latitude: 145, longitude: 288)
Coordinates:
time datetime64[ns] 2020-10-16T12:00:00
step timedelta64[ns] 06:00:00
* isobaricInhPa (isobaricInhPa) int64 850 750 700 600 500
* latitude (latitude) float64 -90.0 -88.75 -87.5 ... 87.5 88.75 90.0
* longitude (longitude) float64 0.0 1.25 2.5 3.75 ... 356.2 357.5 358.8
valid_time datetime64[ns] ...
Data variables:
r (isobaricInhPa, latitude, longitude) float32 ...
Attributes:
GRIB_edition: 2
GRIB_centre: egrr
GRIB_centreDescription: U.K. Met Office - Exeter
GRIB_subCentre: 5
Conventions: CF-1.7
institution: U.K. Met Office - Exeter, <xarray.Dataset>
Dimensions: (latitude: 145, longitude: 288)
Coordinates:
time datetime64[ns] 2020-10-16T12:00:00
step timedelta64[ns] 06:00:00
maxWind int64 0
* latitude (latitude) float64 -90.0 -88.75 -87.5 -86.25 ... 87.5 88.75 90.0
* longitude (longitude) float64 0.0 1.25 2.5 3.75 ... 356.2 357.5 358.8
valid_time datetime64[ns] 2020-10-16T18:00:00
Data variables:
u (latitude, longitude) float32 ...
v (latitude, longitude) float32 ...
icaht (latitude, longitude) float32 ...
Attributes:
GRIB_edition: 2
GRIB_centre: egrr
GRIB_centreDescription: U.K. Met Office - Exeter
GRIB_subCentre: 5
Conventions: CF-1.7
institution: U.K. Met Office - Exeter, <xarray.Dataset>
Dimensions: (latitude: 145, longitude: 288)
Coordinates:
time datetime64[ns] 2020-10-16T12:00:00
step timedelta64[ns] 06:00:00
tropopause int64 0
* latitude (latitude) float64 -90.0 -88.75 -87.5 -86.25 ... 87.5 88.75 90.0
* longitude (longitude) float64 0.0 1.25 2.5 3.75 ... 356.2 357.5 358.8
valid_time datetime64[ns] 2020-10-16T18:00:00
Data variables:
t (latitude, longitude) float32 ...
icaht (latitude, longitude) float32 ...
Attributes:
GRIB_edition: 2
GRIB_centre: egrr
GRIB_centreDescription: U.K. Met Office - Exeter
GRIB_subCentre: 5
Conventions: CF-1.7
institution: U.K. Met Office - Exeter]
Any help greatly appreciated!

This works for me using NWS NCEP grib2 files and should work with U.K. Met Office grib files. It also only grabs the 't' at a specific pressure level.
Use cfgrib.open_datasets() to open the grib file. (I'm using 'data.grib' as an example file name here and using your output of the grib file to get variables):
import cfgrib
ds = cfgrib.open_datasets('data.grib')
Since you want the temperature variable 't' which is located in the 0th index of the grib output, use:
tmp = ds[0].t
However, you still need to specify a pressure level. In order to know what index to use, look at the 'isobaricInhPa' values found in the grib output:
* isobaricInhPa (isobaricInhPa) int64 850 750 700 600 500 ... 175 150 125 100
Think of the values as a list:
[850 750 700 600 500 ... 175 150 125 100]
So if you wanted 't' at 700mb, you would use t[2] because 700 is located at the 2nd index:
tmp700 = ds[0].t[2]
(If you need 'isobaricInhPa' values that aren't shown in the grib file output, use:)
ds[0].isobaricInhPa
And then for the latitude and longitude, use:
lat = ds[0].latitude
lon = ds[0].longitude

Related

Swapping latitude and longitude position in xarray

I have a NetCDF file which has swapped latitude and longitude positions.
The standard way a Netcdf I normally use is defined as follows:
<xarray.DataArray 'pev' (time: 365, latitude: 480, longitude: 1440)>
Coordinates:
* time (time) datetime64[ns] 2001-01-01T11:30:00 ... 2001-12-31T11:30:00
* longitude (longitude) float32 0.0 0.25 0.5 0.75 ... 359.25 359.5 359.75
* latitude (latitude) float32 59.75 59.5 59.25 59.0 ... -59.5 -59.75 -60.0
But the specifications of the NetCDF I am dealing with is as following:
<xarray.DataArray 'ETa' (time: 12, longitude: 720, latitude: 360)>
Coordinates:
* latitude (latitude) float64 89.75 89.25 88.75 ... -88.75 -89.25 -89.75
* longitude (longitude) float64 -179.8 -179.2 -178.8 ... 178.8 179.2 179.8
Dimensions without coordinates: time
Since the position of latitude and longitude is swapped, it's a bit difficult to do analysis without modifying the code at several steps.
Does anyone has come across such a problem and know how to resolve this issue early on using xarray?
Use the ds.transpose() function.
data.transpose('time', 'latitude', 'longitude')

MongoDB - latitude/longitude - signs

Reading here
http://docs.mongodb.org/manual/tutorial/query-a-2dsphere-index/
I find the following:
The following example queries grid coordinates and returns all documents
within a 10 mile radius of longitude 88 W and latitude 30 N. The example
converts the distance, 10 miles, to radians by dividing by the approximate
radius of the earth, 3959 miles:
db.places.find( { loc :
{ $geoWithin :
{ $centerSphere :
[ [ 88 , 30 ] , 10 / 3959 ]
} } } )
I think the "standard" notation is:
East is + (plus) and West is - (minus),
North is + (plus) and South is - (minus).
So why is West + (plus) in this example
on the MongoDB documentation site?
Is it really that way in MongoDB?
In fact, is there any standard which defines if West
maps to + or to - and the same for East, North, South?
See also:
Wikipedia - Latitude and longitude of the Earth
Wikipedia - Geographic coordinate system

Calculate Latitude and longitude more between Latitude/Longitude points?

Latitude: 22.744812,
Longitude: 75.892578
The above would be considered my center point.
And now I need to determine the latitude and longitude points from center point 1000 meter outward to each NSWE corners. So I would have a central long/lat, N, S, E and W long/lat..
So I would end up with 4 additional lat/long pairs.
What I am trying to resolve is a formula, preferably that can be done on a standard calculator to determine these 4 NSWE points based on the central point.
You could use MapKit for that:
- (CLLocationCoordinate2D *) calculateSquareCoordinates:(CLLocation*)center withRadius:(float)radius{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center.coordinate, radius*2, radius*2);
CLLocationCoordinate2D points[4];
points[0] = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
points[1] = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
points[2] = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
points[3] = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
return points;
}
and just call
CLLocationCoordinate2D *fourPoints = [self calculateSquareCoordinates:center withRadius:1000];
on your code.
you will have to use the Haversine formula to calculate the Lat/Long based on distance from a starting Lat/Long. have a look at this Link
The average radius of the earth is around 6371000 metres. This means that
1 degree of lattitude is equivalent to 6371000 * PI / 180 metres
(NB: PI = 3.14159... etc). However, 1 degree of longitude depends on the lattitude that you are. At the equator, one degree of longitude corresponds to the same distance in metres as 1 degree of lattitude. However, at the north and south poles, all longitude values are the same point (i.e. the pole itself), so 1 degree of longitude at the poles is zero metres. The formula for longitude is
1 degree of longitude is equivalent to 637100 * PI / 180 * COS(Lattitude)
where COS is the trigonometric cosine function. If you make these conversions, then you can do the calculation on a standard calculator. However, be aware that these are approximations that work well over short distances (e.g. less than a few hundred kilometers), but over long distances (e.g. thousands of kilometers) they become more and more inaccurate.

Latitude / Longitude Distance Calculation

A quick question about a Lat / Long calculation.
I want to take a value set e.g. Lat: 55.123456 Long -6.123456 and work out the four points that are an arbitrary distance away.
As the given square, I want to work out the value for Latitude on the left and right side. Thus the red lines are 1.5km from the start point. Likewise for the longitude, the blue lines will be 1.5km from the start point. The output will be 4 points, all distances in kilometres.
In short: Latitude + Y = Latitude Value X kilometers away
Working with iPhone at the moment and its for a very rough database calculation.
EDIT: Just to clarify, the distance is so short that curvature (And hence accuracy) is not an issue.
In OBJ-C this should be a decent solution:
float r_earth = 6378 * 1000; //Work in meters for everything
float dy = 3000; //A point 3km away
float dx = 3000; //A point 3km away
float new_latitude = latitude + (dy / r_earth) * (180 / M_PI);
float new_longitude = longitude + (dx / r_earth) * (180 / M_PI) / cos(latitude * 180/M_PI);
Well, for rough calculation with relatively small distances (less than 100km) you may assume that there is 40_000_000/360=111 111 meters per degree of latitude and 111 111*cos(latitude) meters per degree of longitude. This is because a meter was defined as 1/40_000_000 part of the Paris meridian;).
Otherwise you should use great circle distances, as noted in the comments. For high precision you also need to take into account that Earth is slightly oblate spheroid rather than a sphere.
// parameter: offset in meters
float offsetM = 1500; // 1.5km
// degrees / earth circumfence
float degreesPerMeter = 360.0 / 40 000 000;
float toRad = 180 / M_PI;
float latOffsetMeters = offsetM * degreesPerMeter;
float lonOffsetMeters = offsetM * degreesPerMeter * cos (centerLatitude * toRad);
Now simply add +/- latOffsetMeters and +/- lonOffsetMeters to your centerLatitude/ centerLongitude.
Formula is usefull up to hundred kilometers.

How can i get minimum and maximum latitude and longitude using current location and radius?

I want Minimum and Maximum Latitude and Longitude Using Current Location.Suppose i have give the area of 20km so using that latitude and Longitude i want Maximum latitude and Longitude and Minimum latitude and Longitude also want all latitude and Longitude in between this so how can i get it.How can i use of radius in it.Please help me.Thanks in Advance...
you can manually calculate it... I don't know if any other way exist
1° latitude = 69.047 statute miles = 60 nautical miles
= 111.12 kilometers
so for 20 kilometers it would be around 0.18 latitude
For longitude the conversion is the same as latitude except the value is multiplied by the cosine of the latitude.
To set the same range on map for display
newRegion.center=newLocation.coordinate;
// newRegion.span.latitudeDelta = (20*2)/111.12; // For kilometers
newRegion.span.latitudeDelta = (20*2)/60.0; // For Miles
newRegion.span.longitudeDelta = ((20*2)/60.0) *(cos(newRegion.span.latitudeDelta)); // For Miles
mapView.region = newRegion;
It will set 20 kilometer's range on map that is displayed...
so you can find it by
you can find it by
minLattitude = currentLattitude - (RadiusInKm/111.12);
maxLattitude = currentLattitude + (RadiusInKm/111.12);
For longitude same but multiply the result with cosine of latitude...
1) Macros to convert Degrees to Radians:
#define DEGREES_TO_RADIANS(degrees) (degrees / 180.0 * M_PI)
2) Macros to raduis in KM:
#define radiusInKM 5.00
3) Set the minimum and maximum Latitude, Longitude values
CLLocation *location;//your current location
1° latitude = 69.047 statute miles = 60 nautical miles = 111.12 kilometers
double minLat = location.coordinate.latitude - (radiusInKM/111.12);
double maxLat = location.coordinate.latitude + (radiusInKM/111.12);
double minLon = location.coordinate.longitude - (radiusInKM) / fabs(cos(DEGREES_TO_RADIANS(location.coordinate.longitude))*111.12);
double maxLon = location.coordinate.longitude + (radiusInKM) / fabs(cos(DEGREES_TO_RADIANS(location.coordinate.longitude))*111.12);
macros to convert Degrees to Radians
define DEGREES_TO_RADIANS(degrees) (degrees / 180.0 * M_PI)
macros to raduis in KM
define radiusInKM 5.00
set the minimum and maximum Latitude, Longitude values
CLLocation *location;//your current location
1° latitude = 69.047 statute miles = 60 nautical miles = 111.12 kilometers
double minLat = location.coordinate.latitude - (radiusInKM/111.12);
double maxLat = location.coordinate.latitude + (radiusInKM/111.12);
double minLon = location.coordinate.longitude - (radiusInKM) / fabs(cos(DEGREES_TO_RADIANS(location.coordinate.longitude))*111.12);
double maxLon = location.coordinate.longitude + (radiusInKM) / fabs(cos(DEGREES_TO_RADIANS(location.coordinate.longitude))*111.12);