This commit is contained in:
Mario Gil 2022-06-01 19:46:56 -05:00
commit b087889716
3 changed files with 237 additions and 0 deletions

203
ExtractImage.py Normal file
View File

@ -0,0 +1,203 @@
import xarray as xr
import rioxarray as rio
from matplotlib import cm
import numpy as np
import time
import matplotlib
import matplotlib.image as imgg
import os
def write_png(data,name, origin='upper', colormapD=None):
"""
Transform an array of data into a PNG string.
This can be written to disk using binary I/O, or encoded using base64
for an inline PNG like this:
>>> png_str = write_png(array)
>>> "data:image/png;base64,"+png_str.encode('base64')
Inspired from
https://stackoverflow.com/questions/902761/saving-a-numpy-array-as-an-image
Parameters
----------
data: numpy array or equivalent list-like object.
Must be NxM (mono), NxMx3 (RGB) or NxMx4 (RGBA)
origin : ['upper' | 'lower'], optional, default 'upper'
Place the [0,0] index of the array in the upper left or lower left
corner of the axes.
colormap : callable, used only for `mono` image.
Function of the form [x -> (r,g,b)] or [x -> (r,g,b,a)]
for transforming a mono image into RGB.
It must output iterables of length 3 or 4, with values between
0. and 1. Hint: you can use colormaps from `matplotlib.cm`.
Returns
-------
PNG formatted byte string
"""
if colormapD is None:
def colormapD(x):
return (x, x, x, 1)
arr = np.atleast_3d(data)
height, width, nblayers = arr.shape
if nblayers not in [1, 3, 4]:
raise ValueError('Data must be NxM (mono), '
'NxMx3 (RGB), or NxMx4 (RGBA)')
assert arr.shape == (height, width, nblayers)
if nblayers == 1:
arr = np.array(list(map(colormapD, arr.ravel())))
nblayers = arr.shape[1]
if nblayers not in [3, 4]:
raise ValueError('colormap must provide colors of r'
'length 3 (RGB) or 4 (RGBA)')
arr = arr.reshape((height, width, nblayers))
assert arr.shape == (height, width, nblayers)
if nblayers == 3:
arr = np.concatenate((arr, np.ones((height, width, 1))), axis=2)
nblayers = 4
assert arr.shape == (height, width, nblayers)
assert nblayers == 4
# Normalize to uint8 if it isn't already.
if arr.dtype != 'uint8':
with np.errstate(divide='ignore', invalid='ignore'):
arr = arr * 255./arr.max(axis=(0, 1)).reshape((1, 1, 4))
arr[~np.isfinite(arr)] = 0
arr = arr.astype('uint8')
# Eventually flip the image.
if origin == 'lower':
arr = arr[::-1, :, :]
r3 = arr.copy(order='C')
matplotlib.image.imsave(name, r3)
def image_to_url(image,name, colormapD=None, origin='upper'):
"""
Infers the type of an image argument and transforms it into a URL.
Parameters
----------
image: string, file or array-like object
* If string, it will be written directly in the output file.
* If file, it's content will be converted as embedded in the
output file.
* If array-like, it will be converted to PNG base64 string and
embedded in the output.
origin: ['upper' | 'lower'], optional, default 'upper'
Place the [0, 0] index of the array in the upper left or
lower left corner of the axes.
colormap: callable, used only for `mono` image.
Function of the form [x -> (r,g,b)] or [x -> (r,g,b,a)]
for transforming a mono image into RGB.
It must output iterables of length 3 or 4, with values between
0. and 1. You can use colormaps from `matplotlib.cm`.
"""
if 'ndarray' in image.__class__.__name__:
img = write_png(image, origin=origin, colormapD=colormapD,name=name)
def get_color(x,colormap,Min,Max):
decimals = 2
try:
#print(x,Min,Max)
x=(x*1.-Min)/(Max*1.-Min)
#print(x)
if x < 0:
x=0.0
x = np.around(x, decimals=decimals)
if colormap=="Spectral" or colormap=='ocean' or colormap=="RdYlBu":
Tempcm=cm.get_cmap(colormap).reversed()
else:
Tempcm=cm.get_cmap(colormap)
#print(x)
ls = np.around(np.linspace(0,1,10**decimals+1),decimals=decimals)
#print(ls)
if 0 <= x <= 1:
#print(cm.get_cmap('viridis')(ls)[np.argwhere(ls==x)][0][0].shape,cm.get_cmap('viridis')(ls)[np.argwhere(ls==x)])
#print(x,np.argwhere(ls==x))
return Tempcm(ls)[np.argwhere(ls==x)][0][0]
else:
#print(np.array(np.zeros(4)).shape,np.array(np.zeros(4)))
#print(x)
return np.zeros(4)
except:
print(x,np.argwhere(ls==x))
return np.zeros(4)
def ExtractMapImage(file,colormap,countyear,name,nc,geometry=""):
nc = nc.rio.write_crs(4326)
if geometry=="":
try:
nc = nc.rio.clip(geometries)
except:
pass
else:
pass
bounds=[[float(nc.lat.min().values),float(nc.lon.min().values)],[float(nc.lat.max().values),float(nc.lon.max().values)]]
i=countyear
year=int(nc.time[i].values)
print(i,year)
ncVar=nc.DHW_q99
data = ncVar[i,:,:].values
Min=np.around(np.nanquantile(ncVar[int(year)-1985,:,:].values, 0.01),2)
Max=np.around(np.nanmax(ncVar[year-1985,:,:].values),2)
image_to_url(data,name, colormapD=lambda x: get_color(x,colormap,Min,Max), origin="lower")
def ProcessAllImage(ssp,model,Colorpalete,ExportDirectory,DataDirectory):
cc=0
Var="DHW"
for i in ssp:
for j in model:
ff=DataDirectory+"%s_%s_%s_DHW.nc"%(Var,i,j)
for CM in Colorpalete:
for countyear in range(116):
nc = xr.open_dataset(ff, decode_coords="all")
year=int(nc.time[countyear].values)
Evaluado=ExportDirectory+"%s_%s"%(CM,ff.split("/")[-1].replace(".nc","_%s.png"%(year)))
if not os.path.isfile(Evaluado):
cc=cc+1
Total=cc
start=time.time()
cc=0
for i in ssp:
for j in model:
ff=DataDirectory+"%s_%s_%s_DHW.nc"%(Var,i,j)
for CM in Colorpalete:
for countyear in range(116):
nc = xr.open_dataset(ff, decode_coords="all")
year=int(nc.time[countyear].values)
Evaluado=ExportDirectory+"%s_%s"%(CM,ff.split("/")[-1].replace(".nc","_%s.png"%(year)))
if not os.path.isfile(Evaluado):
ExtractMapImage(ff,CM,countyear,Evaluado,nc)
cc=cc+1
now=time.time()
print(cc,(start-now)/cc,(start-now)/cc*(Total-cc))
ssp=("ssp245","ssp370",)#"ssp585",
model=("BCC-CSM2-MR","CanESM5",)#"CanESM5","CESM2","EC-Earth3","IPSL-CM6A-LR","MIROC6","MRI-ESM2-0",,"NorESM2-MM"
Colorpalete=["RdYlBu",'Spectral','ocean',"coolwarm"]
ExportDirectory="images/"
DataDirectory="maps/"
ProcessAllImage(ssp,model,Colorpalete,ExportDirectory,DataDirectory)

34
png2gif.py Normal file
View File

@ -0,0 +1,34 @@
import imageio
import os
import sys
import glob
def create_gif(source, name, duration):
"""
La función de generar gif, la imagen original solo supports png
fuente: lista de imágenes png (ordenadas)
nombre: el nombre del archivo generado
duración: el intervalo de tiempo entre cada imagen
"""
frames = [] # Leer en el búfer
for img in source:
frames.append(imageio.imread(img))
imageio.mimsave(name, frames, 'GIF', duration=duration)
print("Procesamiento completado")
path = "/home/mario/Documentos/Ocean/web2py/applications/BPP/views/default/maps2/"
pic_list =[]
cm="Spectral"
scenario="ssp370"
model="CanESM5"
Rut=path+"%s*%s*%s*.png"%(cm,scenario,model)
for name in glob.glob(Rut):
pic_list.append(name)
pic_list.sort()
gif_name = path+"Animated_%s_%s_%s.gif"%(cm,scenario,model)
print(gif_name)
duration_time = 0.5
create_gif(pic_list, gif_name, duration_time)

0
requiremet.txt Normal file
View File