Swapping latitude and longitude position in xarray - coordinates

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')

Related

How do I extract information by pressure level?

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

Is it accurate to convert latitude and longitude into 3d coordinate on sphere?

In Unity3d,
I Created a sphere and i textured it with Earth texture.
I converted latitude and longitude into 3d coorinates
and i spawned a cube on that position.
the cube is on sphere but it is not accurate.
(for example, when i input "51.504815, -0.128506" for london, the cube is spawned at somewhere in france (44.854302, -0.595576))
i know the earth is not sphere but ellipsoid, and is this affect to result?
what should i do to get accurate converting result to spawn cube in right place?
below is converting function that i used, and i used another functions on the web, but it returned same result.
private Vector3 GetSphericalCoordinates(double latitude, double longitude)
{
latitude = latitude * Math.PI / 180D;
longitude = longitude * Math.PI / 180D;
double x = radius * Math.Cos(latitude) * Math.Sin(longitude);
double y = radius * Math.Sin(latitude);
double z = -radius * Math.Cos(latitude) * Math.Cos(longitude);
return new Vector3((float)x, (float)y, (float)z);
}
and latitude, longitude (0, 0), (90, 0) (0, 90)... is exactly on the quadrant. so i wonder why other lat, lng value is incorrect...
thanks in advance.
It was not accurate because of mesh count and texture UV set.
if you increase mesh count and make texture's UV correct spawned object will be on correct spot.

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.

MKCoordinateSpan in Meters?

I need to create a MKCoordinateSpan that is about 500 meters.
How do I calculate the values to pass into the MKCoordinateSpan constructor?
Answers in any programming (Obj-C, .Net) language are fine.
Another alternative is to use MapKit's MKCoordinateRegionMakeWithDistance function:
MKCoordinateRegion rgn = MKCoordinateRegionMakeWithDistance(
CLLocationCoordinate2DMake(someLatitude, someLongitude), 500, 500);
The MKCoordinateSpan will be in rgn.span.
Unless you need great accuracy you can make it much easier with approximation. The first problem is to find the fraction of a degree of latitude representing 500 meters. Easy since a degree of latitude is a constant in any location, roughly 111 km. So 500 meters is .0045 degrees latitude.
Then it gets harder because length of a degree of longitude varies depending on where you are. It can be approximated with
where alpha is earth's equatorial radius, 6,378,137km, b/a is 0.99664719 (a constant in use for the WGC84 spheroid model in use by all GPS devices) and where phi is the degree of latitude.
Imagine for a second you're lucky enough to be in Melbourne with a longitude of 37.783 degrees S. North or South doesn't matter here. beta works out to be 37.6899 and the rest of it solves to give a longitudinal degree a length of 88km. So 500 meters is .0057 of a degree.
Result for Melbourne - MKCoordinateSpan melbourne500MeterSpan = MKCoordinateSpanMake(.0045, .0057);
You can check your answers and your code with this online calculator
The wiki article on longitude has a lot more detail on this (and it the source of the images here)
Code:
#define EARTH_EQUATORIAL_RADIUS (6378137.0)
#define WGS84_CONSTANT (0.99664719)
#define degreesToRadians(x) (M_PI * (x) / 180.0)
// accepts decimal degrees. Convert from HMS first if that's what you have
double spanOfMetersAtDegreeLongitude(double degrees, double meters) {
double tanDegrees = tanf(degreesToRadians(degrees));
double beta = tanDegrees * WGS84_CONSTANT;
double lengthOfDegree = cos(atan(beta)) * EARTH_EQUATORIAL_RADIUS * M_PI / 180.0;
double measuresInDegreeLength = lengthOfDegree / meters;
return 1.0 / measuresInDegreeLength;
}
In MonoTouch, then using this solution you can use this helper method:
public static void ZoomToCoordinateAndCenter (MKMapView mapView, CLLocationCoordinate2D coordinate, double meters, bool showUserLocationToo, bool animate)
{
if (!coordinate.IsValid ())
return;
mapView.SetCenterCoordinate (coordinate, animate);
mapView.SetRegion (MKCoordinateRegion.FromDistance (coordinate, meters, meters), animate);
}

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);