How to merge multiple MODIS swaths into one plot in python? - python

I want to mosaic/merge multiple swaths of the MODIS dataset (MOD06_L2) using python. I used the example (http://hdfeos.org/zoo/MORE/LAADS/MOD/MOD04_L2_merge.py) to read multiple files and merge. But I am getting an error while doing so, how to correct this error?
I would like to know is there any better way than this, to merge/mosaic MODIS HDF files into one?
import os
import glob
import matplotlib as mpl
import matplotlib.pyplot as plt
# import cartopy.crs as ccrs
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
# The first file in 3 swath files.
FILE_NAME = 'MOD06_L2.A2017126.0655.061.2019226193408.hdf'
GEO_FILE_NAME ='MOD06_L2.A2017126.0655.061.2019226193408.hdf'
DATAFIELD_NAME = 'Brightness_Temperature'
from pyhdf.SD import SD, SDC
i = 0
for file in list(glob.glob('MOD06*.hdf')):
reader = open(file)
hdf = SD(file, SDC.READ)
# Read dataset.
data2D = hdf.select(DATAFIELD_NAME)
data = data2D[:,:].astype(np.double)
hdf_geo = SD(GEO_FILE_NAME, SDC.READ)
# Read geolocation dataset.
lat = hdf_geo.select('Latitude')
latitude = lat[:,:]
lon = hdf_geo.select('Longitude')
longitude = lon[:,:]
# Retrieve attributes.
attrs = data2D.attributes(full=1)
lna=attrs["long_name"]
long_name = lna[0]
aoa=attrs["add_offset"]
add_offset = aoa[0]
fva=attrs["_FillValue"]
_FillValue = fva[0]
sfa=attrs["scale_factor"]
scale_factor = sfa[0]
vra=attrs["valid_range"]
valid_min = vra[0][0]
valid_max = vra[0][1]
ua=attrs["units"]
units = ua[0]
invalid = np.logical_or(data > valid_max,data < valid_min)
invalid = np.logical_or(invalid, data == _FillValue)
data[invalid] = np.nan
data = (data - add_offset) * scale_factor
datam = np.ma.masked_array(data, np.isnan(data))
if i == 0 :
data_m = datam
latitude_m = latitude
longitude_m = longitude
else:
data_m = np.vstack([data_m, datam])
latitude_m = np.vstack([latitude_m, latitude])
longitude_m = np.vstack([longitude_m, longitude])
i = i + 1
m = Basemap(projection='cyl', resolution='l',
llcrnrlat=-90, urcrnrlat=90,
llcrnrlon=-180, urcrnrlon=180)
m.drawcoastlines(linewidth=0.5)
m.drawparallels(np.arange(-90, 91, 45))
m.drawmeridians(np.arange(-180, 180, 45), labels=[True,False,False,True])
sc = m.scatter(longitude_m, latitude_m, c=data_m, s=0.1, cmap=plt.cm.jet,
edgecolors=None, linewidth=0)
cb = m.colorbar()
cb.set_label(units)
# Put title using the first file.
basename = os.path.basename(FILE_NAME)
plt.title('{0}\n{1}'.format(basename, DATAFIELD_NAME))
fig = plt.gcf()
# Save image.
pngfile = "{0}.py.png".format(basename)
fig.savefig(pngfile)
It showing an error
ValueError: 'c' argument has 4604040 elements, which is inconsistent with 'x' and 'y' with size 657720.

Related

My plot is nested in another plot, and negative values are saturated using a diverging colormap

When making a plot using plt.subplot, my plot is nested within another plot, leading to an extra set of axes with ranges 0-1 and cutting off my colorbar.
Additionally, when using a diverging colorbar, all negative values are falsely saturated.
I have used this code format before without having an additional set of axes.
Is there another way to make this kind of plot without using plt.subplot if that is causing the issue?
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib
import cmocean
import h5py
import pandas as pd
import matplotlib.colors as colors
import cartopy
import matplotlib.colormaps as colormaps
july = h5py.File('data/CCS_Colour_Kahru/chl/1km/daily/2016/Daily_Chlorophyll_July.mat','r')
daily_chl_july = july.get('daily_chl')
lat_july = daily_chl_july.get('Latitude')
lon_july = daily_chl_july.get('Longitude')
chl_july = daily_chl_july.get('chl')
date_july = daily_chl_july.get('date')
data_july = daily_chl_july.get('data')
lat_july = np.array(lat_july)
lat_july = lat_july[0]
lon_july = np.array(lon_july)
lon_july = lon_july[0]
chl_july = np.array(chl_july)
inside_lat_july = np.where(lat_july>=(32.9))
lat_july = lat_july[inside_lat_july]
lon_july = lon_july[inside_lat_july]
chl_july = chl_july[inside_lat_july]
inside_lat_july = np.where(lat_july<=(34.05))
lat_july = lat_july[inside_lat_july]
lon_july = lon_july[inside_lat_july]
chl_july = chl_july[inside_lat_july]
inside_lon_july = np.where(lon_july>=(-118.96))
lon_july = lon_july[inside_lon_july]
lat_july = lat_july[inside_lon_july]
chl_july = chl_july[inside_lon_july]
inside_lon_july = np.where(lon_july<=(-117.54))
lon_july = lon_july[inside_lon_july]
lat_july = lat_july[inside_lon_july]
chl_july = chl_july[inside_lon_july]
mean_chl = np.nanmean(chl_july, axis=1)
remove_nan = ~np.isnan(mean_chl)
mean_chl = mean_chl[remove_nan]
chl_july_mean = chl_july[remove_nan]
lat_july_mean = lat_july[remove_nan]
lon_july_mean = lon_july[remove_nan]
for i in range (0,31,1):
day = i+1
chl_now = chl_july_mean[:,i]
remove_nan = ~np.isnan(chl_now)
chl_now_clean1 = chl_now[remove_nan]
lon_now_clean1 = lon_july_mean[remove_nan]
lat_now_clean1 = lat_july_mean[remove_nan]
mean_chl_clean = mean_chl[remove_nan]
if np.size(chl_now_clean1)==0:
continue
anomaly = chl_now_clean1 - mean_chl_clean
print('min')
print(anomaly.min())
print('max')
print(anomaly.max())
fig, ax = plt.subplots(1,1,figsize=(15,10))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent([-118.96,-117.54,32.9,34.05])
im = ax.scatter(lon_now_clean1, lat_now_clean1, norm=colors.TwoSlopeNorm(vmin=-20, vcenter=0, vmax=20), c=anomaly, cmap='PiYG')
ax.add_feature(cfeature.LAND,zorder=4,color='gray')
ax.set_title("Chlorophyll Anomaly 2016 July "+str(day),fontsize=25)
ax.set_xlabel("Longitude",fontsize=20)
ax.set_ylabel("Latitude",fontsize=20)
xticks = np.linspace(-118.96,-117.54,5)
yticks = np.linspace(32.9,34.05,5)
ax.set_xticks(ticks=xticks)
ax.set_yticks(ticks=yticks)
fig.colorbar(im, ax=ax)
im.set_clim(0.1,1.5)
ax.coastlines()
plt.savefig('frankieleelopez/0124anomaly72016'+str(day))
plt.close()
enter image description here

How to convert mat file->numpy file->nifti file to match with nnU-Net data format?

I'm currently documenting how to convert each data type to be compatible with a new deeplearning framework. I'll cut out redundant code in the futrue :)
The following code can be executed on VScode interactive window.
The code has two part.
convert mat file to npy file (.mat -> .npy)
convert npy file to nifti file (.npy -> nii.gz) and add specific name in the path to match with nnU-Net data format. See the nnU-Net dataset_conversion.md if you're interested in it.
How it actually works?
1)10000001.mat -> 10000001.npy
2)10000001.npy -> AORTA_001_0000.nii.gz
The path can be adjusted by a individual user.
#%%
import numpy as np
import nibabel as nb
import pathlib
import numpy as np
from torch.utils.data import Dataset
import scipy.io
root_data = '/mnt/intern/code/dataset/test/original'
root_label = '/mnt/intern/code/dataset/test/label'
examples = []
examples2 = []
data_files = list(pathlib.Path(root_data).iterdir())
label_files = list(pathlib.Path(root_label).iterdir())
for fname in sorted(data_files):
examples += [fname]
for fname2 in sorted(label_files):
examples2 += [fname2]
for i in range(len(data_files)):
fname = examples[i]
fname2 = examples2[i]
data_name = str(pathlib.Path(fname))
label_name = str(pathlib.Path(fname2))
# d = np.load(data_name); l = np.load(label_name)
d_load = scipy.io.loadmat(data_name);
l_load = scipy.io.loadmat(label_name) # matfile data load
data = d_load['data'];
label = l_load['label'] # (512, 512, 251)
np.save('/mnt/intern/mat2npy/original/' + str(fname).split('.')[0][-8:], data)
np.save('/mnt/intern/mat2npy/label/' + str(fname).split('.')[0][-8:], label)
#%%
# Name change to match with nnU-Net data format
import numpy as np
import nibabel as nb
import pathlib
import numpy as np
from torch.utils.data import Dataset
import scipy.io
import numpy as np
import nibabel as nib
root_data = '/mnt/intern/mat2npy/imagesTr'
root_label = '/mnt/intern/mat2npy/labelsTr'
examples = []
examples2 = []
data_files = list(pathlib.Path(root_data).iterdir())
label_files = list(pathlib.Path(root_label).iterdir())
for fname in sorted(data_files):
examples += [fname]
for fname2 in sorted(label_files):
examples2 += [fname2]
for i in range(len(data_files)):
fname = examples[i]
fname2 = examples2[i]
data_name = str(pathlib.Path(fname))
label_name = str(pathlib.Path(fname2))
# d = np.load(data_name); l = np.load(label_name)
d_load = np.load(data_name);
l_load = np.load(label_name) # matfile data load
data = d_load
label = l_load # (512, 512, 251)
data = np.array(data, dtype=np.float32) # You need to replace normal array by yours
label = np.array(label, dtype=np.float32)
affine = np.eye(4)
nifti_data = nib.Nifti1Image(data, affine)
nifti_label = nib.Nifti1Image(label, affine)
nib.save(nifti_data, '/mnt/intern/mat2npy/imagesTr/' + 'AORTA_' + str(fname).split('.')[0][-3:] + '_0000.nii.gz') # Here you put the path + the extionsion 'nii' or 'nii.gz'
nib.save(nifti_label, '/mnt/intern/mat2npy/labelsTr/' + 'AORTA_' + str(fname).split('.')[0][-3:] + '_0000.nii.gz')

How can i return interactive map?

I have this code for a map using a netcdf file of European Centre for Medium-Range Weather Forecasts.
def interactive_map():
import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
#original name -> _grib2netcdf-webmars-public-svc-green-007-6fe5cac1a363ec1525f54343b6cc9fd8-b5oXS9.nc
fn = '7.nc'
ds = nc.Dataset(fn)
#variables
#longitude, latitude, time, pm1
lons = ds.variables['longitude'][:]
lats = ds.variables['latitude'][:]
time = ds.variables['time'][:]
pm = ds.variables['pm1'][:]
mp = Basemap(projection = 'merc',
llcrnrlon = 97.085310,
llcrnrlat = 2.044212,
urcrnrlon = 106.896219,
urcrnrlat = 7.403567,
resolution = 'i')
lon, lat = np.meshgrid(lons, lats)
x, y = mp(lon, lat)
cscheme = mp.pcolor(x, y, np.squeeze(pm[0,:,:]), cmap = 'turbo')
mp.drawcoastlines()
mp.drawstates()
mp.drawcountries()
cbar = mp.colorbar(cscheme, location = 'right')
#plt.show()
plt.savefig('map.png')
https://i.imgur.com/4lndRuY.png
What i want is add the map to a view of web2py, i know it saves an image and i can render the image, but it's possible to show in an interactive map?
This is what i have to show the map in a view:
<!--index.html-->
{{extend 'layout.html'}}
<img src="{{=URL('static','images/map.png')}}" width="500" height="600">
My package ncplot (https://ncplot.readthedocs.io/en/latest/) will automatically create interactive plots for NetCDF files. You just need to do the following:
from ncplot import ncplot
ncplot(fn)

Creating an instance of an object in a for loop and plotting attributes on a matplotlib plot or subplot

The data I have is list of dataframes with the same columns supplied from files of interest input by the user. Dataframe columns and user inputs are passed into the __init__ parameters to create an instance. Some attributes of the instances are lists which I would like to plot when they are created in the loop.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
class Sample():
def __init__(self,initname,initlistA,initlistB,...):
self.name = initname
self.nums_a = initlistA
'''There are more but are unnecessary to show'''
def func(self,listA,scalar_A = 30 ,scalar_B = 10) :
x = stats.binned_statistic(self.nums,self.nums,statistic = 'count', bins = scalar_A, range[0,scalar_B]):
self.right_bins = x[1][1:]
self.y_values = x[0]
fig,axs = plt.subplots()
axs.set_xlabel('str')
axs.set_ylabel('str_2')
#axs.set_ylim(bottom = 0)
#axs.set_xlim(left = 0)
lst_of_dfs = []
files = []
while True:
fname = input('file.xlsx')
if fname =='Done' :break
else:
file=pd.read_excel(fname)
lst_of_dfs.append(file)
files.append(fname)
for x in range(0,len(lst_of_dfs)):
name = files[x]
df = lst_of_dfs[x]
sample = Sample(input('name for {}'.format(name),df['initlistA'],....)
sample.fun()
axs.plot(self.right_bins,self.y_values,marker = 'x', label = self.name)
print(self.y_values)
print(self.right_bins)
axs.set_ylim(bottom = 0)
axs.set_xlim(left = 0)
plt.show()
self.right_bins and self.y_values return lists of equal length in my program. I am just not able to plot these lists on a plot or subplot.

Optimisation of plot animation for large data with dynamic grid

I am trying to generate an animation for a large data with a dynamic grid (ocean waves). I have managed to write a script that is functional but it is time and resource consuming. I was hoping if anyone could see what i can improve in my code to help speed it up.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import animation as anim
import xarray as xr
import PySimpleGUI as sg
import sys
#file importing mechanism
jan = xr.open_dataset('Model/Bar_mig/xboutput_equi.nc')
########################## labeling the variables in the data-set ##############
nx = jan.variables['globalx']
globaltime = jan.variables['globaltime']
zb = jan.variables['zb'][:,0,:]
zs = jan.variables['zs'][:,0,:]
ccz = jan.variables['ccz'][:,:,0,:]
uz = jan.variables['uz'][:,:,0,:]
nz = np.array(range(0,100))
nx = (np.array(range(0,nx.size)))
globaltime_ar = np.array(globaltime)
conc = np.vstack(globaltime_ar)
newdf = pd.DataFrame(conc)
itr = len(newdf.index)
uz1=np.flip(uz,0)
uz2=np.flip(np.flip(uz1,1),axis=0)
depth1 = (zb)
a = np.array(depth1)
b = pd.DataFrame(a)
depth = b.dropna(axis=1, how='all')
zba1 = (np.array(zb))
zsa1 = (np.array(-zs))
zba = pd.DataFrame(zba1)
zsa = pd.DataFrame(zsa1)
This is how i am setting up the dynamic grid. ( example of the the output)
#dynamic grid
for w in range(0,itr):
AA=[]
sizer = depth.iloc[w,]
sizer1 = sizer.dropna(axis=0, how='all')
for j in range(0,sizer1.size):
maxi = -zsa.iloc[w,j]
mini = depth.iloc[w,j]
step = mini/nz.shape[-1]
globals()['col_{}'.format(j)] = pd.DataFrame(np.linspace(maxi,mini,nz.shape[-1],endpoint=True))
globals()['col_{}'.format(j)] = globals()['col_{}'.format(j)].reset_index(drop=True)
AA.append(globals()['col_{}'.format(j)])
globals()['df_{}'.format(w)] = pd.concat(AA, axis=1).iloc[:nz.size]
globals()['df_{}'.format(w)].columns = range(globals()['df_{}'.format(w)].shape[1])
AA.clear()
sg.OneLineProgressMeter('My meter title', w, itr-1, 'key')
from matplotlib import animation as anim
fig = plt.figure(figsize=(15,7.5)) # Create a dummy figure
ax = plt.axes() # Set the axis rigid
mywriter = anim.FFMpegWriter()
scale=1
def animate(w):
w = w*scale
plt.clf()
plt.title(str(w) + 'hr')
y = globals()['df_{}'.format(w)]
x = np.array([nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx,nx])
data2 = np.flip(ccz[w*1,:,:],0)
cont = plt.pcolor(x,y,np.array(data2), cmap = 'jet',
vmin = 0, vmax = 0.03
)
plt.colorbar(label='Concentration Profile ($m^3/m^3$)')
plt.fill_between(nx,min(zb[0])-1,zb[w],color = 'yellow')
point = 350
plt.xlim(point,nx.shape[-1])
plt.ylim(min(zb[0,point:point+1]),max(zb[0,point:]))
plt.xlabel('Cross shore distance (m)')
plt.ylabel('Depth (m)')
fig.tight_layout()
return cont,
ani = anim.FuncAnimation(fig, animate, interval = 1, frames=itr)
ani.save('Sed_Con.mp4', writer=mywriter)

Categories

Resources