You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sedona.apache.org by ji...@apache.org on 2023/09/30 01:06:07 UTC

[sedona] branch master updated: [DOCS] Add raster tutorial (#1034)

This is an automated email from the ASF dual-hosted git repository.

jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git


The following commit(s) were added to refs/heads/master by this push:
     new e23e98cfd [DOCS] Add raster tutorial (#1034)
e23e98cfd is described below

commit e23e98cfdaae6241adec975ca7c85e4dfddb789c
Author: Furqaanahmed Khan <46...@users.noreply.github.com>
AuthorDate: Fri Sep 29 21:05:59 2023 -0400

    [DOCS] Add raster tutorial (#1034)
---
 docs/api/sql/Raster-operators.md | 167 +++++------
 docs/image/rasterized-image.png  | Bin 0 -> 413 bytes
 docs/tutorial/raster.md          | 590 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 665 insertions(+), 92 deletions(-)

diff --git a/docs/api/sql/Raster-operators.md b/docs/api/sql/Raster-operators.md
index cffe7fc0f..4bda00305 100644
--- a/docs/api/sql/Raster-operators.md
+++ b/docs/api/sql/Raster-operators.md
@@ -863,48 +863,7 @@ Output:
 14.0, 204.0, 14.571428571428571, 11.509091348732502, 1.0, 25.0
 ```
 
-
-## Raster based operators
-
-### RS_AddBand
-
-Introduction: Adds a new band to a raster `toRaster` at a specified index `toRasterIndex`. The new band's values are copied from `fromRaster` at a specified band index `fromBand`. 
-If no `toRasterIndex` is provided, the new band is appended to the end of `toRaster`. If no `fromBand` is specified, band `1` from `fromRaster` is copied by default.
-
-!!!Note
-    IllegalArgumentException will be thrown in these cases:
-
-    - The provided Rasters, `toRaster` & `fromRaster` don't have same shape.
-    - The provided `fromBand` is not in `fromRaster`.
-    - The provided `toRasterIndex` is not in or at end of `toRaster`. 
-
-Format: 
-
-```
-RS_AddBand(toRaster: Raster, fromRaster: Raster, fromBand: Integer = 1, toRasterIndex: Integer = at_end)
-```
-
-```
-RS_AddBand(toRaster: Raster, fromRaster: Raster, fromBand: Integer = 1)
-```
-
-```
-RS_AddBand(toRaster: Raster, fromRaster: Raster)
-```
-
-Since: `v1.5.0`
-
-Spark SQL Example:
-
-```sql
-SELECT RS_AddBand(raster1, raster2, 2, 1) FROM rasters
-```
-
-Output:
-
-```
-GridCoverage2D["g...
-```
+## Raster Predicates
 
 ### RS_Contains
 
@@ -913,7 +872,7 @@ The convex hull of the raster is considered in the test.
 
 The rules for testing spatial relationship is the same as `RS_Intersects`.
 
-Format: 
+Format:
 
 `RS_Contains(raster: Raster, geom: Geometry)`
 
@@ -950,7 +909,7 @@ Rules for testing spatial relationship:
 * If both sides are in the same CRS, then perform the relationship test directly.
 * Otherwise, both sides will be transformed to WGS84 before the relationship test.
 
-Format: 
+Format:
 
 `RS_Intersects(raster: Raster, geom: Geometry)`
 
@@ -977,6 +936,79 @@ Output:
 +---------+---------+
 ```
 
+### RS_Within
+
+Introduction: Returns true if the geometry or raster on the left side is within the geometry or raster on the right side.
+The convex hull of the raster is considered in the test.
+
+The rules for testing spatial relationship is the same as `RS_Intersects`.
+
+Format: `RS_Within(raster: Raster, geom: Geometry)`
+
+Format: `RS_Within(geom: Geometry, raster: Raster)`
+
+Format: `RS_Within(raster0: Raster, raster1: Raster)`
+
+Since: `v1.5.0`
+
+Spark SQL Example:
+
+```sql
+SELECT RS_Within(RS_MakeEmptyRaster(1, 20, 20, 2, 22, 1), ST_GeomFromWKT('POLYGON ((0 0, 0 50, 100 50, 100 0, 0 0))')) rast_geom,
+    RS_Within(RS_MakeEmptyRaster(1, 20, 20, 2, 22, 1), RS_MakeEmptyRaster(1, 30, 30, 2, 22, 1)) rast_rast
+```
+
+Output:
+```
++---------+---------+
+|rast_geom|rast_rast|
++---------+---------+
+|     true|     true|
++---------+---------+
+```
+
+## Raster Based Operators
+
+### RS_AddBand
+
+Introduction: Adds a new band to a raster `toRaster` at a specified index `toRasterIndex`. The new band's values are copied from `fromRaster` at a specified band index `fromBand`. 
+If no `toRasterIndex` is provided, the new band is appended to the end of `toRaster`. If no `fromBand` is specified, band `1` from `fromRaster` is copied by default.
+
+!!!Note
+    IllegalArgumentException will be thrown in these cases:
+
+    - The provided Rasters, `toRaster` & `fromRaster` don't have same shape.
+    - The provided `fromBand` is not in `fromRaster`.
+    - The provided `toRasterIndex` is not in or at end of `toRaster`. 
+
+Format: 
+
+```
+RS_AddBand(toRaster: Raster, fromRaster: Raster, fromBand: Integer = 1, toRasterIndex: Integer = at_end)
+```
+
+```
+RS_AddBand(toRaster: Raster, fromRaster: Raster, fromBand: Integer = 1)
+```
+
+```
+RS_AddBand(toRaster: Raster, fromRaster: Raster)
+```
+
+Since: `v1.5.0`
+
+Spark SQL Example:
+
+```sql
+SELECT RS_AddBand(raster1, raster2, 2, 1) FROM rasters
+```
+
+Output:
+
+```
+GridCoverage2D["g...
+```
+
 ### RS_MetaData
 
 Introduction: Returns the metadata of the raster as an array of double. The array contains the following values:
@@ -1081,7 +1113,8 @@ RESAMPLED_RASTER AS (
 SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as rast_metadata from RESAMPLED_RASTER
 ```
 
-`Output`:
+Output:
+
 ```sql
 | 1.0   1.0   2.0   3.0   3.0   5.0|
 | 1.0   1.0   2.0   3.0   3.0   5.0|
@@ -1092,6 +1125,8 @@ SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as
 (-0.33333333333333326,0.19999999999999996,6,5,1.388888888888889,-1.24,0,0,0,1)
 ```
 
+Spark SQL Example:
+
 ```sql
  WITH INPUT_RASTER AS (
    SELECT RS_AddBandFromArray(
@@ -1104,7 +1139,8 @@ SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as
 SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as rast_metadata from RESAMPLED_RASTER
 ```
 
-`Output`:
+Output:
+
 ```sql
 |       NaN         NaN         NaN         NaN         NaN         NaN         NaN|
 |       NaN    3.050000    3.650000    4.250000    5.160000    6.690000    7.200000|
@@ -1115,6 +1151,7 @@ SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as
 (0.0, 0.0, 7.0, 5.0, 1.2, -1.4, 0.0, 0.0, 0.0, 1.0)
 ```
 
+Spark SQL Example:
 
 ```sql
 WITH INPUT_RASTER AS (
@@ -1129,7 +1166,8 @@ RESAMPLED_RASTER AS (
 SELECT RS_AsMatrix(resample_rast) as rast_matrix, RS_Metadata(resample_rast) as rast_metadata from RESAMPLED_RASTER
 ```
 
-`Output`:
+Output:
+
 ```sql
 | 1.0   1.0   2.0   3.0   3.0   5.0   5.0|
 | 1.0   1.0   2.0   3.0   3.0   5.0   5.0|
@@ -1484,38 +1522,7 @@ Output:
 +----+------------+-------+
 ```
 
-### RS_Within
-
-Introduction: Returns true if the geometry or raster on the left side is within the geometry or raster on the right side.
-The convex hull of the raster is considered in the test.
-
-The rules for testing spatial relationship is the same as `RS_Intersects`.
-
-Format: `RS_Within(raster: Raster, geom: Geometry)`
-
-Format: `RS_Within(geom: Geometry, raster: Raster)`
-
-Format: `RS_Within(raster0: Raster, raster1: Raster)`
-
-Since: `v1.5.0`
-
-Spark SQL Example:
-
-```sql
-SELECT RS_Within(RS_MakeEmptyRaster(1, 20, 20, 2, 22, 1), ST_GeomFromWKT('POLYGON ((0 0, 0 50, 100 50, 100 0, 0 0))')) rast_geom,
-    RS_Within(RS_MakeEmptyRaster(1, 20, 20, 2, 22, 1), RS_MakeEmptyRaster(1, 30, 30, 2, 22, 1)) rast_rast
-```
-
-Output:
-```
-+---------+---------+
-|rast_geom|rast_rast|
-+---------+---------+
-|     true|     true|
-+---------+---------+
-```
-
-## Raster to Map Algebra operators
+## Raster to Map Algebra Operators
 
 To bridge the gap between the raster and map algebra worlds, the following operators are provided. These operators convert a raster to a map algebra object. The map algebra object can then be used with the map algebra operators described in the next section.
 
@@ -1632,7 +1639,7 @@ Output:
 For more details and examples about `RS_MapAlgebra`, please refer to the [Map Algebra documentation](../Raster-map-algebra/).
 To learn how to write map algebra script, please refer to [Jiffle language summary](https://github.com/geosolutions-it/jai-ext/wiki/Jiffle---language-summary).
 
-## Map Algebra operators
+## Map Algebra Operators
 
 Map algebra operators work on a single band of a raster. Each band is represented as an array of doubles. The operators return an array of doubles.
 
diff --git a/docs/image/rasterized-image.png b/docs/image/rasterized-image.png
new file mode 100644
index 000000000..c87b83859
Binary files /dev/null and b/docs/image/rasterized-image.png differ
diff --git a/docs/tutorial/raster.md b/docs/tutorial/raster.md
index 0b71149a8..c515453c0 100644
--- a/docs/tutorial/raster.md
+++ b/docs/tutorial/raster.md
@@ -1,23 +1,589 @@
+!!!note
+    Sedona uses 1-based indexing for all raster functions except [map algebra function](../../api/sql/Raster-map-algebra), which uses 0-based indexing.
+
+!!!note
+    Sedona by default enforces geographic coordinates to be in longitude/latitude order.
+
 Starting from `v1.1.0`, Sedona SQL supports raster data sources and raster operators in DataFrame and SQL. Raster support is available in all Sedona language bindings including ==Scala, Java, Python and R==.
 
-## Initial setup
+This page outlines the steps to manage raster data using SedonaSQL.
+
+=== "Scala"
+
+	```scala
+	var myDataFrame = sedona.sql("YOUR_SQL")
+	myDataFrame.createOrReplaceTempView("rasterDf")
+	```
+
+=== "Java"
+
+	```java
+	Dataset<Row> myDataFrame = sedona.sql("YOUR_SQL")
+	myDataFrame.createOrReplaceTempView("rasterDf")
+	```
+
+=== "Python"
+
+	```python
+	myDataFrame = sedona.sql("YOUR_SQL")
+	myDataFrame.createOrReplaceTempView("rasterDf")
+	```
+
+Detailed SedonaSQL APIs are available here: [SedonaSQL API](../../api/sql/Overview). You can find example raster data in [Sedona GitHub repo](https://github.com/apache/sedona/blob/0eae42576c2588fe278f75cef3b17fee600eac90/spark/common/src/test/resources/raster/raster_with_no_data/test5.tiff).
+
+## Set up dependencies
+
+=== "Scala/Java"
+
+	1. Read [Sedona Maven Central coordinates](../setup/maven-coordinates.md) and add Sedona dependencies in build.sbt or pom.xml.
+	2. Add [Apache Spark core](https://mvnrepository.com/artifact/org.apache.spark/spark-core), [Apache SparkSQL](https://mvnrepository.com/artifact/org.apache.spark/spark-sql) in build.sbt or pom.xml.
+	3. Please see [SQL example project](../demo/)
+
+=== "Python"
+
+	1. Please read [Quick start](../../setup/install-python) to install Sedona Python.
+	2. This tutorial is based on [Sedona SQL Jupyter Notebook example](../jupyter-notebook). You can interact with Sedona Python Jupyter notebook immediately on Binder. Click [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/apache/sedona/HEAD?filepath=binder) to interact with Sedona Python Jupyter notebook immediately on Binder.
+
+## Create Sedona config
+
+Use the following code to create your Sedona config at the beginning. If you already have a SparkSession (usually named `spark`) created by Wherobots/AWS EMR/Databricks, please skip this step and can use `spark` directly.
+
+
+==Sedona >= 1.4.1==
+
+You can add additional Spark runtime config to the config builder. For example, `SedonaContext.builder().config("spark.sql.autoBroadcastJoinThreshold", "10485760")`
+
+=== "Scala"
+
+	```scala
+	import org.apache.sedona.spark.SedonaContext
+
+	val config = SedonaContext.builder()
+	.master("local[*]") // Delete this if run in cluster mode
+	.appName("readTestScala") // Change this to a proper name
+	.getOrCreate()
+	```
+	If you use SedonaViz together with SedonaSQL, please add the following line after `SedonaContext.builder()` to enable Sedona Kryo serializer:
+	```scala
+	.config("spark.kryo.registrator", classOf[SedonaVizKryoRegistrator].getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
+	```
+
+=== "Java"
+
+	```java
+	import org.apache.sedona.spark.SedonaContext;
+
+	SparkSession config = SedonaContext.builder()
+	.master("local[*]") // Delete this if run in cluster mode
+	.appName("readTestScala") // Change this to a proper name
+	.getOrCreate()
+	```
+	If you use SedonaViz together with SedonaSQL, please add the following line after `SedonaContext.builder()` to enable Sedona Kryo serializer:
+	```scala
+	.config("spark.kryo.registrator", SedonaVizKryoRegistrator.class.getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
+	```
+
+=== "Python"
+
+	```python
+	from sedona.spark import *
+
+	config = SedonaContext.builder() .\
+	    config('spark.jars.packages',
+	           'org.apache.sedona:sedona-spark-shaded-3.0_2.12:{{ sedona.current_version }},'
+	           'org.datasyslab:geotools-wrapper:{{ sedona.current_geotools }}'). \
+	    getOrCreate()
+	```
+    If you are using Spark versions >= 3.4, please replace the `3.0` in package name of sedona-spark-shaded with the corresponding major.minor version of Spark, such as `sedona-spark-shaded-3.4_2.12:{{ sedona.current_version }}`.
+
+==Sedona < 1.4.1==
+
+The following method has been deprecated since Sedona 1.4.1. Please use the method above to create your Sedona config.
+
+=== "Scala"
+
+	```scala
+	var sparkSession = SparkSession.builder()
+	.master("local[*]") // Delete this if run in cluster mode
+	.appName("readTestScala") // Change this to a proper name
+	// Enable Sedona custom Kryo serializer
+	.config("spark.serializer", classOf[KryoSerializer].getName) // org.apache.spark.serializer.KryoSerializer
+	.config("spark.kryo.registrator", classOf[SedonaKryoRegistrator].getName)
+	.getOrCreate() // org.apache.sedona.core.serde.SedonaKryoRegistrator
+	```
+	If you use SedonaViz together with SedonaSQL, please use the following two lines to enable Sedona Kryo serializer instead:
+	```scala
+	.config("spark.serializer", classOf[KryoSerializer].getName) // org.apache.spark.serializer.KryoSerializer
+	.config("spark.kryo.registrator", classOf[SedonaVizKryoRegistrator].getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
+	```
+
+=== "Java"
+
+	```java
+	SparkSession sparkSession = SparkSession.builder()
+	.master("local[*]") // Delete this if run in cluster mode
+	.appName("readTestScala") // Change this to a proper name
+	// Enable Sedona custom Kryo serializer
+	.config("spark.serializer", KryoSerializer.class.getName) // org.apache.spark.serializer.KryoSerializer
+	.config("spark.kryo.registrator", SedonaKryoRegistrator.class.getName)
+	.getOrCreate() // org.apache.sedona.core.serde.SedonaKryoRegistrator
+	```
+	If you use SedonaViz together with SedonaSQL, please use the following two lines to enable Sedona Kryo serializer instead:
+	```scala
+	.config("spark.serializer", KryoSerializer.class.getName) // org.apache.spark.serializer.KryoSerializer
+	.config("spark.kryo.registrator", SedonaVizKryoRegistrator.class.getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
+	```
+
+=== "Python"
+
+	```python
+	sparkSession = SparkSession. \
+	    builder. \
+	    appName('appName'). \
+	    config("spark.serializer", KryoSerializer.getName). \
+	    config("spark.kryo.registrator", SedonaKryoRegistrator.getName). \
+	    config('spark.jars.packages',
+	           'org.apache.sedona:sedona-spark-shaded-3.0_2.12:{{ sedona.current_version }},'
+	           'org.datasyslab:geotools-wrapper:{{ sedona.current_geotools }}'). \
+	    getOrCreate()
+	```
+    If you are using Spark versions >= 3.4, please replace the `3.0` in package name of sedona-spark-shaded with the corresponding major.minor version of Spark, such as `sedona-spark-shaded-3.4_2.12:{{ sedona.current_version }}`.
+
+## Initiate SedonaContext
+
+Add the following line after creating Sedona config. If you already have a SparkSession (usually named `spark`) created by Wherobots/AWS EMR/Databricks, please call `SedonaContext.create(spark)` instead.
+
+==Sedona >= 1.4.1==
+
+=== "Scala"
+
+	```scala
+	import org.apache.sedona.spark.SedonaContext
+
+	val sedona = SedonaContext.create(config)
+	```
+
+=== "Java"
+
+	```java
+	import org.apache.sedona.spark.SedonaContext;
+
+	SparkSession sedona = SedonaContext.create(config)
+	```
+
+=== "Python"
+
+	```python
+	from sedona.spark import *
+	
+	sedona = SedonaContext.create(config)
+	```
+
+==Sedona < 1.4.1==
+
+The following method has been deprecated since Sedona 1.4.1. Please use the method above to create your SedonaContext.
+
+=== "Scala"
+
+	```scala
+	SedonaSQLRegistrator.registerAll(sparkSession)
+	```
+
+=== "Java"
+
+	```java
+	SedonaSQLRegistrator.registerAll(sparkSession)
+	```
+
+=== "Python"
+
+	```python
+	from sedona.register import SedonaRegistrator
+	
+	SedonaRegistrator.registerAll(spark)
+	```
+
+You can also register everything by passing `--conf spark.sql.extensions=org.apache.sedona.sql.SedonaSqlExtensions` to `spark-submit` or `spark-shell`.
+
+## Load data from files
+
+Assume we have a single raster data file called rasterData.tiff, [at Path](https://github.com/apache/sedona/blob/0eae42576c2588fe278f75cef3b17fee600eac90/spark/common/src/test/resources/raster/raster_with_no_data/test5.tiff).
+
+Use the following code to load the data and create a raw Dataframe.
+
+=== "Scala"
+    ```scala
+    var rawDf = sedona.read.format("binaryFile").load(path_to_raster_data)
+    rawDf.createOrReplaceTempView("rawdf")
+    rawDf.show()
+    ```
+
+=== "Java"
+    ```java
+    Dataset<Row> rawDf = sedona.read.format("binaryFile").load(path_to_raster_data)
+    rawDf.createOrReplaceTempView("rawdf")
+    rawDf.show()
+    ```
+
+=== "Python"
+    ```python
+    rawDf = sedona.read.format("binaryFile").load(path_to_raster_data)
+    rawDf.createOrReplaceTempView("rawdf")
+    rawDf.show()
+    ```
+
+The output will look like this:
+
+```
+|                path|    modificationTime|length|             content|
++--------------------+--------------------+------+--------------------+
+|file:/Download/ra...|2023-09-06 16:24:...|174803|[49 49 2A 00 08 0...|
+```
+
+For multiple raster data files use the following code to load the data [from path](https://github.com/apache/sedona/blob/0eae42576c2588fe278f75cef3b17fee600eac90/spark/common/src/test/resources/raster/) and create raw DataFrame.
+
+!!!note
+    The above code works too for loading multiple raster data files.  if the raster files are in separate directories and the option also makes sure that only `.tif` or `.tiff` files are being loaded.
+
+=== "Scala"
+    ```scala
+    var rawDf = sedona.read.format("binaryFile").option("recursiveFileLookup", "true").option("pathGlobFilter", "*.tif*").load(path_to_raster_data_folder)
+    rawDf.createOrReplaceTempView("rawdf")
+    rawDf.show()
+    ```
+
+=== "Java"
+    ```java
+    Dataset<Row> rawDf = sedona.read.format("binaryFile").option("recursiveFileLookup", "true").option("pathGlobFilter", "*.tif*").load(path_to_raster_data_folder);
+    rawDf.createOrReplaceTempView("rawdf");
+    rawDf.show();
+    ```
+
+=== "Python"
+    ```python
+    rawDf = sedona.read.format("binaryFile").option("recursiveFileLookup", "true").option("pathGlobFilter", "*.tif*").load(path_to_raster_data_folder)
+    rawDf.createOrReplaceTempView("rawdf")
+    rawDf.show()
+    ```
+
+The output will look like this:
+
+```
+|                path|    modificationTime|length|             content|
++--------------------+--------------------+------+--------------------+
+|file:/Download/ra...|2023-09-06 16:24:...|209199|[4D 4D 00 2A 00 0...|
+|file:/Download/ra...|2023-09-06 16:24:...|174803|[49 49 2A 00 08 0...|
+|file:/Download/ra...|2023-09-06 16:24:...|174803|[49 49 2A 00 08 0...|
+|file:/Download/ra...|2023-09-06 16:24:...|  6619|[49 49 2A 00 08 0...|
+```
+
+The content column in the raster table is still in the raw form, binary form.
+
+## Create a Raster type column
+
+All raster operations in SedonaSQL require Raster type objects. Therefore, this should be the next step after loading the data.
+
+### From Geotiff
+
+```sql
+SELECT RS_FromGeoTiff(content) AS rast, modificationTime, length, path FROM rawdf
+```
+
+To verify this, use the following code to print the schema of the DataFrame:
+
+```sql
+rasterDf.printSchema()
+```
+
+The output will be like this:
+
+```
+root
+ |-- rast: raster (nullable = true)
+ |-- modificationTime: timestamp (nullable = true)
+ |-- length: long (nullable = true)
+ |-- path: string (nullable = true)
+```
+
+### From Arc Grid
+
+The raster data is loaded the same way as `tiff` file, but the raster data is stored with the extension `.asc`, ASCII format. The following code creates a Raster type objects from binary data:
+
+```sql
+SELECT RS_FromArcInfoAsciiGrid(content) AS rast, modificationTime, length, path FROM rawdf
+```
+
+## Raster's metadata
+
+Sedona has a function to get the metadata for the raster, and also a function to get the world file of the raster.
+
+### Metadata
+
+This function will return an array of metadata, it will have all the necessary information about the raster, Please refer to [RS_MetaData](../../api/sql/Raster-operators/#rs_metadata).
+
+```sql
+SELECT RS_MetaData(rast) FROM rasterDf
+```
+
+Output for the following function will be:
+
+```
+[-1.3095817809482181E7, 4021262.7487925636, 512.0, 517.0, 72.32861272132695, -72.32861272132695, 0.0, 0.0, 3857.0, 1.0]
+```
+
+The first two elements of the array represent the real world geographic coordinates (like longitude/latitude) of the raster image's top left pixel, while the next two elements represent the pixel dimensions of the raster.
+
+### World File
+
+There are two kinds of georeferences, GDAL and ESRI seen in [world files](https://en.wikipedia.org/wiki/World_file). For more information please refer to [RS_GeoReference](../../api/sql/Raster-operators/#rs_georeference).
+
+```sql
+SELECT RS_GeoReference(rast, "ESRI") FROM rasterDf
+```
+
+The Output will be as follows:
+
+```
+72.328613 
+0.000000 
+0.000000 
+-72.328613 
+-13095781.645176 
+4021226.584486
+```
+
+World files are used to georeference and geo-locate images by establishing an image-to-world coordinate transformation that assigns real-world geographic coordinates to the pixels of the image.
+
+## Raster Manipulation
+
+Since `v1.5.0` there have been many additions to manipulate raster data, we will show you a few example queries.
+
+!!!note
+    Read [SedonaSQL Raster operators](../../api/sql/Raster-operators) to learn how you can use Sedona for raster manipulation.
+
+### Coordinate translation
+
+Sedona allows you to translate coordinates as per your needs. It can translate pixel locations to world coordinates and vice versa.
+
+#### PixelAsPoint
+
+Use [RS_PixelAsPoint](../../api/sql/Raster-operators#rs_pixelaspoint) to translate pixel coordinates to world location.
+
+```sql
+SELECT RS_PixelAsPoint(rast, 450, 400) FROM rasterDf
+```
+
+Output:
+
+```
+POINT (-13063342 3992403.75)
+```
+
+#### World to Raster Coordinate
+
+Use [RS_WorldToRasterCoord](../../api/sql/Raster-operators#rs_worldtorastercoord) to translate world location to pixel coordinates. To just get X coordinate use [RS_WorldToRasterCoordX](../../api/sql/Raster-operators#rs_worldtorastercoordx) and for just Y coordinate use [RS_WorldToRasterCoordY](../../api/sql/Raster-operators#rs_worldtorastercoordy).
+
+```sql
+SELECT RS_WorldToRasterCoord(rast, -1.3063342E7, 3992403.75)
+```
+
+Output:
+
+```
+POINT (450 400)
+```
+
+### Pixel Manipulation
+
+Use [RS_Values](../../api/sql/Raster-operators#rs_values) to fetch values for specified array of Point Geometries. The coordinates in the point geometry are indicative to real world location.
+
+```sql
+SELECT RS_Values(rast, Array(ST_Point(-13063342, 3992403.75), ST_Point(-13074192, 3996020)))
+```
+
+Output:
+
+```
+[132.0, 148.0]
+```
+
+To change values over a grid or area defined by a geometry, we will use [RS_SetValues](../../api/sql/Raster-operators#rs_setvalues).
+
+```sql
+SELECT RS_SetValues(
+        rast, 1, 250, 260, 3, 3,
+        Array(10, 12, 17, 26, 28, 37, 43, 64, 66)
+    )
+```
+
+Follow the links to get more information on how to use the functions appropriately.
+
+### Band Manipulation
+
+Sedona provides APIs to select specific bands from a raster image and create a new raster. For example, to select 2 bands from a raster, you can use the [RS_Band](../../api/sql/Raster-operators#rs_band) API to retrieve the desired multi-band raster.
+
+Let's use a [multi-band raster](https://github.com/apache/sedona/blob/2a0b36989aa895c0781f9a10c907dd726506d0b7/spark/common/src/test/resources/raster_geotiff_color/FAA_UTM18N_NAD83.tif) for this example. The process of loading and converting it to raster type is the same.
+
+```sql
+SELECT RS_Band(colorRaster, Array(1, 2))
+```
+
+Let's say you have many one band rasters and want to add a band to the raster to perform [map algebra operations](#execute-map-algebra-operations). You can do so using [RS_AddBand](../../api/sql/Raster-operators#rs_addband) Sedona function.
+
+```sql
+SELECT RS_AddBand(raster1, raster2, 1, 2)
+```
+
+This will result in `raster1` having `raster2`'s specified band.
+
+### Resample raster data
+
+Sedona allows you to resample raster data using different interpolation methods like nearest neighbor, bilinear, and bicubic to change the cell size or align raster grids, using [RS_Resample](../../api/sql/Raster-operators/#rs_resample).
+
+```sql
+SELECT RS_Resample(rast, 50, -50, -13063342, 3992403.75, true, "bicubic")
+```
+
+For more information please follow the link.
+
+## Execute map algebra operations
+
+Map algebra is a way to perform raster calculations using mathematical expressions. The expression can be a simple arithmetic operations or a complex combination of multiple operations.
+
+The Normalized Difference Vegetation Index (NDVI) is a simple graphical indicator that can be used to analyze remote sensing measurements from a space platform, and assess whether the target being observed contains live green vegetation or not.
+
+```
+NDVI = (NIR - Red) / (NIR + Red)
+```
+
+where NIR is the near-infrared band and Red is the red band.
+
+```sql
+SELECT RS_MapAlgebra(raster, 'D', 'out = (rast[3] - rast[0]) / (rast[3] + rast[0]);') as ndvi FROM raster_table
+```
+
+For more information please refer to [Map Algebra API](../../api/sql/Raster-map-algebra).
+
+## Interoperability between raster and vector data
+
+### Geometry As Raster
+
+Sedona allows you to rasterize a geometry by using [RS_AsRaster](../../api/sql/Raster-writer/#rs_asraster).
+
+```sql
+SELECT RS_AsRaster(
+        ST_GeomFromWKT('POLYGON((150 150, 220 260, 190 300, 300 220, 150 150))'),
+        RS_MakeEmptyRaster(1, 'b', 4, 6, 1, -1, 1),
+        'b', 230
+    )
+```
+
+The image create is as below for the vector is:
+
+![Rasterized vector](../../image/rasterized-image.png)
+
+!!!note
+    The vector coordinates are buffed up to showcase the output, real use case, may or may not match the example.
+
+### Spatial range query
+
+Sedona provides raster predicates to do a range query using a geometry window, for example let's use [RS_Intersects](../../api/sql/Raster-operators#rs_intersects).
+
+```sql
+SELECT rast FROM rasterDf WHERE RS_Intersect(rast, ST_GeomFromWKT('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'))
+```
+
+### Spatial join query
+
+Sedona's raster predicates also have the capability to do a spatial join using the raster column and geometry column, using the same function as above.
+
+```sql
+SELECT r.rast, g.geom FROM rasterDf r, geomDf g WHERE RS_Interest(r.rast, g.geom)
+```
+
+!!!note
+    These range and join queries will filter rasters using the provided geometric boundary and the spatial boundary of the raster.
+
+    Sedona offers more raster predicates to do spatial range query and spatial join query. Please refer to [raster perdicates docs](../../api/sql/Raster-operators/#raster-predicates).
+
+## Visualize raster images
+
+Sedona provides APIs to visualize raster data in an image form. 
+
+### Base64 String
+
+The [RS_AsBase64](../../api/sql/Raster-visualizer#rs_asbase64) encodes the raster data as a Base64 string and can be visualized using [online decoder](https://base64-viewer.onrender.com/).
+
+```sql
+SELECT RS_AsBase64(rast) FROM rasterDf
+```
+
+### HTML Image
+
+The [RS_AsImage](../../api/sql/Raster-visualizer#rs_asimage) returns an HTML img tag, that can be visualized using an HTML viewer or in Jupyter Notebook. For more information please click at the link.
+
+```sql
+SELECT RS_AsImage(rast, 500) FROM rasterDf
+```
+
+The output looks like:
+
+![Output](../../image/DisplayImage.png)
+
+### 2-D Matrix
+
+Sedona offers an API to visualize raster data that is not sufficient for the other APIs mentioned above.
+
+```sql
+SELECT RS_AsMatrix(rast) FROM rasterDf
+```
+
+Output will as follows:
+
+```sql
+| 1   3   4   0|
+| 2   9  10  11|
+| 3   4   5   6|
+```
+
+Please refer to [Raster visualizer docs](../../api/sql/Raster-visualizer) to learn how to make most of the visualizing APIs.
+
+## Save to permanent storage
+
+Sedona has APIs that can save an entire raster column to files in a specified location. Before saving, the raster type column needs to be converted to a binary format. Sedona provides several functions to convert a raster column into a binary column suitable for file storage. Once in binary format, the raster data can then be written to files on disk using the Sedona file storage APIs.
+
+```sparksql
+rasterDf.write.format("raster").option("rasterField", "raster").option("fileExtension", ".tiff").mode(SaveMode.Overwrite).save(dirPath)
+```
+
+Sedona has a few writer functions that create the binary DataFrame necessary for saving the raster images.
+
+### As Arc Grid
+
+Use [RS_AsArcGrid](../../api/sql/Raster-writer#rs_asarcgrid) to get binary Dataframe of raster in Arc Grid format.
+
+```sql
+SELECT RS_AsArcGrid(raster)
+```
 
-1. [Set up dependencies](../sql/#set-up-dependencies)
-2. [Create Sedona config](../sql/#create-sedona-config)
-3. [Initiate SedonaContext](../sql/#initiate-sedonacontext)
+### As GeoTiff
 
-## API docs
+Use [RS_AsGeoTiff](../../api/sql/Raster-writer#rs_asgeotiff) to get binary Dataframe of raster in GeoTiff format.
 
-[Read raster data in DataFrame](../../api/sql/Raster-loader/)
+```sql
+SELECT RS_AsGeoTiff(raster)
+```
 
-[Write raster data in DataFrame](../../api/sql/Raster-writer/)
+### As PNG
 
-[Raster operators in DataFrame](../../api/sql/Raster-operators/)
+Use [RS_AsPNG](../../api/sql/Raster-writer#rs_aspng) to get binary Dataframe of raster in PNG format.
 
-## Tutorials
+```sql
+SELECT RS_AsPNG(raster)
+```
 
-[Python Jupyter Notebook](https://github.com/apache/sedona/blob/master/binder/ApacheSedonaRaster.ipynb)
+Please refer to [Raster writer docs](../../api/sql/Raster-writer) for more details.
 
-## Performance
+## Performance optimization
 
-[Storing large raster geometries in Parquet files](../storing-blobs-in-parquet)
\ No newline at end of file
+When working with large raster datasets, refer to the [documentation on storing raster geometries in Parquet format](../storing-blobs-in-parquet) for recommendations to optimize performance.
\ No newline at end of file