[GRASS-SVN] r70528 - in grass-addons/grass7/raster/r.modis: . libmodis r.modis.download r.modis.import

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Feb 10 06:22:08 PST 2017


Author: lucadelu
Date: 2017-02-10 06:22:08 -0800 (Fri, 10 Feb 2017)
New Revision: 70528

Removed:
   grass-addons/grass7/raster/r.modis/libmodis/convertmodis.py
   grass-addons/grass7/raster/r.modis/libmodis/convertmodis_gdal.py
   grass-addons/grass7/raster/r.modis/libmodis/downmodis.py
   grass-addons/grass7/raster/r.modis/libmodis/parsemodis.py
Modified:
   grass-addons/grass7/raster/r.modis/libmodis/Makefile
   grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.html
   grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.py
   grass-addons/grass7/raster/r.modis/r.modis.html
   grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.html
   grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.py
Log:
r.modis: removed pymodis library locally installed, now it using the system one

Modified: grass-addons/grass7/raster/r.modis/libmodis/Makefile
===================================================================
--- grass-addons/grass7/raster/r.modis/libmodis/Makefile	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/libmodis/Makefile	2017-02-10 14:22:08 UTC (rev 70528)
@@ -3,7 +3,7 @@
 include $(MODULE_TOPDIR)/include/Make/Other.make
 include $(MODULE_TOPDIR)/include/Make/Python.make
 
-MODULES = downmodis rmodislib convertmodis parsemodis convertmodis_gdal __init__
+MODULES = rmodislib __init__
 
 ETCDIR = $(ETC)/r.modis
 

Deleted: grass-addons/grass7/raster/r.modis/libmodis/convertmodis.py
===================================================================
--- grass-addons/grass7/raster/r.modis/libmodis/convertmodis.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/libmodis/convertmodis.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -1,230 +0,0 @@
-#!/usr/bin/env python
-#  class to convert/process modis data
-#
-#  (c) Copyright Luca Delucchi 2010
-#  Authors: Luca Delucchi
-#  Email: luca dot delucchi at iasma dot it
-#
-##################################################################
-#
-#  This MODIS Python class is licensed under the terms of GNU GPL 2.
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License as
-#  published by the Free Software Foundation; either version 2 of
-#  the License, or (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#  See the GNU General Public License for more details.
-#
-##################################################################
-
-from datetime import *
-import os
-import sys
-
-
-class convertModis:
-  """A class to convert modis data from hdf to tif using resample
-  (from MRT tools)
-  """
-  def __init__(self, hdfname, confile, mrtpath):
-    """Initialization function :
-
-       hdfname = the full path to the hdf file
-
-       confile = the full path to the paramater file
-
-       mrtpath = the full path to mrt directory which contains the bin and
-       data directories
-    """
-    # check if the hdf file exists
-    if os.path.exists(hdfname):
-      self.name = hdfname
-    else:
-      raise IOError('%s does not exist' % hdfname)
-    # check if confile exists
-    if os.path.exists(confile):
-      self.conf = confile
-    else:
-      raise IOError('%s does not exist' % confile)
-    # check if mrtpath and subdirectories exists and set environment variables
-    if os.path.exists(mrtpath):
-      if os.path.exists(os.path.join(mrtpath,'bin')):
-        self.mrtpathbin = os.path.join(mrtpath,'bin')
-        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
-                                                                        'data'))
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'bin'))
-      if os.path.exists(os.path.join(mrtpath,'data')):
-        self.mrtpathdata = os.path.join(mrtpath,'data')
-        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'data'))
-    else:
-      raise IOError('The path %s does not exist' % mrtpath)
-
-  def executable(self):
-    """Return the executable of resample MRT software
-    """
-    if sys.platform.count('linux') != -1:
-      if os.path.exists(os.path.join(self.mrtpathbin,'resample')):
-        return os.path.join(self.mrtpathbin,'resample')
-    elif sys.platform.count('win32') != -1:
-      if os.path.exists(os.path.join(self.mrtpathbin,'resample.exe')):
-        return os.path.join(self.mrtpath,'resample.exe')
-
-  def run(self):
-    """Exec the convertion process"""
-    import subprocess
-    execut = self.executable()
-    if not os.path.exists(execut):
-      raise IOError('The path %s does not exist: it could be an erroneus path or '\
-                    + 'software') % execut
-    else:
-      subprocess.call([execut,'-p',self.conf])
-    return "The hdf file %s was converted successfully" % self.name
-
-
-class createMosaic:
-  """A class to convert several MODIS tiles into a mosaic"""
-  def __init__(self,
-              listfile,
-              outprefix,
-              mrtpath,
-              subset = False
-              ):
-    import tempfile
-    # check if the hdf file exists
-    if os.path.exists(listfile):
-      self.basepath = os.path.split(listfile)[0]
-      self.fullpath = os.path.realpath(self.basepath)
-      self.listfiles = listfile
-      self.tmplistfiles = open(os.path.join(tempfile.gettempdir(),
-                               '%s.prm' % str(os.getpid())), 'w')
-      self.HDFfiles = open(listfile).readlines()
-    else:
-      raise IOError('%s not exists' % hdfname)
-    # check if mrtpath and subdirectories exists and set environment variables
-    if os.path.exists(mrtpath):
-      if os.path.exists(os.path.join(mrtpath,'bin')):
-        self.mrtpathbin = os.path.join(mrtpath,'bin')
-        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
-                                                                        'data'))
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'bin'))
-      if os.path.exists(os.path.join(mrtpath,'data')):
-        self.mrtpathdata = os.path.join(mrtpath,'data')
-        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'data'))
-    else:
-      raise IOError('The path %s does not exist' % mrtpath)
-    self.out = os.path.join(self.basepath, outprefix + '.hdf')
-    self.outxml = self.out + '.xml'
-    self.subset = subset
-
-  def write_mosaic_xml(self):
-    """Write the XML metadata file for MODIS mosaic"""
-    from parsemodis import parseModisMulti
-    listHDF = []
-    for i in self.HDFfiles:
-      if i.find(self.basepath) == -1 and i.find('.hdf.xml') == -1:
-        print "Attention: maybe you do not have the full path in the HDF file list"
-        listHDF.append(os.path.join(self.basepath,i.strip()))
-        self.tmplistfiles.write("%s\n" % os.path.join(self.basepath,i.strip()))
-      elif i.find('.hdf.xml') == -1:
-        listHDF.append(i.strip())
-        self.tmplistfiles.write("%s\n" % os.path.join(self.fullpath,i.strip()))
-    pmm = parseModisMulti(listHDF)
-    pmm.writexml(self.outxml)
-    self.tmplistfiles.close()
-
-
-  def executable(self):
-    """Return the executable of mrtmosaic MRT software
-    """
-    if sys.platform.count('linux'):
-      if os.path.exists(os.path.join(self.mrtpathbin,'mrtmosaic')):
-        return os.path.join(self.mrtpathbin,'mrtmosaic')
-    elif sys.platform.count('win32'):
-      if os.path.exists(os.path.join(self.mrtpathbin,'mrtmosaic.exe')):
-        return os.path.join(self.mrtpathbin,'mrtmosaic.exe')
-
-  def run(self):
-    """Exect the mosaic process"""
-    import subprocess
-    execut = self.executable()
-    if not os.path.exists(execut):
-      raise IOError('The path %s does not exist, it could be an erroneus path or '\
-                    + 'software') % execut
-    else:
-      self.write_mosaic_xml()
-      if self.subset:
-        subprocess.call([execut,'-i',self.tmplistfiles.name,'-o',self.out,'-s',
-                         self.subset], stderr = subprocess.STDOUT)
-      else:
-        subprocess.call([execut,'-i',self.tmplistfiles.name,'-o',self.out],
-                        stderr = subprocess.STDOUT)
-    return "The mosaic file %s has been created" % self.out
-
-
-class processModis:
-  """A class to process raw modis data from hdf to tif using swath2grid (from MRT Swath tools)
-  """
-  def __init__(self, 
-              hdfname, confile, mrtpath, 
-              inputhdf = None, outputhdf = None, geolocfile = None
-  ):
-    """Initialization function :
-       hdfname = the full path to the hdf file
-       confile = the full path to the paramater file
-       mrtpath = the full path to mrt directory which contains the bin and 
-                 data directories
-    """
-    # check if the hdf file exists
-    if os.path.exists(hdfname):
-      self.name = hdfname
-    else:
-      raise IOError('%s does not exist' % hdfname)
-    # check if confile exists
-    if os.path.exists(confile):
-      self.conf = confile
-    else:
-      raise IOError('%s does not exist' % confile)
-    # check if mrtpath and subdirectories exists and set environment variables
-    if os.path.exists(mrtpath):
-      if os.path.exists(os.path.join(mrtpath,'bin')):
-        self.mrtpathbin = os.path.join(mrtpath,'bin')
-        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
-                                                                        'data'))
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'bin'))
-      if os.path.exists(os.path.join(mrtpath,'data')):
-        self.mrtpathdata = os.path.join(mrtpath,'data')
-        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
-      else:
-        raise IOError('The path %s does not exist' % os.path.join(mrtpath,'data'))
-    else:
-      raise IOError('The path %s does not exist' % mrtpath)
-
-  def executable(self):
-    """Return the executable of resample MRT software
-    """
-    if sys.platform.count('linux') != -1:
-      if os.path.exists(os.path.join(self.mrtpathbin,'swath2grid')):
-        return os.path.join(self.mrtpathbin,'swath2grid')
-    elif sys.platform.count('win32') != -1:
-      if os.path.exists(os.path.join(self.mrtpathbin,'swath2grid.exe')):
-        return os.path.join(self.mrtpathbin,'swath2grid.exe')
-
-  def run(self):
-    """Exec the convertion process"""
-    import subprocess
-    execut = self.executable()
-    if not os.path.exists(execut):
-      raise IOError('The path %s does not exist, it could be an erroneus path or '\
-                    + 'software') % execut
-    else:
-      subprocess.call([execut,'-pf=%s' % self.conf])
-    return "The hdf file %s has been converted" % self.name

Deleted: grass-addons/grass7/raster/r.modis/libmodis/convertmodis_gdal.py
===================================================================
--- grass-addons/grass7/raster/r.modis/libmodis/convertmodis_gdal.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/libmodis/convertmodis_gdal.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -1,710 +0,0 @@
-#!/usr/bin/env python
-#  class to convert/process modis data using gdal
-#
-#  Some code is coming from GDAL/OGR Test Suite
-#  Copyright (c) 2008, Andrey Kiselev <dron16 at ak4719.spb.edu>
-#  Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
-#  http://trac.osgeo.org/gdal/browser/trunk/autotest/alg/warp.py#L782
-#
-#  (c) Copyright Luca Delucchi 2014
-#  Authors: Luca Delucchi
-#  Email: luca dot delucchi at iasma dot it
-#
-##################################################################
-#
-#  This MODIS Python class is licensed under the terms of GNU GPL 2.
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License as
-#  published by the Free Software Foundation; either version 2 of
-#  the License, or (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#  See the GNU General Public License for more details.
-#
-##################################################################
-"""Convert MODIS HDF file using GDAL Python bindings. It can create GeoTiff
-file (or other GDAL supported formats) or HDF mosaic file for several tiles.
-
-Classes:
-
-* :class:`file_info`
-* :class:`createMosaicGDAL`
-* :class:`convertModisGDAL`
-
-Functions:
-
-* :func:`getResampling`
-* :func:`raster_copy`
-* :func:`raster_copy_with_nodata`
-
-"""
-from __future__ import print_function
-from types import ListType, StringType
-try:
-    import osgeo.gdal as gdal
-except ImportError:
-    try:
-        import gdal
-    except ImportError:
-        raise ImportError('Python GDAL library not found, please install '
-                          'python-gdal')
-
-try:
-    import osgeo.osr as osr
-except ImportError:
-    try:
-        import osr
-    except ImportError:
-        raise ImportError('Python GDAL library not found, please install '
-                          'python-gdal')
-
-
-RESAM_GDAL = ['AVERAGE', 'BILINEAR', 'CUBIC', 'CUBIC_SPLINE', 'LANCZOS',
-              'MODE', 'NEAREST_NEIGHBOR']
-SINU_WKT = 'PROJCS["Sinusoidal_Sanson_Flamsteed",GEOGCS["GCS_Unknown",' \
-           'DATUM["D_unknown",SPHEROID["Unknown",6371007.181,"inf"]],' \
-           'PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]' \
-           ',PROJECTION["Sinusoidal"],PARAMETER["central_meridian",0],' \
-           'PARAMETER["false_easting",0],PARAMETER["false_northing",0]' \
-           ',UNIT["Meter",1]]'
-
-
-def getResampling(res):
-    """Return the GDAL resampling method
-
-       :param str res: the string of resampling method
-    """
-    if res == 'AVERAGE':
-        return gdal.GRA_Average
-    elif res == 'BILINEAR' or res == 'BICUBIC':
-        return gdal.GRA_Bilinear
-    elif res == 'LANCZOS':
-        return gdal.GRA_Lanczos
-    elif res == 'MODE':
-        return gdal.GRA_Mode
-    elif res == 'NEAREST_NEIGHBOR':
-        return gdal.GRA_NearestNeighbour
-    elif res == 'CUBIC_CONVOLUTION' or res == 'CUBIC':
-        return gdal.GRA_Cubic
-    elif res == 'CUBIC_SPLINE':
-        return gdal.GRA_CubicSpline
-
-
-class convertModisGDAL:
-    """A class to convert modis data from hdf to GDAL formats using GDAL
-
-       :param str hdfname: name of input data
-       :param str prefix: prefix for output data
-       :param str subset: the subset to consider
-       :param int res: output resolution
-       :param str outformat: output format, it is possible to use all the
-                             supported GDAL format
-       :param int epsg: the EPSG code for the reprojection of output file
-       :param str wkt: the WKT string for the reprojection of output file
-       :param str resampl: the resampling method to use
-       :param bool vrt: True to read GDAL VRT file created with
-                        createMosaicGDAL
-    """
-    def __init__(self, hdfname, prefix, subset, res, outformat="GTiff",
-                 epsg=None, wkt=None, resampl='NEAREST_NEIGHBOR', vrt=False):
-        """Function for the initialize the object"""
-        # Open source dataset
-        self.in_name = hdfname
-        self.src_ds = gdal.Open(self.in_name)
-        self.layers = self.src_ds.GetSubDatasets()
-        self.output_pref = prefix
-        self.resolution = res
-        if epsg:
-            self.dst_srs = osr.SpatialReference()
-            self.dst_srs.ImportFromEPSG(int(epsg))
-            self.dst_wkt = self.dst_srs.ExportToWkt()
-        elif wkt:
-            try:
-                f = open(wkt)
-                self.dst_wkt = f.read()
-                f.close()
-            except:
-                self.dst_wkt = wkt
-        else:
-            raise Exception('You have to set one of the following option: '
-                            '"epsg", "wkt"')
-        # error threshold the same value as gdalwarp
-        self.error_threshold = 0.125
-        self.resampling = getResampling(resampl)
-        if type(subset) == ListType:
-            self.subset = subset
-        elif type(subset) == StringType:
-            self.subset = subset.replace('(', '').replace(')',
-                                                          '').strip().split()
-        else:
-            raise Exception('Type for subset parameter not supported')
-        self.driver = gdal.GetDriverByName(outformat)
-        self.vrt = vrt
-        if self.driver is None:
-            raise Exception('Format driver %s not found, pick a supported '
-                            'driver.' % outformat)
-
-    def _boundingBox(self, src):
-        """Obtain the bounding box of raster in the new coordinate system
-
-           :param src: a GDAL dataset object
-
-           :return: a bounding box value in lists
-        """
-        src_gtrn = src.GetGeoTransform(can_return_null=True)
-
-        src_bbox_cells = ((0., 0.), (0, src.RasterYSize), (src.RasterXSize, 0),
-                          (src.RasterXSize, src.RasterYSize))
-
-        geo_pts_x = []
-        geo_pts_y = []
-        for x, y in src_bbox_cells:
-            x2 = src_gtrn[0] + src_gtrn[1] * x + src_gtrn[2] * y
-            y2 = src_gtrn[3] + src_gtrn[4] * x + src_gtrn[5] * y
-            geo_pts_x.append(x2)
-            geo_pts_y.append(y2)
-        return ((min(geo_pts_x), min(geo_pts_y)), (max(geo_pts_x),
-                                                   max(geo_pts_y)))
-
-    def _calculateRes(self, minn, maxx, res):
-        """Calculate the number of pixel from extent and resolution
-
-           :param float minn: minimum value of extent
-           :param float maxx: maximum value of extent
-           :param int res: resolution of output raster
-
-           :return: integer number with the number of pixels
-        """
-        return int(round((maxx - minn) / res))
-
-    def _createWarped(self, raster):
-        """Create a warped VRT file to fetch default values for target raster
-        dimensions and geotransform
-
-        :param str raster: the name of raster, for HDF have to be one subset
-        """
-        src = gdal.Open(raster)
-        tmp_ds = gdal.AutoCreateWarpedVRT(src, SINU_WKT,
-                                          self.dst_wkt, self.resampling,
-                                          self.error_threshold)
-
-        if not self.resolution:
-            self.dst_xsize = tmp_ds.RasterXSize
-            self.dst_ysize = tmp_ds.RasterYSize
-            self.dst_gt = tmp_ds.GetGeoTransform()
-        else:
-            bbox = self._boundingBox(tmp_ds)
-            self.dst_xsize = self._calculateRes(bbox[0][0], bbox[1][0],
-                                                self.resolution)
-            self.dst_ysize = self._calculateRes(bbox[0][1], bbox[1][1],
-                                                self.resolution)
-            if self.dst_xsize == 0:
-                raise Exception('Invalid number of pixel 0 for X size. The '
-                                'problem could be in an invalid value of '
-                                'resolution')
-                return 0
-            elif self.dst_ysize == 0:
-                raise Exception('Invalid number of pixel 0 for Y size. The '
-                                'problem could be in an invalid value of '
-                                'resolution')
-                return 0
-            self.dst_gt = [bbox[0][0], self.resolution, 0.0, bbox[1][1], 0.0,
-                           -self.resolution]
-        tmp_ds = None
-        src = None
-        return 0
-
-    def _progressCallback(self, pct, message, user_data):
-        """For the progress status"""
-        return 1  # 1 to continue, 0 to stop
-
-    def _reprojectOne(self, l):
-        """Reproject a single subset of MODIS product
-
-        l = complete name of input dataset
-        """
-        l_src_ds = gdal.Open(l)
-        meta = l_src_ds.GetMetadata()
-        band = l_src_ds.GetRasterBand(1)
-        if '_FillValue' in meta.keys():
-            fill_value = meta['_FillValue']
-        elif band.GetNoDataValue():
-            fill_value = band.GetNoDataValue()
-        else:
-            fill_value = None
-        datatype = band.DataType
-        try:
-            l_name = l.split(':')[-1]
-            out_name = "{pref}_{lay}.tif".format(pref=self.output_pref,
-                                                 lay=l_name)
-        except:
-            out_name = "{pref}.tif".format(pref=self.output_pref)
-        if self.vrt:
-            out_name = "{pref}.tif".format(pref=self.output_pref)
-        try:
-            dst_ds = self.driver.Create(out_name, self.dst_xsize,
-                                        self.dst_ysize, 1, datatype)
-        except:
-            raise Exception('Not possibile to create dataset %s' % out_name)
-            return 0
-        dst_ds.SetProjection(self.dst_wkt)
-        dst_ds.SetGeoTransform(self.dst_gt)
-        if fill_value:
-            dst_ds.GetRasterBand(1).SetNoDataValue(float(fill_value))
-            dst_ds.GetRasterBand(1).Fill(float(fill_value))
-        cbk = self._progressCallback
-        # value for last parameter of above self._progressCallback
-        cbk_user_data = None
-        try:
-            gdal.ReprojectImage(l_src_ds, dst_ds, SINU_WKT, self.dst_wkt,
-                                self.resampling, 0, self.error_threshold, cbk,
-                                cbk_user_data)
-            print("Layer {name} reprojected".format(name=l))
-        except:
-            raise Exception('Not possibile to reproject dataset '
-                            '{name}'.format(name=l))
-            return 0
-        dst_ds.SetMetadata(meta)
-        dst_ds = None
-        l_src_ds = None
-        return 0
-
-    def run_vrt_separated(self):
-        """Reproject VRT created by createMosaicGDAL, function write_vrt with
-        sepatated=True
-        """
-        self._createWarped(self.in_name)
-        self._reprojectOne(self.in_name)
-        print("Dataset '{name}' reprojected".format(name=self.in_name))
-
-    def run(self):
-        """Reproject all the subset of choosen layer"""
-        if self.vrt:
-            self.run_vrt_separated()
-            return
-        else:
-            self._createWarped(self.layers[0][0])
-            n = 0
-            for i in self.subset:
-                if str(i) == '1':
-                    self._reprojectOne(self.layers[n][0])
-                n = n + 1
-            print("All layer for dataset '{name}' "
-                  "reprojected".format(name=self.in_name))
-
-
-# =============================================================================
-def raster_copy(s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
-                t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
-                nodata=None):
-    """Copy a band of raster into the output file.
-
-       Function copied from gdal_merge.py
-    """
-    if nodata is not None:
-        return raster_copy_with_nodata(s_fh, s_xoff, s_yoff, s_xsize, s_ysize,
-                                       s_band_n, t_fh, t_xoff, t_yoff, t_xsize,
-                                       t_ysize, t_band_n, nodata)
-
-    s_band = s_fh.GetRasterBand(s_band_n)
-    t_band = t_fh.GetRasterBand(t_band_n)
-
-    data = s_band.ReadRaster(s_xoff, s_yoff, s_xsize, s_ysize,
-                             t_xsize, t_ysize, t_band.DataType)
-    t_band.WriteRaster(t_xoff, t_yoff, t_xsize, t_ysize, data, t_xsize,
-                       t_ysize, t_band.DataType)
-
-    return 0
-
-
-def raster_copy_with_nodata(s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
-                            t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
-                            nodata):
-    """Copy a band of raster into the output file with nodata values.
-
-       Function copied from gdal_merge.py
-    """
-    try:
-        import numpy as Numeric
-    except ImportError:
-        import Numeric
-
-    s_band = s_fh.GetRasterBand(s_band_n)
-    t_band = t_fh.GetRasterBand(t_band_n)
-
-    data_src = s_band.ReadAsArray(s_xoff, s_yoff, s_xsize, s_ysize,
-                                  t_xsize, t_ysize)
-    data_dst = t_band.ReadAsArray(t_xoff, t_yoff, t_xsize, t_ysize)
-
-    nodata_test = Numeric.equal(data_src, nodata)
-    to_write = Numeric.choose(nodata_test, (data_src, data_dst))
-
-    t_band.WriteArray(to_write, t_xoff, t_yoff)
-
-    return 0
-
-
-class file_info:
-    """A class holding information about a GDAL file.
-
-       Class copied from gdal_merge.py
-
-       :param str filename: Name of file to read.
-
-       :return: 1 on success or 0 if the file can't be opened.
-    """
-
-    def init_from_name(self, filename):
-        """Initialize file_info from filename"""
-        fh = gdal.Open(filename)
-        if fh is None:
-            return 0
-
-        self.filename = filename
-        self.bands = fh.RasterCount
-        self.xsize = fh.RasterXSize
-        self.ysize = fh.RasterYSize
-        self.band_type = fh.GetRasterBand(1).DataType
-        self.block_size = fh.GetRasterBand(1).GetBlockSize()
-        self.projection = fh.GetProjection()
-        self.geotransform = fh.GetGeoTransform()
-        self.ulx = self.geotransform[0]
-        self.uly = self.geotransform[3]
-        self.lrx = self.ulx + self.geotransform[1] * self.xsize
-        self.lry = self.uly + self.geotransform[5] * self.ysize
-
-        meta = fh.GetMetadata()
-        if '_FillValue' in meta.keys():
-            self.fill_value = meta['_FillValue']
-        else:
-            self.fill_value = None
-
-        ct = fh.GetRasterBand(1).GetRasterColorTable()
-        if ct is not None:
-            self.ct = ct.Clone()
-        else:
-            self.ct = None
-
-        return 1
-
-    def copy_into(self, t_fh, s_band=1, t_band=1, nodata_arg=None):
-        """Copy this files image into target file.
-
-        This method will compute the overlap area of the file_info objects
-        file, and the target gdal.Dataset object, and copy the image data
-        for the common window area.  It is assumed that the files are in
-        a compatible projection. no checking or warping is done.  However,
-        if the destination file is a different resolution, or different
-        image pixel type, the appropriate resampling and conversions will
-        be done (using normal GDAL promotion/demotion rules).
-
-        :param t_fh: gdal.Dataset object for the file into which some or all
-                     of this file may be copied.
-        :param s_band:
-        :param t_band:
-        :param nodata_arg:
-
-        :return: 1 on success (or if nothing needs to be copied), and zero one
-                 failure.
-
-        """
-        t_geotransform = t_fh.GetGeoTransform()
-        t_ulx = t_geotransform[0]
-        t_uly = t_geotransform[3]
-        t_lrx = t_geotransform[0] + t_fh.RasterXSize * t_geotransform[1]
-        t_lry = t_geotransform[3] + t_fh.RasterYSize * t_geotransform[5]
-
-        # figure out intersection region
-        tgw_ulx = max(t_ulx, self.ulx)
-        tgw_lrx = min(t_lrx, self.lrx)
-        if t_geotransform[5] < 0:
-            tgw_uly = min(t_uly, self.uly)
-            tgw_lry = max(t_lry, self.lry)
-        else:
-            tgw_uly = max(t_uly, self.uly)
-            tgw_lry = min(t_lry, self.lry)
-
-        # do they even intersect?
-        if tgw_ulx >= tgw_lrx:
-            return 1
-        if t_geotransform[5] < 0 and tgw_uly <= tgw_lry:
-            return 1
-        if t_geotransform[5] > 0 and tgw_uly >= tgw_lry:
-            return 1
-
-        # compute target window in pixel coordinates.
-        tw_xoff = int((tgw_ulx - t_geotransform[0]) / t_geotransform[1] + 0.1)
-        tw_yoff = int((tgw_uly - t_geotransform[3]) / t_geotransform[5] + 0.1)
-        tw_xsize = int((tgw_lrx - t_geotransform[0]) / t_geotransform[1] + 0.5) - tw_xoff
-        tw_ysize = int((tgw_lry - t_geotransform[3]) / t_geotransform[5] + 0.5) - tw_yoff
-
-        if tw_xsize < 1 or tw_ysize < 1:
-            return 1
-
-        # Compute source window in pixel coordinates.
-        sw_xoff = int((tgw_ulx - self.geotransform[0]) / self.geotransform[1])
-        sw_yoff = int((tgw_uly - self.geotransform[3]) / self.geotransform[5])
-        sw_xsize = int((tgw_lrx - self.geotransform[0])
-                       / self.geotransform[1] + 0.5) - sw_xoff
-        sw_ysize = int((tgw_lry - self.geotransform[3])
-                       / self.geotransform[5] + 0.5) - sw_yoff
-
-        if sw_xsize < 1 or sw_ysize < 1:
-            return 1
-
-        # Open the source file, and copy the selected region.
-        s_fh = gdal.Open(self.filename)
-
-        return \
-            raster_copy(s_fh, sw_xoff, sw_yoff, sw_xsize, sw_ysize, s_band,
-                        t_fh, tw_xoff, tw_yoff, tw_xsize, tw_ysize, t_band,
-                        nodata_arg)
-
-
-class createMosaicGDAL:
-    """A class to mosaic modis data from hdf to GDAL formats using GDAL
-
-       :param list hdfnames: a list containing the name of tile to mosaic
-       :param str subset: the subset of layer to consider
-       :param str outformat: the output format to use, this parameter is
-                             not used for the VRT output, supported values
-                             are HDF4Image, GTiff, HFA, and maybe something
-                             else not tested.
-    """
-    def __init__(self, hdfnames, subset, outformat="HDF4Image"):
-        """Function for the initialize the object"""
-        # Open source dataset
-        self.in_names = hdfnames
-        # #TODO use resolution into mosaic.
-        # self.resolution = res
-        if not subset:
-            self.subset = None
-        elif type(subset) == ListType:
-            self.subset = subset
-        elif type(subset) == StringType:
-            self.subset = subset.replace('(', '').replace(')',
-                                                          '').strip().split()
-        else:
-            raise Exception('Type for subset parameter not supported')
-        self.driver = gdal.GetDriverByName(outformat)
-        if self.driver is None:
-            raise Exception('Format driver %s not found, pick a supported '
-                            'driver.' % outformat)
-        driverMD = self.driver.GetMetadata()
-        if 'DCAP_CREATE' not in driverMD:
-            raise Exception('Format driver %s does not support creation and'
-                            ' piecewise writing.\nPlease select a format that'
-                            ' does, such as GTiff (the default) or HFA (Erdas'
-                            ' Imagine).' % format)
-        self._initLayers()
-        self._getUsedLayers()
-        self._names_to_fileinfos()
-
-    def _initLayers(self):
-        """Set up the variable self.layers as dictionary for each choosen
-        subset"""
-        if type(self.in_names) == ListType:
-            src_ds = gdal.Open(self.in_names[0])
-        else:
-            raise Exception("The input value should be a list of HDF files")
-        layers = src_ds.GetSubDatasets()
-        self.layers = {}
-        n = 0
-        if not self.subset:
-            self.subset = [1 for i in range(len(layers))]
-        for i in self.subset:
-            if str(i) == '1':
-                name = layers[n][0].split(':')[-1]
-                self.layers[name] = []
-            n = n + 1
-
-    def _getUsedLayers(self):
-        """Add each subset to the correct list for each input layers"""
-        for name in self.in_names:
-            src_ds = gdal.Open(name)
-            layers = src_ds.GetSubDatasets()
-            n = 0
-            for i in self.subset:
-                if str(i) == '1':
-                    name = layers[n][0].split(':')[-1]
-                    self.layers[name].append(layers[n][0])
-                n = n + 1
-
-    def _names_to_fileinfos(self):
-        """Translate a list of GDAL filenames, into file_info objects.
-        Returns a list of file_info objects. There may be less file_info
-        objects than names if some of the names could not be opened as GDAL
-        files.
-        """
-        self.file_infos = {}
-        for k, v in self.layers.iteritems():
-            self.file_infos[k] = []
-            for name in v:
-                fi = file_info()
-                if fi.init_from_name(name) == 1:
-                    self.file_infos[k].append(fi)
-        self.file_infos
-
-    def _calculateNewSize(self):
-        """Return the new size of output raster
-
-           :return: X size, Y size and geotransform parameters
-        """
-        values = self.file_infos.values()
-        l1 = values[0][0]
-        ulx = l1.ulx
-        uly = l1.uly
-        lrx = l1.lrx
-        lry = l1.lry
-        for fi in self.file_infos[self.file_infos.keys()[0]]:
-            ulx = min(ulx, fi.ulx)
-            uly = max(uly, fi.uly)
-            lrx = max(lrx, fi.lrx)
-            lry = min(lry, fi.lry)
-        psize_x = l1.geotransform[1]
-        psize_y = l1.geotransform[5]
-
-        geotransform = [ulx, psize_x, 0, uly, 0, psize_y]
-        xsize = int((lrx - ulx) / geotransform[1] + 0.5)
-        ysize = int((lry - uly) / geotransform[5] + 0.5)
-        return xsize, ysize, geotransform
-
-    def write_mosaic_xml(self, prefix):
-        """Write the XML metadata file for MODIS mosaic
-
-           :param str prefix: the prefix for the XML file containing metadata
-        """
-        from parsemodis import parseModisMulti
-        import os
-        listHDF = []
-        for i in self.in_names:
-            listHDF.append(os.path.realpath(i.strip()))
-        pmm = parseModisMulti(listHDF)
-        pmm.writexml("%s.xml" % prefix)
-
-    def run(self, output):
-        """Create the mosaik
-
-           :param str output: the name of output file
-        """
-        values = self.file_infos.values()
-        l1 = values[0][0]
-        xsize, ysize, geotransform = self._calculateNewSize()
-        t_fh = self.driver.Create(output, xsize, ysize,
-                                  len(self.file_infos.keys()), l1.band_type)
-        if t_fh is None:
-            raise Exception('Not possibile to create dataset %s' % output)
-            return
-
-        t_fh.SetGeoTransform(geotransform)
-        t_fh.SetProjection(l1.projection)
-        i = 1
-        for names in self.file_infos.values():
-            fill = None
-            if names[0].fill_value:
-                fill = float(names[0].fill_value)
-                t_fh.GetRasterBand(i).SetNoDataValue(fill)
-                t_fh.GetRasterBand(i).Fill(fill)
-            for n in names:
-                n.copy_into(t_fh, 1, i, fill)
-            i = i + 1
-        self.write_mosaic_xml(output)
-        t_fh = None
-
-    def _calculateOffset(self, fileinfo, geotransform):
-        """Return the offset between main origin and the origin of current
-        file
-
-        :param fileinfo: a file_info object
-        :param geotransform: the geotransform parameters to keep x and y origin
-        """
-        x = abs(int((geotransform[0] - fileinfo.ulx) / geotransform[1]))
-        y = abs(int((geotransform[3] - fileinfo.uly) / geotransform[5]))
-        return x, y
-
-    def write_vrt(self, output, separate=True):
-        """Write VRT file
-
-        :param str output: the prefix of output file
-        :param bool separate: True to write a VRT file for each band, False to
-                              write an unique file
-        """
-
-        def write_complex(outfile, f, geot):
-            """Write a complex source to VRT file"""
-            out.write('\t\t<ComplexSource>\n')
-            out.write('\t\t\t<SourceFilename relativeToVRT="0">{name}'
-                      '</SourceFilename>\n'.format(name=f.filename.replace('"', '')))
-            out.write('\t\t\t<SourceBand>1</SourceBand>\n')
-            out.write('\t\t\t<SourceProperties RasterXSize="{x}" '
-                      'RasterYSize="{y}" DataType="{typ}" '
-                      'BlockXSize="{bx}" BlockYSize="{by}" />'
-                      '\n'.format(x=f.xsize, y=f.ysize,
-                                  typ=f.band_type, bx=f.block_size[0],
-                                  by=f.block_size[1]))
-            out.write('\t\t\t<SrcRect xOff="0" yOff="0" xSize="{x}" '
-                      'ySize="{y}" />\n'.format(x=f.xsize, y=f.ysize))
-            xoff, yoff = self._calculateOffset(f, geot)
-            out.write('\t\t\t<DstRect xOff="{xoff}" yOff="{yoff}" '
-                      'xSize="{x}" ySize="{y}" />'
-                      '\n'.format(xoff=xoff, yoff=yoff, x=f.xsize,
-                                  y=f.ysize))
-            if l1.fill_value:
-                out.write('\t\t\t<NODATA>{va}</NODATA>'
-                          '\n'.format(va=f.fill_value))
-            out.write('\t\t</ComplexSource>\n')
-
-        xsize, ysize, geot = self._calculateNewSize()
-        if separate:
-            for k in self.file_infos.keys():
-                l1 = self.file_infos[k][0]
-                out = open("{pref}_{band}.vrt".format(pref=output, band=k),
-                           'w')
-                out.write('<VRTDataset rasterXSize="{x}" rasterYSize="{y}">'
-                          '\n'.format(x=xsize, y=ysize))
-                out.write('\t<SRS>{proj}</SRS>\n'.format(proj=l1.projection))
-                out.write('\t<GeoTransform>{geo0}, {geo1}, {geo2}, {geo3},'
-                          ' {geo4}, {geo5}</GeoTransform>'
-                          '\n'.format(geo0=geot[0], geo1=geot[1], geo2=geot[2],
-                                      geo3=geot[3], geo4=geot[4],
-                                      geo5=geot[5]))
-                gtype = gdal.GetDataTypeName(l1.band_type)
-                out.write('\t<VRTRasterBand dataType="{typ}" band="1"'
-                          '>\n'.format(typ=gtype))
-                if l1.fill_value:
-                    out.write('\t\t<NoDataValue>{val}</NoDataValue'
-                              '>\n'.format(val=l1.fill_value))
-                out.write('<ColorInterp>Gray</ColorInterp>\n')
-                for f in self.file_infos[k]:
-                    write_complex(out, f, geot)
-                out.write('\t</VRTRasterBand>\n')
-                out.write('</VRTDataset>\n')
-                out.close()
-        else:
-            values = self.file_infos.values()
-            l1 = values[0][0]
-            band = 1  # the number of band
-            out = open("{pref}.vrt".format(pref=output), 'w')
-            out.write('<VRTDataset rasterXSize="{x}" rasterYSize="{y}">'
-                      '\n'.format(x=xsize, y=ysize))
-            out.write('\t<SRS>{proj}</SRS>\n'.format(proj=l1.projection))
-            out.write('\t<GeoTransform>{geo0}, {geo1}, {geo2}, {geo3},'
-                      ' {geo4}, {geo5}</GeoTransform>\n'.format(geo0=geot[0],
-                      geo1=geot[1], geo2=geot[2], geo3=geot[3], geo4=geot[4],
-                      geo5=geot[5]))
-            for k in self.file_infos.keys():
-                l1 = self.file_infos[k][0]
-                out.write('\t<VRTRasterBand dataType="{typ}" band="{n}"'
-                          '>\n'.format(typ=gdal.GetDataTypeName(l1.band_type),
-                                       n=band))
-                if l1.fill_value:
-                    out.write('\t\t<NoDataValue>{val}</NoDataValue>\n'.format(
-                              val=l1.fill_value))
-                out.write('\t\t<ColorInterp>Gray</ColorInterp>\n')
-                for f in self.file_infos[k]:
-                    write_complex(out, f, geot)
-                out.write('\t</VRTRasterBand>\n')
-                band += 1
-            out.write('</VRTDataset>\n')
-            out.close()

Deleted: grass-addons/grass7/raster/r.modis/libmodis/downmodis.py
===================================================================
--- grass-addons/grass7/raster/r.modis/libmodis/downmodis.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/libmodis/downmodis.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -1,835 +0,0 @@
-#!/usr/bin/env python
-#  class to download modis data
-#
-#  (c) Copyright Luca Delucchi 2010
-#  (c) Copyright Logan C Byers 2014
-#  Authors: Luca Delucchi
-#           Logan C Byers
-#  Email: luca dot delucchi at iasma dot it
-#         loganbyers at ku.edu
-#
-##################################################################
-#
-#  This MODIS Python class is licensed under the terms of GNU GPL 2.
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License as
-#  published by the Free Software Foundation; either version 2 of
-#  the License, or (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#  See the GNU General Public License for more details.
-#
-##################################################################
-"""Module to download MODIS HDF files from NASA repository.
-It supports both FTP and HTTP repositories
-
-Classes:
-
-* :class:`modisHtmlParser`
-* :class:`downModis`
-
-Functions:
-
-* :func:`urljoin`
-* :func:`getNewerVersion`
-* :func:`str2date`
-
-"""
-from __future__ import print_function
-
-from datetime import date
-from datetime import timedelta
-import os
-import glob
-import logging
-import socket
-from ftplib import FTP
-import ftplib
-try:
-    import requests
-except ImportError:
-    import urllib2
-from HTMLParser import HTMLParser
-import re
-
-global GDAL
-
-try:
-    import osgeo.gdal as gdal
-    GDAL = True
-except ImportError:
-    try:
-        import gdal
-        GDAL = True
-    except ImportError:
-        GDAL = False
-        print('WARNING: Python GDAL library not found, please install it to'
-              ' check data downloaded with pyModis')
-# setup gdal
-if GDAL:
-    gdal.UseExceptions()
-    gdalDriver = gdal.GetDriverByName('HDF4')
-    if not gdalDriver:
-        GDAL = False
-        print("GDAL installation has no support for HDF4, please update GDAL")
-
-
-def urljoin(*args):
-    """Joins given arguments into a url. Trailing but not leading slashes are
-    stripped for each argument.
-    http://stackoverflow.com/a/11326230
-
-    :return: a string
-    """
-
-    return "/".join(map(lambda x: str(x).rstrip('/'), args))
-
-
-def getNewerVersion(oldFile, newFile):
-    """Check two files to determine which is newer
-
-       :param str oldFile: one of the two similar files
-       :param str newFile: one of the two similar files
-
-       :return: the name of newer file
-    """
-    # get the processing date (YYYYDDDHHMMSS) from the file strings
-    if oldFile.split('.')[4] > newFile.split('.')[4]:
-        return oldFile
-    else:
-        return newFile
-
-
-def str2date(datestring):
-    """Convert to datetime.date object from a string
-
-       :param str datestring string with format (YYYY-MM-DD)
-
-       :return: a datetime.date object representing datestring
-    """
-    if '-' in datestring:
-        stringSplit = datestring.split('-')
-    elif '.' in datestring:
-        stringSplit = datestring.split('.')
-    elif ' ' in datestring:
-        stringSplit = datestring.split(' ')
-    return date(int(stringSplit[0]), int(stringSplit[1]), int(stringSplit[2]))
-
-
-class modisHtmlParser(HTMLParser):
-    """A class to parse HTML
-
-       :param fh: content of http request
-    """
-    def __init__(self, fh):
-        """Function to initialize the object"""
-        HTMLParser.__init__(self)
-        self.fileids = []
-        self.feed(fh)
-
-    def handle_starttag(self, tag, attrs):
-        if tag == 'a':
-            attrD = dict(attrs)
-            self.fileids.append(attrD['href'].replace('/', ''))
-
-    def get_all(self):
-        """Return everything"""
-        return self.fileids
-
-    def get_dates(self):
-        """Return a list of directories with date"""
-        regex = re.compile('(\d{4})[/.-](\d{2})[/.-](\d{2})$')
-        return [elem for elem in self.fileids if regex.match(elem)]
-
-    def get_tiles(self, prod, tiles, jpeg=False):
-        """Return a list of files to download
-
-           :param str prod: the code of MODIS product that we are going to
-                            analyze
-           :param list tiles: the list of tiles to consider
-           :param bool jpeg: True to also check for jpeg data
-        """
-        finalList = []
-        for i in self.fileids:
-            # distinguish jpg from hdf by where the tileID is within the string
-            # jpgs have the tileID at index 3, hdf have tileID at index 2
-            name = i.split('.')
-            # if product is not in the filename, move to next filename in list
-            if not name.count(prod):
-                continue
-            # if tiles are not specified and the file is not a jpg, add to list
-            if not tiles and not (name.count('jpg') or name.count('BROWSE')):
-                finalList.append(i)
-            # if tiles are specified
-            if tiles:
-                # if a tileID is at index 3 and jpgs are to be downloaded
-                if tiles.count(name[3]) == 1 and jpeg:
-                    finalList.append(i)
-                # if a tileID is at in index 2, it is known to be HDF
-                elif tiles.count(name[2]) == 1:
-                    finalList.append(i)
-        return finalList
-
-
-class downModis:
-    """A class to download MODIS data from NASA FTP or HTTP repositories
-
-       :param str destinationFolder: where the files will be stored
-       :param str password: the password, it should be your email address
-                            to connect to a FTP server. Do not use this
-                            variable if the server is an HTTP server
-       :param str user: the user name, by default 'anonymous', used to
-                        connect to an FTP server. Do not use this variable
-                        if the server is an HTTP server
-       :param str url: the base url from where to download the MODIS data,
-                       it can be FTP or HTTP but it has to start with
-                       'ftp://' or 'http://'
-       :param str path: the directory where the data that you want to
-                        download are stored on the FTP server. For HTTP
-                        requests, this is the part of the url between the 'url'
-                        parameter and the 'product' parameter.
-       :param str product: the code of the product to download, the code
-                           should be idential to the one of the url
-       :param str tiles: a set of tiles to be downloaded, None == all tiles.
-                         This can be passed as a string of tileIDs separated
-                         by commas, or as a list of individual tileIDs
-       :param str today: the day to start downloading; in order to pass a
-                         date different from today use the format YYYY-MM-DD
-       :param str enddate: the day to end downloading; in order to pass a
-                           date use the format YYYY-MM-DD. This day must be
-                           before the 'today' parameter. Downloading happens
-                           in reverse order (currently)
-       :param int delta: timelag i.e. the number of days starting from
-                         today backwards. Will be overwritten if
-                         'enddate' is specifed during instantiation
-       :param bool jpeg: set to True if you want to download the JPG overview
-                         file in addition to the HDF
-       :param bool debug: set to True if you want to obtain debug information
-       :param int timeout: Timeout value for HTTP server (seconds)
-       :param bool checkgdal: variable to set the GDAL check
-    """
-    def __init__(self, destinationFolder, password=None, user="anonymous",
-                 url="http://e4ftl01.cr.usgs.gov", tiles=None, path="MOLT",
-                 product="MOD11A1.005", today=None, enddate=None, delta=10,
-                 jpg=False, debug=False, timeout=30, checkgdal=True):
-        """Function to initialize the object"""
-
-        # prepare the base url and set the url type (ftp/http)
-        if 'ftp://' in url:
-            self.url = url.replace('ftp://', '').rstrip('/')
-            self.urltype = 'ftp'
-        elif 'http://' in url:
-            self.url = url
-            self.urltype = 'http'
-        else:
-            raise IOError("The url should contain 'ftp://' or 'http://'")
-        # user for download using ftp
-        self.user = user
-        # password for download using ftp
-        self.password = password
-        # the product (product_code.004 or product_cod.005)
-        self.product = product
-        self.product_code = product.split('.')[0]
-        # url directory where data are located
-        self.path = urljoin(path, self.product)
-        # tiles to downloads
-        if type(tiles) == str:
-            self.tiles = tiles.split(',')
-        else:  # tiles are list, tuple, or None
-            self.tiles = tiles
-        # set destination folder
-        if os.access(destinationFolder, os.W_OK):
-            self.writeFilePath = destinationFolder
-        else:
-            raise Exception("Folder to store downloaded files does not exist"
-                            " or is not writeable")
-        # return the name of product
-        if len(self.path.split('/')) == 2:
-            self.product = self.path.split('/')[1]
-        elif len(self.path.split('/')) == 3:
-            self.product = self.path.split('/')[2]
-        # write a file with the name of file to be downloaded
-        self.filelist = open(os.path.join(self.writeFilePath,
-                                          'listfile{pro}.txt'.format(pro=self.product)),
-                                          'w')
-        # set if to download jpgs
-        self.jpeg = jpg
-        # today, or the last day in the download series chronologically
-        self.today = today
-        # chronologically the first day in the download series
-        self.enday = enddate
-        # default number of days to consider if enddate not specified
-        self.delta = delta
-        # status of tile download
-        self.status = True
-        # for debug, you can download only xml files
-        self.debug = debug
-        # for logging
-        log_filename = os.path.join(self.writeFilePath,
-                                    'modis{pro}.log'.format(pro=self.product))
-        log_format = '%(asctime)s - %(levelname)s - %(message)s'
-        logging.basicConfig(filename=log_filename, level=logging.DEBUG,
-                            format=log_format)
-        # global connection attempt counter
-        self.nconnection = 0
-        # timeout for HTTP connection before failing (seconds)
-        self.timeout = timeout
-        # files within the directory where data will be saved
-        self.fileInPath = []
-        for f in os.listdir(self.writeFilePath):
-            if os.path.isfile(os.path.join(self.writeFilePath, f)):
-                self.fileInPath.append(f)
-        global GDAL
-        if not GDAL and checkgdal:
-            logging.warning("WARNING: Python GDAL library is not found")
-        elif GDAL and not checkgdal:
-            GDAL = False
-
-    def removeEmptyFiles(self):
-        """Function to remove files in the download directory that have
-           filesize equal to 0
-        """
-        year = str(date.today().year)
-        prefix = self.product.split('.')[0]
-        files = glob.glob1(self.writeFilePath, '%s.A%s*' % (prefix, year))
-        for f in files:
-            fil = os.path.join(self.writeFilePath, f)
-            if os.path.getsize(fil) == 0:
-                os.remove(fil)
-
-    def connect(self, ncon=20):
-        """Connect to the server and fill the dirData variable
-
-           :param int ncon: maximum number of attempts to connect to the HTTP
-                            server before failing
-        """
-        if self.urltype == 'ftp':
-            self._connectFTP(ncon)
-        elif self.urltype == 'http':
-            self._connectHTTP(ncon)
-        if len(self.dirData) == 0:
-            raise Exception("There are some troubles with the server. "
-                            "The directory seems to be empty")
-
-    def _connectHTTP(self, ncon=20):
-        """Connect to HTTP server, create a list of directories for all days
-
-           :param int ncon: maximum number of attempts to connect to the HTTP
-                            server before failing. If ncon < 0, connection
-                            attempts are unlimited in number
-        """
-        self.nconnection += 1
-        try:
-            try:
-                http = requests.get(urljoin(self.url, self.path),
-                                    timeout=self.timeout)
-                self.dirData = modisHtmlParser(http.content).get_dates()
-            except:
-                http = urllib2.urlopen(urljoin(self.url, self.path),
-                                       timeout=self.timeout)
-                self.dirData = modisHtmlParser(http.read()).get_dates()
-            self.dirData.reverse()
-        except:
-            logging.error('Error in connection')
-            if self.nconnection <= ncon or ncon < 0:
-                self._connectHTTP()
-
-    def _connectFTP(self, ncon=20):
-        """Set connection to ftp server, move to path where data are stored,
-           and create a list of directories for all days
-
-           :param int ncon: maximum number of attempts to connect to the FTP
-                            server before failing.
-
-        """
-        self.nconnection += 1
-        try:
-            # connect to ftp server
-            self.ftp = FTP(self.url)
-            self.ftp.login(self.user, self.password)
-            # enter in directory
-            self.ftp.cwd(self.path)
-            self.dirData = []
-            # return data inside directory
-            self.ftp.dir(self.dirData.append)
-            # reverse order of data for have first the nearest to today
-            self.dirData.reverse()
-            # ensure dirData contains only directories, remove all references to files
-            self.dirData = [elem.split()[-1] for elem in self.dirData if elem.startswith("d")]
-            if self.debug:
-                logging.debug("Open connection {url}".format(url=self.url))
-        except (EOFError, ftplib.error_perm), e:
-            logging.error('Error in connection: {err}'.format(err=e))
-            if self.nconnection <= ncon:
-                self._connectFTP()
-
-    def closeFTP(self):
-        """Close ftp connection and close the file list document"""
-        self.ftp.quit()
-        self.closeFilelist()
-        if self.debug:
-            logging.debug("Close connection {url}".format(url=self.url))
-
-    def closeFilelist(self):
-        """Function to close the file list of where the files are downloaded"""
-        self.filelist.close()
-
-    def setDirectoryIn(self, day):
-        """Enter into the file directory of a specified day
-
-           :param str day: a string representing a day in format YYYY.MM.DD
-        """
-        try:
-            self.ftp.cwd(day)
-        except (ftplib.error_reply, socket.error), e:
-            logging.error("Error {err} entering in directory "
-                          "{name}".format(err=e, name=day))
-            self.setDirectoryIn(day)
-
-    def setDirectoryOver(self):
-        """Move up within the file directory"""
-        try:
-            self.ftp.cwd('..')
-        except (ftplib.error_reply, socket.error), e:
-            logging.error("Error {err} when trying to come back".format(err=e))
-            self.setDirectoryOver()
-
-    def _getToday(self):
-        """Set the dates for the start and end of downloading"""
-        if self.today is None:
-            # set today variable from datetime.date method
-            self.today = date.today()
-        elif type(self.today) == str:
-            # set today variable from string data passed by user
-            self.today = str2date(self.today)
-        # set enday variable to data passed by user
-        if type(self.enday) == str:
-            self.enday = str2date(self.enday)
-        # set delta
-        if self.today and self.enday:
-            if self.today < self.enday:
-                self.today, self.enday = self.enday, self.today
-            delta = self.today - self.enday
-            self.delta = abs(delta.days) + 1
-
-    def getListDays(self):
-        """Return a list of all selected days"""
-        self._getToday()
-
-        today_s = self.today.strftime("%Y.%m.%d")
-        # dirData is reverse sorted
-        for i, d in enumerate(self.dirData):
-            if d <= today_s:
-                today_index = i
-                break
-#            else:
-#                logging.error("No data available for requested days")
-#                import sys
-#                sys.exit()
-        days = self.dirData[today_index:][:self.delta]
-        # this is useful for 8/16 days data, delta could download more images
-        # that you want
-        if self.enday is not None:
-            enday_s = self.enday.strftime("%Y.%m.%d")
-            delta = 0
-            # make a full cycle from the last index and find
-            # it make a for cicle from the last value and find the internal
-            # delta to remove file outside temporaly range
-            for i in range(0, len(days)):
-                if days[i] < enday_s:
-                    break
-                else:
-                    delta = delta + 1
-            # remove days outside new delta
-            days = days[:delta]
-        return days
-
-    def getAllDays(self):
-        """Return a list of all days"""
-        return self.dirData
-
-    def getFilesList(self, day=None):
-        """Returns a list of files to download. HDF and XML files are
-           downloaded by default. JPG files will be downloaded if
-           self.jpeg == True.
-
-           :param str day: the date of data in format YYYY.MM.DD
-
-           :return: a list of files to download for the day
-        """
-        if self.urltype == 'http':
-            return self._getFilesListHTTP(day)
-        elif self.urltype == 'ftp':
-            return self._getFilesListFTP()
-
-    def _getFilesListHTTP(self, day):
-        """Returns a list of files to download from http server, which will
-           be HDF and XML files, and optionally JPG files if specified by
-           self.jpeg
-
-           :param str day: the date of data in format YYYY.MM.DD
-        """
-        # return the files list inside the directory of each day
-        try:
-            url = urljoin(self.url, self.path, day)
-            if self.debug:
-                logging.debug("The url is: {url}".format(url=url))
-            try:
-                http = modisHtmlParser(requests.get(url,
-                                       timeout=self.timeout).content)
-            except:
-                http = modisHtmlParser(urllib2.urlopen(url,
-                                       timeout=self.timeout).read())
-            # download JPG files also
-            if self.jpeg:
-                # if tiles not specified, download all files
-                if not self.tiles:
-                    finalList = http.get_all()
-                # if tiles specified, download all files with jpegs
-                else:
-                    finalList = http.get_tiles(self.product_code,
-                                               self.tiles, jpeg=True)
-            # if JPG files should not be downloaded, get only HDF and XML
-            else:
-                finalList = http.get_tiles(self.product_code, self.tiles)
-            if self.debug:
-                logging.debug("The number of file to download is: "
-                              "{num}".format(num=len(finalList)))
-            return finalList
-        except (socket.error), e:
-            logging.error("Error {err} when try to receive list of "
-                          "files".format(err=e))
-            self._getFilesListHTTP(day)
-
-    def _getFilesListFTP(self):
-        """Create a list of files to download from FTP server, it is possible
-           choose to download also the JPG overview files or only the HDF files
-        """
-        def cicle_file(jpeg=False):
-            """Check the type of file"""
-            finalList = []
-            for i in self.listfiles:
-                name = i.split('.')
-                # distinguish jpeg files from hdf files by the number of index
-                # where find the tile index
-                if not self.tiles and not (name.count('jpg') or
-                                           name.count('BROWSE')):
-                    finalList.append(i)
-                # is a jpeg of tiles number
-                if self.tiles:
-                    if self.tiles.count(name[3]) == 1 and jpeg:
-                        finalList.append(i)
-                # is a hdf of tiles number
-                    elif self.tiles.count(name[2]) == 1:
-                        finalList.append(i)
-            return finalList
-
-        # return the file's list inside the directory of each day
-        try:
-            self.listfiles = self.ftp.nlst()
-            # download also jpeg
-            if self.jpeg:
-                # finallist is ugual to all file with jpeg file
-                if not self.tiles:
-                    finalList = self.listfiles
-                # finallist is ugual to tiles file with jpeg file
-                else:
-                    finalList = cicle_file(jpeg=True)
-            # not download jpeg
-            else:
-                finalList = cicle_file()
-            if self.debug:
-                logging.debug("The number of file to download is: "
-                              "{num}".format(num=len(finalList)))
-            return finalList
-        except (ftplib.error_reply, socket.error), e:
-            logging.error("Error {err} when trying to receive list of "
-                          "files".format(err=e))
-            self._getFilesListFTP()
-
-    def checkDataExist(self, listNewFile, move=False):
-        """Check if a file already exists in the local download directory
-
-           :param list listNewFile: list of all files, returned by getFilesList
-                                    function
-           :param bool move: it is useful to know if a function is called from
-                             download or move function
-           :return: list of files to download
-        """
-        # different return if this method is used from downloadsAllDay() or
-        # moveFile()
-        if not move:
-            listOfDifferent = list(set(listNewFile) - set(self.fileInPath))
-        elif move:
-            listOfDifferent = list(set(self.fileInPath) - set(listNewFile))
-        return listOfDifferent
-
-    def checkFile(self, filHdf):
-        """Check by using GDAL to be sure that the download went ok
-
-           :param str filHdf: name of the HDF file to check
-
-           :return: 0 if file is correct, 1 for error
-        """
-        try:
-            gdal.Open(filHdf)
-            return 0
-        except (RuntimeError), e:
-            logging.error(e)
-            return 1
-
-    def downloadFile(self, filDown, filHdf, day):
-        """Download a single file
-
-           :param str filDown: name of the file to download
-           :param str filHdf: name of the file to write to
-           :param str day: the day in format YYYY.MM.DD
-        """
-        if self.urltype == 'http':
-            self._downloadFileHTTP(filDown, filHdf, day)
-        elif self.urltype == 'ftp':
-            self._downloadFileFTP(filDown, filHdf)
-
-    def _downloadFileHTTP(self, filDown, filHdf, day):
-        """Download a single file from the http server
-
-           :param str filDown: name of the file to download
-           :param str filHdf: name of the file to write to
-           :param str day: the day in format YYYY.MM.DD
-        """
-        filSave = open(filHdf, "wb")
-        try:  # download and write the file
-            try:  # use request module
-                http = requests.get(urljoin(self.url, self.path, day, filDown))
-                orig_size = http.headers['content-length']
-                filSave.write(http.content)
-            except:  # use urllib2 module
-                http = urllib2.urlopen(urljoin(self.url, self.path, day,
-                                               filDown))
-                orig_size = http.headers['content-length']
-                filSave.write(http.read())
-
-        # if local file has an error, try to download the file again
-        except:
-            logging.error("Cannot download {name}. "
-                          "Retrying..".format(name=filDown))
-            filSave.close()
-            os.remove(filSave.name)
-            self._downloadFileHTTP(filDown, filHdf, day)
-        filSave.close()
-        transf_size = os.path.getsize(filSave.name)
-        if int(orig_size) == int(transf_size):
-            # if no xml file, delete the HDF and redownload
-            if filHdf.find('.xml') == -1:
-                test = False
-                if GDAL:
-                    test = self.checkFile(filHdf)
-                if test:
-                    os.remove(filSave.name)
-                    self._downloadFileHTTP(filDown, filHdf, day)
-                else:
-                    self.filelist.write("{name}\n".format(name=filDown))
-                    if self.debug:
-                        logging.debug("File {name} downloaded "
-                                      "correctly".format(name=filDown))
-                    return 0
-            else:  # xml exists
-                self.filelist.write("{name}\n".format(name=filDown))
-                if self.debug:
-                    logging.debug("File {name} downloaded "
-                                  "correctly".format(name=filDown))
-                return 0
-        # if filesizes are different, delete and try again
-        else:
-            logging.warning("Different size for file {name} - original data: "
-                            "{orig}, downloaded: {down}".format(name=filDown,
-                                                                orig=orig_size,
-                                                                down=transf_size))
-            os.remove(filSave.name)
-            self._downloadFileHTTP(filDown, filHdf, day)
-
-    def _downloadFileFTP(self, filDown, filHdf):
-        """Download a single file from ftp server
-
-           :param str filDown: name of the file to download
-           :param str filHdf: name of the file to write to
-        """
-        filSave = open(filHdf, "wb")
-        try:  # transfer file from ftp
-            self.ftp.retrbinary("RETR " + filDown, filSave.write)
-            self.filelist.write("{name}\n".format(name=filDown))
-            if self.debug:
-                logging.debug("File {name} downloaded".format(name=filDown))
-        # if error during download process, try to redownload the file
-        except (ftplib.error_reply, socket.error, ftplib.error_temp,
-                EOFError), e:
-            logging.error("Cannot download {name}, the error was '{err}'. "
-                          "Retrying...".format(name=filDown, err=e))
-            filSave.close()
-            os.remove(filSave.name)
-            try:
-                self.ftp.pwd()
-            except (ftplib.error_temp, EOFError), e:
-                self._connectFTP()
-            self._downloadFileFTP(filDown, filHdf)
-        filSave.close()
-        orig_size = self.ftp.size(filDown)
-        transf_size = os.path.getsize(filSave.name)
-        if orig_size == transf_size:
-            return 0
-        else:
-            logging.warning("Different size for file {name} - original data: "
-                            "{orig}, downloaded: {down}".format(name=filDown,
-                                                                orig=orig_size,
-                                                                down=transf_size))
-            os.remove(filSave.name)
-            self._downloadFileFTP(filDown, filHdf)
-
-    def dayDownload(self, day, listFilesDown):
-        """Downloads tiles for the selected day
-
-           :param str day: the day in format YYYY.MM.DD
-           :param list listFilesDown: list of the files to download, returned
-                                      by checkDataExist function
-        """
-        # for each file in files' list
-        for i in listFilesDown:
-            fileSplit = i.split('.')
-            filePrefix = "{a}.{b}.{c}.{d}".format(a=fileSplit[0],
-                                                  b=fileSplit[1],
-                                                  c=fileSplit[2],
-                                                  d=fileSplit[3])
-
-            # check if this file already exists in the save directory
-            oldFile = glob.glob1(self.writeFilePath, filePrefix + "*"
-                                 + fileSplit[-1])
-            numFiles = len(oldFile)
-            # if it doesn't exist
-            if numFiles == 0:
-                file_hdf = os.path.join(self.writeFilePath, i)
-            # if one does exist
-            elif numFiles == 1:
-                # check the version of file, delete local file if it is older
-                fileDown = getNewerVersion(oldFile[0], i)
-                if fileDown != oldFile[0]:
-                    os.remove(os.path.join(self.writeFilePath, oldFile[0]))
-                    file_hdf = os.path.join(self.writeFilePath, fileDown)
-            elif numFiles > 1:
-                logging.error("There are to many files for "
-                              "{name}".format(name=i))
-            if numFiles == 0 or (numFiles == 1 and fileDown != oldFile[0]):
-                self.downloadFile(i, file_hdf, day)
-
-    def downloadsAllDay(self, clean=False, allDays=False):
-        """Download all requested days
-
-           :param bool clean: if True remove the empty files, they could have
-                              some problems in the previous download
-           :param bool allDays: download all passable days
-        """
-        if clean:
-            self.removeEmptyFiles()
-        # get the days to download
-        if allDays:
-            days = self.getAllDays()
-        else:
-            days = self.getListDays()
-        # log the days to download
-        if self.debug:
-            logging.debug("The number of days to download is: "
-                          "{num}".format(num=len(days)))
-        # download the data
-        if self.urltype == 'http':
-            self._downloadAllDaysHTTP(days)
-        elif self.urltype == 'ftp':
-            self._downloadAllDaysFTP(days)
-
-    def _downloadAllDaysHTTP(self, days):
-        """Downloads all the tiles considered from HTTP server
-
-           :param list days: the list of days to download
-        """
-        # for each day
-        for day in days:
-            # obtain list of all files
-            listAllFiles = self.getFilesList(day)
-            # filter files based on local files in save directory
-            listFilesDown = self.checkDataExist(listAllFiles)
-            # download files for a day
-            self.dayDownload(day, listFilesDown)
-        self.closeFilelist()
-        if self.debug:
-            logging.debug("Download terminated")
-        return 0
-
-    def _downloadAllDaysFTP(self, days):
-        """Downloads all the tiles considered from FTP server
-
-           :param list days: the list of days to download
-        """
-        # for each day
-        for day in days:
-            # enter in the directory of day
-            self.setDirectoryIn(day)
-            # obtain list of all files
-            listAllFiles = self.getFilesList()
-            # filter files based on local files in save directory
-            listFilesDown = self.checkDataExist(listAllFiles)
-            # download files for a day
-            self.dayDownload(day, listFilesDown)
-            self.setDirectoryOver()
-        self.closeFTP()
-        if self.debug:
-            logging.debug("Download terminated")
-        return 0
-
-    def debugLog(self):
-        """Function to create the debug file
-
-        :return: a Logger object to use to write debug info
-        """
-        # create logger
-        logger = logging.getLogger("PythonLibModis debug")
-        logger.setLevel(logging.DEBUG)
-        # create console handler and set level to debug
-        ch = logging.StreamHandler()
-        ch.setLevel(logging.DEBUG)
-        # create formatter
-        formatter = logging.Formatter("%(asctime)s - %(name)s - "
-                                      "%(levelname)s - %(message)s")
-        # add formatter to console handler
-        ch.setFormatter(formatter)
-        # add console handler to logger
-        logger.addHandler(ch)
-        return logger
-
-    def debugDays(self):
-        """This function is useful to debug the number of days"""
-        logger = self.debugLog()
-        days = self.getListDays()
-        # if length of list of days and the delta of days are different
-        if len(days) != self.delta:
-            # for each day
-            for i in range(1, self.delta + 1):
-                # calculate the current day using datetime.timedelta
-                delta = timedelta(days=i)
-                day = self.today - delta
-                day = day.strftime("%Y.%m.%d")
-                # check if day is in the days list
-                if day not in days:
-                    logger.critical("This day {day} is not present on "
-                                    "list".format(day=day))
-        # the length of list of days and delta are equal
-        else:
-            logger.info("debugDays() : getListDays() and self.delta are same "
-                        "length")
-
-    def debugMaps(self):
-        """ Prints the files to download to the debug stream"""
-        logger = self.debugLog()
-        days = self.getListDays()
-        for day in days:
-            listAllFiles = self.getFilesList(day)
-            string = day + ": " + str(len(listAllFiles)) + "\n"
-            logger.debug(string)

Deleted: grass-addons/grass7/raster/r.modis/libmodis/parsemodis.py
===================================================================
--- grass-addons/grass7/raster/r.modis/libmodis/parsemodis.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/libmodis/parsemodis.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -1,954 +0,0 @@
-#!/usr/bin/env python
-#  class to parse modis data
-#
-#  (c) Copyright Luca Delucchi 2010
-#  Authors: Luca Delucchi
-#  Email: luca dot delucchi at iasma dot it
-#
-##################################################################
-#
-#  This MODIS Python class is licensed under the terms of GNU GPL 2.
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License as
-#  published by the Free Software Foundation; either version 2 of
-#  the License, or (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#  See the GNU General Public License for more details.
-#
-##################################################################
-"""Simple class to parse MODIS metadata file, it can also write the XML
-metadata file for a mosaic.
-
-Classes:
-
-* :class:`parseModis`
-* :class:`parseModisMulti`
-
-"""
-
-from __future__ import print_function
-import string
-import os
-
-# lists of parameters accepted by resample MRT software
-# projections
-PROJ_LIST = ['AEA', 'GEO', 'HAM', 'IGH', 'ISIN', 'LA', 'LCC', 'MOL', 'PS',
-             'SIN', 'TM', 'UTM', 'MERCAT']
-# resampling
-RESAM_LIST = ['NEAREST_NEIGHBOR', 'BICUBIC', 'CUBIC_CONVOLUTION', 'NONE']
-RESAM_LIST_SWATH = ['NN', 'BI', 'CC']
-
-# datum
-DATUM_LIST = ['NODATUM', 'NAD27', 'NAD83', 'WGS66', 'WGS72', 'WGS84']
-SPHERE_LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
-               19, 20]
-
-
-class parseModis:
-    """Class to parse MODIS xml files, it can also create the parameter
-       configuration file for resampling MODIS DATA with the MRT software or
-       convertmodis Module
-
-       :param str filename: the name of MODIS hdf file
-    """
-
-    def __init__(self, filename):
-        """Function to initialize the object"""
-        from xml.etree import ElementTree
-        if os.path.exists(filename):
-            # hdf name
-            self.hdfname = filename
-        else:
-            raise Exception('{name} does not exist'.format(name=filename))
-
-        if os.path.exists(self.hdfname + '.xml'):
-            # xml hdf name
-            self.xmlname = self.hdfname + '.xml'
-        else:
-            raise Exception('{name}.xml does not exist'.format(name=self.hdfname))
-
-        # tif name for the output file for resample MRT software
-        self.tifname = self.hdfname.replace('.hdf', '.tif')
-        with open(self.xmlname) as f:
-            self.tree = ElementTree.parse(f)
-        # return the code of tile for conf file
-        self.code = os.path.split(self.hdfname)[1].split('.')[-2]
-        self.path = os.path.split(self.hdfname)[0]
-
-    def __str__(self):
-        """Print the file without xml tags"""
-        retString = ""
-        try:
-            for node in self.tree.iter():
-                if node.text.strip() != '':
-                    retString = "{tag} = {val}\n".format(tag=node.tag,
-                                                         val=node.text)
-        except:
-            for node in self.tree.getiterator():
-                if node.text.strip() != '':
-                    retString = "{tag} = {val}\n".format(tag=node.tag,
-                                                         val=node.text)
-        return retString
-
-    def getRoot(self):
-        """Set the root element"""
-        self.rootree = self.tree.getroot()
-
-    def retDTD(self):
-        """Return the DTDVersion element"""
-        self.getRoot()
-        return self.rootree.find('DTDVersion').text
-
-    def retDataCenter(self):
-        """Return the DataCenterId element"""
-        self.getRoot()
-        return self.rootree.find('DataCenterId').text
-
-    def getGranule(self):
-        """Set the GranuleURMetaData element"""
-        self.getRoot()
-        self.granule = self.rootree.find('GranuleURMetaData')
-
-    def retGranuleUR(self):
-        """Return the GranuleUR element"""
-        self.getGranule()
-        return self.granule.find('GranuleUR').text
-
-    def retDbID(self):
-        """Return the DbID element"""
-        self.getGranule()
-        return self.granule.find('DbID').text
-
-    def retInsertTime(self):
-        """Return the InsertTime element"""
-        self.getGranule()
-        return self.granule.find('InsertTime').text
-
-    def retLastUpdate(self):
-        """Return the LastUpdate element"""
-        self.getGranule()
-        return self.granule.find('LastUpdate').text
-
-    def retCollectionMetaData(self):
-        """Return the CollectionMetaData element as dictionary"""
-        self.getGranule()
-        collect = {}
-        for i in self.granule.find('CollectionMetaData').getiterator():
-            if i.text.strip() != '':
-                collect[i.tag] = i.text
-        return collect
-
-    def retDataFiles(self):
-        """Return the DataFiles element as dictionary"""
-        self.getGranule()
-        collect = {}
-        datafiles = self.granule.find('DataFiles')
-        for i in datafiles.find('DataFileContainer').getiterator():
-            if i.text.strip() != '':
-                collect[i.tag] = i.text
-        return collect
-
-    def retDataGranule(self):
-        """Return the ECSDataGranule elements as dictionary"""
-        self.getGranule()
-        datagran = {}
-        for i in self.granule.find('ECSDataGranule').getiterator():
-            if i.text.strip() != '':
-                datagran[i.tag] = i.text
-        return datagran
-
-    def retPGEVersion(self):
-        """Return the PGEVersion element"""
-        self.getGranule()
-        return self.granule.find('PGEVersionClass').find('PGEVersion').text
-
-    def retRangeTime(self):
-        """Return the RangeDateTime elements as dictionary"""
-        self.getGranule()
-        rangeTime = {}
-        for i in self.granule.find('RangeDateTime').getiterator():
-            if i.text.strip() != '':
-                rangeTime[i.tag] = i.text
-        return rangeTime
-
-    def retBoundary(self):
-        """Return the maximum extend (Bounding Box) of the MODIS file as
-           dictionary"""
-        self.getGranule()
-        self.boundary = []
-        lat = []
-        lon = []
-        spatialContainer = self.granule.find('SpatialDomainContainer')
-        horizontal = spatialContainer.find('HorizontalSpatialDomainContainer')
-        boundary = horizontal.find('GPolygon').find('Boundary')
-        for i in boundary.findall('Point'):
-            la = float(i.find('PointLongitude').text)
-            lo = float(i.find('PointLatitude').text)
-            lon.append(la)
-            lat.append(lo)
-            self.boundary.append({'lat': la, 'lon': lo})
-        extent = {'min_lat': min(lat), 'max_lat': max(lat),
-                  'min_lon': min(lon), 'max_lon': max(lon)}
-        return extent
-
-    def retMeasure(self):
-        """Return statistics of QA as dictionary"""
-        value = {}
-        self.getGranule()
-        mes = self.granule.find('MeasuredParameter')
-        mespc = mes.find('MeasuredParameterContainer')
-        value['ParameterName'] = mespc.find('ParameterName').text
-        meStat = mespc.find('QAStats')
-        qastat = {}
-        for i in meStat.getiterator():
-            if i.tag != 'QAStats':
-                qastat[i.tag] = i.text
-        value['QAStats'] = qastat
-        meFlag = mespc.find('QAFlags')
-        flagstat = {}
-        for i in meFlag.getiterator():
-            if i.tag != 'QAFlags':
-                flagstat[i.tag] = i.text
-        value['QAFlags'] = flagstat
-        return value
-
-    def retPlatform(self):
-        """Return the platform values as dictionary."""
-        value = {}
-        self.getGranule()
-        plat = self.granule.find('Platform')
-        value['PlatformShortName'] = plat.find('PlatformShortName').text
-        instr = plat.find('Instrument')
-        value['InstrumentShortName'] = instr.find('InstrumentShortName').text
-        sensor = instr.find('Sensor')
-        value['SensorShortName'] = sensor.find('SensorShortName').text
-        return value
-
-    def retPSA(self):
-        """Return the PSA values as dictionary, the PSAName is the key and
-        and PSAValue is the value
-        """
-        value = {}
-        self.getGranule()
-        psas = self.granule.find('PSAs')
-        for i in psas.findall('PSA'):
-            value[i.find('PSAName').text] = i.find('PSAValue').text
-        return value
-
-    def retInputGranule(self):
-        """Return the input files (InputGranule) used to process the considered
-        file"""
-        value = []
-        self.getGranule()
-        for i in self.granule.find('InputGranule').getiterator():
-            if i.tag != 'InputGranule':
-                value.append(i.text)
-        return value
-
-    def retBrowseProduct(self):
-        """Return the BrowseProduct element"""
-        self.getGranule()
-        try:
-            value = self.granule.find('BrowseProduct').find('BrowseGranuleId').text
-        except:
-            value = None
-        return value
-
-    def confResample(self, spectral, res=None, output=None, datum='WGS84',
-                     resample='NEAREST_NEIGHBOR', projtype='GEO', utm=None,
-                     projpar='( 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 '
-                     '0.0 0.0 0.0 0.0 )', bound=None):
-        """Create the parameter file to use with resample MRT software to
-        create tif (geotiff) file
-
-        :param str spectral: the spectral subset to be used, see the product
-                             table to understand the layer that you want use.
-                             For example:
-
-                             * NDVI ( 1 1 1 0 0 0 0 0 0 0 0 0) copy only layer
-                               NDVI, EVI and QA VI the other layers are not used
-                             * LST ( 1 1 0 0 1 1 0 0 0 0 0 0 ) copy only layer
-                               daily and nightly temperature and QA
-
-        :param int res: the resolution for the output file, it must be set in
-                        the map unit of output projection system. The software
-                        will use the original resolution of input file if res
-                        not set
-
-        :param str output: the output name, if not set if not set the prefix
-                           name of input hdf file will be used
-
-        :param utm: the UTM zone if projection system is UTM
-
-        :param str resample: the type of resampling, the valid values are:
-
-                             * NN (nearest neighbor)
-                             * BI (bilinear)
-                             * CC (cubic convolution)
-
-        :param str projtype: the output projection system, valid values are:
-
-                             * AEA (Albers Equal Area)
-                             * ER (Equirectangular)
-                             * GEO (Geographic Latitude/Longitude)
-                             * HAM (Hammer)
-                             * ISIN (Integerized Sinusoidal)
-                             * IGH (Interrupted Goode Homolosine)
-                             * LA (Lambert Azimuthal)
-                             * LCC (LambertConformal Conic)
-                             * MERCAT (Mercator)
-                             * MOL (Mollweide)
-                             * PS (Polar Stereographic)
-                             * SIN (Sinusoidal)
-                             * UTM (Universal TransverseMercator)
-
-        :param str datum: the datum to use, the valid values are:
-
-                          * NAD27
-                          * NAD83
-                          * WGS66
-                          * WGS76
-                          * WGS84
-                          * NODATUM
-
-        :param str projpar: a list of projection parameters, for more info
-                            check the Appendix C of MODIS reprojection tool
-                            user manual https://lpdaac.usgs.gov/content/download/4831/22895/file/mrt41_usermanual_032811.pdf
-
-        :param dict bound: dictionary with the following keys:
-
-                           * max_lat
-                           * max_lon
-                           * min_lat
-                           * min_lon
-        """
-        # check if spectral it's write with correct construct ( value )
-        if string.find(spectral, '(') == -1 or  string.find(spectral, ')') == -1:
-            raise Exception('ERROR: The spectral string should be similar to:'
-                            ' ( 1 0 )')
-        # output name
-        if not output:
-            fileout = self.tifname
-        else:
-            fileout = output
-        # the name of the output parameters files for resample MRT software
-        filename = os.path.join(self.path, '{cod}_mrt_resample.conf'.format(cod=self.code))
-        # if the file already exists it remove it
-        if os.path.exists(filename):
-            os.remove(filename)
-        # open the file
-        conFile = open(filename, 'w')
-        conFile.write("INPUT_FILENAME = {name}\n".format(name=self.hdfname))
-        conFile.write("SPECTRAL_SUBSET = {spec}\n".format(spec=spectral))
-        conFile.write("SPATIAL_SUBSET_TYPE = INPUT_LAT_LONG\n")
-        if not bound:
-            # return the boundary from the input xml file
-            bound = self.retBoundary()
-        else:
-            if 'max_lat' not in bound or 'min_lat' not in bound or \
-               'min_lon' not in bound or 'max_lon' not in bound:
-                raise Exception('bound variable is a dictionary with the '
-                                'following keys: max_lat, min_lat, min_lon,'
-                                ' max_lon')
-        # Order:  UL: N W  - LR: S E
-        conFile.write("SPATIAL_SUBSET_UL_CORNER = ( {mala} {milo} )"
-                      "\n".format(mala=bound['max_lat'], milo=bound['min_lon']))
-        conFile.write("SPATIAL_SUBSET_LR_CORNER = ( {mila} {malo} )"
-                      "\n".format(mila=bound['min_lat'], malo=bound['max_lon']))
-        conFile.write("OUTPUT_FILENAME = {out}\n".format(out=fileout))
-        # if resample is in resam_list set it otherwise return an error
-        if resample in RESAM_LIST:
-            conFile.write("RESAMPLING_TYPE = {res}\n".format(res=resample))
-        else:
-            raise Exception('The resampling type {res} is not supportet.\n'
-                            'The resampling type supported are '
-                            '{reslist}'.format(res=resample, reslist=RESAM_LIST))
-        # if projtype is in proj_list set it otherwise return an error
-        if projtype in PROJ_LIST:
-            conFile.write("OUTPUT_PROJECTION_TYPE = {typ}\n".format(typ=projtype))
-        else:
-            raise Exception('The projection type {typ} is not supported.\n'
-                            'The projections supported are '
-                            '{proj}'.format(typ=projtype, proj=PROJ_LIST))
-        conFile.write("OUTPUT_PROJECTION_PARAMETERS = {proj}\n".format(proj=projpar))
-        # if datum is in datum_list set the parameter otherwise return an error
-        if datum in DATUM_LIST:
-            conFile.write("DATUM = {dat}\n".format(dat=datum))
-        else:
-            raise Exception('The datum {dat} is not supported.\n'
-                            'The datum supported are '
-                            '{datum}'.format(dat=datum, datum=DATUM_LIST))
-        # if utm is not None write the UTM_ZONE parameter in the file
-        if utm:
-            conFile.write("UTM_ZONE = {zone}\n".format(zone=utm))
-        # if res is not None write the OUTPUT_PIXEL_SIZE parameter in the file
-        if res:
-            conFile.write("OUTPUT_PIXEL_SIZE = {pix}\n".format(pix=res))
-        conFile.close()
-        return filename
-
-    def confResample_swath(self, sds, geoloc, res, output=None,
-                           sphere='8', resample='NN', projtype='GEO', utm=None,
-                           projpar='0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 '
-                           '0.0 0.0 0.0 0.0 0.0', bound=None):
-        """Create the parameter file to use with resample MRT software to
-           create tif (geotiff) file
-
-        :param str sds: Name of band/s (Science Data Set) to resample
-        :param str geoloc: Name geolocation file (example MOD3, MYD3)
-        :param int res: the resolution for the output file, it must be set in
-                        the map unit of output projection system. The software
-                        will use the original resolution of input file if res
-                        not set
-
-        :param str output: the output name, if not set the prefix name of
-                           input hdf file will be used
-
-        :param int sphere: Output sphere number. Valid options are:
-
-                           * 0=Clarke 1866
-                           * 1=Clarke 1880
-                           * 2=Bessel
-                           * 3=International 1967
-                           * 4=International 1909
-                           * 5=WGS 72
-                           * 6=Everest
-                           * 7=WGS 66
-                           * 8=GRS1980/WGS 84
-                           * 9=Airy
-                           * 10=Modified Everest
-                           * 11=Modified Airy
-                           * 12=Walbeck
-                           * 13=Southeast Asia
-                           * 14=Australian National
-                           * 15=Krassovsky
-                           * 16=Hough
-                           * 17=Mercury1960
-                           * 18=Modified Mercury1968
-                           * 19=Sphere 19 (Radius 6370997)
-                           * 20=MODIS Sphere (Radius 6371007.181)
-
-        :param str resample: the type of resampling, the valid values are:
-
-                             * NN (nearest neighbor)
-                             * BI (bilinear)
-                             * CC (cubic convolution)
-
-        :param str projtype: the output projection system, valid values are:
-
-                             * AEA (Albers Equal Area)
-                             * ER (Equirectangular)
-                             * GEO (Geographic Latitude/Longitude)
-                             * HAM (Hammer)
-                             * ISIN (Integerized Sinusoidal)
-                             * IGH (Interrupted Goode Homolosine)
-                             * LA (Lambert Azimuthal)
-                             * LCC (LambertConformal Conic)
-                             * MERCAT (Mercator)
-                             * MOL (Mollweide)
-                             * PS (Polar Stereographic),
-                             * SIN ()Sinusoidal)
-                             * UTM (Universal TransverseMercator)
-
-        :param utm: the UTM zone if projection system is UTM
-
-        :param str projpar: a list of projection parameters, for more info
-                            check the Appendix C of MODIS reprojection tool
-                            user manual https://lpdaac.usgs.gov/content/download/4831/22895/file/mrt41_usermanual_032811.pdf
-
-        :param dict bound: dictionary with the following keys:
-
-                           * max_lat
-                           * max_lon
-                           * min_lat
-                           * min_lon
-        """
-        # output name
-        if not output:
-            fileout = self.tifname
-        else:
-            fileout = output
-        # the name of the output parameters files for resample MRT software
-        filename = os.path.join(self.path,
-                                '{cod}_mrt_resample.prm'.format(cod=self.code))
-        # if the file already exists it remove it
-        if os.path.exists(filename):
-            os.remove(filename)
-        # open the file
-        conFile = open(filename, 'w')
-        conFile.write("INPUT_FILENAME = {name}\n".format(name=self.hdfname))
-        conFile.write("GEOLOCATION_FILENAME = {name}\n".format(name=geoloc))
-        conFile.write("INPUT_SDS_NAME = {name}\n".format(name=sds))
-        conFile.write("OUTPUT_SPATIAL_SUBSET_TYPE = LAT_LONG\n")
-        if not bound:
-            # return the boundary from the input xml file
-            bound = self.retBoundary()
-        else:
-            if 'max_lat' not in bound or 'min_lat' not in bound or \
-               'min_lon' not in bound or 'max_lon' not in bound:
-                raise Exception('bound variable is a dictionary with the '
-                                'following keys: max_lat, min_lat, min_lon,'
-                                ' max_lon')
-        # Order:  UL: N W  - LR: S E
-        conFile.write("OUTPUT_SPACE_UPPER_LEFT_CORNER (LONG LAT) = {milo} "
-                      "{mala}\n".format(mala=bound['max_lat'],
-                                        milo=bound['min_lon']))
-        conFile.write("OUTPUT_SPACE_LOWER_RIGHT_CORNER (LONG LAT) = {mila} "
-                      "{malo}\n".format(mila=bound['min_lat'],
-                                        malo=bound['max_lon']))
-        conFile.write("OUTPUT_FILENAME = {name}\n".format(name=fileout))
-        conFile.write("OUTPUT_FILE_FORMAT = GEOTIFF_FMT\n")
-        # if resample is in resam_list set it otherwise return an error
-        if resample in RESAM_LIST_SWATH:
-            conFile.write("KERNEL_TYPE (CC/BI/NN) = {res}"
-                          "\n".format(res=resample))
-        else:
-            raise Exception('The resampling type {typ} is not supportet.\n'
-                            'The resampling type supported are '
-                            '{swa}'.format(typ=resample, swa=RESAM_LIST_SWATH))
-        # if projtype is in proj_list set it otherwise return an error
-        if projtype in PROJ_LIST:
-            conFile.write("OUTPUT_PROJECTION_NUMBER = {typ}\n".format(typ=projtype))
-        else:
-            raise Exception('The projection type {typ} is not supported.\n'
-                            'The projections supported are '
-                            '{proj}'.format(typ=projtype, proj=PROJ_LIST))
-        conFile.write("OUTPUT_PROJECTION_PARAMETER = {prj}\n".format(prj=projpar))
-        # if sphere is in sphere_list set it otherwise return an error
-        if int(sphere) in SPHERE_LIST:
-            conFile.write("OUTPUT_PROJECTION_SPHERE = {sph}\n".format(sph=sphere))
-        else:
-            raise Exception('The sphere {sph} is not supported.\nThe spheres'
-                            'supported are {sphere}'.format(sph=sphere,
-                                                            sphere=SPHERE_LIST))
-        # if utm is not None write the UTM_ZONE parameter in the file
-        if utm:
-            if utm < '-60' or utm > '60':
-                raise Exception('The valid UTM zone are -60 to 60')
-            else:
-                conFile.write("OUTPUT_PROJECTION_ZONE = {utm}\n".format(utm=utm))
-        # if res is not None write the OUTPUT_PIXEL_SIZE parameter in the file
-        if res:
-            conFile.write("OUTPUT_PIXEL_SIZE = {res}\n".format(res=res))
-        conFile.close()
-        return filename
-
-
-class parseModisMulti:
-    """A class to obtain some variables for the xml file of several MODIS
-       tiles. It can also create the xml file
-
-       :param list hdflist: python list containing the hdf files
-    """
-
-    def __init__(self, hdflist):
-        """Function to initialize the object"""
-        from xml.etree import ElementTree
-        self.ElementTree = ElementTree
-        self.hdflist = hdflist
-        self.parModis = []
-        self.nfiles = 0
-        # for each hdf files create a parseModis object
-        for i in hdflist:
-            self.parModis.append(parseModis(i))
-            self.nfiles += 1
-
-    def _most_common(self, lst):
-        """Return the most common value of a list"""
-        return max(set(lst), key=lst.count)
-
-    def _checkval(self, vals):
-        """Internal function to return values from list
-
-        :param list vals: list of values
-        """
-        if vals.count(vals[0]) == self.nfiles:
-            return [vals[0]]
-        else:
-            outvals = []
-            for i in vals:
-                if outvals.count(i) == 0:
-                    outvals.append(i)
-        return outvals
-
-    def _checkvaldict(self, vals):
-        """Internal function to return values from dictionary
-
-        :param dict vals: dictionary of values
-        """
-        keys = vals[0].keys()
-        outvals = {}
-        for k in keys:
-            valtemp = []
-            for v in vals:
-                valtemp.append(v[k])
-            if valtemp.count(valtemp[0]) == self.nfiles:
-                outvals[k] = valtemp[0]
-            elif len(valtemp) == self.nfiles:
-                outvals[k] = self._most_common(valtemp)
-            else:
-                raise Exception('Something wrong reading XML files')
-
-        return outvals
-
-    def _minval(self, vals):
-        """Internal function to return the minimum value
-
-        :param list vals: list of values
-        """
-        outval = vals[0]
-        for i in range(1, len(vals)):
-            if outval > i:
-                outval = i
-        return outval
-
-    def _maxval(self, vals):
-        """Internal function to return the maximum value
-
-        :param list vals: list of values
-        """
-        outval = vals[0]
-        for i in range(1, len(vals)):
-            if outval < i:
-                outval = i
-        return outval
-
-    def _cicle_values(self, obj, values):
-        """Internal function to add values from a dictionary
-
-        :param obj: element to add values
-
-        :param values: dictionary containing keys and values
-        """
-        for k, v in values.iteritems():
-            elem = self.ElementTree.SubElement(obj, k)
-            elem.text = v
-
-    def _addPoint(self, obj, lon, lat):
-        """Internal function to add a point in boundary xml tag
-
-        :param obj: element to add point
-        :param lon: longitude of point
-        :param lat: latitude of point
-        """
-        pt = self.ElementTree.SubElement(obj, 'Point')
-        ptlon = self.ElementTree.SubElement(pt, 'PointLongitude')
-        ptlon.text = str(self.boundary[lon])
-        ptlat = self.ElementTree.SubElement(pt, 'PointLatitude')
-        ptlat.text = str(self.boundary[lat])
-
-    def valDTD(self, obj):
-        """Function to add DTDVersion
-
-        :param obj: element to add DTDVersion
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retDTD())
-        for i in self._checkval(values):
-            dtd = self.ElementTree.SubElement(obj, 'DTDVersion')
-            dtd.text = i
-
-    def valDataCenter(self, obj):
-        """Function to add DataCenter
-
-        :param obj: element to add DataCenter
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retDataCenter())
-        for i in self._checkval(values):
-            dci = self.ElementTree.SubElement(obj, 'DataCenterId')
-            dci.text = i
-
-    def valGranuleUR(self, obj):
-        """Function to add GranuleUR
-
-        :param obj: element to add GranuleUR
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retGranuleUR())
-        for i in self._checkval(values):
-            gur = self.ElementTree.SubElement(obj, 'GranuleUR')
-            gur.text = i
-
-    def valDbID(self, obj):
-        """Function to add DbID
-
-        :param obj: element to add DbID
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retDbID())
-        for i in self._checkval(values):
-            dbid = self.ElementTree.SubElement(obj, 'DbID')
-            dbid.text = i
-
-    def valInsTime(self, obj):
-        """Function to add the minimum of InsertTime
-
-        :param obj: element to add InsertTime
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retInsertTime())
-        obj.text = self._minval(values)
-
-    def valCollectionMetaData(self, obj):
-        """Function to add CollectionMetaData
-
-        :param obj: element to add CollectionMetaData
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retCollectionMetaData())
-        self._cicle_values(obj, self._checkvaldict(values))
-
-    def valDataFiles(self, obj):
-        """Function to add DataFileContainer
-
-        :param obj: element to add DataFileContainer
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retDataFiles())
-        for i in values:
-            dfc = self.ElementTree.SubElement(obj, 'DataFileContainer')
-            self._cicle_values(dfc, i)
-
-    def valPGEVersion(self, obj):
-        """Function to add PGEVersion
-
-        :param obj: element to add PGEVersion
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retPGEVersion())
-        for i in self._checkval(values):
-            pge = self.ElementTree.SubElement(obj, 'PGEVersion')
-            pge.text = i
-
-    def valRangeTime(self, obj):
-        """Function to add RangeDateTime
-
-        :param obj: element to add RangeDateTime
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retRangeTime())
-        self._cicle_values(obj, self._checkvaldict(values))
-
-    def valBound(self):
-        """Function return the Bounding Box of mosaic"""
-        boundary = self.parModis[0].retBoundary()
-        for i in range(1, len(self.parModis)):
-            bound = self.parModis[i].retBoundary()
-            if bound['min_lat'] < boundary['min_lat']:
-                boundary['min_lat'] = bound['min_lat']
-            if bound['min_lon'] < boundary['min_lon']:
-                boundary['min_lon'] = bound['min_lon']
-            if bound['max_lat'] > boundary['max_lat']:
-                boundary['max_lat'] = bound['max_lat']
-            if bound['max_lon'] > boundary['max_lon']:
-                boundary['max_lon'] = bound['max_lon']
-        self.boundary = boundary
-
-    def valMeasuredParameter(self, obj):
-        """Function to add ParameterName
-
-        :param obj: element to add ParameterName
-        """
-        valuesQAStats = []
-        valuesQAFlags = []
-        valuesParameter = []
-        for i in self.parModis:
-            valuesQAStats.append(i.retMeasure()['QAStats'])
-            valuesQAFlags.append(i.retMeasure()['QAFlags'])
-            valuesParameter.append(i.retMeasure()['ParameterName'])
-        for i in self._checkval(valuesParameter):
-            pn = self.ElementTree.SubElement(obj, 'ParameterName')
-            pn.text = i
-
-    def valInputPointer(self, obj):
-        """Function to add InputPointer
-
-        :param obj: element to add InputPointer
-        """
-        for i in self.parModis:
-            for v in i.retInputGranule():
-                ip = self.ElementTree.SubElement(obj, 'InputPointer')
-                ip.text = v
-
-    def valPlatform(self, obj):
-        """Function to add Platform elements
-
-        :param obj: element to add Platform elements
-        """
-        valuesSName = []
-        valuesInstr = []
-        valuesSensor = []
-        for i in self.parModis:
-            valuesSName.append(i.retPlatform()['PlatformShortName'])
-            valuesInstr.append(i.retPlatform()['InstrumentShortName'])
-            valuesSensor.append(i.retPlatform()['SensorShortName'])
-        for i in self._checkval(valuesSName):
-            pn = self.ElementTree.SubElement(obj, 'PlatformShortName')
-            pn.text = i
-
-        valInstr = self._checkval(valuesInstr)
-        valSens = self._checkval(valuesSensor)
-
-        if len(valInstr) != len(valSens):
-            raise Exception('Something wrong reading XML files')
-        else:
-            for i in range(len(valInstr)):
-                ins = self.ElementTree.SubElement(obj, 'Instrument')
-                pn = self.ElementTree.SubElement(ins, 'InstrumentShortName')
-                pn.text = valInstr[i]
-                sens = self.ElementTree.SubElement(ins, 'Sensor')
-                ps = self.ElementTree.SubElement(sens, 'SensorShortName')
-                ps.text = valSens[i]
-
-    def valInsertTime(self, obj):
-        """Function to add InsertTime elements
-
-        :param obj: element to add InsertTime elements
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retInsertTime())
-        for i in self._checkval(values):
-            gur = self.ElementTree.SubElement(obj, 'InsertTime')
-            gur.text = i
-
-    def valLastUpdate(self, obj):
-        """Function to add LastUpdate elements
-
-        :param obj: element to add LastUpdate elements
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retLastUpdate())
-        for i in self._checkval(values):
-            gur = self.ElementTree.SubElement(obj, 'LastUpdate')
-            gur.text = i
-
-    def valDataGranule(self, obj):
-        """Function to add DataFileContainer
-
-        :param obj: element to add DataFileContainer
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retDataGranule())
-        for i in values:
-            dfc = self.ElementTree.SubElement(obj, 'ECSDataGranule')
-            self._cicle_values(dfc, i)
-
-    def valBrowseProduct(self, obj):
-        """Function to add BrowseGranuleId
-
-        :param obj: element to add BrowseGranuleId
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retBrowseProduct())
-        for i in self._checkval(values):
-            dfc = self.ElementTree.SubElement(obj, 'BrowseGranuleId')
-            dfc.text = i
-
-    def valPSA(self, obj):
-        """Function to add PSA
-
-        :param obj: element to add PSA
-        """
-        values = []
-        for i in self.parModis:
-            values.append(i.retPSA())
-        for k in sorted(values[0].keys()):
-            psa = self.ElementTree.SubElement(obj, 'PSA')
-            psaname = self.ElementTree.SubElement(psa, 'PSAName')
-            psaname.text = k
-            for s in values:
-                psaval = self.ElementTree.SubElement(psa, 'PSAValue')
-                psaval.text = s[k]
-
-    def writexml(self, outputname, pretty=True):
-        """Write a xml file for a mosaic
-
-        :param str outputname: the name of output xml file
-        :param bool pretty: write prettyfy output, by default true
-        """
-
-        # the root element
-        granule = self.ElementTree.Element('GranuleMetaDataFile')
-        # add DTDVersion
-        self.valDTD(granule)
-        # add DataCenterId
-        self.valDataCenter(granule)
-        # add GranuleURMetaData
-        gurmd = self.ElementTree.SubElement(granule, 'GranuleURMetaData')
-        # add GranuleUR
-        self.valGranuleUR(gurmd)
-        # add dbID
-        self.valDbID(gurmd)
-        # add InsertTime
-        self.valInsertTime(gurmd)
-        # add LastUpdate
-        self.valLastUpdate(gurmd)
-        # add CollectionMetaData
-        cmd = self.ElementTree.SubElement(gurmd, 'CollectionMetaData')
-        self.valCollectionMetaData(cmd)
-        # add DataFiles
-        df = self.ElementTree.SubElement(gurmd, 'DataFiles')
-        self.valDataFiles(df)
-        # add ECSDataGranule
-        self.valDataGranule(gurmd)
-        # add PGEVersionClass
-        pgevc = self.ElementTree.SubElement(gurmd, 'PGEVersionClass')
-        self.valPGEVersion(pgevc)
-        # add RangeDateTime
-        rdt = self.ElementTree.SubElement(gurmd, 'RangeDateTime')
-        self.valRangeTime(rdt)
-        # add SpatialDomainContainer
-        sdc = self.ElementTree.SubElement(gurmd, 'SpatialDomainContainer')
-        hsdc = self.ElementTree.SubElement(sdc, 'HorizontalSpatialDomainContainer')
-        gp = self.ElementTree.SubElement(hsdc, 'GPolygon')
-        bound = self.ElementTree.SubElement(gp, 'Boundary')
-        self.valBound()
-        self._addPoint(bound, 'min_lon', 'max_lat')
-        self._addPoint(bound, 'max_lon', 'max_lat')
-        self._addPoint(bound, 'min_lon', 'min_lat')
-        self._addPoint(bound, 'max_lon', 'min_lat')
-        # add MeasuredParameter
-        mp = self.ElementTree.SubElement(gurmd, 'MeasuredParameter')
-        mpc = self.ElementTree.SubElement(mp, 'MeasuredParameterContainer')
-        self.valMeasuredParameter(mpc)
-        # add Platform
-        pl = self.ElementTree.SubElement(gurmd, 'Platform')
-        self.valPlatform(pl)
-        # add PSAs
-        psas = self.ElementTree.SubElement(gurmd, 'PSAs')
-        # add all PSA
-        self.valPSA(psas)
-        # add InputGranule and InputPointer
-        ig = self.ElementTree.SubElement(gurmd, 'InputGranule')
-        self.valInputPointer(ig)
-        # add BrowseProduct
-        bp = self.ElementTree.SubElement(gurmd, 'BrowseProduct')
-        self.valBrowseProduct(bp)
-        output = open(outputname, 'w')
-        output.write('<?xml version="1.0" encoding="UTF-8"?>')
-        output.write('<!DOCTYPE GranuleMetaDataFile SYSTEM "http://ecsinfo.'
-                     'gsfc.nasa.gov/ECSInfo/ecsmetadata/dtds/DPL/ECS/'
-                     'ScienceGranuleMetadata.dtd">')
-        if pretty:
-            import xml.dom.minidom as minidom
-            reparsed = minidom.parseString(self.ElementTree.tostring(granule))
-            output.write(reparsed.toprettyxml(indent="\t"))
-        else:
-            output.write(self.ElementTree.tostring(granule))
-        output.close()

Modified: grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.html
===================================================================
--- grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.html	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.html	2017-02-10 14:22:08 UTC (rev 70528)
@@ -6,19 +6,22 @@
 
 <h2>NOTE</h2>
 
-To be able to download data the user needs a <em>user</em> and <em>password</em> 
+r.modis modules need <a href="www.pymodis.org" target="_blank">pyModis</a> library.
+Please install it before.
+
+To be able to download data the user needs a <em>user</em> and <em>password</em>
 provided by NASA. The user should register at <a href="https://urs.earthdata.nasa.gov/users/new"
 target="_blank">https://urs.earthdata.nasa.gov/users/new</a>;
 then login and move to his/her profile page. Once there, under 'My applications'
-tab, the user needs to approve the following applications: 'LP DAAC Data Pool' 
+tab, the user needs to approve the following applications: 'LP DAAC Data Pool'
 and 'Earthdata Search'.
 <p>
-If the user is already registered, he/she just needs to login and enable the 
+If the user is already registered, he/she just needs to login and enable the
 mentioned applications at <a href="https://urs.earthdata.nasa.gov/home" target="_blank">https://urs.earthdata.nasa.gov/home</a>
 <p>
 In order to download the desired product(s), the username and password must be
-provided through the <em>settings</em> option. This There are two alternatives; 
-either pass a file in which the first line is the username, usually 'anonymous' 
+provided through the <em>settings</em> option. This There are two alternatives;
+either pass a file in which the first line is the username, usually 'anonymous'
 and, the second line is the password, usually the user's e-mail address, as below:
 <div class="code"><pre>
   your_NASA_username
@@ -34,21 +37,21 @@
 <p>
 By default, the downloaded files are stored in the path where the settings
 file is saved. The user can change this directory with the <em>folder</em>
-option. The <em>folder</em> option is required when user and password are 
+option. The <em>folder</em> option is required when user and password are
 passed through the standard input.
 <p>
 The needed time for the download depends on the number of requested tiles, days
-and the type of MODIS product. For example, the NDVI product ranges from 5 MB 
+and the type of MODIS product. For example, the NDVI product ranges from 5 MB
 to 270 MB and the LST product ranges from 2 MB to 21 MB.
 
 <h2>EXAMPLES</h2>
 
 Download the daily MODIS LST product from the Terra satellite using the default
-options (all available tiles from newest available date) and passing the user 
-and password from standard input. Note that when settings is read from standard 
+options (all available tiles from newest available date) and passing the user
+and password from standard input. Note that when settings is read from standard
 input, the option folder must be specified.
 <div class="code"><pre>
-r.modis.download settings=- folder=/tmp 
+r.modis.download settings=- folder=/tmp
 </pre></div>
 
 Reading the user and password options from a file. Images will be downloaded to
@@ -70,7 +73,7 @@
 </pre></div>
 
 To use <em>r.modis.download</em> in a script and concatenate with another module,
-the user needs to set the <em>-g</em> flag to return the name of the file that 
+the user needs to set the <em>-g</em> flag to return the name of the file that
 contains the list of downloaded HDF files:
 <div class="code"><pre>
 r.modis.download -g settings=$HOME/.grass7/r.modis/SETTING startday=2011-05-01 endday=2011-05-31

Modified: grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.py
===================================================================
--- grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/r.modis.download/r.modis.download.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -155,7 +155,7 @@
 def main():
     try:
         from rmodislib import product
-        from downmodis import downModis
+        from pymodis.downmodis import downModis
     except:
         grass.fatal("r.modis library is not installed")
     # check if you are in GRASS

Modified: grass-addons/grass7/raster/r.modis/r.modis.html
===================================================================
--- grass-addons/grass7/raster/r.modis/r.modis.html	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/r.modis.html	2017-02-10 14:22:08 UTC (rev 70528)
@@ -109,6 +109,10 @@
       validation definitions.</li>
 </ul>
 
+<h2>NOTE</h2>
+r.modis modules need <a href="www.pymodis.org" target="_blank">pyModis</a> library.
+Please install it before.
+
 <h2>SEE ALSO</h2>
 
 <em>

Modified: grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.html
===================================================================
--- grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.html	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.html	2017-02-10 14:22:08 UTC (rev 70528)
@@ -4,6 +4,9 @@
 
 <h2>NOTE</h2>
 
+r.modis modules need <a href="www.pymodis.org" target="_blank">pyModis</a> library.
+Please install it before.
+
 The input file is given as list of full paths to the MODIS HDF files,
 one per line. The input file(s) have to be inside the folder where
 the HDF files are stored.

Modified: grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.py
===================================================================
--- grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.py	2017-02-10 11:14:18 UTC (rev 70527)
+++ grass-addons/grass7/raster/r.modis/r.modis.import/r.modis.import.py	2017-02-10 14:22:08 UTC (rev 70528)
@@ -165,6 +165,11 @@
 
 def confile(pm, opts, q, mosaik=False):
     """Create the configuration file for MRT software"""
+    try:
+        # try to import pymodis (modis) and some classes for r.modis.download
+        from rmodislib import resampling, product, projection
+    except:
+        grass.fatal("r.modis library is not installed")
     # return projection and datum
     projObj = projection()
     proj = projObj.returned()
@@ -182,7 +187,7 @@
     else:
         spectr = spectral(opts, prod, q)
     # out prefix
-    pref = prefix(opts)
+    pref = modis_prefix(pm.hdfname)
     # resampling
     resampl = resampling(opts['method']).returned()
     # projpar
@@ -239,6 +244,11 @@
 
 def import_tif(basedir, rem, write, pm, prod, target=None, listfile=None):
     """Import TIF files"""
+    try:
+        # try to import pymodis (modis) and some classes for r.modis.download
+        from rmodislib import projection
+    except:
+        grass.fatal("r.modis library is not installed")
     # list of tif files
     pref = modis_prefix(pm.hdfname)
     tifiles = glob.glob1(basedir, "{pr}*.tif".format(pr=pref))
@@ -306,6 +316,17 @@
 def single(options, remove, an, ow, fil):
     """Convert the HDF file to TIF and import it
     """
+    try:
+        # try to import pymodis (modis) and some classes for r.modis.download
+        from rmodislib import product, projection, get_proj
+    except:
+        grass.fatal("r.modis library is not installed")
+    try:
+        from pymodis.convertmodis import convertModis
+        from pymodis.convertmodis_gdal import convertModisGDAL
+        from pymodis.parsemodis import parseModis
+    except:
+        grass.fatal("pymodis library is not installed")
     listfile, basedir = list_files(options)
     # for each file
     for i in listfile:
@@ -349,6 +370,17 @@
 def mosaic(options, remove, an, ow, fil):
     """Create a daily mosaic of HDF files convert to TIF and import it
     """
+    try:
+        # try to import pymodis (modis) and some classes for r.modis.download
+        from rmodislib import product, projection, get_proj
+    except:
+        grass.fatal("r.modis library is not installed")
+    try:
+        from pymodis.convertmodis import convertModis, createMosaic
+        from pymodis.convertmodis_gdal import createMosaicGDAL, convertModisGDAL
+        from pymodis.parsemodis import parseModis
+    except:
+        grass.fatal("pymodis library is not installed")
     dictfile, targetdir = list_files(options, True)
     pid = str(os.getpid())
     # for each day
@@ -434,15 +466,6 @@
 
 
 def main():
-
-    try:
-        # try to import pymodis (modis) and some classes for r.modis.download
-        from rmodislib import resampling, product, projection, get_proj
-        from convertmodis import convertModis, createMosaic
-        from convertmodis_gdal import createMosaicGDAL, convertModisGDAL
-        from parsemodis import parseModis
-    except:
-        grass.fatal("r.modis library is not installed")
     # check if you are in GRASS
     gisbase = os.getenv('GISBASE')
     if not gisbase:



More information about the grass-commit mailing list