OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
color_dtdb.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # encoding: utf-8
3 
4 import os
5 import sys
6 import datetime
7 import math
8 from PIL import Image as im
9 from PIL import ImageDraw
10 from PIL import ImageFilter
11 from PIL import ImageMath
12 from PIL import ImageEnhance
13 from PIL import ImageOps as imo
14 from PIL import ImageColor as imc
15 
16 import viirs_files as vf
17 import numpy as np
18 import xarray as xr
19 import matplotlib as mpl
20 import matplotlib.pyplot as plt
21 from matplotlib import cm
22 
23 W410 = 0
24 W445 = 1
25 W490 = 2
26 W550 = 3
27 W670 = 4
28 W865 = 5
29 W1240 = 6
30 W1610 = 7
31 W2250 = 8
32 NWL = 9
33 
34 wlstr = ["410","445","490","550","670","865","1240","1610","2250"]
35 
36 Kb = 0.114
37 Kr = 0.299
38 
39 RGB2YCbCr = np.array([[0.257, 0.504, 0.098],[-0.148, -0.291, 0.439],[0.439, -0.368, -0.071]])
40 YCbCr2RGB = np.array([[1.0, 0.0, 1.596],[1.0, -0.392, -0.813],[1.0, 2.017, 0.0]])
41 
42 def rgb2ycbcr(r,g,b):
43  y = RGB2YCbCr[0,0]*r + RGB2YCbCr[0,1]*g + RGB2YCbCr[0,2]*b
44  u = RGB2YCbCr[1,0]*r + RGB2YCbCr[1,1]*g + RGB2YCbCr[1,2]*b
45  v = RGB2YCbCr[2,0]*r + RGB2YCbCr[2,1]*g + RGB2YCbCr[2,2]*b
46  return y,u,v
47 
48 def ycbcr2rgb(y,cb,cr):
49  r = YCbCr2RGB[0,0]*y + YCbCr2RGB[0,1]*cb + YCbCr2RGB[0,2]*cr
50  g = YCbCr2RGB[1,0]*y + YCbCr2RGB[1,1]*cb + YCbCr2RGB[1,2]*cr
51  b = YCbCr2RGB[2,0]*y + YCbCr2RGB[2,1]*cb + YCbCr2RGB[2,2]*cr
52  return r,g,b
53 
54 
55 RGB2YUV = np.array([[0.299, 0.587, 0.114],[-0.14713, -0.28886, 0.436],[0.615, -0.51499, -0.10001]])
56 YUV2RGB = np.array([[1.0, 0.0, 1.13983],[1.0, -0.39465, -0.58060],[1.0, 2.03211, 0.0]])
57 
58 def rgb2yuv(r,g,b):
59  y = (RGB2YUV[0,0]*r + RGB2YUV[0,1]*g + RGB2YUV[0,2]*b)
60  u = (RGB2YUV[1,0]*r + RGB2YUV[1,1]*g + RGB2YUV[1,2]*b)
61  v = (RGB2YUV[2,0]*r + RGB2YUV[2,1]*g + RGB2YUV[2,2]*b)
62  return y,u,v
63 
64 def yuv2rgb(y,u,v):
65  r = (YUV2RGB[0,0]*y + YUV2RGB[0,1]*u + YUV2RGB[0,2]*v)
66  g = (YUV2RGB[1,0]*y + YUV2RGB[1,1]*u + YUV2RGB[1,2]*v)
67  b = (YUV2RGB[2,0]*y + YUV2RGB[2,1]*u + YUV2RGB[2,2]*v)
68  return r,g,b
69 
70 
71 def rgb2ycbcr2(r,g,b):
72  y = Kr*r + (1-Kr-Kb)*g + Kb*b
73  pb = (b-y)/(1-Kb)/2
74  pr = (r-y)/(1-Kr)/2
75  return y,pb,pr
76 
77 def ycbcr2rgb2(y,pb,pr):
78  r = 2*pr*(1-Kr) + y
79  b = 2*pb*(1-Kb) + y
80  g = (y - Kr*r - Kb*b)/(1-Kr-Kb)
81  return r,g,b
82 
83 
84 def histeq(im,nbr_bins=256):
85 
86  #get image histogram
87  imhist,bins = np.histogram(im.flatten(),nbr_bins)
88 
89  cdf = imhist.cumsum() #cumulative distribution function
90  cdf = cdf/cdf[-1]
91 
92  #use linear interpolation of cdf to find new pixel values
93  im2 = np.interp(im.flatten(),bins[:-1],cdf)
94 
95  plt.plot(bins[:-1],imhist)
96  plt.plot(bins[:-1],cdf)
97  #plt.show()
98  plt.clf()
99 
100  plt.plot(np.divide(im2[0:10000],im.flatten()[0:10000]))
101  #plt.show()
102  plt.clf()
103 
104  return im2.reshape(im.shape), cdf
105 
106 
107 def pseudocolor(val, minval, maxval):
108  # Scale val to be in the range [0, 1]
109  val = (val - minval) / (maxval - minval)
110  # Return RGBA tuple from nipy_spectral colormap
111  return cm.nipy_spectral(val)
112 
113 def plot_scalar_array(ds_str, title_str, mina, maxa):
114  fig = plt.figure(facecolor='k')
115  ds = xr.load_dataset(filepath,group='/geophysical_data',mask_and_scale=True)[ds_str].values
116  #np.clip(ds, mina, maxa, ds)
117  ml = mpl.cm.ScalarMappable(norm=None, cmap='turbo')
118  ml.set_clim(mina, maxa)
119  ml.set_array(ds)
120  aec = ml.to_rgba(ds, alpha=None)
121  fig.figimage(aec,resize=True)
122  loc = plt.LinearLocator(11)
123  fig.set_figwidth(fig.get_figwidth()*1.1)
124  fig.set_figheight(fig.get_figheight()*1.04)
125  axa = fig.add_axes([0.94, 0.1, 0.012, 0.8], frameon=True)
126  axa.tick_params(colors='c', labelsize=10, length=20, width=2, pad=5, right=True)
127  axa.yaxis.set_major_locator(loc)
128  tvals = loc.tick_values(mina, maxa)
129  fig.colorbar(ml, cax=axa, ticks=tvals )
130  fig.suptitle(x + title_str, color='c', size=10, y=0.99)
131 # plt.show()
132  plt.savefig(outpath, facecolor=fig.get_facecolor())
133  plt.close(fig)
134  fig.clf()
135 
136 def plot_rgb():
137  blue = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_490'].values
138  green = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_550'].values
139  red = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_670'].values
140  ro = np.clip(np.nan_to_num(red),0,1.0)
141  go = np.clip(np.nan_to_num(green),0,1.0)
142  bo = np.clip(np.nan_to_num(blue),0,1.0)
143  ao = np.ones_like(ro)
144 
145  y, u, v = rgb2yuv(ro, go, bo)
146  y += 0.001
147  y = y/np.max(y)
148  yh, Y_cdf = histeq(y)
149  maxo_all = max(np.max(ro), np.max(go), np.max(bo)) + 0.001
150  ro /= maxo_all
151  go /= maxo_all
152  bo /= maxo_all
153 
154  gamma = 1.0
155  ga = np.ones_like(ro)*gamma
156  rg = np.power(ro, ga)
157  gg = np.power(go, ga)
158  bg = np.power(bo, ga)
159  yg = np.power(yh, ga)
160 
161  ys = np.divide(yg,y)
162  rg = np.multiply(ys,ro)
163  gg = np.multiply(ys,go)
164  bg = np.multiply(ys,bo)
165 
166  scale = 255
167  im_red = im.fromarray(np.uint8(np.clip(rg,0,1.0)*scale))
168  im_green = im.fromarray(np.uint8(np.clip(gg,0,1.0)*scale))
169  im_blue = im.fromarray(np.uint8(np.clip(bg,0,1.0)*scale))
170  im_alpha = im.fromarray(np.uint8(np.clip(ao,0,1.0)*scale))
171 
172  im_rgb = im.merge("RGBA", (im_red, im_green, im_blue, im_alpha))
173  return np.asarray(im_rgb)/255.0
174 
175 # Start program execution
176 
177 args = sys.argv
178 
179 dtdb_dirpath = args[1]
180 dataset = args[2]
181 
182 colors = "123"
183 if len(args) > 3:
184  colors = args[3]
185  bc = np.int(args[3][0])-1
186  gc = np.int(args[3][1])-1
187  rc = np.int(args[3][2])-1
188 else:
189  bc = 1
190  gc = 2
191  rc = 3
192 
193 logfile = ""
194 if len(args) > 4:
195  logfile = args[4]
196  command = "date > " + logfile
197  result = os.system(command)
198 
199 dtdb_dircontents = os.listdir(dtdb_dirpath)
200 dtdb_dircontents.sort()
201 
202 for x in dtdb_dircontents:
203 
204  if x[0] == ".":
205  continue
206 
207  filepath = dtdb_dirpath + "/" + x
208 
209  if not os.path.isfile(filepath):
210  continue
211 
212  if (dataset == "retrievals"):
213  image_path = dtdb_dirpath + "/IMAGES"
214  if not os.path.isdir(image_path):
215  os.mkdir(image_path)
216  image_path = image_path + "/geophysical_data"
217 
218  for dname in ["ae", "aot_550", "fmf_550", "sse"]:
219 
220  outfilename = x + "_" + dname + ".png"
221  path = image_path + "_" + dname
222  if not os.path.isdir(path):
223  os.mkdir(path)
224  outpath = path + "/" + outfilename
225 
226  if dname == "ae":
227  title_str = ' Angstrom Exponent'
228  ds_str = 'ae'
229  maxa = 2.0
230  mina = 0.0
231  elif dname == "aot_550":
232  title_str = ' Log base 10 of Aerosol Optical Depth at 550 nm'
233  ds_str = 'aot_550'
234  maxa = 1.4
235  mina = -1.2
236 # elif dname == "aot_550":
237 # title_str = ' Aerosol Optical Depth at 550 nm'
238 # ds_str = 'aot_550'
239 # maxa = 1.0
240 # mina = 0.0
241  elif dname == "fmf_550":
242  title_str = ' Fine Mode Fraction'
243  ds_str = 'fmf_550'
244  maxa = 1.0
245  mina = 0.0
246  elif dname == "sse":
247  title_str = ' Log base 10 of Normalized Sum of Squares Error'
248  ds_str = 'residual_error'
249  maxa = 1.0
250  mina = -3.0
251  else:
252  print ("invalid dataset name: ", dname)
253  continue
254 
255  plot_scalar_array(ds_str, title_str, mina, maxa)
256  print (x)
257  continue
258  elif (dataset == "histogram"):
259  image_path = dtdb_dirpath + "/IMAGES"
260  if not os.path.isdir(image_path):
261  os.mkdir(image_path)
262  image_path1 = image_path + "/histograms"
263  outfilename1 = x + "_hist_410.png"
264  if not os.path.isdir(image_path1):
265  os.mkdir(image_path1)
266  outpath1 = image_path1 + "/" + outfilename1
267  image_path2 = image_path + "/maps"
268  outfilename2 = x + "_map.png"
269  if not os.path.isdir(image_path2):
270  os.mkdir(image_path2)
271  outpath2 = image_path2 + "/" + outfilename2
272  ct = [3200,3200]
273  st = [0,0]
274 
275  refwl = W865
276  refbs = W410
277  nbins = 100
278  hmin = 0
279  hmax = 10
280  max0 = 0.0
281  min0 = -2.0
282  max1 = 2.5
283  min1 = -0.5
284  hist = np.zeros((NWL, nbins, nbins))
285  cmap = cm.get_cmap('turbo')
286  fig1 = plt.figure(figsize=(16,10))
287  fig2 = plt.figure(figsize=(16,8))
288 
289  irgb = plot_rgb()
290  ax2 = fig2.add_subplot(2,4,1)
291  ax2.set_title(x)
292  plt.xticks([])
293  plt.yticks([])
294  plt.imshow(irgb)
295 
296  rfl0 = xr.load_dataset(filepath,group='/observations')['rhot_'+wlstr[refwl]].values[st[0]:st[0]+ct[0],st[1]:st[1]+ct[1]]
297  lrfl0 = np.log10(np.clip(rfl0, a_min=0.0001, a_max=1.0))
298  rflbs = xr.load_dataset(filepath,group='/observations')['rhot_'+wlstr[refbs]].values[st[0]:st[0]+ct[0],st[1]:st[1]+ct[1]]
299  lrflbs = np.log10(np.clip(rflbs, a_min=0.0001, a_max=1.0))
300  ax2 = fig2.add_subplot(2,4,5)
301  ax2.set_title("log10(RHOT_"+wlstr[refwl]+")")
302  ml = mpl.cm.ScalarMappable(norm=None, cmap=cmap)
303  ml.set_clim(min0, max0)
304  ml.set_array(lrfl0)
305  aec = ml.to_rgba(lrfl0, alpha=None)
306  plt.xticks([])
307  plt.yticks([])
308  plt.imshow(aec)
309 
310  for wl in range(NWL):
311 
312  if (wl==W445):
313  continue
314  elif (wl==W410):
315  wl1 = 1
316  wl2 = 1
317  bwl2 = False
318  elif (wl==W865):
319  wl1 += 1
320  wl2 += 1
321  bwl2 = False
322  else:
323  wl1 += 1
324  wl2 += 1
325  bwl2 = True
326 
327  rfl1 = xr.load_dataset(filepath,group='/observations')['rhot_'+wlstr[wl]].values[st[0]:st[0]+ct[0],st[1]:st[1]+ct[1]]
328  lrfl1 = lrflbs - np.log10(np.clip(rfl1, a_min=0.0001, a_max=1.0))
329 
330  try:
331  hist[wl], edges = np.histogramdd((lrfl0.flatten(),lrfl1.flatten()), range=[[min0,max0],[min1,max1]],bins=nbins, density=True)
332  except Exception as inst:
333  print(type(inst))
334  print(inst)
335  print ("Numpy.histogramdd failure ... exiting")
336  sys.exit()
337 
338  ax1 = fig1.add_subplot(2,4,wl1)
339  xpos0, ypos0 = np.meshgrid(edges[0][:-1]+edges[0][1:], edges[1][:-1]+edges[1][1:])
340  cp1 = ax1.contourf(xpos0/2, ypos0/2, np.clip(hist[wl].T, a_min=hmin, a_max=hmax), levels=100, cmap=cmap)
341  ax1.set_title("RHOT_"+wlstr[wl])
342  ax1.set_xlabel("log10 (RHOT_"+wlstr[refwl]+")")
343  if wl1==1 or wl1==5:
344  ax1.set_ylabel("log10(RHOT_"+wlstr[wl]+" / RHOT_"+wlstr[refwl]+")")
345  bticks = True
346  else:
347  bticks = False
348 
349  ax1.tick_params(labelleft=bticks, left=bticks)
350  ax1.grid(b=True, which='major', color='#666666', linestyle='-')
351  ax1.minorticks_on()
352  ax1.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2)
353 
354  if (bwl2):
355  ax2 = fig2.add_subplot(2,4,wl2)
356  ax2.set_title("log10(RHOT_"+wlstr[wl]+" / RHOT_"+wlstr[refwl]+")")
357  # cp2 = ax2.contourf(lrfl1, levels=np.arange(-1.0,1.0,0.1), cmap=cmap)
358  ml.set_clim(min1, max1)
359  ml.set_array(lrfl1)
360  aec = ml.to_rgba(lrfl1, alpha=None)
361  plt.xticks([])
362  plt.yticks([])
363  plt.imshow(aec)
364 
365  fig2.tight_layout()
366 # fig2.show()
367  plt.savefig(outpath2, facecolor=fig2.get_facecolor())
368  plt.close(fig2)
369  fig2.clf()
370 
371 # fig1.colorbar(cp1)
372  loc = plt.LinearLocator(11)
373  tvals = loc.tick_values(hmin, hmax)
374  ml = mpl.cm.ScalarMappable(norm=None, cmap='turbo')
375  ml.set_clim(hmin, hmax)
376  fig1.subplots_adjust(bottom=0.1, top=0.9, left=0.1, right=0.9, wspace=0.02, hspace=0.02)
377  cb_ax = fig1.add_axes([0.93, 0.1, 0.02, 0.8])
378  fig1.colorbar(ml, cax=cb_ax, ticks=tvals)
379  fig1.suptitle(x)
380 # fig1.tight_layout()
381  plt.savefig(outpath1, facecolor=fig1.get_facecolor())
382 # fig1.show()
383  plt.close(fig1)
384  fig1.clf()
385  print (x)
386  continue
387 
388  try:
389  if (dataset == "observations"):
390 # refl = xr.load_dataset(filepath,group='/observations')['rhot']
391  bluec = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_490'].values
392  greenc = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_550'].values
393  redc = xr.load_dataset(filepath,group='/observations',mask_and_scale=True)['rhot_670'].values
394  elif (dataset == "aot"):
395  ocean = xr.load_dataset(filepath,group='/geophysical_data')['AOT_ocean']
396  land = xr.load_dataset(filepath,group='/geophysical_data')['AOT_land']
397  land = xr.load_dataset(filepath,group='/geolocation')['land_water']
398  bluec = ocean[bc,:,:]
399  greenc = ocean[gc,:,:]
400  redc = ocean[rc,:,:]
401  np.putmask(bluec, lw>0, land[0,:,:])
402  np.putmask(greenc, lw>0, land[1,:,:])
403  np.putmask(redc, lw>0, land[2,:,:])
404  elif (dataset == "cloudmask"):
405  cldmsk = xr.load_dataset(filepath,group='/meteorology')['cloud_mask']
406  cldtst = xr.load_dataset(filepath,group='/quality')['cloud_test']
407  bluec = np.zeros_like(cldmsk, dtype=np.int16)
408  greenc = np.zeros_like(cldmsk, dtype=np.int16)
409  redc = np.zeros_like(cldmsk, dtype=np.int16)
410  nomask = np.zeros_like(cldmsk, dtype=np.int16)
411  bluec = cldmsk[:,:]
412  np.putmask(greenc[:,:], cldtst[:,:]<0, -cldtst[:,:])
413  np.putmask(bluec[:,:], cldtst[:,:]<0, nomask[:,:])
414  np.putmask(redc[:,:], cldtst[:,:]>0, cldtst[:,:])
415  np.putmask(bluec[:,:], cldtst[:,:]>0, nomask[:,:])
416  colors = "rgb"
417  except Exception as e:
418  print (" Error loading dataset ... exiting")
419  continue
420 
421  if (dataset == "observations" or dataset == "aot" or dataset == "cloudmask"):
422  ro = np.clip(np.nan_to_num(redc),0,10.0)
423  go = np.clip(np.nan_to_num(greenc),0,10.0)
424  bo = np.clip(np.nan_to_num(bluec),0,10.0)
425 
426  if np.isnan(np.sum(ro)):
427  print (np.max(ro), np.max(go), np.max(bo))
428  continue
429 
430  y, u, v = rgb2yuv(ro, go, bo)
431  y += 0.001
432  y = y/np.max(y)
433  yh, Y_cdf = histeq(y)
434 # u *= 1
435 # v *= 1
436 # rh, gh, bh = yuv2rgb(yh, u, v)
437 
438  mino_all = min(np.min(ro), np.min(go), np.min(bo))
439  # ro -= mino_all
440  # go -= mino_all
441  # bo -= mino_all
442  maxo_all = max(np.max(ro), np.max(go), np.max(bo)) + 0.001
443  ro /= maxo_all
444  go /= maxo_all
445  bo /= maxo_all
446 
447  gamma = 1.0
448  ga = np.ones_like(ro)*gamma
449  rg = np.power(ro, ga)
450  gg = np.power(go, ga)
451  bg = np.power(bo, ga)
452  yg = np.power(yh, ga)
453 
454  ys = np.divide(yg,y)
455  rg = np.multiply(ys,ro)
456  gg = np.multiply(ys,go)
457  bg = np.multiply(ys,bo)
458 
459  scale = 255
460  im_red = im.fromarray(np.uint8(np.clip(rg,0,1.0)*scale))
461  im_green = im.fromarray(np.uint8(np.clip(gg,0,1.0)*scale))
462  im_blue = im.fromarray(np.uint8(np.clip(bg,0,1.0)*scale))
463 
464  im_rgb = im.merge("RGB", (im_red, im_green, im_blue))
465 
466  # im_rgb.show()
467  set = dataset.partition("/")
468  outfilename = x + "_" + set[2] + "_" + colors + ".png"
469 
470  image_path = dtdb_dirpath + "/IMAGES"
471  if not os.path.isdir(image_path):
472  os.mkdir(image_path)
473  image_path = image_path + "/" + set[0]
474  if not os.path.isdir(image_path):
475  os.mkdir(image_path)
476  image_path = image_path + set[1] + set[2] + "_" + colors
477  if not os.path.isdir(image_path):
478  os.mkdir(image_path)
479 
480  outpath = image_path + "/" + outfilename
481  im_rgb.save( outpath )
482 
483  print (x)
484 
def ycbcr2rgb(y, cb, cr)
Definition: color_dtdb.py:48
def plot_scalar_array(ds_str, title_str, mina, maxa)
Definition: color_dtdb.py:113
def plot_rgb()
Definition: color_dtdb.py:136
def rgb2ycbcr2(r, g, b)
Definition: color_dtdb.py:71
def yuv2rgb(y, u, v)
Definition: color_dtdb.py:64
def rgb2ycbcr(r, g, b)
Definition: color_dtdb.py:42
def histeq(im, nbr_bins=256)
Definition: color_dtdb.py:84
def rgb2yuv(r, g, b)
Definition: color_dtdb.py:58
def pseudocolor(val, minval, maxval)
Definition: color_dtdb.py:107
def ycbcr2rgb2(y, pb, pr)
Definition: color_dtdb.py:77