# Documentatie NDFF Connector Plugin

## Inleiding

De Nationale Databank Flora en Fauna (NDFF) bevat Nederlandse Flora en Fauna waarnemingen, en heeft een REST interface om waarnemingen in te voeren of op te vragen: https://api.ndff.nl/api/v2/

De ‘NDFF Connector Plugin’ is een QGIS plugin om lokale waarnemingen te uploaden naar de NDFF door geauthoriseerde gebruikers.

De ‘NDFF Connector Plugin’ maakt gebruik van de ‘NDFF Connector’ bibliotheek (Python module), die ook gebruikt kan worden voor andere ‘client’ applicaties (bv R of Command Line Interface)

## Overzicht

### De NDFF API

De NDFF gebruikt OAuth voor de authorisatie van clients.

Bijna alle waarden bij de NDFF zijn “uri’s”: dus niet nederlandse of latijnse soortnamen, maar zoiets als: “http://ndff-ecogrid.nl/taxonomy/taxa/pipistrellusnathusii”

De NDFF wenst JSON of XML te ontvangen, wij gaan voor JSON, een voorbeeld is:

    {
       "abundanceSchema": "http://ndff-ecogrid.nl/codes/scales/exact_count",
       "abundanceValue": 1,
       "activity": "http://ndff-ecogrid.nl/codes/domainvalues/observation/activities/calling",
       "determinationMethod": "http://ndff-ecogrid.nl/codes/domainvalues/observation/determinationmethods/550",
       "extrainfo": [],
       "dataset": "http://notatio.nl/dataset/2",
       "biotope": "http://ndff-ecogrid.nl/codes/domainvalues/location/biotopes/unknown",
       "identity": "http://notatio.nl/waarneming/7500",
       "involved": [
           {
           "involvementType": "http://ndff-ecogrid.nl/codes/involvementtypes/data_owner",
           "person": "http://telmee.nl/contacts/persons/1261085"
           }
       ],
       "lifestage": "http://ndff-ecogrid.nl/codes/domainvalues/observation/lifestages/509",
       "location": {
           "buffer": 5,
           "geometry": {
               "type": "Point",
               "coordinates": [
                   408241,
                   78648
                   ]
               }
           },
       "periodStart": "2014-08-29 01:22:00",
       "periodStop": "2014-08-29 01:22:00",
       "sex": "http://ndff-ecogrid.nl/codes/domainvalues/observation/sexes/undefined",
       "subjectType": "http://ndff-ecogrid.nl/codes/subjecttypes/live/individual",
       "surveyMethod": "http://ndff-ecogrid.nl/codes/domainvalues/survey/surveymethods/na",
       "taxon": "http://ndff-ecogrid.nl/taxonomy/taxa/pipistrellusnathusii",
       "dwelling": "http://ndff-ecogrid.nl/codes/domainvalues/observation/dwellings/unknown",
       "extrainfo": [
           {
             "key": "http://ndff-ecogrid.nl/codes/keys/external/location_id",
             "value": "NL09_GROO6140002"
           },
           {
             "key": "http://ndff-ecogrid.nl/codes/keys/external/original_visit_id",
             "value": "NL09_GROO6140002_2014_7_21_VISB1_1"
           }
       ]
    }

De crux van een client is dus om van eigen data in staat te zijn om daar de JSON van te maken, EN DE MAPPINGS te maken van de waarden in de eigen data (zoals soortnamen of soort-id’s) en de URI’s van de NDFF.

### NDFF Plugin

De NDFF-Connector plugin leeft hier: https://gitlab.com/rduivenvoorde/ndff-connector-plugin

Er is gekozen voor een QGIS plugin omdat QGIS standaard heel veel verschillende soorten databronnen kan ‘openen’.

Daarnaast kun je in QGIS ‘eenvoudig’ (met zogenaamde expressies in virtuele kolommen), velden aanpassen of uitbreiden. Bijvoorbeeld: als de records een getal als unieke ID hebben, kun je met een virtuele kolom er eenvoudige een unieke URI-identifier van maken. Of als je data een vreemde datum/tijd notatie heeft, kun je die via een een expressie in QGIS omcatten naar een juiste notatie of zelfs een QDateTime object.

De plugin kan van zo’n databron de ‘records’ dan 1 voor 1 inlezen, en (via de library en de ingestelde mappings) een NDFF-Object ervan maken en tonen aan de gebruiker.

### NDFF Library

De NDFF-Connector library leeft hier: https://gitlab.com/rduivenvoorde/ndff-connector

Een paar eigenschappen van de library:

- een library die gebruikt kan worden om een NDFF-client te maken

- geschreven in Python (installeerbaar via pip install ndff)

- initialiseert zich op basis van een set xxx.csv bestanden in een ndff_settings directory

- onderscheid een aantal objecten:

    - het API object (om mee te communiceren)

    - het Datasource object (om records uit te lezen, voor verschillende databronnen)

    - het NDFF object (om te mappen tussen record en NDFF json, en te sturen naar de API)

    - de NdffConnector: het belangrijkste object, de connectie en baas over alles

De library kan gebruikt worden om ‘clients’ mee te schrijven.

Voorbeelden:

- een QGIS plugin (zie verder), die zorgt voor een GUI etc, maar die verder de library gebruikt voor communicatie en instellingen

- een stuk R die de library via reticulate gebruikt

- een Command Line Interface

- een web applicatie die data asynchrone ‘behandelt’ en de library gebruikt voor communicatie en instellingen

## NDFF-Connector Plugin Gebruikshandleiding

### Starten en Authorisatie

Ten eerste moet er een QGIS project zijn met lagen van de data welke moet worden verwerkt.

Open het het hoofdscherm van de Plugin door in de plugin toolbar de NDFF button aan te klikken

OF door via het menu Web / NDFF Connector Plugin het item NDFF Connector Dialoog te kiezen.

Bij het starten van de plugin zal die eerst vragen om de benodigde authorisatie gegevens.

Voer alle gegevens in, de gegevens zijn te vinden op de pdf die u heeft gekregen van het beheerteam bij de toegangsaanvraag.

Kies een ‘omgeving’, begin altijd in de ‘Acceptatie’-omgeving.

Het ‘Domain’ is een getal van meestal 3 cijfers, welke te vinden is IN de voorbeeldlinkjes in de pdf na het woordje ‘domain’ (zie afbeelding, daar ‘708’).

De ‘Domain-key’ wordt meestal leeggelaten.

Klik evt op de knop ‘TEST DEZE INSTELLINGEN’ om te kijken of u verbinding kunt maken met uw gedeelte/domain van de NDFF.

Klik op OK om deze instellingen op te slaan onder een duidelijke naam, bijvoorbeeld: ‘AcceptatieOmgevingMijnBedrijf`.

U kunt meerder ‘Verbindings-profielen’ maken, voor de verschillende (acc/prd) omgevingen, maar ook bv met de inloggegevens van derden.

LET OP: om waarnemingen naar de NDFF te versturen, stuurt u deze vaak EERST naar de accepatie-omgeving ( https://accapi.ndff.nl ) en pas daarna naar de produktie omgeving, via de url https://api.ndff.nl .

Daarna verschijnt het hoofdscherm van de Plugin, helemaal leeg. Lees verder over het Hoofdscherm onder de afbeelding.

### Gebruik van het Hoofdscherm

Het is belangrijk om enig begrip te hebben van de zaken die geregeld moeten zijn om UW gegevens naar de NDFF te sturen:

- uw veldnamen komen waarschijnlijk NIET overeen met de veldnamen bij de NDFF. Er is een VELDmapping nodig. Dit is (per laag/datasource) een mapping van de veldnaam/kolomnaam naar de NDFF-veldnaam.

- de NDFF data moeten vaak URI’s bevatten, als uw data dat niet heeft, is een DATAmapping nodig. Dit is een mapping van bijvoorbeeld UW soortnamen naar de taxon-URI’s zoals te vinden bij de NDFF

- missende velden kunt u laten vullen met ‘standaard waarden’ (vaak een URI voor bv ‘niet aanwezig’ oid)

- de NDFF wil een begindatum (en liefst ook een einddatum) die MOET in de gegevens aanwezig zijn in het juiste ‘formaat’. Indien dat niet zo is kunt u QGIS expressie gebruiken om het gewenste formaat te verkrijgen.

- de NDFF wil van elke waarneming de locatie als een x/lon en y/lat. De plugin kan die uit de (geografische) data halen, OF u wijst een x en y column aan in de data

- het geheel van VELDmappings, DATAmappings, laag/datasource kan worden gegeslagen in een zogenaamde NDFF-Configuratie. In de praktijk is dat een mapje genaamde ‘ndff_settings’ met daarin een set .csv bestanden

- in het Hoofdscherm maakt u de Mappings aan (of u hergebruikt eerder aangemaakte), en krijgt u feedback of de Mappings voldoende zijn en of een Waarneming voldoende/juist is beschreven

Hieronder een dataset met in de linkerkolom de Veldmappings (bv het veld ‘soort’ in de data wordt gemapped naar ‘taxon’ bij de NDFF) en in de rechterkolom de Datamappings (bv spreeuw -> http://ndff-ecogrid.nl/taxonomy/taxa/sturnusvulgaris )

### Gebruik van QGIS Expressies

Met virtuele kolommen in QGIS kun je met QGIS Expressies een soort tijdelijke waarden aanmaken.

Handig wanneer een dataset niet de juiste waarde(s) bevat.

#### Identity

De ‘identity’ van een waarneming is altijd een URI (een soort URL, maar hoeft niet een echte (resolvable) link te zijn).

Vaak gebruik je daarvoor een ‘id’ (kolom) uit je dataset PLUS een slim opgezette voorloper URL. Bv: http://mijnbedrijf.nl/2022/project_x/id_kolom of http://mijnbedrijf.nl/projectnummer_x/vogels/id_kolom.

Stel nu dat je in je data nog geen identity URI hebt, dan kun je met virtuele kolommen op basis van QGIS expressies zo’n URI maken.

Een voorbeeld:

    # het deel tussen enkele quote's is een tekst string
    # het || (pipe) symbool plakt ze aan elkaar ('concatenate')
    # het deel tussen de dubbele aanhalingstekens is dan een bestaande kolomnaam
    'http://zuidt.nl/waarnemingen/20220419/vleermuizen/' ||  "gid"
    # als gid bv de waarde 33 heeft, dan wordt de URI: 'http://zuidt.nl/waarnemingen/20220419/vleermuizen/gid'

Nog mooier wordt het natuurlijk wanneer die identitie WEL in een browser opgezocht kan worden. Dat zou kunnen door een web applicatie te bouwen die zo’n identity bv opzoekt in een database en dan toont, maar je zou ook een waarneming.nl of waarnemingpro URL kunnen gebruiken daarvoor.

WaarnemingPro bijvoorbeeld geeft in zijn Excel/CSV dumps een ‘id’ mee die dezelfde voor WaarnemingPro unieke ID is die ze gebruiken om de Edit webapplicatie te openen. Je kunt die gebruiken om vanuit de NDFF gegevens dan dus direkt naar die pagina te linken. Een voorbeeld:

    'http://mijnbedrijfsnaam.wrnpro.nl/fieldwork/observations/' || "id" || '/edit'

Je zou dat ook in je data/excel al kunnen doen, maar dan met een Excel formule als:

    =hyperlink("http://mijnbedrijfsnaam.wrnpro.nl/fieldwork/observations/"&[kolom met noemer "id" vaak A]&"/edit")

Zowel in de NDFF dialoog, als met de I-tool in QGIS kun je dan wisselen tussen de wrnpro webapp en QGIS.

#### Datum en Tijd

De NDFF API kan omgaan met een hele serie van Datum Tijd formaten (voor start en eindtijd van een waarneming).

Eigenlijk is zo’n datum-tijd (timestamp) gebaseerd op https://en.wikipedia.org/wiki/ISO_8601

Een paar voorbeelden van formaten: YYYY-MM-DDThh:mm:ss, YYYY-MM-DD hh:mm:ss, YYYY-MM-DDThh:mm, YYYY-MM-DD hh:mm, YYYY-MM-DDThh, YYYY-MM-DD hh, YYYY-MM-DD, YYYY-MM, YYYY

Merk op dat dit anders is dan een Nederlands Datumveld: die doet meestal DD/MM/YYYY

Ook hier weer kunnen expressie helpen.

Stel je hebt een aparte datum (bv “date”) en tijd (bv “time”) kolom (maar WEL al in de juiste formaten):

    "date" || 'T' || "time" || ':00'

Stel je hebt alleen een Nederlandse datum notatie zoals (23/02/2022 staat dan in je data)

    # format_date maakt van een Date object een tekst in het opgegeven formaat
    # to_date maakt van (de NL) datumtekst op basis van het format een Date object
    format_date(
          to_date( '23/02/2022', 'd/M/yyyy'),
          'yyyy-MM-dd'
    )

Dit is een voorbeeld van data waar datum en tijd over twee kolommen staat: Datum en Tijd.

EN: soms is geen tijd gegeven in de data (die is dan leeg of NULL)

De Datum kolom staat in Nederlandse notatie: “28-3-2020” en de tijd staat er zonder seconden: “13:35”

Hieronder de expressie. Er wordt eerst gechecked of TIjd leeg is, ALS die leeg is formateer dan alleen de datum.

Als de Tijd er wel is, formateer dan de Datum (omzetten van NL notatie naar de ISO notatie) EN de Tijd (hieronder worden de seconden ‘:00’ er nog achter geplakt omdat in de data die niet staan. Maar als je WEL al seconden hebt kan het ` || :00 ` stukje eruit):

    IF ( "Tijd" IS NULL   OR   "Tijd"  in ('', ' ', 'NULL') )

        format_date(
            to_date( "Datum", 'd-M-yyyy'),
            'yyyy-MM-dd'
        ),

        format_date(
            to_date( "Datum", 'd-M-yyyy'),
            'yyyy-MM-dd'
        )
        || ' ' || "Tijd" || ':00'

    )

Om te te testen of een waarde LEEG of NULL is kun je ook de functie ‘coalesce’ gebruiken, dus de IF hierboven kun je ook schrijven als:

    # onderstaande betekent: geef de eerste NON null waarde terug: als Tijd dus NULL of leeg is, dan retourneer je ''
    coalesce( "Tijd", '') in ('', ' ', 'NULL', '-')

Een ander uitgebreider voorbeeld om een Datetime te maken van de individuele getalletjes:

    format_date(
        make_datetime(
            year(to_datetime( "datetime_start" )),
            month(to_datetime(  "datetime_start" )),
            day(to_datetime(  "datetime_start" )),
            hour(to_datetime(  "datetime_start" )),
            1+minute(to_datetime(  "datetime_start" )),
            second(to_datetime(  "datetime_start" ))
            ),
        'yyyy-MM-ddTHH:mm:ss'
    )

In de QGIS Expressie-builder staan veel voorbeelden bij de expressies.

## NDFF-Connector Plugin Technische handleiding

### Settings (mappen)

### NDFF settings

OAuth bij de plugin

### Dataset en configuratie

### Data-veld -> NDFF-veld mappings

### Data-waarde -> NDFF-uri mappings

### Locatie

### Extra velden

## NDFF-connector library (technisch)

OAuth bij de library

## Indices and tables

- Index

- Module Index

- Search Page