<jupyter_start><jupyter_text>BEST AVAILABLE PIXEL COMPOSITE (BAP) *in Google Earth Engine Python API*based on *Pixel-Based Image Compositing for Large-Area DenseTime Series Applications and Science (White, 2014)*https://goo.gl/Fi8fCY* **Author**: <NAME>* **email**: <EMAIL>* **GitHub**: github.com/fitoprincipe* **Repository GeeBap**: github.com/fitoprincipe/geebap  Install Packages<jupyter_code>import sys
!{sys.executable} -m pip install --upgrade geebap<jupyter_output><empty_output><jupyter_text>Make imports<jupyter_code># Import Earth Engine and initialize
import ee
ee.Initialize()

# Import packages
import geebap
from geebap import bap, season, filters, masks, \
                   scores, satcol, functions
from geetools import tools
import pprint

print('version', geebap.__version__)<jupyter_output>('version', '0.0.9')<jupyter_text>SeasonThis object holds information of the growing season (start, end and doy *best day of year*). You can make your own, or use 2 pre-made: `Growing_South` and `Growing_North`. This object does not hold any year, just day and month. For example, the pre-made `Growing_South` starts on November 15 (11-15) and ends on March 15 (03-15). But it has a method to add a year, see the example in the code:<jupyter_code>a_season = season.Season.Growing_South()
ini, end = a_season.add_year(2000)

print ini, end<jupyter_output><empty_output><jupyter_text>Note that when the season covers two years, start date is in the previous year.  CollectionsThe main method to create a BAP uses a `ColGroup` object, that is basically a group of `Collection` objects. You can see all groups:<jupyter_code>satcol.ColGroup.options()<jupyter_output><empty_output><jupyter_text>You could also make your own `ColGroup`, but you have to keep in mind that it is composed by `satcol.Collection` objects.As the process is made to combine pixels from all collections, `Collection` object renames the bands of each collection to match across all, resulting in the following names: BLUE, GREEN, RED, NIR, SWIR, SWIR2, ATM_OP. Also, each collection has methods ready to map a vegetation index: `ndvi`, `evi` and `nbr`.   MasksThere is *(by now)* one mask you can include in the process: clouds<jupyter_code>cld_mask = masks.Clouds()<jupyter_output><empty_output><jupyter_text>FiltersThere are *(by now)* two filters you can use in the process:**cloud percentage**: `filters.CloudsPercent`**masked pixel percentage**: `filters.MaskPercent`. This filter can be used **only** if maskpercent score is included in the process.<jupyter_code>filt_cld = filters.CloudsPercent()
filt_mask = filters.MaskPercent()<jupyter_output><empty_output><jupyter_text>ScoresThis is what makes the difference. Every score has its own parameters, but all share two main params:**range_out**: the range of values the score will be, by default it is (0, 1)**sleep**: as the creaton of a BAP composite is a 'concatenated' process, it can make more requests that are allowed, so if you set this parameter, the process will wait those seconds until the next computing.  White's scores  DOY (best day of the year)Basically, pixels from images closer to that date will have higher scoreIt takes 2 params:**season**: You can use the same as the one for the process, or not. Each `Season` object has its own *doy*. By default it is `Season.Growing_South`**formula**: distribution ecuation. There are two (by now) options: `Normal` (https://en.wikipedia.org/wiki/Normal_distribution) or `Exponential` (https://en.wikipedia.org/wiki/Exponential_distribution). Default is `Normal`<jupyter_code>doy = scores.Doy()<jupyter_output><empty_output><jupyter_text>SatelliteIt uses a list of available satellite for each year that you can check:<jupyter_code># List of satellites for 2000
season.SeasonPriority.relation[2000]<jupyter_output><empty_output><jupyter_text>the score has one main param:**rate**: how much score will decrease for each satellite. For example, for 2000, if rate is 0.05 (default value):* 'LANDSAT/LE07/C01/T1_SR' --> 1* 'LANDSAT/LE7_L1T_TOA_FMASK' --> 0.95* 'LANDSAT/LT05/C01/T1_SR' --> 0.90* 'LANDSAT/LT5_L1T_TOA_FMASK' --> 0.85*NOTE: may be the correct name would be 'ratio', so I may change it in the future*<jupyter_code>sat = scores.Satellite()<jupyter_output><empty_output><jupyter_text>Atmospheric OpacityIt uses the atmospheric opacity band computed by Surface Reflectance, so only SR collections will have this score. If the process uses a non-SR collection, like TOA, the this score will be zero.<jupyter_code>atm_op = scores.AtmosOpacity()<jupyter_output><empty_output><jupyter_text>Distance to maskThis assigns a score regarding the distance of the pixel to the closest masked pixel. As the only mask is for clouds, it could be considered 'distance to cloud'. It has 3 main params:**unit**: unit to measure distance. Defaults to 'meters'**dmax**: max distance. Pixel further than this distance will have score 1. Defaults to 600**dmin**: min distance. Defaults to 0 (next pixel from the maks will have score 0).<jupyter_code>dist = scores.CloudDist()<jupyter_output><empty_output><jupyter_text>Custom Scores *(not White's)*  OutliersIt computes an statistics over the whole collection (in the season) and assigns score regarding the *distance* of each pixel value to that statistic. It has 3 main parameters:**bands**: a list of bands to include in the process. The process splits the score in the number of given bands. For example, if 4 bands are given, the max score for each band will be 0.25**process**: one of 'mean' or 'median'. Defaults to 'mean'**dist**: distance from 'mean' or 'median'. Defaults to 0.7*NOTE: bands must be in the image, so if you use a vegetation index, be sure to include it in the process*<jupyter_code>out = scores.Outliers(("ndvi",))<jupyter_output><empty_output><jupyter_text>Mask percentageIt computes the precentage of masked pixels in the image (not the whole scene). It has one main parameter:**band**: the band that holds the mask.<jupyter_code>maskper = scores.MaskPercent()<jupyter_output><empty_output><jupyter_text>Vegetation IndexThis scores is based on the absolute value of the given index, parametrized to `range_out`. The only parameter is **index**: the name of it (*ndvi*, *evi* or *nbr*). Defaults to *ndvi*.<jupyter_code>ind = scores.Index("ndvi")<jupyter_output><empty_output><jupyter_text>Multiple years (seasons)If you want to use images from a range of seasons, and not just only one, this scores prioritizes the main season. Take in count that a season may hold 2 years, but the main is the least (see `Season`). It has 3 main params:**main_year**: this is the central year. Images from this year (season) will have score 1**season**: a `Season` object.**ratio**: amount of score that will decrease as it goes further to the main year. Defaults to 0.05. It is similar to *rate* parameter in `Satellite`.<jupyter_code># Will not use it in the test
# multi = scores.MultiYear()<jupyter_output><empty_output><jupyter_text>Making the composite (BAP)Next step is to create a `Bap` object. It has the following parameters:**year**: The main year. Remember that a season can have 2 years.**range**: for multiyear composites you can specify a 'range' as a tuple: (years before, years after). Defaults to (0, 0).For example, if `range=(1, 1)` and `year=2000`, will compute 1999, 2000 and 2001.**colgroup**: `ColGroup` object. If `None` it will use the list computed by `SeasonPriority`. Defaults to `None`.**season**: a `Season` object**scores**: a list of `Score` objects**masks**: a list of `Mask` objects**filters**: a list of `Filter` objects**fmap**: custom function to apply before computing scores. At this point bands have new names (NIR, SWIR, etc) and vegetation index is computed.<jupyter_code>bap = bap.Bap(year=2010, range=(0, 0),
              season=a_season,
              masks=(cld_mask,),
              scores=(doy, sat, atm_op, dist, out, maskper, ind),
              filters=(filt_cld, filt_mask))<jupyter_output><empty_output><jupyter_text>Define a site<jupyter_code>site = ee.Geometry.Polygon([[-71,-42],
                            [-71,-43],
                            [-72,-43],
                            [-72,-42]])<jupyter_output><empty_output><jupyter_text>Finally, compute the composite`Bap` object has a method named `bestpixel` that creates one image out of the pixels with higher score in the collection (which includes all collections given). It has the following parameters:**site**: The site where the composite will be computed**indices**: a list of vegetation indices. Defaults to `None`**name**: name for the band that holds the final score. Defaults to *score***bands**: a list of bands that will be on the image (in case you don't need all). Defaults to `None` which means *include all bands***normalize**: normalize the final score to be between 0 and 1. Defaults to `True`**bbox**: distance of the buffer around the site. Defaults to 0.**force**: if there are no images for the specified parameters, and this is set to `True`, an empty image will be created. Defaults to `True`This method return a `namedtuple`, so `.image` will be the composite and `.col` will be the collection<jupyter_code>composite = bap.bestpixel(site=site, indices=("ndvi",))<jupyter_output><empty_output><jupyter_text>Get the composite from the results<jupyter_code>image = composite.image<jupyter_output><empty_output><jupyter_text>Watch the resulting composite*it may take a while..*<jupyter_code>from IPython.display import Image
url = image.getThumbUrl({'min':0, 'max':0.7, 'region':site.getInfo()['coordinates']})
Image(url=url, format='png', embed=True)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10306291390728477, 'fraction_numerical': 0.014176324503311258, 'mean_word_length': 5.308746736292428, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 86, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '20', 'dir': 'jupyter-structured-clean-dedup', 'id': '613437', 'license': 'MIT', 'n_tokens_mistral': 2988, 'n_tokens_neox': 2825, 'n_words': 1172, 'path': 'examples/best-available-pixel/best-available-pixel-composite.ipynb', 'repo_name': 'schnjaso2/ee-jupyter-contrib', 'size': '9694'}