Documentatie NDFF Connector Plugin
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


.. contents:: `Inhoud`
   :depth: 5


Inleiding
=========

.. image:: img/NDFFlogo.png
   :alt: Het hoofdscherm van de plugin

De `Nationale Databank Flora en Fauna (NDFF) <https://ndff.nl>`_ 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 <https://qgis.org>`_ 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

.. image:: img/toolbar-icon.png
   :alt: De NDFF button

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.

.. image:: img/authorisatie_gegevens_leeg.png
   :alt: De (lege) dialoog voor de NDFF 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.

.. image:: img/plugin_main_window_leeg.png
   :alt: Het lege hoofdscherm van de plugin


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 )

.. image:: img/plugin_main_window.png
   :alt: Het hoofdscherm van de plugin


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.

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.

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'


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 (even de seconden ':00' erachter plakken)

::

    if(  "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'

    )

Een ander uitgebreider voorbeeld::

    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
------------

.. image:: img/plugin_main_window2.png
   :alt: Het hoofdscherm van de plugin


NDFF-connector library (technisch)
==================================

OAuth bij de library


Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

