Create an example xarray.DataArray whose shape is (40 * 50).
import xarray as xr
import numpy as np
data = xr.DataArray(data=np.arange(2000).reshape((40, 50)), dims=("y", "x"))
data.plot()
Create an ABSESpy model with 10 * 10 natural patch module.
from abses import MainModel
model = MainModel()
print(f"Model created: {model}")
[15:02:11][WARNING][nature] the nature's CRS has been changed to epsg:4326.
Using ABSESpy version: v0.7.0
name MainModel state init tick 0 dtype: object
from abses import load_data
from abses.viz.plotting import plot_raster
raster_path = load_data("farmland.tif")
cropland = model.nature.create_module(
how="from_file",
raster_file=raster_path,
apply_raster=True,
attr_name="test",
name="cropland",
)
# Plot the ingested raster attribute
plot_raster(cropland, attr="test")
# Create a test module for demonstration
module = model.nature.create_module(shape=(50, 40), name="test_module")
When apply raster of a xarray.DataArray to natural module, the raster will be automatically reprojected to the natural module's spatial extent.
module.apply_raster(
data, attr_name="test", cover_crs=True, resampling_method="bilinear"
)
ax = module.get_xarray("test").plot()
note: edge effect may exists when re-projecting the raster.
Working with real data¶
Here, we have a demo of how to load climate data and apply it to the natural module. When loading the data, the data will be automatically reprojected to the natural module's spatial extent.
from abses import load_data
from abses.viz.plotting import plot_raster
raster_path = load_data("farmland.tif")
cropland2 = model.nature.create_module(
how="from_file",
raster_file=raster_path,
apply_raster=True,
name="cropland2",
attr_name="cropland",
)
plot_raster(cropland2, attr="cropland")
/Users/songshgeo/Documents/VSCode/ABSESpy/abses/nature.py:170: UserWarning: Converting PatchModule from crs EPSG:4326 to the crs of BaseNature - EPSG:4326. Please check your crs settings if this is unintended, or set `GeoSpace.warn_crs_conversion` to `False` to suppress this warning message. self.add_layer(module)
<matplotlib.collections.QuadMesh at 0x320f277d0>
data = xr.open_dataset(load_data("precipitation.nc"))
data
<xarray.Dataset> Size: 13MB
Dimensions: (lat: 400, lon: 700, time: 12)
Coordinates:
* lat (lat) float32 2kB 15.05 15.15 15.25 15.35 ... 54.75 54.85 54.95
* lon (lon) float32 3kB 70.05 70.15 70.25 70.35 ... 139.8 139.9 140.0
* time (time) datetime64[ns] 96B 2018-01-16T10:30:00 ... 2018-12-16T10:...
Data variables:
prec (time, lat, lon) float32 13MB ...
Attributes:
Conventions: CF-1.0
history: Created at 2016-04-02 14:55:55 UTC by the ITPCAS Data Fusio...
source: ITPCAS Data Fusion System (Version: 01.02.0240)
institution: Institute of Tibetan Plateau Research, Chinese Academy of S...
title: Monthly mean precipitation rate from the ITPCAS China Meteo...
description: Data from ITPCAS China Meteorological Forcing Dataset (Vers...
references: He, J., and K. Yang, 2011: China Meteorological Forcing Dat...a_month = data.sel(time="2013-01", method="nearest")
a_month["prec"].plot()
a_month
<xarray.Dataset> Size: 1MB
Dimensions: (lat: 400, lon: 700)
Coordinates:
* lat (lat) float32 2kB 15.05 15.15 15.25 15.35 ... 54.75 54.85 54.95
* lon (lon) float32 3kB 70.05 70.15 70.25 70.35 ... 139.8 139.9 140.0
time datetime64[ns] 8B 2018-01-16T10:30:00
Data variables:
prec (lat, lon) float32 1MB ...
Attributes:
Conventions: CF-1.0
history: Created at 2016-04-02 14:55:55 UTC by the ITPCAS Data Fusio...
source: ITPCAS Data Fusion System (Version: 01.02.0240)
institution: Institute of Tibetan Plateau Research, Chinese Academy of S...
title: Monthly mean precipitation rate from the ITPCAS China Meteo...
description: Data from ITPCAS China Meteorological Forcing Dataset (Vers...
references: He, J., and K. Yang, 2011: China Meteorological Forcing Dat...When applying the raster data to an existing module, ABSESpy automatically project match it to the current CRS.
Dynamic raster data¶
The NetCDF dataset has three dims: 'time', 'x'(longitude), and 'y'(latitude).
One benefit of using ABSESpy is to update the dataset by real-world time. Below is an example:
def update_precipitation(data, time):
import pandas as pd
# drop timezone to avoid mismatch
idx = pd.DatetimeIndex(data.indexes["time"]).tz_localize(None)
ds = data.assign_coords(time=idx)
# use a naive datetime for selection
return ds.sel(time=time.dt.naive(), method="nearest")
cropland.add_dynamic_variable(
name="prec",
data=data,
function=update_precipitation,
cover_crs=True,
)
Create Module from Vector Dataset¶
In this example, we will create a PatchModule and geo-agents with a shapefile dataset.
import geopandas as gpd
data_path = load_data("YR_cities.zip")
gdf = gpd.read_file(data_path)
gdf.head()
| City_ID | Ratio | area | Shaoefile_ | Perfecture | Province_n | geometry | |
|---|---|---|---|---|---|---|---|
| 0 | 100 | 0.546595 | 3958.281245 | 128.0 | C100 | Henan | POLYGON ((113.38580 35.47040, 113.39200 35.464... |
| 1 | 102 | 0.385113 | 15258.027194 | 170.0 | C102 | Henan | POLYGON ((112.03220 35.04700, 112.03260 35.045... |
| 2 | 106 | 0.567869 | 4273.313471 | 197.0 | C106 | Henan | POLYGON ((115.19540 36.20580, 115.19700 36.203... |
| 3 | 107 | 0.389969 | 9951.746614 | 215.0 | C107 | Henan | POLYGON ((111.96140 35.07840, 111.96400 35.076... |
| 4 | 109 | 0.601268 | 8279.739196 | 290.0 | C109 | Henan | POLYGON ((113.67120 35.83740, 113.67660 35.835... |
# Create a new model, and import the above GeoDataFrame as a patch module.
model = MainModel()
yr_basin = model.nature.create_module(
how="from_vector",
vector_file=gdf,
resolution=0.1, # 0.1 degree.
major_layer=True,
name="yellow_river",
attr_name="area",
apply_raster=True,
)
from abses.viz.plotting import plot_raster
plot_raster(yr_basin, attr="area")
[15:02:13][WARNING][nature] the nature's CRS has been changed to GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]. /Users/songshgeo/Documents/VSCode/ABSESpy/abses/nature.py:170: UserWarning: Converting PatchModule from crs EPSG:4326 to the crs of BaseNature - EPSG:4326. Please check your crs settings if this is unintended, or set `GeoSpace.warn_crs_conversion` to `False` to suppress this warning message. self.add_layer(module) /Users/songshgeo/Documents/VSCode/ABSESpy/abses/viz/viz_nature.py:56: UserWarning: No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument. ax.legend(**legend_kwargs)
<Axes: title={'center': 'spatial_ref = 0'}, xlabel='x', ylabel='y'>
def update_precipitation(data, time):
import pandas as pd
idx = pd.DatetimeIndex(data.indexes["time"]).tz_localize(None)
ds = data.assign_coords(time=idx)
return ds.sel(time=time.dt.naive(), method="nearest")
yr_basin.add_dynamic_variable(
name="prec",
data=data,
function=update_precipitation,
cover_crs=True,
)
from abses import Actor
class County(Actor):
"""City in the Yellow River Basin."""
marker = "^"
color = "#FFFF80"
model.agents.new_from_gdf(
gdf,
unique_id="City_ID",
attrs=["area", "Province_n"],
)
yr_basin.random.new(County, size=50)
<ActorsList: (50)County>