An object-oriented python package for species distribution modelling using deep learning.
The package allows for a more intuitive and easy exploration of biodiversity patterns by
modelling preferences for a great number of environmental variables.
Instructions for installing and using the sdmdl package can be found here.
Case study
The functionality of this package and the estimates of environmental preferences it
obtains is demonstrated by way of a use case on domesticated crops and their wild progenitors.
The raw uninterpreted results of this case study can be found here.
publiceerbare, herbruikbare Python toolkit voor SDM-DL (app. note; pyPI package)
toepassing van toolkit op use cases (2+ research papers)
formuleren van vervolg(-aanvraag)
use cases:
HS voor Observation.org data om beeldherkenning mee te schalen.
idem voor planten met/zonder secundaire houtigheid
idem voor planten met ectomycorrhiza, arbusculaire mycorrhiza, of iets anders
idem voor gedomesticeerde versus wilde planten
toolkit:
consumeren van occurrences van diverse bronnen (GBIF/Observation.org/derden). In scope: transformeren van data in diverse formats (e.g. TSV/CSV/DarwinCore/JSON). Out of scope: opschonen van data, wat b.v. kan met CoordinateCleaner etc.
consumeren van GIS data van diverse bronnen (bioclim/envirem/derden/map queries). In scope: importeren van diverse formats (e.g. TIFF/BIL); croppen; herprojecteren; bufferen. Out of scope: complexere GIS operaties.
consumeren van andere variabelen (metadata van waarnemingen)
configureren/runnen/evalueren van model training. In scope: prepareren van input vectors (e.g. co-occurrences ja/nee); configureren/parameteriseren van DNN topologie; epochs. Evaluatie van AUC's en variable contributions.
projecteren van modelvoorspellingen. In scope: genereren van habitat suitability (HS) kaarten/data sets voor huidige verspreiding. Out of scope: IPCC klimaatvoorspellingen.
When running SDMDL, there is a very small chance of running into the following error:
ValueError: minvalue must be less than or equal to maxvalue
in: color.py, cm.py, collections.py, artist.py
This error occurs in sdmdl/trainer.py, on lines 235-239 and/or 242-246 when figures are created in the validate_model function.
This traces back to SHAP being unable to create a figure using matplotlib, as features contribute to the model outcome equally.
This is fixed in SHAP version 0.34 and onwards, however, updating to this version would break the SDMDL package even further.
Op heel veel plekken los van elkaar worden dezelfde paden hard gecodeerd in de code.
(Voorbeeld: /data/GIS/layers/... komt heel vaak terug in de code). Dat is een probleem
omdat we hierdoor vanaf nu getrouwd zijn met bepaalde locaties die vrijwel niet meer te
wijzigen zijn. Bovendien is de code niet consequent: de ene keer is het gis, de andere
keer GIS. Dat werkt op OSX en Windows maar niet op Linux (want dat is case sensitive).
Niet alleen is dat een probleem voor onszelf, maar nog veel erger voor eventuele
gebruikers (=Wouter), die hun TIF layers op exact de juiste (niet-gedocumenteerde) plek,
met de juiste naam, in een specifieke nesting moeten zetten. Dat gaat ze nooit lukken.
Een iets betere optie zou zijn dat zo'n pad maximaal op een plek staat, namelijk
binnen de code van een configuratie-object (of andere abstractie) die paden beheert. De
kennis over de paden is dan geconcentreerd op een plek en hoeft dus alleen daar aangepast
te worden. Nog beter is als die kennis op nul plekken in de code staat, en volledig
afhankelijk is van een configuratiebestand.
Gerelateerd hier aan is ook het probleem dat hard gecodeerd getest wordt op .tif,
terwijl de bestands-extensie in werkelijkheid niet case sensitive hoeft te zijn (dus .TIF is ook een valide naam), en zelfs ook iets anders zou kunnen zijn (nl. .tiff of .TIFF).
Oplossing: paden laten beheren via een configuratie abstractie
Probleem: te lange methods
Elke method (of functie) moet ongeveer een scherm vol zijn: ±40 regels. Als dat onmogelijk
lijkt dan probeert de method dus te veel te doen en moet opgesplitst worden: http://wiki.c2.com/?LongMethodSmell
Oplossing: methods opsplitsen
Probleem: hard gecodeerde dictionary keys
Op een aantal plekken in de code zijn kolomnamen van de DarwinCore archives hard
gecodeerd, en laten dan een mix zien van CamelCase en underscore_case. Dit is een
probleem omdat we hierdoor getrouwd zijn met hele specifieke (en custom) structuren
voor onze data. Als Wouter met de data van observation.org aan de slag wil dan heeft
hij vast andere namen voor de kolommen. Wat er moet gebeuren is dat er een Occurrence
class is (of iets dergelijks) die dit intern beheert zodat de rest van de code de
specifieke details van de databestanden niet hoeft te weten. Als dan blijkt dat het in
observation.org decimal_latitude in plaats van decimalLatitude us dan hoeft er maar op
een plek iets aangepast te worden. Bijkomend voordeel is dat je zo ook geen typefouten
in de code kan krijgen (bijvoorbeeld, per ongeluk data["decima1Latitude"]).
Oplossing: een aparte class voor DarwinCore records, idealiter als subclass van een
al bestande DarwinCore library
Probleem: niet (goed) testbare code
Een verzameling losse scripts is niet hetzelfde als een hebruikbare, testbare API. Het
moet mogelijk zijn om elk stukje van de code via een unit test te verifieren. Dat kan
eigenlijk alleen maar (of althans, op een veel meer voor de hand liggende manier) als
de code bestaat uit classes die door de unit test suite geimporteerd kunnen worden om
zo de functionaliteit van elke method te testen. Het doel is dat de coverage om en
nabij de 100% wordt.
Het moet zo zijn dat we uiteindelijk automatisch goede documentatie kunnen genereren
(bijvoorbeeld op readthedocs). Dat gaan we doen door een combinatie van goede docstrings
in de code en goede [.rst](https://en.wikipedia.org/wiki/ReStructuredText) documentatie,
te beginnen bij /docs/index.rst
Aan de collecties van scripts kan je in grote lijnen zien hoe de API er uit zou moeten
zien. De namen die ik hier hanteer dienen even als voorbeeldjes:
config - een class die de configuratiebestanden (e.g. YAML) inleest en de waardes
via methods beschikbaar maakt aan de rest. Is verantwoordelijk voor het aanleveren
van defaults (dus niet via magic numbers elders in de code), het construeren van
locaties van invoer- en uitvoerbestanden.
model_trainer - een class die de training van het model aanstuurt, d.w.z. de
input parameters vanuit de configuratie ophaalt en overdraagt aan keras, vervolgens
de voortgang / het succes van de training evalueert, en het model kan opslaan
model_predictor - gegeven een getraind model (eventueel in te lezen van een bestand)
zorgt deze class dat er voorspellingen gedaan worden
gis_handler - weet alles van het inlezen, croppen, rescalen, plotten, wegschrijven
van GIS data
occurrence_handler - weet alles van het inlezen, filteren, converteren, wegschrijven
van DarwinCore (-achtige) data
Good code documentation - meaning both documentation at the level of methods (in progress, getting there) and at the user level, i.e. a Usage example with a simple, working, analysis run through in /docs/index.rst
paper.md / paper.bib - the idea is that the Usage example is written up in such a way that it integrates automatically in a paper.md that can be submitted to JOSS. For example, with some basic grep/redirect logic so that the correct section(s) in index.rst end(s) up in the markdown. rst -> markdown via pandoc
Submissions - the repository is now activated on Zenodo.org, such that when we prepare a release, it will be tagged with a DOI, at which point we will insert it as a badge on the homepage README.md. We will then submit to JOSS, deal with the reviews, and add their badge upon acceptance.
De Python scripts moeten uitgekleed worden zodanig dat alle functionaliteit in OO classes komt te staan. Eventuele scripts die dan nog nodig (of nuttig) zijn bevatten dan bijna geen code maar zijn puur wrappers rond de OO classes.
Er is nu een soort duplicatie van zowel een scripts folder als de sdmdl folder met schijnbaar dezelfde code. Scripts folder opschonen.
The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.