Python regridding a 2D rotated mesh grid - python-2.7

I have a 2D rotated rectangular grid with longitude and latitude values with dimension [405, 555] and I can't understand how to regrid it, I want a rectangular grid with the axis "parallel" to Parallels and Meridians.
I tried to use scipy interpolation functions as: griddata or RegularGridInterpolator, but I always have problem with the old grid dimension because they are 2D and rotated, the values are not repeated and I don't know how to solve it.
Sorry I can't post my original code and data because they are proprietary and I don't know how to create a MWE.
I tried this:
import scipy.interpolate.ndgriddata as ndgriddata
import numpy as np
x = np.linspace(35.0, 42.0, 405) # my new longitude
y = np.linspace(36.0, 48.0, 555) # my new latitude
X, Y = np.meshgrid(x, y)
# grid_lon: old 2D array [405, 555] for the longitude
# grid_lat: old 2D array [405, 555] for the latitude
# data: old 2D array [405, 555] for the data
test = ndgriddata.griddata((grid_lon, grid_lat), data, (X, Y), method="linear")
but, of course I obtain the error:
ValueError: invalid shape for input data points
I know like this is complicated to answer it but if someone have an idea, please let me know.
Thanks,
Ciccio

I had just to flatten the old coordinates and the data.
ndgriddata.griddata((grid_lon.flatten(), grid_lat.flatten()),
data.flatten(), (X, Y), method="linear")

Related

GeoDjango: How to create a circle anywhere on earth based on point and radius?

I have a similar question to this one. Using geodjango, I want to draw a circle on a map with a certain radius in km. However, the suggested solution
a) does not use km but instead degrees, and
b) becomes an oval further north or south.
Here is what I do:
from django.contrib.gis import geos
lat = 49.17
lng = -123.96
center = geos.Point(lng, lat)
radius = 0.01
circle = center.buffer(radius)
# And I then use folium to show a map on-screen:
map = folium.Map(
location=[lat,lng],
zoom_start=14,
attr="Mapbox"
)
folium.GeoJson(
circle.geojson,
name="geojson",
).add_to(map)
The result is this:
How can I
a) draw a circle that is always 3 km in radius, independent from the position on the globe, and
b) ensure this is a circle and not an oval at all latitudes?
Here is the Code
from django.contrib.gis import geos
import folium
lat = 49.17
lng = -123.96
center = geos.Point(x=lng, y=lat, srid=4326)
center.transform(3857) # Transform Projection to Web Mercator
radius = 3000 # now you can use meters
circle = center.buffer(radius)
circle.transform(4326) # Transform back to WGS84 to create geojson
# And I then use folium to show a map on-screen:
map = folium.Map(
location=[lat,lng],
zoom_start=14,
attr="Mapbox"
)
geojson = folium.GeoJson(
circle.geojson,
name="geojson",
)
geojson.add_to(map)
Explanation
This problem occurs due to Map Projections.
Lat/Long Coordinates are represented by the Map Projection WGS84. The Values are in degrees.
The map you see in folium has another map projection (Web Mercator). It tries to represent the world as a plane, which produces distortions to the north and south. The coordinate values are in meters.
On a globe your created circle would look completely round, but because folium uses another projection it gets distorted.
It is also important to know that every projection is represented by a number (EPSG Code). With this epsg codes, you can transform your coordinates from one projection into another.
Web Mercator -> EPSG 3857
WGS84 -> EPSG 4326
With my Code you now get a round circle in folium for Web Mercator, but be aware that it would look oval and distorted, when looking at it on a globe.
This is just a very easy explanation. You might have a look at Map Projections to better understand the problem.
This guide gives a good overview:
Map Projections
try this
folium.Circle(
radius=3000,
location=[lat,lng],
popup="Whatever name",
color="#3186cc",
fill=True,
fill_color="#3186cc",
).add_to(m)

Clip a defined region in IRIS cube using a shapefile

I handle iris cubes containing meteorological data (lon, lat, precipitation, temperature,...) and I am interested in calculating statistics in defined areas (for example a country).
This post explains how to crop the cube with a box (min lon, min lat, max lon, max lat) but I would like to go a step further and select a precise area using a shapefile.
This post explains that it is possible to crop an image using a shapefile associated to a mask, but I don't know how I can make it work for my iris cubes.
If somebody could give me an example or explain me how to do that it would be very useful.
PS: I am quite noobie with python
Having read the shapefile using e.g. Fiona something like this should work:
from shapely.geometry import MultiPoint
# Create a mask for the data
mask = np.ones(cube.shape, dtype=bool)
# Create a set of x,y points from the cube
x, y = np.meshgrid(cube.coord(axis='X').points, cube.coord(axis='Y').points)
lat_lon_points = np.vstack([x.flat, y.flat])
points = MultiPoint(lat_lon_points.T)
# Find all points within the region of interest (a Shapely geometry)
indices = [i for i, p in enumerate(points) if region.contains(p)]
mask[np.unravel_index(indices)] = False
# Then apply the mask
if isinstance(cube.data, np.ma.MaskedArray):
cube.data.mask &= mask
else:
cube.data = np.ma.masked_array(cube.data, mask)
This only works for 2D cubes, but just needs tweaking for higher dimensions so that the mask is only over the lat/lon dimensions.
I actually implemented this behaviour in CIS recently so that you can do cube.subset(shape=region) which might be easier for you.

Axis rotation with an oriented bounding box

I'm trying to put an oriented bounding box around the stamford rabbit for a project. To do this, I create a covariance matrix with the vertices and use the eigenvector columns as the new axis vectors for the OBB.
To draw the OBB, I take the cross product of the vector columns with the x,y and z axes to find the vector perpendicular both, then I use the dot product to find the angle between them.
//rv,uv,fv are the normalised column vectors from the eigenvector matrix.
// Calculate cross product for normal
crossv1x[0] = xaxis[1]*rv[2] - xaxis[2]*rv[1];
crossv1x[1] = xaxis[2]*rv[0] - xaxis[0]*rv[2];
crossv1x[2] = xaxis[0]*rv[1] - xaxis[1]*rv[0];
// Calculate cross product for normal
crossv2y[0] = yaxis[1]*uv[2] - yaxis[2]*uv[1];
crossv2y[1] = yaxis[2]*uv[0] - yaxis[0]*uv[2];
crossv2y[2] = yaxis[0]*uv[1] - yaxis[1]*uv[0];
// Calculate cross product for normal
crossv3z[0] = zaxis[1]*fv[2] - zaxis[2]*fv[1];
crossv3z[1] = zaxis[2]*fv[0] - zaxis[0]*fv[2];
crossv3z[2] = zaxis[0]*fv[1] - zaxis[1]*fv[0];
//dot product:
thetaX = dot(xaxis,rv,1)*180/PI;
thetaY = dot(yaxis,uv,1)*180/PI;
thetaZ = dot(zaxis,fv,1)*180/PI;
I then apply a rotation around the cross product vector with an angle determined by the dot product (glRotatef(angle,cross[0],cross1,cross[2]) for each axis). I then draw an axis aligned bounding box, then to the inverse rotation back to the original position.
glRotatef(thetaY,crossv2y[0],crossv2y[1],crossv2y[2]);
glRotatef(thetaZ,crossv3z[0],crossv3z[1],crossv3z[2]);
glRotatef(thetaX,crossv1x[0],crossv1x[1],crossv1x[2]);
glTranslatef(-meanX, -meanY, -meanZ);
glColor3f(1.0f,0.0f,0.0f);
AOBB(1); //Creates an axis aligned box.
glRotatef(-thetaX,crossv1x[0],crossv1x[1],crossv1x[2]);
glRotatef(-thetaZ,crossv3z[0],crossv3z[1],crossv3z[2]);
glRotatef(-thetaY,crossv2y[0],crossv2y[1],crossv2y[2]);
As you can see below, the box does not fit exactly onto the rabbit, nor does it align with the axis I have drawn... Am I missing something here? Ive fried my brain trying to find the solution but to no avail...
To draw the OBB, I take the cross product of the vector columns with the x,y and z axes to find the vector perpendicular both, then I use the dot product to find the angle between them.
Those "vector columns?" Those are actually the columns of the rotation matrix you want to generate.
So instead of using these vectors to compute rotation angles, just build a matrix with those (normalized) vectors as the columns. Upload it with glMultMatrix, and you should be fine.

How to plot a scatter diagram using rpy2 in python?

I have a dataset like below in dictionary format,
data={'a': [10, 11,12,5,4,3,1], 'b': [7, 18,5,11,9,2,0]}
How we can make a scatter plot in python using rpy2? where x axis is the months and y axis are the mutiples of 5? we need to plot the graph with the above values where a and b are the data points
Months should be based on the length of each key i.e for the above data we have 7 months since we have 7 data points
This is a pretty involved data structure, and it's not completely clear what you're looking to do in terms of plotting. Here are a few hints, but it'd be easiest to help you if you would post the code you've tried but hasn't worked.
The R plot function takes two vectors corresponding to the x-axis values (months, here), and y-axis values (frequencies?). You'll want to go through your graph_data dictionary and calculate the y-axis values you want to plot for each month, and then make a corresponding vector for x containing the month numbers. For example:
x = [1,2,3,4]
y = [0.7, 0.9, 0.2, 0.4]
To do the plotting from rpy2, you'll need to convert the lists to vectors like so:
from rpy2 import robjects
x_vector = robjects.IntVector(x)
y_vector = robjects.FloatVector(y)
Then do the plotting:
robjects.r.plot(x_vector, y_vector, xlab="month", ylab="freq", main="")

GeoDjango: How to create a circle based on point and radius

I have the following (simplified) Model:
class Zone(gismodels.Model):
name = gismodels.CharField()
poly = gismodels.PolygonField()
I want to create and save a polygon that represents a circle, based upon a given point and radius.
The only way I can figure out how to achieve this, is to call the postgis ST_Buffer function using raw SQL. I'm really hoping that there is another way.
Is it possible to access the GEOS buffer methods?
Yes, it is possible to use the geos buffer method:
>>> from django.contrib.gis import geos
>>> center = geos.Point(5, 5)
>>> radius = 2
>>> circle = center.buffer(radius)
>>> circle
<Polygon object at 0x1029d8370>
The radius here is in the same units as the coordinates of the points. This will work for some coordinate systems like UTM, but not as well for others.
Also, while this is appropriate for constructing a circular geometry, the PostGIS documentation notes that for doing radius searches ST_DWithin is more efficient.
I spent a ridiculous amount of time trying to get this working. Since this is the number one google search result, here's what worked for me:
radius_km = radius*1.609 # convert miles to km
point = target.geolocation # a django PointField using SRID 4326
# re-project point to a flat coordinate system
# so we can use meters instead of degrees below,
# AND get an actual circle instead of oval
point.transform(6347)
poly = point.buffer(radius_km*1000) # get a circular polygon from radius
poly.transform(4326)# re-project the resulting polygon back
Bonus: If you're doing this so you can get a circle on a google static map, grab polyline:
import polyline
import ast
geo = ast.literal_eval(poly.geojson) # turn the text into a dict
points = geo['coordinates'][0]
pl = polyline.encode(points, geojson=True, precision=5) # make a polyline out of the polygon for google
map_url += '&path=color:0x00000000%7Cfillcolor:0x0000AA33%7Cweight:1%7Cenc:' + pl