Skip to content
Snippets Groups Projects
saveKml.py 7.42 KiB
Newer Older
Narayanarao Bhogapurapu's avatar
Narayanarao Bhogapurapu committed
#!/usr/bin/env python3
#
# Author: Heresh Fattahi
# Copyright 2016
#
import argparse
import isce
import isceobj
import os
from osgeo import gdal
import matplotlib as mpl;  #mpl.use('Agg')
import matplotlib.pyplot as plt
from pykml.factory import KML_ElementMaker as KML
import numpy as np
mpl.use('Agg')

def createParser():
    '''
    Create command line parser.
    '''

    parser = argparse.ArgumentParser( description='Create a kml file from geocoded products.')
    parser.add_argument('-f', '--filelist', dest='prodlist', type=str, required=True,
            help='Input file to be geocoded')
#    parser.add_argument('-b', '--bbox', dest='bbox', type=str, required=True,
#            help='Bounding box (SNWE)')
    parser.add_argument('-m', '--min', dest='min', type=float, default=None,
            help='minimum value of colorscale')
    parser.add_argument('-M', '--max', dest='max', type=float, default=None,
            help='maximum value of color scale')
    parser.add_argument('-d', '--dpi', dest='dpi', type=int, default=500,
            help='dpi of the png image')
    parser.add_argument('-c', '--color_map', dest='color_map', type=str, default='jet',
            help='matplotlib colormap')
    parser.add_argument('-u', '--unit', dest='unit', type=str, default='',
            help='unit in which data is displayed')
    parser.add_argument('-s', '--scale', dest='scale', type=float, default=1.0,
            help= 'scale factor to scale the data before display')
    parser.add_argument('-b', '--start_time', dest='startTime', type=str, default='',
            help= 'start time of the observation')
    parser.add_argument('-e', '--end_time', dest='endTime', type=str, default='',
            help= 'end time of the observation')    
    parser.add_argument('-r', '--reverse_color_map', dest='reverseColorMap', type=str, default='no',
            help= 'reverse color map (default: no)') 
    parser.add_argument('-w', '--rewrap', dest='rewrap', type=str, default='no',
            help= 'reverse color map (default: no)')
    parser.add_argument('-n', '--band_number', dest='bandNumber', type=int, default=1,
            help='band number if multiple bands exist')
    return parser

def cmdLineParse(iargs = None):
    '''
    Command line parser.
    '''

    parser = createParser()
    inps =  parser.parse_args(args = iargs)

    inps.prodlist = inps.prodlist.split()
    return inps

def reverse_colourmap(cmap, name = 'my_cmap_r'):
    """
    In: 
    cmap, name 
    Out:
    my_cmap_r

    Explanation:
    t[0] goes from 0 to 1
    row i:   x  y0  y1 -> t[0] t[1] t[2]
                   /
                  /
    row i+1: x  y0  y1 -> t[n] t[1] t[2]

    so the inverse should do the same:
    row i+1: x  y1  y0 -> 1-t[0] t[2] t[1]
                   /
                  /
    row i:   x  y1  y0 -> 1-t[n] t[2] t[1]
    """
    reverse = []
    k = []

    for key in cmap._segmentdata:
        k.append(key)
        channel = cmap._segmentdata[key]
        data = []

        for t in channel:
            data.append((1-t[0],t[2],t[1]))
        reverse.append(sorted(data))

    LinearL = dict(zip(k,reverse))
    my_cmap_r = mpl.colors.LinearSegmentedColormap(name, LinearL)
    return my_cmap_r

def get_lat_lon(file):

    ds=gdal.Open(file)
    b=ds.GetRasterBand(1)

    width=b.XSize
    length = b.YSize

    minLon = ds.GetGeoTransform()[0]
    deltaLon = ds.GetGeoTransform()[1]
    maxLon = minLon + width*deltaLon    

    maxLat = ds.GetGeoTransform()[3]
    deltaLat = ds.GetGeoTransform()[5]
    minLat = maxLat + length*deltaLat

    return minLat, maxLat, minLon, maxLon

def rewrap(unw):
   rewrapped = unw - np.round(unw/(2*np.pi)) * 2*np.pi
   return rewrapped

def display(file,inps):
    ds = gdal.Open(file)
    b = ds.GetRasterBand(inps.bandNumber)
    data = b.ReadAsArray()
    data = data*inps.scale
    data[data==0]=np.nan
    #data = np.ma.masked_where(data == 0, data)
    if inps.rewrap=='yes':
       data = rewrap(data)

    if inps.min is None:
       inps.min = np.nanmin(data)

    if inps.max is None:
       inps.max = np.nanmax(data)

    width = b.XSize
    length = b.YSize    

    fig = plt.figure()
    fig = plt.figure(frameon=False)
    # fig.set_size_inches(width/1000,length/1000)
    ax = plt.Axes(fig, [0., 0., 1., 1.], )
   # ax.patch.set_alpha(0.0)
    ax.set_axis_off()
    fig.add_axes(ax)

    aspect = width/(length*1.0)
    # ax.imshow(data,aspect='normal')
    cmap = plt.get_cmap(inps.color_map)
    if inps.reverseColorMap=='yes':
       cmap = reverse_colourmap(cmap) 
    cmap.set_bad(alpha=0.0)
 #   cmap.set_under('k', alpha=0)
    try:     ax.imshow(data, aspect = 'auto', vmax = inps.max, vmin = inps.min, cmap = cmap)
    except:  ax.imshow(data, aspect = 'auto', cmap = cmap)

    ax.set_xlim([0,width])
    ax.set_ylim([length,0])

    # figName = k+'.png'
    figName = file + '.png'
    plt.savefig(figName, pad_inches=0.0, transparent=True, dpi=inps.dpi)

    #############################
    #pc = plt.figure(figsize=(1,4))
    pc = plt.figure(figsize=(1.3,2))
    axc = pc.add_subplot(111)
    cmap=mpl.cm.get_cmap(name=inps.color_map)
    if inps.reverseColorMap=='yes':     
       cmap = reverse_colourmap(cmap)
    norm = mpl.colors.Normalize(vmin=inps.min, vmax=inps.max)
    clb = mpl.colorbar.ColorbarBase(axc,cmap=cmap,norm=norm, orientation='vertical')
    clb.set_label(inps.unit)
    pc.subplots_adjust(left=0.25,bottom=0.1,right=0.4,top=0.9)
    #pc.subplots_adjust(left=0.0,bottom=0.0,right=1.0,top=1.0)
   # pc.savefig(file+'_colorbar.png',transparent=True,dpi=300)
    pc.savefig(file+'_colorbar.png',dpi=300)

    return file + '.png' , file+'_colorbar.png'

def writeKML(file, img, colorbarImg,inps):
  South, North, West, East = get_lat_lon(file)  
  ############## Generate kml file
  print ('generating kml file')
  doc = KML.kml(KML.Folder(KML.name(os.path.basename(file))))
  slc = KML.GroundOverlay(KML.name(os.path.basename(img)),KML.Icon(KML.href(os.path.basename(img))),\
                          KML.TimeSpan(KML.begin(),KML.end()),\
                          KML.LatLonBox(KML.north(str(North)),KML.south(str(South)),\
                                        KML.east(str(East)),  KML.west(str(West))))
  doc.Folder.append(slc)

  #############################
  print ('adding colorscale')
  latdel = North-South
  londel = East-West
  
  slc1   = KML.ScreenOverlay(KML.name('colorbar'),KML.Icon(KML.href(os.path.basename(colorbarImg))),
        KML.overlayXY(x="0.0",y="1",xunits="fraction",yunits="fraction",),
        KML.screenXY(x="0.0",y="1",xunits="fraction",yunits="fraction",),
        KML.rotationXY(x="0.",y="1.",xunits="fraction",yunits="fraction",),
        KML.size(x="0",y="0.3",xunits="fraction",yunits="fraction",),
      )


  doc.Folder.append(slc1)

  

  #############################
  from lxml import etree
  kmlstr = etree.tostring(doc, pretty_print=True)
  print (kmlstr)
  kmlname = file + '.kml'
  print ('writing '+kmlname)
  kmlfile = open(kmlname,'wb')
  kmlfile.write(kmlstr)
  kmlfile.close()

  kmzName = file + '.kmz'
  print ('writing '+kmzName)
  cmdKMZ = 'zip ' + kmzName +' '+ os.path.basename(kmlname) +' ' + os.path.basename(img) + ' ' + os.path.basename(colorbarImg)
  os.system(cmdKMZ)



def runKml(inps):

    for file in inps.prodlist:
       file = os.path.abspath(file)
       img,colorbar = display(file,inps) 
       writeKML(file,img,colorbar,inps)

def main(iargs=None):
    '''
    Main driver.
    '''
    inps = cmdLineParse(iargs)
    runKml(inps)


if __name__ == '__main__':
    main()