"""
# Introduction

The maps you create in this course portray the surface of the earth in two dimensions.  But, as you know, the world is actually a three-dimensional globe. So we have to use a method called a **map projection** to render it as a flat surface.  

Map projections can't be 100% accurate.  Each projection distorts the surface of the Earth in some way, while retaining some useful property.  For instance,
- the *equal-area* projections (like "Lambert Cylindrical Equal Area", or "Africa Albers Equal Area Conic") preserve area.  This is a good choice, if you'd like to calculate the area of a country or city, for example.
- the *equidistant* projections (like "Azimuthal Equidistant projection") preserve distance.  This would be a good choice for calculating flight distance.

<center>
<img src="https://i.imgur.com/noBRRNR.png" width="700">
<b>List of map projections</b> (<a href="https://bit.ly/2kOHTBs">Source</a>)<br/><br/>
</center>

We use a **coordinate reference system (CRS)** to show how the projected points correspond to real locations on Earth.  In this tutorial, you'll learn more about coordinate reference systems, along with how to use them in GeoPandas.
"""

import geopandas as gpd
import pandas as pd
"""
# Setting the CRS

When we create a GeoDataFrame from a shapefile, the CRS is already imported for us. 
"""
# Load a GeoDataFrame containing regions in Ghana
regions = gpd.read_file("../input/geospatial-learn-course-data/ghana/ghana/Regions/Map_of_Regions_in_Ghana.shp")
print(regions.crs)
"""
How do you interpret that?

Coordinate reference systems are referenced by [European Petroleum Survey Group (EPSG)](http://www.epsg.org/) codes.

This GeoDataFrame uses [EPSG 32630](https://epsg.io/32630), which is more commonly called the "Mercator" projection. This projection preserves angles (making it useful for sea navigation) and slightly distorts area. 

However, when creating a GeoDataFrame from a CSV file, we have to set the CRS.  [EPSG 4326](https://epsg.io/4326) corresponds to coordinates in latitude and longitude.
"""
# Create a DataFrame with health facilities in Ghana
facilities_df = pd.read_csv("../input/geospatial-learn-course-data/ghana/ghana/health_facilities.csv")

# Convert the DataFrame to a GeoDataFrame
facilities = gpd.GeoDataFrame(facilities_df, geometry=gpd.points_from_xy(facilities_df.Longitude, facilities_df.Latitude))

# Set the coordinate reference system (CRS) to EPSG 4326
facilities.crs = {'init': 'epsg:4326'}

# View the first five rows of the GeoDataFrame
facilities.head()
"""
In the code cell above, to create a GeoDataFrame from a CSV file, we needed to use both Pandas and GeoPandas:
- We begin by creating a DataFrame containing columns with latitude and longitude coordinates.
- To convert it to a GeoDataFrame, we use `gpd.GeoDataFrame()`.  
- The `gpd.points_from_xy()` function creates `Point` objects from the latitude and longitude columns.
"""
"""
# Re-projecting

Re-projecting refers to the process of changing the CRS.  This is done in GeoPandas with the `to_crs()` method.

When plotting multiple GeoDataFrames, it's important that they all use the same CRS.  In the code cell below, we change the CRS of the `facilities` GeoDataFrame to match the CRS of `regions` before plotting it.
"""
# Create a map
ax = regions.plot(figsize=(8,8), color='whitesmoke', linestyle=':', edgecolor='black')
facilities.to_crs(epsg=32630).plot(markersize=1, ax=ax)
"""
The `to_crs()` method modifies only the "geometry" column: all other columns are left as-is.
"""
# The "Latitude" and "Longitude" columns are unchanged
facilities.to_crs(epsg=32630).head()
"""
In case the EPSG code is not available in GeoPandas, we can change the CRS with what's known as the "proj4 string" of the CRS.  For instance, the proj4 string to convert to latitude/longitude coordinates is as follows:
```
+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
```
"""
# Change the CRS to EPSG 4326
regions.to_crs("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs").head()
"""
# Attributes of geometric objects

As you learned in the first tutorial, for an arbitrary GeoDataFrame, the type in the "geometry" column depends on what we are trying to show: for instance, we might use:
- a Point for the epicenter of an earthquake, 
- a LineString for a street, or 
- a Polygon to show country boundaries.

All three types of geometric objects have built-in attributes that you can use to quickly analyze the dataset.  For instance, you can get the x- and y-coordinates of a Point from the `x` and `y` attributes, respectively.
"""
# Get the x-coordinate of each point
facilities.geometry.head().x
"""
And, you can get the length of a LineString from the `length` attribute.  

Or, you can get the area of a Polygon from the `area` attribute.
"""
# Calculate the area (in square meters) of each polygon in the GeoDataFrame 
regions.loc[:, "AREA"] = regions.geometry.area / 10**6

print("Area of Ghana: {} square kilometers".format(regions.AREA.sum()))
print("CRS:", regions.crs)
regions.head()
"""
In the code cell above, since the CRS of the `regions` GeoDataFrame is set to EPSG 32630 (a "Mercator" projection), the area calculation is slightly less accurate than if we had used an equal-area projection like "Africa Albers Equal Area Conic".

But this yields the area of Ghana as approximately 239585 square kilometers, which is not too far off from [the correct answer](https://www.google.com/search?q=area+of+ghana).
"""
"""
# Your turn

Use what you've learned to **[track bird migration to South America](https://www.kaggle.com/kernels/fork/5832146)**.
"""
"""
---




*Have questions or comments? Visit the [course discussion forum](https://www.kaggle.com/learn/geospatial-analysis/discussion) to chat with other learners.*
"""