Crop the grid in a numpy array using a polygom cutline - python

How do I crop a EPSG:25832 raster stored in a numpy array with a wkt polygon?

You don't need to save it in disk, you can use it as temporary object. You can simply use "Mem" format :
from osgeo import gdal, gdal_array as gdarr
input_raster = "path/to/rgb.tif"
# or if the input is already a gdal raster object you can use that gdal object
input_raster=gdal.Open("path/to/rgb.tif")
input_kml = "path/to/cropline.kml" # or any other format
ds = gdal.Warp('',
input_raster,
format = 'Mem',
cutlineDSName = input_kml, # or any other file format
cutlineLayer = 'extent', # if cutline is a shapefile no need for this cutlineLayer
dstNodata = -9999) # select your no data value
#do stuff with ds object, it is your cropped dataset
#for example convert it to numpy array
npDs=ds.gdarr.DatasetReadAsArray(ds, 0, 0, ds.RasterXSize, ds.RasterYSize)
print(npDs.shape)
If you have a numpy array its more tricky because you need to know the geotransform params of that numpy array. My advice is to send back this numpy array to gdal object and then you can do that using gdal.warp()

Related

Saving 3 dimensional array to a file in Python

I want to save a 3 dimensional arrays values to a txt or csv file in python.
dCx, dCy
I used:
numpy.savetxt('C:/Users/musa/Desktop/LOCO_All_tests/FODO_Example/AllQ/dCx.csv',dCx,delimiter=',')
numpy.savetxt('C:/Users/musa/Desktop/LOCO_All_tests/FODO_Example/AllQ/dCy.csv',dCy,delimiter=',')
And to load it again:
dCx = numpy.genfromtxt('C:/Users/musa/Desktop/LOCO_All_tests/FODO_Example/AllQ/dCx.csv', delimiter=',')
dCy = numpy.genfromtxt('C:/Users/musa/Desktop/LOCO_All_tests/FODO_Example/AllQ/dCy.csv', delimiter=',')
But i got the error massage
"Expected 1D or 2D array, got 3D array instead"
Si i wanted to change the 3d arrays first to 2 arrays and then save it to the files, and when uploaded again i convert it back to 3d for example:
dCx2 = np.array(dCx).reshape(np.array(dCx).shape[0], -1)
dCy2 = np.array(dCy).reshape(np.array(dCy).shape[0], -1)
and after loaded to variable named dCx3 and dCy3 i used:
dCx = np.array(dCx3).reshape(
np.array(dCx3).shape[0], np.array(dCx3).shape[1] // np.array(dCx).shape[2], np.array(dCx).shape[2])
#dCy = np.array(dCy3).reshape(
# np.array(dCy3).shape[0], np.array(dCy3).shape[1] // np.array(dCy).shape[2], np.array(dCy).shape[2])
I am looking for a better method that i can used in the saving the 3d arrays to file, or a method to convert the 2d into 3d without having to measure the original arrays every time as it is used in this line:
np.array(dCy).shape[2], np.array(dCy).shape[2])
Use numpy.save(filepath, data) and data = numpy.load(filepath).
These are binary file formats, and generic for any type of NumPy data
Try tofile. it works for in my case. but array will write in 1D
import numpy as np
arr=np.arange(0,21).reshape(7,3)
arr.tofile('file.txt',sep=',')
arr2=np.fromfile('file.txt',sep=',')

Save 3D array into a stack of 2D images in Python

I made a 3D array, which consists of numbers(0~4). What I want is to save 3D array as a stack of 2D images(if possible, save *.tiff file). What am I supposed to do?
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
Actually, I made it. This is my code.
With this code, I don't need to stack a series of 2D image(array).
Make a 3D array, and save it. That is just what I did for this.
import numpy as np
from skimage.external import tifffile as tif
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
tif.imsave('a.tif', a, bigtiff=True)
This should work. I haven't tested it but I have separated color images into RGB slices using this method and it should work pretty much the same way here, assuming you don't want to do anything with those pixel values first. (They will be very close to the same color in an image).
import imageio
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
for i in range(100):
newimage = a[:, :, i]
imageio.imwrite("path/to/image%d.tiff" %i, newimage)
What exactly do you mean by "stack"? As you refer to tiff as output format, I assume here you want your data in one file as a multiframe-tiff.
This can easily be done with imageio's mimwrite() function:
# import numpy as np
# a = np.random.randint(0,5, size=(100,100,100))
# a = a.astype('int8')
import imageio
imageio.mimwrite("image.tiff", a)
Note that this function relies on having the counter for your several frames as first parameter and x and y follw. See also its documentation.
However, if I'm wrong and you want to have n (e.g. 100) separate tif-files, you can also use the normal imwrite() function in a loop:
n = len(a)
for i in range(n):
imageio.imwrite(f'image_{i:03}.tiff', a[i])

Extracting specific netcdf info and converting to GeoTIFF in python

I am attempting to extract a specific set of data from a netCDF file and then convert said data to a GeoTIFF.
So far I have managed to extract the data I want using netCDF4, all the data in the file are stored as 1d arrays (lat, lon, data I want) and assigning them to a 2d array. The netcdf file that I am working with was subsetted to a specific region. From here however I am at a loss.
I have a slight understanding of how geotiff conversion works via what I have read at these links:
https://borealperspectives.wordpress.com/2014/01/16/data-type-mapping-when-using-pythongdal-to-write-numpy-arrays-to-geotiff/
http://adventuresindevelopment.blogspot.co.uk/2008/12/create-geotiff-with-python-and-gdal.html
And here is what I have currently:
import netCDF4
import numpy as np
from osgeo import gdal
from osgeo import osr
#Reading in data from files and extracting said data
ncfile = netCDF4.Dataset("data.nc", 'r')
dataw = ncfile.variables["dataw"][:]
lat = ncfile.variables["Latitude"][:]
long = ncfile.variables["Longitude"][:]
n = len(dataw)
x = np.zeros((n,3), float)
x[:,0] = long[:]
x[:,1] = lat[:]
x[:,2] = dataw[:]
nx = len(long)
ny = len(lat)
xmin, ymin, xmax, ymax = [long.min(), lat.min(), long.max(), lat.max()]
xres = (xmax - xmin) / float(nx)
yres = (ymax - ymin) / float(ny)
geotransform = (xmin, xres, 0, ymax, 0, -yres)
#Creates 1 raster band file
dst_ds = gdal.GetDriverByName('GTiff').Create('myGeoTIFF.tif', ny, nx, 1, gdal.GDT_Float32)
dst_ds.SetGeoTransform(geotransform) # specify coords
srs = osr.SpatialReference() # establish encoding
srs.ImportFromEPSG(3857) # WGS84 lat/long
dst_ds.SetProjection(srs.ExportToWkt()) # export coords to file
dst_ds.GetRasterBand(1).WriteArray(x) # write r-band to the raster
dst_ds.FlushCache() # write to disk
dst_ds = None # save, close
The process of geotiff creation above I have largely sourced from here:
How do I write/create a GeoTIFF RGB image file in python?
I have attempted this based on the understanding that the array I want to write to the raster is a 2d array with 3 columns, 2 of co-ords and 1 of data. My result which I check in snap is a black page with a white line along the LHS.
So my question is as follows:
How can I extract the necessary geotransform data from my netcdf file, adjust the geotransform parameters appropriately and subsequently use the extracted lat long + dataw arrays to write to a geotiff file?
Try using gdal_translate command line to convert to geotiff file
gdal_translate NETCDF:"<filename.nc>":<varible name> <required_file>.tif

Reading a .VTK polydata file and converting it into Numpy array

I want to convert a .VTK ASCII polydata file into numpy array of just the coordinates of the points. I first tried this: https://stackoverflow.com/a/11894302 but it stores a (3,3) numpy array where each entry is actually the coordinates of THREE points that make that particular cell (in this case a triangle). However, I don't want the cells, I want the coordinates of each point (without repeatition). Next I tried this: https://stackoverflow.com/a/23359921/6619666 with some modifications. Here is my final code. Instead of numpy array, the values are being stored as a tuple but I am not sure if that tuple represents each point.
import sys
import numpy
import vtk
from vtk.util.numpy_support import vtk_to_numpy
reader = vtk.vtkPolyDataReader()
reader.SetFileName('Filename.vtk')
reader.ReadAllScalarsOn()
reader.ReadAllVectorsOn()
reader.Update()
nodes_vtk_array= reader.GetOutput().GetPoints().GetData()
print nodes_vtk_array
Please give suggestions.
You can use dataset_adapter from vtk.numpy_interface:
from vtk.numpy_interface import dataset_adapter as dsa
polydata = reader.GetOutput()
numpy_array_of_points = dsa.WrapDataObject(polydata).Points
From Kitware blog:
It is possible to access PointData, CellData, FieldData, Points
(subclasses of vtkPointSet only), Polygons (vtkPolyData only) this
way.
You can get the point coordinates from a polydata object like so:
polydata = reader.GetOutput()
points = polydata.GetPoints()
array = points.GetData()
numpy_nodes = vtk_to_numpy(array)

Load sequence of PNGs into vtkImageData for 3D volume render using python

I have a sequence of about 100 PNG files containing 512x512 pre-segmented CAT scan data. I want to use vtk on Python to create a 3D model using marching cubes algorithm. The part that I don't know how to do is to load the sequence of PNG files and convert them to a single vtk pixel data object suitable for sending to the vtkDiscreteMarchingCubes algorithm.
I also think that I need to convert the pixel values of the PNG data because right now the data is in the alpha channel, so this needs to be converted into scalar data with values of zero and 1.
use vtkPNGreader and load in individual slices and then populate a vtkImageData which you can define the dimensions as and for each z-slice or image fill the image data form the output of the reader into your vtkImageData.
Rough pseudocode - not checked for bugs :)
import vtk
from vtk.util import numpy_support
pngfiles = glob.glob('*.png')
png_reader = vtk.vtkPNGReader()
png_reader.SetFileName(pngfiles[0])
x,y = png_reader.GetOutput().GetDimensions()
data_3d = np.zeros([x,y,len(pngfiles)])
for i,p in enumerate(png):
png_reader.SetFileName(pngfiles[0])
png_reader.Update()
img_data = png_reader.GetOutput()
data_3D[:,:,i] = numpy_support.vtk_to_numpy(img_data)
#save your 3D numpy array out.
data_3Dvtk = numpy_support.numpy_to_vtk(data_3D)
Just in case anyone stumbles on here looking for another way to do this only using vtk, you can use vtkImageAppend class.
def ReadImages(files):
reader = vtk.vtkPNGReader()
image3D = vtk.vtkImageAppend()
image3D.SetAppendAxis(2)
for f in files:
reader.SetFileName(f)
reader.Update()
t_img = vtk.vtkImageData()
t_img.DeepCopy(reader.GetOutput())
image3D.AddInputData(t_img)
image3D.Update()
return image3D.GetOutput()
for converting the data you can take a look at what the output of t_img.GetPointData().GetArray('PNGImage') gives and see if it is the expected value.

Categories

Resources