diff --git a/.gitignore b/.gitignore index 03cb041..df2b0f4 100644 --- a/.gitignore +++ b/.gitignore @@ -60,4 +60,5 @@ bap_env/ data/ crear_BAP_manual.py -readme.py \ No newline at end of file +readme.py +crear_compuesto_archivo.py \ No newline at end of file diff --git a/README.rst b/README.rst index 5b38622..d57f271 100644 --- a/README.rst +++ b/README.rst @@ -60,6 +60,10 @@ Available Indices Basic Usage ----------- +*Considerations:* + +- Sites size must not be too big. Works with 300 km2 tiles + .. code:: python from geebap import bap, season, filters, masks, \ @@ -89,13 +93,13 @@ Basic Usage filters = (filt_cld, filt_mask) # SCORES - doy = scores.Pdoy() - sat = scores.Psat() - op = scores.Pop() - out = scores.Poutlier(("ndvi",)) - ind = scores.Pindice("ndvi") - mascpor = scores.Pmascpor() - dist = scores.Pdist() + doy = scores.Doy() + sat = scores.Satellite() + op = scores.AtmosOpacity() + out = scores.Outliers(("ndvi",)) + ind = scores.Index("ndvi") + mascpor = scores.MaskPercent() + dist = scores.CloudDist() # Combine scores in a tuple scores = (doy, sat, op, out, ind, mascpor, dist) diff --git a/geebap/__init__.py b/geebap/__init__.py index 1afe2a4..0cf9ccd 100644 --- a/geebap/__init__.py +++ b/geebap/__init__.py @@ -12,7 +12,7 @@ __summary__ = "Generate a 'Best Available Pixel' image in Google Earth Engine" __uri__ = "" -__version__ = "0.1" +__version__ = "0.0.2" __author__ = "Rodrigo E. Principe" __email__ = "rprincipe@ciefap.org.ar" diff --git a/geebap/bap.py b/geebap/bap.py index af7bed3..0a1ef9d 100644 --- a/geebap/bap.py +++ b/geebap/bap.py @@ -32,9 +32,19 @@ class Bap(object): def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None, masks=None, filters=None, bbox=0, season=None, fmap=None): - """ + """ The Bap object is designed to be independet of the site and the + method that will be used to generate the composite. + + :param year: The year of the final composite. If the season covers two + years the last one will be used. Ej. + + ..code:: - :param year: + season = Season(ini="15-12", end="15-01") + bap = Bap(year=2000) + + to generate the composite the code will use images from + 15-12-1999 to 15-01-2000 :type year: int :param range: :type range: tuple @@ -56,7 +66,7 @@ def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None, # check_type("filters", filters, tuple) check_type("year", year, int) # check_type("range", range, tuple) - check_type("bbox", bbox, int) + # check_type("bbox", bbox, int) check_type("season", season, temp.Season) if year < MIN_YEAR or year > MAX_YEAR: @@ -70,7 +80,7 @@ def __init__(self, year=None, range=(0, 0), colgroup=None, scores=None, self.scores = scores self.masks = masks self.filters = filters - self.bbox = bbox + # self.bbox = bbox self.season = season self.fmap = fmap @@ -108,7 +118,7 @@ def date_range(self): @property def score_names(self): if self.scores: - punt = [p.nombre for p in self.scores] + punt = [p.name for p in self.scores] return functions.replace_duplicate(punt) else: return [] @@ -140,7 +150,7 @@ def collist(self): print "Intersection:", intersect return [satcol.Collection.from_id(ID) for ID in intersect] - def collection(self, site, indices=None, normalize=True, **kwargs): + def collection(self, site, indices=None, normalize=True, bbox=0): """ :param indices: vegetation indices to include in the final image. If None, no index is calculated @@ -185,22 +195,21 @@ def collection(self, site, indices=None, normalize=True, **kwargs): # Obtengo el ID de la coleccion cid = colobj.ID - # Obtengo el nombre abreviado para agregar a los metadatos + # Obtengo el name abreviado para agregar a los metadatos short = colobj.short - # Imagen del bandID de la coleccion + # Imagen del col_id de la coleccion bid = colobj.bandIDimg # diccionario para agregar a los metadatos con la relation entre - # satelite y bandID - # prop_codsat = {colobj.ID: colobj.bandID} - toMetadata["codsat_"+short] = colobj.bandID + # satelite y col_id + # prop_codsat = {colobj.ID: colobj.col_id} + toMetadata["col_id_"+short] = colobj.col_id # Collection completa de EE c = colobj.colEE # Filtro por el site - # TODO: Use bbox parameter if isinstance(site, ee.Feature): site = site.geometry() c2 = c.filterBounds(site) @@ -236,17 +245,23 @@ def collection(self, site, indices=None, normalize=True, **kwargs): if size == 0: continue # 1 # corto la imagen con la region para minimizar los calculos - def cut(img): - return img.clip(site) + if bbox == 0: + def cut(img): + return img.clip(site) + else: + def cut(img): + bounds = site.buffer(bbox) + return img.clip(bounds) + c = c.map(cut) # Mascaras if self.masks: for m in self.masks: c = c.map( - m.map(col=col, anio=anio, colEE=c)) + m.map(col=col, year=anio, colEE=c)) if self.debug: - print " SIZE AFTER THE MASK "+m.nombre, \ + print " BANDS AFTER THE MASK "+m.nombre, \ ee.Image(c.first()).bandNames().getInfo() # Transformo los valores enmascarados a cero @@ -283,13 +298,13 @@ def cut(img): # Puntajes if self.scores: for p in self.scores: - if self.verbose: print "** "+p.nombre+" **" + if self.verbose: print "** "+p.name+" **" # Espero el tiempo seteado en cada puntaje sleep = p.sleep for t in range(sleep): sys.stdout.write(str(t+1)+".") time.sleep(1) - c = c.map(p.map(col=col, anio=anio, colEE=c, geom=site)) + c = c.map(p.map(col=col, year=anio, colEE=c, geom=site)) # DEBUG if self.debug and n > 0: @@ -310,7 +325,7 @@ def cut(img): # Selecciona solo las bandas que tienen en comun todas las # Colecciones - # METODO ANTERIOR: funcionaba, pero si agregaba una banda + # METODO ANTERIOR: funcionaba, pero si agregaba una band # con fmap, no se seleccionaba ''' def sel(img): @@ -332,15 +347,15 @@ def sel(img): # Convierto los valores de las mascaras a 0 c = c.map(functions.antiMask) - # Agrego la banda de fecha a la imagen + # Agrego la band de fecha a la imagen c = c.map(date.Date.map()) - # Agrego la banda bandID de la coleccion + # Agrego la band col_id de la coleccion def addBandID(img): return img.addBands(bid) c = c.map(addBandID) - if self.debug: print " AFTER ADDING bandID BAND:", \ + if self.debug: print " AFTER ADDING col_id BAND:", \ ee.Image(c.first()).bandNames().getInfo() # Convierto a lista para agregar a la coleccion anterior @@ -364,19 +379,23 @@ def addBandID(img): # Selecciono las bandas en comun de todas las imagenes newcol = functions.select_match(newcol) - if self.debug: print " BEFORE score:", \ + if self.debug: print " BEFORE score:", scores, "\n", \ ee.Image(newcol.first()).bandNames().getInfo() # Calcula el puntaje total sumando los puntajes ftotal = functions.sumBands("score", scores) newcol = newcol.map(ftotal) + if self.debug: + print " AFTER score:", \ + ee.Image(newcol.first()).bandNames().getInfo() + if normalize: newcol = newcol.map( functions.parameterize((0, maxpunt), (0, 1), ("score",))) if self.debug: - print " AFTER score:", \ + print " AFTER parametrize:", \ ee.Image(newcol.first()).bandNames().getInfo() output = namedtuple("ColBap", ("col", "dictprop")) @@ -431,7 +450,8 @@ def calcUnpix(self, site, name="score", bands=None, **kwargs): prop.update(fechaprop) return img.set(prop) - def bestpixel(self, site, name="score", bands=None, **kwargs): + def bestpixel(self, site, name="score", bands=None, + indices=None, normalize=True, bbox=0): """ Generate the BAP composite using the pixels that have higher final score. This is a custom method @@ -441,14 +461,15 @@ def bestpixel(self, site, name="score", bands=None, **kwargs): :type name: str :param bands: name of the bands to include in the final image :type bands: list - :param kwargs: + :param kwargs: see Bap.collection() method :return: A namedtuple: .image = the Best Available Pixel Composite (ee.Image) .col = the collection of images used to generate the BAP (ee.ImageCollection) :rtype: namedtuple """ - colbap = self.collection(site=site, **kwargs) + colbap = self.collection(site=site, indices=indices, + normalize=normalize, bbox=bbox) imgCol = colbap.col prop = colbap.dictprop @@ -528,10 +549,10 @@ def setprop(self, img, **kwargs): @classmethod def White(cls, year, range, season): - psat = scores.Psat() - pdist = scores.Pdist() - pdoy = scores.Pdoy(temporada=season) - pop = scores.Pop() + psat = scores.Satellite() + pdist = scores.CloudDist() + pdoy = scores.Doy(season=season) + pop = scores.AtmosOpacity() colG = satcol.ColGroup.SR() masc = masks.Clouds() filt = filters.CloudsPercent() @@ -549,14 +570,14 @@ def Modis(cls, year, range, season, index=None): :param index: Indice de vegetacion para el cual se va a calcular el puntaje. Debe coincidir con el que se usará en el metodo de generacion del Bap (ej: CalcUnpix). Si es None se omite el calculo - del puntaje por indice, lo que puede genera malos resultados + del puntaje por index, lo que puede genera malos resultados :return: """ # Puntajes - pdist = scores.Pdist() - pdoy = scores.Pdoy(temporada=season) - pmasc = scores.Pmascpor() - pout = scores.Poutlier(("nirXred",)) + pdist = scores.CloudDist() + pdoy = scores.Doy(season=season) + pmasc = scores.MaskPercent() + pout = scores.Outliers(("nirXred",)) colG = satcol.ColGroup.Modis() masc = masks.Clouds() @@ -566,7 +587,7 @@ def Modis(cls, year, range, season, index=None): if index: pindice = scores.PIndice(index) - pout2 = scores.Poutlier((index,)) + pout2 = scores.Outliers((index,)) pjes.append(pindice) pjes.append(pout2) diff --git a/geebap/date.py b/geebap/date.py index 3696042..a6b1445 100644 --- a/geebap/date.py +++ b/geebap/date.py @@ -5,7 +5,7 @@ class Date(object): - """ Agrega una banda de nombre *fecha* de tipo *Uint16* que toma de la + """ Agrega una band de name *fecha* de tipo *Uint16* que toma de la propiedad *system:time_start* y computa la cantidad de dias que transcurrieron a partir del 1970-01-01. Agrega a la imagen una propiedad con el id de la imagen llamada 'id_img' @@ -23,7 +23,7 @@ def __init__(self): def map(name="date"): """ :PARAMETROS: - :param name: name que se le dara a la banda + :param name: name que se le dara a la band :type name: str """ def wrap(img): diff --git a/geebap/expressions.py b/geebap/expressions.py index f20accb..2037604 100644 --- a/geebap/expressions.py +++ b/geebap/expressions.py @@ -73,10 +73,10 @@ class Expression(object): exp = Expression.Exponential(range=(0, 100)) exp2 = Expression.Exponential(range=(0, 5000), normalize=True) - # Defino las funciones, indicando el nombre de la banda resultante + # Defino las funciones, indicando el name de la band resultante # y la variable que se usará para el cálculo fmap = exp.map("otronombre", prop="CLOUD_COVER") - fmap2 = exp2.map("nombre", banda="NIR") + fmap2 = exp2.map("name", band="NIR") # Mapeo los resultados newcol = imgcol.map(fmap) @@ -140,11 +140,11 @@ def format_ee(self): @staticmethod def adjust(name, valor): - """ Ajusta el valor de la banda resultante multipliandolo por 'valor' + """ Ajusta el valor de la band resultante multipliandolo por 'valor' - :param valor: Valor de ajuste + :param valor: Valor de adjust :type valor: float - :param name: name de la banda que contiene el valor a ajustar + :param name: name de la band que contiene el valor a ajustar :type name: str :return: La funcion para map() :rtype: function @@ -269,7 +269,7 @@ def map(self, name="expression", band=None, prop=None, eval=None, esa band, y si es una propiedad, el argumento será la propiedad. :type eval: function :param map: funcion para aplicarle al valor final. Puede usarse para - hacer un ajuste o ponderacion. El argumento de la funcion debe ser + hacer un adjust o ponderacion. El argumento de la funcion debe ser la imagen con la band agregada :type map: function :return: la funcion para map() @@ -374,23 +374,23 @@ def Exponential(cls, a=-10, range=(0, 100), **kwargs): **kwargs) @classmethod - def Normal(cls, range=(0, 100), factor=-0.5, **kwargs): + def Normal(cls, range=(0, 100), ratio=-0.5, **kwargs): """ Campana de Normal :param rango: Rango entre los que oscilan los valores de entrada :type rango: tuple - :param factor: factor de 'agusamiento' de la curva. Debe ser menor a + :param ratio: factor de 'agusamiento' de la curva. Debe ser menor a cero. Cuanto menor sea, mas 'fina' será la curva - :type factor: float + :type ratio: float :param kwargs: :return: """ - if factor > 0: - print "el factor de la curva gaussiana debe ser menor a cero, convirtiendo.." - factor *= -1 + if ratio > 0: + print "el ratio de la curva gaussiana debe ser menor a cero, convirtiendo.." + ratio *= -1 if not isinstance(range, tuple): raise ValueError("el range debe ser una tupla") - exp = "exp(((({var}-{mean})/{std})**2)*{factor})/(sqrt(2*pi)*{std})" - return cls(expression=exp, range=range, factor=factor, + exp = "exp(((({var}-{mean})/{std})**2)*{ratio})/(sqrt(2*pi)*{std})" + return cls(expression=exp, range=range, ratio=ratio, name="Normal", **kwargs) \ No newline at end of file diff --git a/geebap/functions.py b/geebap/functions.py index 33765a8..892ae64 100755 --- a/geebap/functions.py +++ b/geebap/functions.py @@ -362,7 +362,7 @@ def wrap(img): diff = list_diff(todas, inter) imagen = img.select(inter) - # Porcentaje del valor actual de la banda en el rango de valores + # Porcentaje del valor actual de la band en el rango de valores porcent = imagen.subtract(min0).divide(rango0) # Teniendo en cuenta el porcentaje en el que se encuentra el valor @@ -382,27 +382,29 @@ def wrap(img): return wrap -def replace_duplicate(list): +def replace_duplicate(list, separator="_"): """ replace duplicated values from a list adding a suffix with a number :param list: list to be processed :type list: ee.List + :param separator: string to separate the name and the suffix + :type separator: str :return: new list with renamed values :rtype: ee.List """ def wrap(a): - newlist = [a[0]] + newlist = [a[0]] # list with first element for i, v in enumerate(a): - if i == 0: continue + if i == 0: continue # skip first element # t = a[i+1:] if v in newlist: - if "_" in v: - two = v.split("_") + if separator in v: + two = v.split(separator) orig = two[0] n = int(two[1]) - newval = "{}_{}".format(orig, n+1) + newval = "{}{}{}".format(orig, separator, n+1) else: - newval = v+"_1" + newval = v+separator+"1" newlist.append(newval) else: newlist.append(v) diff --git a/geebap/indices.py b/geebap/indices.py index 54f297c..14d8025 100644 --- a/geebap/indices.py +++ b/geebap/indices.py @@ -145,6 +145,6 @@ def calc(img): col2 = col.map(ndvi("B5", "B4")) # i = ee.Image(col2.first()) - i = ndvi("B5", "B4")(img) + i = nbr("B7", "B4")(img) v = i.reduceRegion(ee.Reducer.first(), p, 30) print v.getInfo() diff --git a/geebap/masks.py b/geebap/masks.py index 5cacab6..21bc976 100644 --- a/geebap/masks.py +++ b/geebap/masks.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -""" Modulo que contiene las clases para las mascaras a aplicar en la generacion +""" Module containing the classes +Modulo que contiene las clases para las mascaras a aplicar en la generacion del compuesto BAP """ import satcol @@ -23,7 +24,7 @@ class Clouds(Mask): """ Mascara de nubes propia de la coleccion """ def __init__(self, **kwargs): super(Clouds, self).__init__(**kwargs) - self.nombre = "nubes" + self.nombre = "clouds" def map(self, col, **kwargs): """ @@ -50,7 +51,7 @@ class Equivalent(Mask): la misma (DATE_ACQUIRED) :type fechafld: str - :param fld: banda de la imagen en la que está el valor de fmask (fmask) + :param fld: band de la imagen en la que está el valor de fmask (fmask) :type fld: str :param col: colección que se quiere enmascarar STRING (argumento) @@ -60,7 +61,7 @@ class Equivalent(Mask): def __init__(self, **kwargs): super(Equivalent, self).__init__(**kwargs) - self.nombre = "equivalente" + self.nombre = "equivalent" def map(self, col, **kwargs): """ diff --git a/geebap/satcol.py b/geebap/satcol.py index 5f141e3..4d834b2 100644 --- a/geebap/satcol.py +++ b/geebap/satcol.py @@ -43,8 +43,8 @@ def __init__(self, **kwargs): # ID Privado self.__ID = None - # bandid para crear una banda que identifique a la col - self.bandID = kwargs.get("bandID", None) + # bandid para crear una band que identifique a la col + self.col_id = kwargs.get("col_id", None) # IDENTIFICADOR DEL PROCESO self.process = kwargs.get("process", None) @@ -139,7 +139,7 @@ def invert_bandsrel(self): @property def bandIDimg(self): - return ee.Image.constant(self.bandID).select([0], ["bandID"]) + return ee.Image.constant(self.col_id).select([0], ["col_id"]) @property def renamed(self): @@ -153,8 +153,8 @@ def ID(self): def ID(self, id): if self.__ID is not None: raise ValueError( - "El Objeto ya tiene el ID '{}'".format(self.__ID) + \ - " y no puede ser modificado") + "The collection already has ID '{}'".format(self.__ID) + \ + " and cannot be modified") elif id in Collection.__OPTIONS: self.__ID = id @@ -162,7 +162,7 @@ def ID(self, id): else: # raise Collection.VERROR raise ValueError( - "El id de la coleccion debe ser una de: {}".format( + "ID must be one of: {}".format( Collection.__OPTIONS)) @property @@ -188,7 +188,7 @@ def satmask(self): return Collection.__OPTIONS.index(self.ID) + 1 except: raise ValueError( - "{} no esta en {}".format(self.ID, Collection.__OPTIONS)) + "{} is not in {}".format(self.ID, Collection.__OPTIONS)) @property def colEE(self): @@ -210,8 +210,8 @@ def ndvi(self): @property def nbr(self): """ Funcion para calcular el nbr usando map() """ - if self.NIR and self.SWIR and init: - return indices.nbr(self.NIR, self.SWIR) + if self.NIR and self.SWIR2 and init: + return indices.nbr(self.NIR, self.SWIR2) else: return None @@ -225,10 +225,11 @@ def evi(self): # NORMAL METHOD def rename(self, drop=False): - """ Renombra las bands de una coleccion por sus equivalentes + """ Renames the name of the bands for its equivalents - :param img: + :param drop: :return: + :rtype: function """ # drop = drop @@ -330,7 +331,7 @@ def Landsat2(cls): copy = deepcopy(Collection.Landsat1()) # L1 copy.kws["ini"] = 1975 copy.kws["end"] = 1983 - copy.kws["bandID"] = 2 + copy.kws["col_id"] = 2 copy.kws["short"] = "L2" obj = cls(**copy.kws) @@ -345,7 +346,7 @@ def Landsat3(cls): copy.kws["scale"] = 40 copy.kws["ini"] = 1978 copy.kws["end"] = 1983 - copy.kws["bandID"] = 3 + copy.kws["col_id"] = 3 copy.kws["short"] = "L3" obj = cls(**copy.kws) @@ -355,10 +356,10 @@ def Landsat3(cls): @classmethod def Landsat4TOA(cls): - escalables = ["B1", "B2", "B3", "B4", "B5"] + escalables = ["B1", "B2", "B3", "B4", "B5", "B7"] bandscale = dict(B1=30, B2=30, B3=30, B4=30, B5=30, B6=120, B7=30) obj = cls(BLUE="B1", GREEN="B2", RED="B3", NIR="B4", SWIR="B5", - to_scale=escalables, clouds_fld="CLOUD_COVER", + SWIR2="B7", to_scale=escalables, clouds_fld="CLOUD_COVER", process="TOA", max=1, fclouds=cld.fmask, scale=30, bandscale=bandscale, bandmask="B1", family="Landsat", clouds_band="fmask", ini=1982, end=1993, bandID=4, @@ -372,7 +373,7 @@ def Landsat5TOA(cls): copy = deepcopy(Collection.Landsat4TOA()) copy.kws["ini"] = 1984 copy.kws["end"] = 2013 - copy.kws["bandID"] = 5 + copy.kws["col_id"] = 5 copy.kws["short"] = "L5TOA" obj = cls(**copy.kws) @@ -389,7 +390,7 @@ def Landsat5USGS(cls): copy.kws["ATM_OP"] = "sr_atmos_opacity" copy.kws["equiv"] = "LANDSAT/LT5_L1T_TOA_FMASK" copy.kws["clouds_band"] = "cfmask" - copy.kws["bandID"] = 6 + copy.kws["col_id"] = 6 copy.kws["short"] = "L5USGS" obj = cls(**copy.kws) @@ -406,7 +407,7 @@ def Landsat5LEDAPS(cls): copy.kws["fclouds"] = cld.ledaps copy.kws["equiv"] = "LANDSAT/LT5_L1T_TOA_FMASK" copy.kws["clouds_band"] = "QA" - copy.kws["bandID"] = 7 + copy.kws["col_id"] = 7 copy.kws["short"] = "L5LEDAPS" obj = cls(**copy.kws) @@ -420,7 +421,7 @@ def Landsat7TOA(cls): copy.kws["bandscale"] = dict(B1=30, B2=30, B3=30, B4=30, B5=30, B6=60, B7=30, B8=15) copy.kws["ini"] = 1999 - copy.kws["bandID"] = 8 + copy.kws["col_id"] = 8 copy.kws["short"] = "L7TOA" obj = cls(**copy.kws) @@ -437,7 +438,7 @@ def Landsat7USGS(cls): copy.kws["fclouds"] = cld.usgs copy.kws["ATM_OP"] = "sr_atmos_opacity" copy.kws["clouds_band"] = "cfmask" - copy.kws["bandID"] = 9 + copy.kws["col_id"] = 9 copy.kws["short"] = "L7USGS" obj = cls(**copy.kws) @@ -453,7 +454,7 @@ def Landsat7LEDAPS(cls): copy.kws["equiv"] = copy_TOA.equiv copy.kws["bandscale"] = copy_TOA.bandscale copy.kws["ini"] = copy_TOA.ini - copy.kws["bandID"] = 10 + copy.kws["col_id"] = 10 copy.kws["short"] = "L7LEDAPS" obj = cls(**copy.kws) @@ -476,7 +477,7 @@ def Landsat8TOA(cls): copy.kws["SWIR2"] = "B7" copy.kws["ini"] = 2013 copy.kws["bandmask"] = "B2" - copy.kws["bandID"] = 11 + copy.kws["col_id"] = 11 copy.kws["short"] = "L8TOA" obj = cls(**copy.kws) @@ -495,7 +496,7 @@ def Landsat8USGS(cls): # copy.kws["ATM_OP"] = copy_usgs.ATM_OP copy.kws["equiv"] = "LANDSAT/LC8_L1T_TOA_FMASK" copy.kws["bandscale"] = copy.bandscale - copy.kws["bandID"] = 12 + copy.kws["col_id"] = 12 copy.kws["short"] = "L8USGS" obj = cls(**copy.kws) @@ -545,7 +546,7 @@ def ModisAqua(cls): copy = deepcopy(Collection.ModisTerra()) copy.kws["ini"] = 2002 copy.kws["short"] = "MODAQ" - copy.kws["bandID"] = 15 + copy.kws["col_id"] = 15 obj = cls(**copy.kws) # CAMBIO @@ -713,6 +714,9 @@ def Todas(cls): if __name__ == "__main__": + l5led = ee.Image("LEDAPS/LT5_L1T_SR/LT52310901984169XXX03") + l8toa = ee.Image("LANDSAT/LC8_L1T_TOA_FMASK/LC82310902013344LGN00") + ''' c = Collection.Landsat1() c._ID = "LEDAPS/LE7_L1T_SR" @@ -794,6 +798,14 @@ def Todas(cls): g1 = ColGroup.SR() print g1.ids + + ls = ColGroup.SR() + print ls.collections + print ls.bandsrel() ''' - ls = ColGroup.Todas() - print ls.collections \ No newline at end of file + Cl5led = Collection.Landsat5LEDAPS() + print Cl5led.bandasrel_original, '\n', Cl5led.bandsrel + print Cl5led.to_scale + + newL5toa = Cl5led.rename(True)(l5led) + print newL5toa.bandNames().getInfo() diff --git a/geebap/scores.py b/geebap/scores.py index 5e9a79a..e1d3ea8 100644 --- a/geebap/scores.py +++ b/geebap/scores.py @@ -75,19 +75,19 @@ def apply(img): return apply -class Puntaje(object): +class Score(object): __metaclass__ = ABCMeta - def __init__(self, nombre="puntaje", rango_in=None, formula=None, - rango_out=(0, 1), sleep=0, **kwargs): + def __init__(self, name="score", range_in=None, formula=None, + range_out=(0, 1), sleep=0, **kwargs): """ Clase Base para los puntajes - :param nombre: nombre del puntaje - :type nombre: str + :param name: name del puntaje + :type name: str :param rango: range de valores entre los que variará el puntaje :type rango: tuple :param normalizar: indica si se debe normalize, es decir, hacer que los valores varien entre 0 y 1 :type normalizar: bool - :param ajuste: factor de ajuste o ponderacion del puntaje + :param ajuste: factor de adjust o ponderacion del puntaje :type ajuste: float :param formula: :type formula: @@ -96,27 +96,27 @@ def __init__(self, nombre="puntaje", rango_in=None, formula=None, :param max: valor maximo del range :param min: valor minimo del range """ - self.nombre = nombre - self.rango_in = rango_in + self.name = name + self.range_in = range_in self.formula = formula - self.rango_out = rango_out + self.range_out = range_out self.sleep = sleep @property - def normalizar(self): + def normalize(self): return True @property def max(self): - return self.rango_out[1] + return self.range_out[1] @property def min(self): - return self.rango_out[0] + return self.range_out[0] - def ajuste(self): - if self.rango_out != (0, 1): - return functions.parameterize((0, 1), self.rango_out, [self.nombre]) + def adjust(self): + if self.range_out != (0, 1): + return functions.parameterize((0, 1), self.range_out, [self.name]) else: return lambda x: x @@ -128,18 +128,18 @@ def wrap(img): return img return wrap - def vacio(self, img): - """ Metodo comun para todos los puntajes. Agrega una banda a cada - imagen con el nombre del puntaje y ceros en todos sus pixeles + def empty(self, img): + """ Metodo comun para todos los puntajes. Agrega una band a cada + imagen con el name del puntaje y ceros en todos sus pixeles """ - i = ee.Image.constant(0).select([0], [self.nombre]).toFloat() + i = ee.Image.constant(0).select([0], [self.name]).toFloat() return img.addBands(i) -class PnubeEs(Puntaje): +class CloudScene(Score): def __init__(self, **kwargs): - """ Puntaje para el porcentaje de nubes de la escena completa. La banda - resultante de cualquiera de los metodos tendrá como nombre 'pnube_es' + """ Score para el porcentaje de nubes de la escena completa. La band + resultante de cualquiera de los metodos tendrá como name 'pnube_es' :param a: valor **a** de la funcion EXPONENCIAL :type a: float @@ -149,48 +149,48 @@ def __init__(self, **kwargs): independientemente del range :type normalizar: bool """ - super(PnubeEs, self).__init__(**kwargs) + super(CloudScene, self).__init__(**kwargs) # self.normalize = normalize # heredado - # self.ajuste = ajuste # heredado - self.rango_in = (0, 100) - self.nombre = kwargs.get("nombre", "pnube_es") + # self.adjust = adjust # heredado + self.range_in = (0, 100) + self.name = kwargs.get("name", "score-cld-esc") - self.formula = Expression.Exponential(rango=self.rango_in, - normalizar=self.normalizar, + self.formula = Expression.Exponential(rango=self.range_in, + normalizar=self.normalize, **kwargs) def map(self, col, **kwargs): if col.nubesFld: - # fmap = Expression.adjust(self.nombre, self.ajuste) - fmap = self.ajuste() - return self.formula.map(self.nombre, + # fmap = Expression.adjust(self.name, self.adjust) + fmap = self.adjust() + return self.formula.map(self.name, prop=col.nubesFld, map=fmap, **kwargs) else: - return self.vacio + return self.empty -class Pdist(Puntaje): +class CloudDist(Score): kernels = {"euclidean": ee.Kernel.euclidean, "manhattan": ee.Kernel.manhattan, "chebyshev": ee.Kernel.chebyshev } - def __init__(self, dmax=600, dmin=0, unidad="meters", **kwargs): - """ Puntaje para la 'distancia a la mascara'. La banda - resultante de cualquiera de los metodos tendrá como nombre 'pdist' + def __init__(self, dmax=600, dmin=0, unit="meters", **kwargs): + """ Score para la 'distancia a la mascara'. La band + resultante de cualquiera de los metodos tendrá como name 'pdist' - :param bandmask: Nombre de la banda enmascarada que se usara para el + :param bandmask: Nombre de la band enmascarada que se usara para el process :type bandmask: str :param kernel: Kernel que se usara. Opciones: euclidean, manhattan, chebyshev :type kernel: str - :param unidad: Unidad que se usara con el kernel. Opciones: meters, + :param unit: Unidad que se usara con el kernel. Opciones: meters, pixels - :type unidad: str + :type unit: str :param dmax: distancia maxima para la cual se calculara el puntaje. Si el pixel está mas lejos de la mascar que este valor, el puntaje toma valor 1. @@ -198,13 +198,13 @@ def __init__(self, dmax=600, dmin=0, unidad="meters", **kwargs): :param dmin: distancia minima para la cual se calculara el puntaje :type dmin: int """ - super(Pdist, self).__init__(**kwargs) + super(CloudDist, self).__init__(**kwargs) self.kernel = kwargs.get("kernel", "euclidean") - self.unidad = unidad + self.unit = unit self.dmax = dmax self.dmin = dmin - self.nombre = kwargs.get("nombre", "pdist") - self.rango_in = (dmin, dmax) + self.name = kwargs.get("name", "score-cld-dist") + self.range_in = (dmin, dmax) self.sleep = kwargs.get("sleep", 10) # GEE @@ -217,8 +217,8 @@ def dminEE(self): return ee.Image.constant(self.dmin) def kernelEE(self): - fkernel = Pdist.kernels[self.kernel] - return fkernel(radius=self.dmax, units=self.unidad) + fkernel = CloudDist.kernels[self.kernel] + return fkernel(radius=self.dmax, units=self.unit) def map(self, col, **kwargs): """ @@ -228,13 +228,13 @@ def map(self, col, **kwargs): :param kwargs: :return: """ - nombre = self.nombre + nombre = self.name # bandmask = self.bandmask bandmask = col.bandmask kernelEE = self.kernelEE() dmaxEE = self.dmaxEE dminEE = self.dminEE - ajuste = self.ajuste() + ajuste = self.adjust() def wrap(img): """ calcula el puntaje de distancia a la nube. @@ -243,7 +243,7 @@ def wrap(img): Propósito: para usar en la función map() de GEE Objetivo: - :return: la propia imagen con una banda agregada llamada 'pdist' + :return: la propia imagen con una band agregada llamada 'pdist' :rtype: ee.Image """ # Selecciono los pixeles con valor distinto de cero @@ -320,8 +320,8 @@ def mask_kernel(self, img): return img.updateMask(buff) -class Pdoy(Puntaje): - """ Puntaje para el "Day Of Year" (doy). Toma una fecha central y aplica +class Doy(Score): + """ Score para el "Day Of Year" (doy). Toma una fecha central y aplica una funcion gaussiana :Opcionales: @@ -341,174 +341,175 @@ class Pdoy(Puntaje): :type formula: Expression """ - def __init__(self, factor=-0.5, formula=Expression.Normal, - temporada=season.Season.Growing_South(), + def __init__(self, ratio=-0.5, formula=Expression.Normal, + season=season.Season.Growing_South(), **kwargs): - super(Pdoy, self).__init__(**kwargs) + super(Doy, self).__init__(**kwargs) # PARAMETROS - self.mes_doy = temporada.doy_month - self.dia_doy = temporada.doy_day + self.doy_month = season.doy_month + self.doy_day = season.doy_day - self.mes_ini = temporada.ini_month - self.dia_ini = temporada.ini_day + self.ini_month = season.ini_month + self.ini_day = season.ini_day # FACTOR DE AGUSADO DE LA CURVA GAUSSIANA - self.factor = float(factor) + self.ratio = float(ratio) # FORMULA QUE SE USARA PARA EL CALCULO self.exp = formula - self.nombre = kwargs.get("nombre", "pdoy") + self.name = kwargs.get("name", "score-doy") # DOY - def doy(self, anio): + def doy(self, year): """ Dia mas representativo del año (de la season) - :param anio: Año - :type anio: int + :param year: Año + :type year: int :return: el dia mas representativo de la season :rtype: ee.Date """ - d = "{}-{}-{}".format(anio, self.mes_doy, self.dia_doy) + d = "{}-{}-{}".format(year, self.doy_month, self.doy_day) return ee.Date(d) - def inicial(self, anio): + def ini_date(self, year): """ - :return: fecha inicial + :return: fecha ini_date :rtype: ee.Date """ - d = "{}-{}-{}".format(anio-1, self.mes_ini, self.dia_ini) + d = "{}-{}-{}".format(year - 1, self.ini_month, self.ini_day) return ee.Date(d) - def final(self, anio): + def end_date(self, year): """ :return: fecha final :rtype: ee.Date """ - dif = self.doy(anio).difference(self.inicial(anio), "day") - return self.doy(anio).advance(dif, "day") + dif = self.doy(year).difference(self.ini_date(year), "day") + return self.doy(year).advance(dif, "day") - def rango_doy(self, anio): + def doy_range(self, year): """ :return: Cantidad de dias desde el inicio al final :rtype: ee.Number """ - return self.final(anio).difference(self.inicial(anio), "day") + return self.end_date(year).difference(self.ini_date(year), "day") - def secuencia(self, anio): - return ee.List.sequence(1, self.rango_doy(anio).add(1)) + def sequence(self, year): + return ee.List.sequence(1, self.doy_range(year).add(1)) # CANT DE DIAS DEL AÑO ANTERIOR - def ult_dia(self, anio): - return ee.Date.fromYMD(ee.Number(anio - 1), 12, 31).getRelative( + def last_day(self, year): + return ee.Date.fromYMD(ee.Number(year - 1), 12, 31).getRelative( "day", "year") - def media(self, anio): + def mean(self, year): """ :return: Valor de la mean en un objeto de Earth Engine :rtype: ee.Number """ - return ee.Number(self.secuencia(anio).reduce(ee.Reducer.mean())) + return ee.Number(self.sequence(year).reduce(ee.Reducer.mean())) - def std(self, anio): + def std(self, year): """ :return: Valor de la mean en un objeto de Earth Engine :rtype: ee.Number """ - return ee.Number(self.secuencia(anio).reduce(ee.Reducer.stdDev())) + return ee.Number(self.sequence(year).reduce(ee.Reducer.stdDev())) - def get_doy(self, fecha, anio): + def get_doy(self, date, year): """ Obtener el dia del año al que pertenece una imagen - :param fecha: fecha para la cual se quiere calcular el dia al cual + :param date: date para la cual se quiere calcular el dia al cual pertence segun el objeto creado - :type fecha: ee.Date - :param anio: año (season) a la cual pertenece la imagen - :return: el dia del año al que pretenece la imagen segun el objeto actual + :type date: ee.Date + :param year: año (season) a la cual pertenece la imagen + :return: el dia del año al que pretenece la imagen segun el objeto + actual :rtype: int """ - ini = self.inicial(anio) - return fecha.difference(ini, "day") + ini = self.ini_date(year) + return date.difference(ini, "day") # VARIABLES DE EE - @property - def castigoEE(self): - return ee.Number(self.castigo) + # @property + # def castigoEE(self): + # return ee.Number(self.castigo) - def anioEE(self, anio): - return ee.Number(anio) + def ee_year(self, year): + return ee.Number(year) - def map(self, anio, **kwargs): - media = execli(self.media(anio).getInfo)() - std = execli(self.std(anio).getInfo)() - ran = execli(self.rango_doy(anio).getInfo)() + def map(self, year, **kwargs): + media = execli(self.mean(year).getInfo)() + std = execli(self.std(year).getInfo)() + ran = execli(self.doy_range(year).getInfo)() self.rango_in = (1, ran) # exp = Expression.Normal(mean=mean, std=std) expr = self.exp(media=media, std=std, - rango=self.rango_in, normalizar=self.normalizar, **kwargs) + rango=self.rango_in, normalizar=self.normalize, **kwargs) def transform(prop): date = ee.Date(prop) - pos = self.get_doy(date, anio) + pos = self.get_doy(date, year) return pos - return expr.map(self.nombre, prop="system:time_start", eval=transform, - map=self.ajuste(), **kwargs) + return expr.map(self.name, prop="system:time_start", eval=transform, + map=self.adjust(), **kwargs) -class Pop(Puntaje): - def __init__(self, rango_in=(100, 300), formula=Expression.Exponential, +class AtmosOpacity(Score): + def __init__(self, range_in=(100, 300), formula=Expression.Exponential, **kwargs): - """ Puntaje por opacidad de la atmosfera + """ Score por opacidad de la atmosfera :param rango: Rango de valores entre los que se calculara el puntaje :type rango: tuple - :param formula: Formula de distribucion que se usara. Debe ser un + :param formula: Formula de distribution que se usara. Debe ser un unbounded object :type formula: Expression :Propiedades estaticas: :param expr: Objeto expression, con todas sus propiedades """ - super(Pop, self).__init__(**kwargs) - self.rango_in = rango_in + super(AtmosOpacity, self).__init__(**kwargs) + self.range_in = range_in self.formula = formula - self.nombre = kwargs.get("nombre", "pop") + self.name = kwargs.get("name", "score-atm-op") @property def expr(self): - expresion = self.formula(rango=self.rango_in) + expresion = self.formula(rango=self.range_in) return expresion def map(self, col, **kwargs): if col.ATM_OP: - return self.expr.map(name=self.nombre, + return self.expr.map(name=self.name, band=col.ATM_OP, - map=self.ajuste(), + map=self.adjust(), **kwargs) else: - return self.vacio + return self.empty -class Pmascpor(Puntaje): - """ Puntaje *porcentaje de mascara* +class MaskPercent(Score): + """ Score *porcentaje de mascara* :ARGUMENTOS: - :param geom: geometría sobre la cual se va a calcular el indice + :param geom: geometría sobre la cual se va a calcular el index :type geom: ee.Feature - :param banda: banda de la imagen que contiene los pixeles enmascarados que + :param banda: band de la imagen que contiene los pixeles enmascarados que se van a contar :type banda: str """ - def __init__(self, banda=None, maxPixels=1e13, **kwargs): - super(Pmascpor, self).__init__(**kwargs) - self.banda = banda + def __init__(self, band=None, maxPixels=1e13, **kwargs): + super(MaskPercent, self).__init__(**kwargs) + self.band = band self.maxPixels = maxPixels - self.nombre = kwargs.get("nombre", "pmascpor") + self.name = kwargs.get("name", "score-maskper") self.sleep = kwargs.get("sleep", 30) # TODO: ver param geom, cambiar por el área de la imagen @@ -516,13 +517,13 @@ def map(self, col, geom=None, **kwargs): """ Calcula el puntaje para porcentaje de pixeles enmascarados. (Para usar en la función *map* de GEE) - :returns: la propia imagen con una banda agregada llamada 'pnube' + :returns: la propia imagen con una band agregada llamada 'pnube' (0 a 1) y una nueva propiedad llamada 'mascpor' con este valor """ scale = col.scale - nombre = self.nombre - banda = self.banda if self.banda else col.bandmask - ajuste = self.ajuste() + nombre = self.name + banda = self.band if self.band else col.bandmask + ajuste = self.adjust() if banda: def wrap(img): @@ -559,29 +560,29 @@ def wrap(img): return ajuste(img.addBands(imgpor).updateMask(ceros).set(nombre, numpor)) else: - wrap = self.vacio + wrap = self.empty return wrap -class Psat(Puntaje): - """ Puntaje según el satelite +class Satellite(Score): + """ Score según el satelite - :param sat: nombre del satelite + :param sat: name del satelite :type sat: str :param anio: año de analisis :type anio: int :METODOS: - :map(col, year, nombre): funcion que mapea en una coleccion el puntaje + :map(col, year, name): funcion que mapea en una coleccion el puntaje del satelite segun la funcion de prioridades creada en -objetos- del modulo CIEFAP """ def __init__(self, rate=0.05, **kwargs): - super(Psat, self).__init__(**kwargs) - self.nombre = kwargs.get("nombre", "psat") + super(Satellite, self).__init__(**kwargs) + self.name = kwargs.get("name", "score-sat") self.rate = rate ''' @staticmethod @@ -593,9 +594,9 @@ def map(self, col, **kwargs): """ Funcion que mapea en una coleccion el puntaje del satelite segun la funcion de prioridades creada en -objetos- del modulo CIEFAP """ - nombre = self.nombre + nombre = self.name theid = col.ID - ajuste = self.ajuste() + ajuste = self.adjust() def wrap(img): # CALCULA EL PUNTAJE: @@ -632,19 +633,19 @@ def wrap(img): return wrap -class Poutlier(Puntaje): +class Outliers(Score): """ Objeto que se crear para la detección de valores outliers en - la banda especificada + la band especificada :Obligatorios: :param col: colección de la cual se extraera la serie de datos :type col: - :param banda: nombre de la banda que se usará + :param banda: name de la band que se usará :type banda: str :Opcionales: - :param proceso: nombre del process que se usará ("mean" / "mediana") + :param proceso: name del process que se usará ("mean" / "mediana") :type proceso: str :param dist: distancia al valor medio que se usará. Por ejemplo, si es 1, se considerará outlier si cae por fuera de +-1 desvío de la mean @@ -654,31 +655,31 @@ class Poutlier(Puntaje): :param max: puntaje máximo que se le asignará a un valor que no sea outlier :type max: int - :param distribucion: Funcion de distribucion que se usará. Puede ser + :param distribucion: Funcion de distribution que se usará. Puede ser 'discreta' o 'gauss' :type distribucion: str """ - def __init__(self, bandas, proceso="mean", **kwargs): + def __init__(self, bands, process="mean", **kwargs): """ - :param bandas: Lista o tuple de bandas. Las bandas deben estar en la + :param bands: Lista o tuple de bands_ee. Las bands_ee deben estar en la imagen. - :type bandas: tuple - :param proceso: Opciones: 'mean' o 'mediana' - :type proceso: str + :type bands: tuple + :param process: Opciones: 'mean' o 'mediana' + :type process: str """ - super(Poutlier, self).__init__(**kwargs) - - # TODO: el param bandas esta mas relacionado a la coleccion... pensarlo mejor.. - # if not (isinstance(bandas, tuple) or isinstance(bandas, list)): - # raise ValueError("El parametro 'bandas' debe ser una tupla o lista") - self.bands = bandas - self.bandas = ee.List(bandas) - - # self.col = col.select(self.bandas) - self.proceso = proceso - self.distribucion = kwargs.get("distribucion", "discreta") - # TODO: distribucion + super(Outliers, self).__init__(**kwargs) + + # TODO: el param bands esta mas relacionado a la coleccion... pensarlo mejor.. + # if not (isinstance(bands, tuple) or isinstance(bands, list)): + # raise ValueError("El parametro 'bands' debe ser una tupla o lista") + self.bands = bands + self.bands_ee = ee.List(bands) + + # self.col = col.select(self.bands) + self.process = process + self.distribution = kwargs.get("distribution", "discreta") + # TODO: distribution self.dist = kwargs.get("dist", 1) ''' self.minVal = kwargs.get("min", 0) @@ -686,19 +687,19 @@ def __init__(self, bandas, proceso="mean", **kwargs): self.rango_final = (self.minVal, self.maxVal) self.rango_orig = (0, 1) ''' - self.rango_in = (0, 1) - # self.lenbandas = float(len(bandas)) - # self.incremento = float(1/self.lenbandas) - self.nombre = kwargs.get("nombre", "poutlier") + self.range_in = (0, 1) + # self.bandslength = float(len(bands)) + # self.increment = float(1/self.bandslength) + self.name = kwargs.get("name", "score-outlier") self.sleep = kwargs.get("sleep", 10) @property - def lenbandas(self): + def bandslength(self): return float(len(self.bands)) @property - def incremento(self): - return float(1/self.lenbandas) + def increment(self): + return float(1 / self.bandslength) def map(self, colEE, **kwargs): """ Mapea el valor outlier de modo discreto @@ -708,19 +709,19 @@ def map(self, colEE, **kwargs): :param colEE: coleccion de EE que se quiere procesar :type colEE: ee.ImageCollection - :param nombre: nombre que se le dará a la banda + :param nombre: name que se le dará a la band :type nombre: str - :return: una imagen (ee.Image) con una banda cuyo nombre tiene la + :return: una imagen (ee.Image) con una band cuyo name tiene la siguiente estructura: "pout_banda" ej: "pout_ndvi" :rtype: ee.Image """ - nombre = self.nombre - bandas = self.bandas - rango_orig = self.rango_in - rango_fin = self.rango_out - incremento = self.incremento + nombre = self.name + bandas = self.bands_ee + rango_orig = self.range_in + rango_fin = self.range_out + incremento = self.increment col = colEE.select(bandas) - proceso = self.proceso + proceso = self.process def masktemp(img): m = img.select([0]).neq(0) @@ -771,24 +772,24 @@ def wrap(img): return wrap -class Pindice(Puntaje): - def __init__(self, indice="ndvi", **kwargs): - super(Pindice, self).__init__(**kwargs) - self.indice = indice - self.rango_in = kwargs.get("rango_in", (-1, 1)) - self.nombre = kwargs.get("nombre", "pindice") +class Index(Score): + def __init__(self, index="ndvi", **kwargs): + super(Index, self).__init__(**kwargs) + self.index = index + self.range_in = kwargs.get("range_in", (-1, 1)) + self.name = kwargs.get("name", "score-index") def map(self, **kwargs): - ajuste = self.ajuste() + ajuste = self.adjust() def wrap(img): - ind = img.select([self.indice]) - p = functions.parameterize(self.rango_in, self.rango_out)(ind) - p = p.select([0], [self.nombre]) + ind = img.select([self.index]) + p = functions.parameterize(self.range_in, self.range_out)(ind) + p = p.select([0], [self.name]) return ajuste(img.addBands(p)) return wrap -class Pmulti(Puntaje): +class MultiYear(Score): """Calcula el puntaje para cada imagen cuando creo una imagen BAP a partir de imagenes de varios años @@ -803,22 +804,22 @@ class Pmulti(Puntaje): segun la funcion de prioridades creada en -objetos- del modulo CIEFAP :METODO ESTATICO: - :mapnull: agrega la banda *pmulti* con valor 0 (cero) + :mapnull: agrega la band *pmulti* con valor 0 (cero) """ - def __init__(self, anio_central, temporada, factor=0.05, **kwargs): - super(Pmulti, self).__init__(**kwargs) - self.anio_central = anio_central - self.temporada = temporada - self.factor = factor - self.nombre = "pmulti" + def __init__(self, main_year, season, ratio=0.05, **kwargs): + super(MultiYear, self).__init__(**kwargs) + self.main_year = main_year + self.season = season + self.ratio = ratio + self.name = kwargs.get("name", "score-multi") def map(self, **kwargs): - """ Funcion para agregar una banda pmulti a la imagen con el puntaje + """ Funcion para agregar una band pmulti a la imagen con el puntaje según la distancia al año central """ - a = self.anio_central - ajuste = self.ajuste() + a = self.main_year + ajuste = self.adjust() def wrap(img): @@ -828,17 +829,17 @@ def wrap(img): # FECHA DE LA IMAGEN imgdate = ee.Date(img.date()) - diff = ee.Number(self.temporada.year_diff_ee(imgdate, a)) + diff = ee.Number(self.season.year_diff_ee(imgdate, a)) - pje1 = ee.Number(diff).multiply(ee.Number(self.factor)) + pje1 = ee.Number(diff).multiply(ee.Number(self.ratio)) pje = ee.Number(1).subtract(pje1) - imgpje = ee.Image.constant(pje).select([0], [self.nombre]) + imgpje = ee.Image.constant(pje).select([0], [self.name]) # return funciones.pass_date(img, img.addBands(imgpje)) return ajuste(img.addBands(imgpje).updateMask(ceros)) return wrap if __name__ == "__main__": - psat = Psat() - print psat.normalizar, psat.rango_out \ No newline at end of file + psat = Satellite() + print psat.normalize, psat.range_out \ No newline at end of file diff --git a/geebap/season.py b/geebap/season.py index 8cc06d1..ae92a1c 100644 --- a/geebap/season.py +++ b/geebap/season.py @@ -56,7 +56,7 @@ def check_valid_date(date): @staticmethod def check_between(date, ini, end, raiseE=True): - """ Verifica que la fecha dada este entre la inicial y la final + """ Verifica que la fecha dada este entre la ini_date y la final :param date: :param ini: diff --git a/geebap/sites.py b/geebap/sites.py index 026ba48..27de7be 100644 --- a/geebap/sites.py +++ b/geebap/sites.py @@ -8,7 +8,8 @@ class Site(object): """ Site Class to store sites related to fusion tables """ - def __init__(self, name, id_ft, id_fld, name_fld=None, n_feat=0): + def __init__(self, name=None, id_ft=None, id_fld=None, name_fld=None, + n_feat=0): """ :param name: name of the site :type name: str @@ -90,9 +91,9 @@ def from_gsheet(url, sheet, name=None, id_ft=None, id_fld=None, name_fld=None): :param url: :param sheet: - :param name: - :param id_ft: - :param id_fld: + :param name: name of field that holds the name of the site + :param id_ft: name of field that holds the id of the fusion table + :param id_fld: name of field that holds the ID of the site :param name_fld: """ content = requests.get(url) @@ -103,9 +104,11 @@ def from_gsheet(url, sheet, name=None, id_ft=None, id_fld=None, name_fld=None): for n, row in enumerate(sheet): if n == 0: continue if row[name] == "": continue - params = [row[name], row[id_ft], row[id_fld]] - params = params.append(row[name_fld]) if name_fld else params - site = (row[name], Site(*params)) + # params = [row[name], row[id_ft], row[id_fld]] + # print params + # params = params.append(row[name_fld]) if name_fld else params + site = (row[name], Site(name=row[name], id_ft=row[id_ft], + id_fld=row[id_fld], name_fld=row[name_fld])) sites.append(site) return dict(sites) diff --git a/geebap/tests/test_bap.py b/geebap/tests/test_bap.py index 7d1a32e..255072d 100644 --- a/geebap/tests/test_bap.py +++ b/geebap/tests/test_bap.py @@ -20,12 +20,12 @@ def setUp(self): self.coleccion = satcol.ColGroup.Landsat() # SCORES - self.psat = scores.Psat() - self.pop = scores.Pop() - self.pmascpor = scores.Pmascpor() - self.pindice = scores.Pindice() - self.pout = scores.Poutlier(("ndvi",)) - self.pdoy = scores.Pdoy() + self.psat = scores.Satellite() + self.pop = scores.AtmosOpacity() + self.pmascpor = scores.MaskPercent() + self.pindice = scores.Index() + self.pout = scores.Outliers(("ndvi",)) + self.pdoy = scores.Doy() # SITES self.sitio = ee.Geometry.Polygon( @@ -36,10 +36,11 @@ def setUp(self): self.centroid = self.sitio.centroid() def test_bap2016_0(self): + pmulti = scores.MultiYear(2016, self.temporada) objbap = bap.Bap(year=2016, colgroup=self.coleccion, season=self.temporada, scores=(self.pindice, self.pmascpor, self.psat, - self.pout, self.pop, self.pdoy), + self.pout, self.pop, self.pdoy, pmulti), masks=(self.nubes,), filters=(self.filtro,)) sitio = self.sitio @@ -61,5 +62,5 @@ def test_bap2016_0(self): self.assertIsInstance(value, dict) # self.assertEqual(value["BLUE"], 0.008500000461935997) - # self.assertEqual(value["bandID"], 12.0) + # self.assertEqual(value["col_id"], 12.0) # self.assertEqual(value["ndvi"], 0.872759222984314) \ No newline at end of file diff --git a/setup.py b/setup.py index 3be3125..624cf86 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ def read(fname): # the setup setup( name='geebap', - version="0.1", + version=__version__, description='Generate a "Best Available Pixel (BAP)" composite in Google '\ 'Earth Engine (GEE)', # long_description=read('README'),