You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import datetime
import re
import copy
import os
import xarray as xr
import numpy as np
import pandas as pd
import seaborn as sns
import colorcet as cc
import pathlib
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
def global_mean(ds):
''' Area-weighted global-mean value of a single field '''
weights = np.cos(np.abs(ds.latitude * np.arccos(-1)/180.))
weights = weights/weights.mean()
return((ds * weights).mean(dim=["latitude", "longitude"]))
figDir = pathlib.Path(os.environ['FIGURE_DIR'])
dataDir = pathlib.Path("data-processed")
# original data - needed only to show the number of observations per day/month
cacheDir = pathlib.Path("modis-data-original")
sample_month = "2021-07-01"
Pixel counts - one day, one month
Access the raw files in environment variable MODIS_DATA_CACHE_DIR
#
# When using raw files the lat/lon information is at the top level and each variable
# in it's own group; we have to associate the position information by hand
#
def read_one_group(filename, groupname):
''' Access the variables from a single group including location information
Fields need to be transposed (.T) before plotting geographically '''
f = xr.open_dataset(filename, engine="netcdf4", group=groupname)
f["latitude"] = xr.open_dataset(filename, engine="netcdf4").latitude
f["longitude"] = xr.open_dataset(filename, engine="netcdf4").longitude
return(f)
sns.set_context("paper")
fig = plt.figure(figsize = (12, 9))
axes = fig.subplots(nrows=2, subplot_kw={'projection': map_projection()})
example_daily_file = [f for f in cacheDir.glob("MCD06COSP_D3_MODIS.A2021196*")][0]
example_monthly_file = [f for f in cacheDir.glob("MCD06COSP_M3_MODIS.A2021182*")][0]
# One day
daily = read_one_group(example_daily_file, "Cloud_Mask_Fraction")
pl = daily.Pixel_Counts.T.plot(ax = axes[0],
transform=ccrs.PlateCarree(),
add_colorbar=False)
axes[0].set_title("Number of observations, July 15 2021")
# One month
monthly = read_one_group(example_monthly_file, "Cloud_Mask_Fraction")
norm = monthly.Pixel_Counts/31.
pl = norm.T.plot(ax = axes[1],
transform=ccrs.PlateCarree(),
add_colorbar=False)
axes[1].set_title("Average daily observations, July 2021")
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Number of observations/day")
if saveFigs:
# fig.savefig(figDir.joinpath("Observation-numbers.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
fig.savefig(figDir.joinpath("Observation-numbers.png"), dpi=150, transparent=True, bbox_inches = "tight")
sns.set_context("paper")
fig = plt.figure(figsize = (12, 12))
axes = fig.subplots(nrows=3, subplot_kw={'projection': map_projection()})
cm = copy.copy(cc.m_fire)
cm.set_bad("0.85")
# Cloud mask fraction
rat = (month.Cloud_Mask_Fraction_High/month.Cloud_Mask_Fraction)
pl = rat.plot(ax = axes[0],
transform=ccrs.PlateCarree(),
vmin = 0, vmax = 1,
cmap = cm,
add_colorbar=False)
axes[0].set_title("Fraction of clouds that are high, July 2021")
rat = (month.Cloud_Mask_Fraction_Mid/month.Cloud_Mask_Fraction)
pl = rat.plot(ax = axes[1],
transform=ccrs.PlateCarree(),
vmin = 0, vmax = 1,
cmap = cm,
add_colorbar=False)
axes[1].set_title("Fraction of clouds that are mid, July 2021")
rat = (month.Cloud_Mask_Fraction_Low/month.Cloud_Mask_Fraction)
pl = rat.plot(ax = axes[2],
transform=ccrs.PlateCarree(),
vmin = 0, vmax = 1,
cmap = cm,
add_colorbar=False)
axes[2].set_title("Fraction of clouds that are low, July 2021")
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Cloud fraction")
if saveFigs:
# fig.savefig(figDir.joinpath("Cloud-fractions.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
fig.savefig(figDir.joinpath("Cloud-height-partitioning.png"), dpi=150, transparent=True, bbox_inches = "tight")
Liquid/ice clouds
sns.set_context("paper")
fig = plt.figure(figsize = (12, 9))
axes = fig.subplots(nrows=2, subplot_kw={'projection': map_projection()})
cm = copy.copy(cc.m_CET_CBL1)
cm.set_bad("0.85")
# Cloud mask fraction
rat = (month.Cloud_Retrieval_Fraction_Ice/month.Cloud_Retrieval_Fraction_Total)
pl = rat.plot(ax = axes[0],
transform=ccrs.PlateCarree(),
vmin = 0, vmax = 1,
cmap = cm,
add_colorbar=False)
axes[0].set_title("Fraction of clouds that are ice, July 2021")
rat = (month.Cloud_Retrieval_Fraction_Liquid/month.Cloud_Retrieval_Fraction_Total)
pl = rat.plot(ax = axes[1],
transform=ccrs.PlateCarree(),
vmin = 0, vmax = 1,
cmap = cm,
add_colorbar=False)
axes[1].set_title("Fraction of clouds that are liquid, July 2021")
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Cloud fraction")
if saveFigs:
# fig.savefig(figDir.joinpath("Cloud-fractions.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
fig.savefig(figDir.joinpath("Cloud-phase-partitioning.png"), dpi=150, transparent=True, bbox_inches = "tight")
Optical thickness - geometric and arithmetic means
sns.set_context("paper")
fig = plt.figure(figsize = (12, 9))
axes = fig.subplots(nrows=2, subplot_kw={'projection': map_projection()})
cm = copy.copy(cc.m_CET_L18_r)
cm.set_bad("0.85")
#cm = cc.m_CET_L20
# Cloud optical thickness
data = month["Cloud_Optical_Thickness_Total"]
pl = data.plot(ax = axes[0],
transform=ccrs.PlateCarree(),
vmin=0, vmax=40,
cmap = cm,
add_colorbar=False)
axes[0].set_title("Arithemtic mean optical thickness, July 2021")
data = np.power(10, month["Cloud_Optical_Thickness_Log10_Total"])
pl = data.plot(ax = axes[1],
transform=ccrs.PlateCarree(),
vmin=0, vmax=40,
cmap = cm,
add_colorbar=False)
axes[1].set_title("Geometric mean optical thickness, July 2021")
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Optical thickness")
if saveFigs:
# fig.savefig(figDir.joinpath("Cloud-fractions.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
fig.savefig(figDir.joinpath("Cloud-optical-thickness.png"), dpi=150, transparent=True, bbox_inches = "tight")
Joint histogram figures
sns.set_context("paper")
fig = plt.figure(figsize = (7.75, 8.9))
cmap = cc.m_blues
axes = fig.subplots(nrows=3, ncols=2, sharex=True, sharey=True)
def get_joint_histo(v, s=""):
hname = f"Cloud_Optical_Thickness_{v}_vs_Cloud_Top_Pressure"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
return(gmh[hname])
#
# Joint histograms vs cloud top pressure: (cloudy, partly-cloudy) x (total, liquid, ice)
#
# Normalize the color bar to the figure with the biggest cloud fractions
vmax = np.max(get_joint_histo("Total"))
for i, s in enumerate(["", "_PCL"]): # Top row/subset is cloudy, bottom row/subset is partly-cloudy (PCL)
for r, v in enumerate(["Total", "Ice", "Liquid"]):
hname = f"Cloud_Optical_Thickness{s}_{v}_vs_Cloud_Top_Pressure"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
#
# imshow() seems to show the first array dimension from top to bottom and the second dimension
# from left to right, so we transpose the DataArray before plotting
#
pl = axes[r, i].imshow(gmh[hname].T, cmap = cmap, vmin=0, vmax=vmax)
#
# Labeling the axes
#
if r==2:
# Simplified axis label
axes[r, i].set_xlabel("cloud optical thickness")
tau_var = [ k for k in gmh.coords if "optical_thickness" in k and "bnds" in k][0]
tau_bnds = gmh[tau_var]
axes[r, i].set_xticks(np.arange(len(tau_bnds))-.5)
axes[r, i].set_xticklabels(tau_bnds.values)
#
# y axis label, tick values on left-most panel only
#
if i==0:
jnt_var = [ k for k in gmh.coords if "optical_thickness" not in k and "bnds" in k][0]
axes[r, i].set_ylabel(jnt_var.replace("bnds", "").replace("_", " ") + "(hPa)")
jnt_bnds = gmh[jnt_var]
axes[r, i].set_yticks(np.arange(len(jnt_bnds))-.5)
axes[r, i].set_yticklabels(jnt_bnds.values)
axes[0,0].annotate("Total", (0,0))
axes[1,0].annotate("Ice", (0,0))
axes[2,0].annotate("Liquid", (0,0))
axes[0,0].annotate("Fully-cloudy", (4,0))
axes[0,1].annotate("Partly-cloudy", (4,0))
fig.tight_layout()
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.5, aspect = 15, label="Cloud fraction")
fig.savefig(figDir.joinpath("Tau-pc-histograms.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
sns.set_context("paper")
fig = plt.figure(figsize = (10.5, 6.75))
cmap = cc.m_CET_L17 # New colormap because different axes
axes = fig.subplots(ncols=2, nrows=2, sharex=True)
#
# Joint histograms of optical thickness vs particle size
#
v = "Liquid"; s = ""
hname = f"Cloud_Optical_Thickness_vs_Cloud_Particle_Size{s}_{v}"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
vmax = np.max(gmh[hname])
for i, s in enumerate(["", "_PCL"]): # Top row/subset is cloudy, bottom row/subset is partly-cloudy (PCL)
for r, v in enumerate(["Ice", "Liquid"]):
hname = f"Cloud_Optical_Thickness_vs_Cloud_Particle_Size{s}_{v}"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
#
# imshow() seems to show the first array dimension from top to bottom and the second dimension
# from left to right, so we transpose the DataArray before plotting
#
pl = axes[r, i].imshow(gmh[hname].T, cmap, vmin=0, vmax=vmax) # Normalization from the figure above
#
# Labeling the axes
#
# x-axis labels only in bottom row
if r==1:
# Simplified axis label
axes[r, i].set_xlabel("cloud optical thickness")
tau_var = [ k for k in gmh.coords if "optical_thickness" in k and "bnds" in k][0]
tau_bnds = gmh[tau_var]
axes[r, i].set_xticks(np.arange(len(tau_bnds))-.5)
axes[r, i].set_xticklabels(tau_bnds.values)
#
# y axis labels - need separately for each column
#
jnt_var = [ k for k in gmh.coords if "optical_thickness" not in k and "bnds" in k][0]
axes[r, i].set_ylabel(jnt_var.replace("cloud","").replace("bnds", "").replace("_", " ").replace(" pcl", "") +
" ($\mu$m)")
jnt_bnds = gmh[jnt_var]
axes[r, i].set_yticks(np.arange(len(jnt_bnds))-.5)
axes[r, i].set_yticklabels(jnt_bnds.values)
axes[r, i].invert_yaxis()
axes[0,0].annotate("Ice", (0,5))
axes[1,0].annotate("Liquid", (0,5))
axes[0,0].annotate("Fully-cloudy", (4,5))
axes[0,1].annotate("Partly-cloudy", (4,5))
fig.tight_layout()
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Cloud fraction")
fig.savefig(figDir.joinpath("Tau-re-histograms.pdf"), dpi=600, transparent=True, bbox_inches = "tight")
sns.set_context("paper")
fig = plt.figure(figsize = (10.5, 6.75))
cmap = cc.m_CET_CBTL2_r # New colormap because different axes
axes = fig.subplots(ncols=2, nrows=2)
#
# Joint histograms vs cloud top pressure: (cloudy, partly-cloudy) x (total, liquid, ice)
#
v = "Liquid"; s = ""
hname = f"Cloud_Water_Path_vs_Cloud_Particle_Size{s}_{v}"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
vmax = np.max(gmh[hname])
for i, s in enumerate(["", "_PCL"]): # Top row/subset is cloudy, bottom row/subset is partly-cloudy (PCL)
for r, v in enumerate(["Ice", "Liquid"]):
hname = f"Cloud_Water_Path_vs_Cloud_Particle_Size{s}_{v}"
fname = dataDir.joinpath(f"modis-cosp-{hname}.nc")
gmh = global_mean(xr.open_dataset(fname).sel(date=sample_month))
#
# imshow() seems to show the first array dimension from top to bottom and the second dimension
# from left to right, so we transpose the DataArray before plotting
#
pl = axes[r, i].imshow(gmh[hname].T, cmap, vmin=0, vmax=vmax) # Normalization from the figure above
#
# Labeling the axes
#
tau_var = [ k for k in gmh.coords if "cloud_particle" not in k and "bnds" in k][0]
#
# Simplified axis label
#
axes[r, i].set_xlabel(tau_var.replace("bnds", "").replace("_", " ").replace("pcl ", ""))
tau_bnds = gmh[tau_var]
axes[r, i].set_xticks(np.arange(len(tau_bnds))-.5)
axes[r, i].set_xticklabels(tau_bnds.values)
#
# y axis labels - need separately for each column
#
jnt_var = [ k for k in gmh.coords if "cloud_particle" in k and "bnds" in k][0]
axes[r, i].set_ylabel(jnt_var.replace("cloud","").replace("bnds", "").replace("_", " ").replace(" pcl", "") +
" ($\mu$m)")
jnt_bnds = gmh[jnt_var]
axes[r, i].set_yticks(np.arange(len(jnt_bnds))-.5)
axes[r, i].set_yticklabels(jnt_bnds.values)
axes[r, i].invert_yaxis()
axes[0,0].annotate("Ice", (0,5))
axes[1,0].annotate("Liquid", (0,5))
axes[0,0].annotate("Fully-cloudy", (4,5))
axes[0,1].annotate("Partly-cloudy", (4,5))
fig.tight_layout()
fig.colorbar(pl, ax=axes.ravel().tolist(), shrink = 0.75, aspect = 15, label="Cloud fraction")
fig.savefig(figDir.joinpath("LWP-re-histograms.pdf"), dpi=600, transparent=True, bbox_inches = "tight")