How would I extract a region of some NEMO ocean model output in Iris? - python-iris

Is there a straightforward way to extract a region from an Iris cube which is described by 2D latitude and longitude variables, for example using NEMO ocean model data?
I found this workaround but was wondering if there was a way to do this in 'pure' Iris, without having to resort to defining a new function?
For example, if I have this cube...
In [30]: print(cube)
mole_concentration_of_dimethyl_sulfide_in_sea_water / (mol m-3) (time: 780; cell index along second dimension: 330; cell index along first dimension: 360)
Dimension coordinates:
time x - -
cell index along second dimension - x -
cell index along first dimension - - x
Auxiliary coordinates:
latitude - x x
longitude - x x
... and then try to extract a region using intersection, I get this...
>>> subset = cube.intersection(longitude=(-10, 10))
CoordinateMultiDimError: Multi-dimensional coordinate not supported: 'longitude'
Thanks!

As you can see from the error messsage, iris does not currently support subsetting by multi-dimensional coordinates, so you have to write a function similar to bbox_extract_2Dcoords() in that blog post. All it does is creates a boolean mask with values set to True within your region of interest and False outside. Then the boundaries of this region are used as indices to subset the cube.
An alternative would be to regrid the data to a regular grid defined by 1D longitude and latitude and then subset the data using the standard Constraint() method.

Related

Extracting a 3D derived coord to its own cube

I have loaded some data on a hybrid-p grid with iris which looks like this:
specific_humidity / (1) (atmosphere_hybrid_sigma_pressure_coordinate: 48; latitude: 160; longitude: 320)
Dimension coordinates:
atmosphere_hybrid_sigma_pressure_coordinate x - -
latitude - x -
longitude - - x
Auxiliary coordinates:
vertical coordinate formula term: a(k) x - -
vertical coordinate formula term: b(k) x - -
vertical pressure x - -
surface_air_pressure - x x
Derived coordinates:
air_pressure x x x
Scalar coordinates:
time: 2005-11-01 00:00:00
vertical coordinate formula term: reference pressure: 101325.0 Pa
Attributes:
Conventions: CF-1.4
What I want is to turn the pressure coordinate into a cube for use in calculations. I can do this with the following code:
p_cube=humid.copy(humid.coord('air_pressure').points)
p_cube.rename('air_pressure')
p_cube.units=humd_1t.coord('air_pressure').units
But is there a neater way?
Good question, to which I don't think there is a better solution to the one you've already provided.
From a design perspective, Iris' coordinates aren't quite cubes (with things like their own coordinates, cell measures & methods, etc.). It seems that really in order to do such a thing properly Iris would need to gain the concept of a Dataset (where multiple phenomena share a single set of coordinates).
The only slightly neater approach (untested) might be to do:
p_cube=humid.copy(humid.coord('air_pressure').points)
p_cube.metadata = humid.coord('air_pressure').metadata
Though I'm not 100% sure if it is valid to provide a CoordMetadata object when defining the cube's metadata.
HTH

Fitting of a sphere using SVD/LMS

I would like to fit a MR binary data of 281*398*104 matrix which is not a perfect sphere, and find out the center and radius of sphere and error also. I know LMS or SVD is a good choice to fit for sphere.
I have tried sphereFit from matlab file exchange but got an error,
>> sphereFit(data)
Warning: Matrix is singular to working precision.
> In sphereFit at 33
ans =
NaN NaN NaN
Would you let me know where is the problem, or any others solution?
If you want to use sphere fitting algorithm you should first extract the boundary points of the object you assume to be a sphere. The result should be represented by a N-by-3 array containing coordinates of the points. Then you can apply sphereFit function.
In order to obtain boundary point of a binary object, there are several methods. One method is to apply morphological erosion (you need the "imerode" function from the image processing toolbox) with small structuring element, then compute set difference between the two images, and finally use the "find" function to transform binary image into a coordinate array.
the idea is as follow:
dataIn = imerode(data, ones([3 3 3]));
bnd = data & ~data2;
inds = find(bnd);
[y, x, z] = ind2sub(size(data), inds); % be careful about x y order
points = [x y z];
sphere = sphereFitting(points);
By the way, the link you gave refers to circle fitting, I suppose you wanted to point to a sphere fitting submission?
regards,

create 3D image from coordinates and intensity values

I am trying to create a 3D array of size 1000x1000x1000 with all the elements (corresponding to voxels) being zero and then assign a random value in the 2000 to 2001 range instead of 0 to some specific elements in the array and finally store it as a binary file.
The array named "coord" is the Nx3 matrix coordinates (x,y,z) of the points that I need them to be assigned the random value in the 3D array.))
I should mention that all the x,y,z values of the coordinate matrix are floating point numbers with: 0<=x<=1000 0<=y<=1000 0<=z<=1000
My aim is to export the 3D matrix in a binary format (other than MATLAB's default binary format) so that I can use it with other programs.
Here is what I've been up to so far:
load coord;
a=coord(:,1);
b=coord(:,2);
c=coord(:,3);
d=rand(1000,1)*2000;
dd = 0:2:1000;
[xq,yq,zq] = meshgrid(dd,dd,dd);
vq = griddata3(a,b,c,d,xq,yq,zq,'nearest');
h=figure;
plot3(a,b,c,'ro')
%=========================================%
fid=fopen('data.bin','w');
fwrite(fid,vq,'single');
fclose(fid);
In the above code a, b and c are the coordinates of each point and d is the corresponding intensity values for the desired range. While it is possible to create a 3D mesh (using meshgrid) and then interpolate the intensity values for mesh points (using griddata3), the final result (vq) would not be the actual points (ai,bi,ci) and corresponding intensities , but rather an interpolated set of points which is pretty useful for visualization purposes (for instance if you like to fit a 3D surface which fits through actual data).
I am simply trying to find a way to store the actual data-points and their intensities into a file and export it.
Any help is highly appreciated.
If you want to save to files that will allow importing into a visualization software, a series of Tiff files will most likely be convenient, i.e.
maxValue = 2000; % this is the maximum signal that can possibly occur
% according to your code
for z = 1:size(vq,3)
%# convert slice z to 16 bit
currentSlice = vq(:,:,z);
currentSlice = uint16(round(currentSlice/maxValue))
%# save to file
imwrite(currentSlice, sprintf('testImg_z%04i.tif',z),'tif');
end
Note that if you create a double array of dimensions 1000x1000x1000, you'll need 8GB of contiguous RAM.
How about something like:
%# 3D array
voxels = zeros([1000 1000 1000]);
%# round points coordinates, and clamp to valid range [1,1000]
load coords
coords = round(coords);
coords = min(max(coords,1),1000);
%# convert to linear indices
idx = sub2ind(size(voxels), coords(:,1), coords(:,2), coords(:,3));
%# random values in the 2000 to 2001 range
v = rand(size(idx)) + 2000;
%# assign those values to the chosen points
voxels(idx) = v;

MatLab - Best way of finding the closest value

I'm working with Matlab's image toolbox. In particular, after binarizing and labeling an image, I run
props = regionprops(labeledImage, 'Centroid');
to get the centroid of all the connected objects. Now, I would like to find the one closer to a pair of coordinates (namely the center of the image). Of course I know I could use a for loop checking each props[i].Centroid pair of coordinates, but that's slow and there must be a matlaby way of doing it...
which is...?
Thanks in advance
The output from REGIONPROPS will be an N-by-1 structure array with one field 'Centroid' that contains a 1-by-2 array. You can first concatenate all these arrays into an N-by-2 array using the function VERTCAT. Then you can replicate your image center coordinates (assumed to be in a 1-by-2 array) using the function REPMAT so that it becomes an N-by-2 array. Now you can compute the distances using vectorized operations and find the index of the value with the minimum distance using the function MIN:
props = regionprops(labeledImage, 'Centroid');
centers = vertcat(props.Centroid); %# Vertically concatenate the centroids
imageCenter = [x y]; %# Your image center coordinates
origin = repmat(imageCenter,numel(props),1); %# Replicate the coordinates
squaredDistance = sum(abs(centers-origin).^2,2); %# Compute the squared distance
[~,minIndex] = min(squaredDistance); %# Find index of the minimum
Note that since you just want the minimum distance, you can just use the squared distances and avoid a needless call to SQRT. Also note that the function BSXFUN could be used as an alternative to replicating the image center coordinates to subtract them from the object centroids.

Displaying a subset of longitude/latitude points?

I have an array of coordinates (latitude and longitude) maded in this way:
[0] = "45.01234,9.12345"
[1] = "46.11111,9.12345"
[2] = "47.22222,9.98765"
[...] etc
In a loop, convert these coordinates in meters (UTM northing / UTM easting) and after that I convert these coords in pixel (X / Y) on screen (the output device is an iPhone) to draw a route line on a custom map.
[0] = "512335.00000,502333.666666"
[...] etc
The returning pixel are passed to a method that draw a line on screen (simulating a route calculation).
[0] = "20,30"
[1] = "21,31"
[2] = "25,40"
[...] etc
As coordinate (lat/lon) are too many, I need to truncate lat/lon array eliminating the values that doesn't fill in the map bound (the visible part of map on screen).
Map bounds are 2 couple of coords lat/lon, upper left, and lower right.
Now, what is the best way to loop on this array (NOT SORTED) and check if a value is or not in bound and after remove the value that is outside?
To return a clean array that contains only the coords visible on screen?
Note: the coords array is a very big array. 4000/5000 Couple of items.
This is a method that should be looped every drag or zoom.
How can I optimize search and controls in this array?
I'd suggest breaking this into several steps:
Convert each longitude/latitude pair into a pair of meters in your new coordinate system.
Create a kd-tree data structure holding all the points in the set. This allows you to efficiently query which points lie in a given rectangular range very efficiently.
Whenever the viewport changes, find all points in the kd-tree that will be displayed in that rectangle.
To display the points, iterate over the set of points that will be displayed and display each of them.

Resources