Instead of specifying all inputs using set_input, it is possible to use a config file. A config file can be loaded using read_config_file or it can be read and executed immediately by using run_config_file.
The syntax of the config file is explained more in detail in Niche Configuration file, but is already introduced here because it will be used in the next examples.
If you want to recreate the examples below, the config files can be found under the docs
folder, so if you extract all the data the you should be able to run the examples from the notebook.
Niche models can be compared using a NicheDelta class. This can be used to compare different scenario's.
In our example, we will compare the results of the running Niche two times, once using a simple model and once using a full model.
In [ ]:
import niche_vlaanderen as nv
import matplotlib.pyplot as plt
simple = nv.Niche()
simple.run_config_file("simple.yml")
full = nv.Niche()
full.run_config_file("full.yml")
delta = nv.NicheDelta(simple, full)
ax = delta.plot(7)
plt.show()
It is also possible to show the areas in a dataframe by using the table attribute.
In [ ]:
delta.table.head()
Like Niche, NicheDelta also has a write method, which takes a directory as an argument.
In [ ]:
delta.write("comparison_output", overwrite_files=True)
In many cases, it is not only important to find out which vegetation types are possible given the different input files, but also to find out how much change would be required to mhw
or mlw
to allow a certain vegetation type.
To create deviation maps, it is necessary to run a model with the deviation
option.
In [ ]:
dev = nv.Niche()
dev.set_input("mhw","../testcase/zwarte_beek/input/mhw.asc")
dev.set_input("mlw","../testcase/zwarte_beek/input/mhw.asc")
dev.set_input("soil_code","../testcase/zwarte_beek/input/soil_code.asc")
dev.run(deviation=True, full_model=False)
The deviation maps can be plotted by specifying either mhw or mlw with the vegetation type, eg mhw_14 (to show the deviation between mhw and the required mhw for vegetation type 14). Positive values indicate that the actual condition is too dry for the vegetation type. Negative values indicate that the actual condition is too wet for the vegetation type.
In [ ]:
dev.plot("mlw")
dev.plot("mlw_14")
plt.show()
Niche also contains a helper function that allows one to calculate the possible vegetation by using a vector dataset, such as a .geojson or .shp file.
The vegetation is returned as a pandas dataframe, where shapes are identified by their id and the area not covered by a shape gets shape_id
-1.
In [ ]:
df = full.zonal_stats("../testcase/zwarte_beek/input/study_area_l72.geojson")
df
In [ ]:
import niche_vlaanderen as nv
import matplotlib.pyplot as plt
full = nv.Niche()
full.run_config_file("full.yml")
full.write("output_abiotic", overwrite_files=True)
Now it is possible to adapt the acidity
and nutrient_level
grids outside niche. For this demo, we will use some Python magic to make all nutrient levels one level lower. Note that there is no need to do this in Python, any other tool could be used as well. So if you don't understand this code - don't panic (and ignore the warning)!
In [ ]:
import rasterio
with rasterio.open("output_abiotic/full_nutrient_level.tif") as src:
nutrient_level = src.read(1)
profile = src.profile
nodata = src.nodatavals[0]
nutrient_level[nutrient_level != nodata] = nutrient_level[nutrient_level != nodata] -1
# we can not have nutrient level 0, so we set all places where this occurs to 1
nutrient_level[nutrient_level ==0 ] = 1
with rasterio.open("output_abiotic/adjusted_nutrient.tif", 'w', **profile) as dst:
dst.write(nutrient_level, 1)
Next we will create a new niche model using the same options as our previous full models, but we will also add the previously calculated acidity and nutrient level values as input, and run with the abiotic=True
option. Note that we use the read_config_file
method (and not run_config_file
) because we still want to edit the configuration before running.
In [ ]:
adjusted = nv.Niche()
adjusted.read_config_file("full.yml")
adjusted.set_input("acidity", "output_abiotic/full_acidity.tif")
adjusted.set_input("nutrient_level", "output_abiotic/adjusted_nutrient.tif")
adjusted.name = "adjusted"
adjusted.run(abiotic=True)
adjusted.plot(7)
full.plot(7)
plt.show()
One is free to adapt the standard code tables that are used by NICHE. By specifying the paths to the adapted code tables in a NICHE class object, the standard code tables can be overwritten. In this way, standard model functioning can be tweaked. However, it is strongly advised to use ecological data that is reviewed by experts and to have in-depth knowledge of the model functioning.
The possible code tables that can be adapted and set within a NICHE object are:
ct_acidity, ct_soil_mlw_class, ct_soil_codes, lnk_acidity, ct_seepage, ct_vegetation, ct_management, ct_nutrient_level and ct_mineralisation
After adapting the vegetation code table for type 7 (Caricion gracilis) on peaty soil (V) by randomly altering the maximum mhw
and mlw
to 5 and 4 cm resp. (i.e. below ground, instead of standard values of -28 and -29 cm) and saving the file to ct_vegetation_adj7.csv, the adjusted model can be built and run.
In [ ]:
adjusted_ct = nv.Niche(ct_vegetation = "ct_vegetation_adj7.csv")
adjusted_ct.read_config_file("full.yml")
adjusted_ct.run()
Example of changed potential area of Caricion gracilis vegetation type because of the changes set in the vegetation code table:
In [ ]:
adjusted_ct.plot(7)
full.plot(7)
plt.show()
Potential area is shrinking because of the range of grondwater levels that have become more narrow (excluding the wettest places).