<jupyter_start><jupyter_text>Reading in Sentinel-2 ImagesSentinel-2 is an observation mission developed by the European Space Agency to monitor the surface of the Earth [official website](http://www.esa.int/Our_Activities/Observing_the_Earth/Copernicus/Sentinel-2).Sets of images are taken of the surface where each image corresponds to a specific wavelength. These images can provide useful data for a wide variety of industries, however, the format they are stored in can prove difficult to work with. This being `JPEG 2000` (file extension `.jp2`), an image compressionformat for JPEGs that allows for improved quality and compression ratio. Why Use GeoPySparkThere are few libraries and/or applications that can work with `jp2`s and big data, which can make processing large amounts of sentinel data difficult. However, by using GeoPySpark in conjunction with the tools available in Python, we are able to read in and work with large sets of sentinel imagery.  Getting the DataBefore we can start this tutorial, we will need to get the sentinel images. All sentinel data can be found on Amazon's S3 service, and we will be downloading it straight from there.We will download three different `jp2`s that represent the same area and time in different wavelengths: Aerosol detection (443 nm), Water vapor (945 nm), and Cirrus (1375 nm). These bands are chosen because they are all in the same 60m resolution. The tiles we will be working with cover the eastern coast of Corsica taken on January 4th, 2017.For more information on the way the data is stored on S3, please see this [link](http://sentinel-pds.s3-website.eu-central-1.amazonaws.com/).<jupyter_code>!curl -o /tmp/B01.jp2 http://sentinel-s2-l1c.s3.amazonaws.com/tiles/32/T/NM/2017/1/4/0/B01.jp2
!curl -o /tmp/B09.jp2 http://sentinel-s2-l1c.s3.amazonaws.com/tiles/32/T/NM/2017/1/4/0/B09.jp2
!curl -o /tmp/B10.jp2 http://sentinel-s2-l1c.s3.amazonaws.com/tiles/32/T/NM/2017/1/4/0/B10.jp2<jupyter_output><empty_output><jupyter_text>The CodeNow that we have the files, we can begin to read them into GeoPySpark.<jupyter_code>import rasterio
import geopyspark as gps
import numpy as np

from pyspark import SparkContext
conf = gps.geopyspark_conf(master="local[*]", appName="sentinel-ingest-example")
pysc = SparkContext(conf=conf)<jupyter_output><empty_output><jupyter_text>Reading in the JPEG 2000's`rasterio`, being backed by GDAL, allows us to read in the `jp2`s. Once they are read in, we will then combine the three seperate numpy arrays into one. This combined array represents a single, multiband raster.<jupyter_code>jp2s = ["/tmp/B01.jp2", "/tmp/B09.jp2", "/tmp/B10.jp2"]
arrs = []

for jp2 in jp2s:
    with rasterio.open(jp2) as f:
        arrs.append(f.read(1))

data = np.array(arrs, dtype=arrs[0].dtype)
data<jupyter_output><empty_output><jupyter_text>Creating the RDDWith our raster data in hand, we can how begin the creation of a Python `RDD`. Please see the [core concepts](core-concepts.ipynb) guide for more information on what the following instances represent.<jupyter_code># Create an Extent instance from rasterio's bounds
extent = gps.Extent(*f.bounds)

# The EPSG code can also be obtained from the information read in via rasterio
projected_extent = gps.ProjectedExtent(extent=extent, epsg=int(f.crs.to_dict()['init'][5:]))
projected_extent<jupyter_output><empty_output><jupyter_text>You may have noticed in the above code that we did something weird to get the `CRS` from the rasterio file. This had to be done because the way rasterio formats the projection of the read in rasters is not compatible with how GeoPySpark expects the `CRS` to be in. Thus, we had to do a bit of extra work to get it into the correct state<jupyter_code># Projection information from the rasterio file
f.crs.to_dict()
# The projection information formatted to work with GeoPySpark
int(f.crs.to_dict()['init'][5:])
# We can create a Tile instance from our multiband, raster array and the nodata value from rasterio
tile = gps.Tile.from_numpy_array(numpy_array=data, no_data_value=f.nodata)
tile
# Now that we have our ProjectedExtent and Tile, we can create our RDD from them
rdd = pysc.parallelize([(projected_extent, tile)])
rdd<jupyter_output><empty_output><jupyter_text>Creating the LayerFrom the `RDD`, we can now create a `RasterLayer` using the `from_numpy_rdd` method.<jupyter_code># While there is a time component to the data, this was ignored for this tutorial and instead the focus is just
# on the spatial information. Thus, we have a LayerType of SPATIAL.
raster_layer = gps.RasterLayer.from_numpy_rdd(layer_type=gps.LayerType.SPATIAL, numpy_rdd=rdd)
raster_layer<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08224459198971942, 'fraction_numerical': 0.02291711287213536, 'mean_word_length': 5.210106382978723, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '138688', 'license': 'Apache-2.0', 'n_tokens_mistral': 1576, 'n_tokens_neox': 1476, 'n_words': 573, 'path': 'notebook-demos/reading-in-sentinel-data.ipynb', 'repo_name': 'lossyrob/geotrellis-python', 'size': '4669'}