diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/README.md b/abis_mapping/templates/incidental_occurrence_data_v2/README.md deleted file mode 100644 index d2595b7c..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Template Description -A template to translate some Darwin Core fields - -# Template Instructions -See `instructions.pdf` for more details diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.csv b/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.csv deleted file mode 100644 index bb22a2c8..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.csv +++ /dev/null @@ -1,17 +0,0 @@ -providerRecordID,providerRecordIDSource,locality,decimalLatitude,decimalLongitude,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,eventDate,samplingProtocol,basisOfRecord,recordedBy,recordNumber,occurrenceStatus,habitat,establishmentMeans,organismRemarks,individualCount,organismQuantity,organismQuantityType,lifeStage,sex,reproductiveCondition,ownerRecordID,ownerRecordIDSource,collectionCode,catalogNumber,catalogNumberSource,otherCatalogNumbers,otherCatalogNumbersSource,preparations,preparedDate,associatedSequences,sequencingMethod,verbatimIdentification,dateIdentified,identifiedBy,identificationMethod,scientificName,identificationQualifier,identificationRemarks,acceptedNameUsage,kingdom,taxonRank,threatStatus,conservationJurisdiction,threatStatusCheckProtocol,threatStatusDateDetermined,threatStatusDeterminedBy -1,WAM,Cowaramup Bay Road,-33.8,115.21,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Calothamnus lateralis var. crassus,,Stream Environment and Water Pty Ltd,,Calothamnus lateralis var. crassus,,,,Plantae,,,,,, -2,WAM,Cowaramup Bay Road,-33.86,115.01,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,, -3,WAM,Cowaramup Bay Road,-33.86,115.01,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,, -4,WAM,Cowaramup Bay Road,-33.86,115.01,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,, -5,WAM,Cowaramup Bay Road,-33.86,114.99,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,, -6,WAM,Cowaramup Bay Road,-33.86,114.99,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,, -7,WAM,Cowaramup Bay Road,-33.86,114.99,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,, -8022FSJMJ079c5cf,WAM,Cowaramup Bay Road,-33.86,114.99,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,, -9,WAM,Cowaramup Bay Road,-33.86,115.02,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,, -10,WAM,Cowaramup Bay Road,-33.86,115.02,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,, -11,WAM,Cowaramup Bay Road,-33.86,115.02,WGS84,,,26/09/2019,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia ?excelsa,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,?,One unopened flower when recorded and one leaf only. ID not confirmed,,Plantae,,,,,, -12,WAM,,-33.8,115.21,WGS84,,,26/09/2019,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,,,,Plantae,,,,,, -13,WAM,Cowaramup Bay Road,-33.86,115.02,WGS84,,,26/09/2019,,PreservedSpecimen,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,CC123,WAM,,,,,,,,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,, -14,WAM,Cowaramup Bay Road,-33.86,115.02,WGS84,20,Coordinates rounded to the nearest 10 km for conservation concern,26/09/2019,,HumanObservation,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,CC456,WAM,,,,,,,Caladenia ?excelsa,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,?,Could not confirm the ID due to damaged flower,,Plantae,,,,,, -8022FSJMJ079c5cf,WAM,Cowaramup Bay Road,-33.8,115.21,WGS84,50,Coordinates rounded to the nearest 10 km for conservation concern,26/09/2019,human observation,PreservedSpecimen,Stream Environment and Water Pty Ltd,PE:12:8832,present,"Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.",native,Dried out leaf tips,2,,,adult,male,No breeding evident,MR-456,Stream Environment and Water Pty Ltd,32237,ARACH,WAM,BHP2012-7521 | M12378,BHP,Wet (in ethanol or some other preservative),26/09/2019,https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1,Sanger dideoxy sequencing,Caladenia ?excelsa,2019-09-27T12:34+08:00,Stream Environment and Water Pty Ltd,Visually identified in the field (sighting),Caladenia excelsa,species incerta,no flowers present,Caladenia excelsa Hopper & A.P.Br.,Plantae,species,VU,WA,Check against Threatened and Priority Fauna List WA available from https://www.dpaw.wa.gov.au/plants-and-animals/threatened-species-and-communities/threatened-animals. Last updated 13 June 2022,,WA-BIO -ABC123,WAM,Cowaramup Bay Road,-33.8,115.21,WGS84,30,Coordinates generalised,26/09/2019,new sampling protocol,new basis of record,Stream Environment and Water Pty Ltd,PE:12:8833,new occurrence status,new habitat,new establishment means,Leaves brown,6,,,new life stage,new sex,new reproductiveCondition,MR-457,Stream Environment and Water Pty Ltd,32238,ARACH,WAM,BHP2012-7522 | M12379,BHP,new preparations,27/09/2019,https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1,new sequencing method,Caladenia ?excelsa,2019-09-27T12:34+08:00,Stream Environment and Water Pty Ltd,new identification method,Caladenia excelsa,new identification qualifier,new remarks,Caladenia excelsa Hopper & A.P.Br.,new kingdom,new taxon rank,new threat status,WA,a random selection,, diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.ttl b/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.ttl deleted file mode 100644 index 6d5cc592..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/examples/margaret_river_flora/margaret_river_flora.ttl +++ /dev/null @@ -1,2104 +0,0 @@ -@prefix dcterms: . -@prefix dwc: . -@prefix geo: . -@prefix prov: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix sosa: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - - a rdfs:Datatype ; - skos:prefLabel "catalogNumber source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:definition "An identifier for the dataset" ; - skos:prefLabel "Gaia Resources datasetID" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "otherCatalogNumbers source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "ownerRecordID source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "providerRecordID source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "recordNumber source" ; - prov:wasAttributedTo . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "acceptedNameUsage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa Hopper & A.P.Br." ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "acceptedNameUsage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa Hopper & A.P.Br." ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "establishmentMeans-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "native" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "establishmentMeans-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new establishment means" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "individualCount-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult 2 ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "individualCount-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult 6 ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "lifeStage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "adult" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "lifeStage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new life stage" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "occurrenceStatus-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "present" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "occurrenceStatus-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new occurrence status" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "organismRemarks-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Dried out leaf tips" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "organismRemarks-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Leaves brown" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "reproductiveCondition-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "No breeding evident" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "reproductiveCondition-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new reproductiveCondition" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Calothamnus lateralis var. crassus" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "sex-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "male" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "sex-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new sex" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "threatStatus-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - prov:wasInfluencedBy ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "VU" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "threatStatus-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasInfluencedBy ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new threat status" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Calothamnus lateralis var. crassus" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a prov:Agent ; - schema:name "WAM" . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "PreservedSpecimen" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "HumanObservation" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "PreservedSpecimen" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new basis of record" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "WA" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "WA" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam." ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new habitat" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "?" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "?" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "species incerta" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new identification qualifier" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "One unopened flower when recorded and one leaf only. ID not confirmed" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Could not confirm the ID due to damaged flower" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "no flowers present" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new remarks" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Wet (in ethanol or some other preservative)" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new preparations" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "species" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new taxon rank" ; - tern:hasValue . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of basisOfRecord." ; - skos:inScheme ; - skos:prefLabel "new basis of record" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationQualifier." ; - skos:inScheme ; - skos:prefLabel "new identification qualifier" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of preparations." ; - skos:inScheme ; - skos:prefLabel "Wet (in ethanol or some other preservative)" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of preparations." ; - skos:inScheme ; - skos:prefLabel "new preparations" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of taxonRank." ; - skos:inScheme ; - skos:prefLabel "new taxon rank" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:definition "The existence of the organism from this kingdom sampled at a particular place at a particular time." ; - skos:inScheme ; - skos:prefLabel "new kingdom occurrence" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:definition "A specimen sampled from an organism of this kingdom." ; - skos:inScheme ; - skos:prefLabel "new kingdom specimen" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of samplingProtocol." ; - skos:inScheme ; - skos:prefLabel "new sampling protocol" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sequencingMethod." ; - skos:inScheme ; - skos:prefLabel "Sanger dideoxy sequencing" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sequencingMethod." ; - skos:inScheme ; - skos:prefLabel "new sequencing method" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatusCheckProtocol." ; - skos:inScheme ; - skos:prefLabel "Check against Threatened and Priority Fauna List WA available from https://www.dpaw.wa.gov.au/plants-and-animals/threatened-species-and-communities/threatened-animals. Last updated 13 June 2022" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatusCheckProtocol." ; - skos:inScheme ; - skos:prefLabel "a random selection" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of establishmentMeans." ; - skos:inScheme ; - skos:prefLabel "new establishment means" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of lifeStage." ; - skos:inScheme ; - skos:prefLabel "new life stage" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of occurrenceStatus." ; - skos:inScheme ; - skos:prefLabel "new occurrence status" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of reproductiveCondition." ; - skos:inScheme ; - skos:prefLabel "No breeding evident" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of reproductiveCondition." ; - skos:inScheme ; - skos:prefLabel "new reproductiveCondition" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sex." ; - skos:inScheme ; - skos:prefLabel "new sex" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatus." ; - skos:inScheme ; - skos:prefLabel "WA/new threat status" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a prov:Agent ; - schema:name "BHP" . - - a prov:Agent ; - schema:name "WA-BIO" . - - a prov:Agent ; - schema:name "WAM" . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1" ; - void:inDataset ; - rdfs:comment "sequence-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1" ; - void:inDataset ; - rdfs:comment "sequence-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Calothamnus lateralis var. crassus" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation Jurisdiction = WA" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation Jurisdiction = WA" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates rounded to the nearest 10 km for conservation concern" . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates rounded to the nearest 10 km for conservation concern" . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates generalised" . - - a tern:IRI, - tern:Value ; - rdfs:label "establishmentMeans-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "establishmentMeans-value" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdfs:label "habitat" ; - rdf:value "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam." . - - a tern:Text, - tern:Value ; - rdfs:label "habitat" ; - rdf:value "new habitat" . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "One unopened flower when recorded and one leaf only. ID not confirmed" . - - a tern:Text, - tern:Value ; - rdf:value "Could not confirm the ID due to damaged flower" . - - a tern:Text, - tern:Value ; - rdf:value "no flowers present" . - - a tern:Text, - tern:Value ; - rdf:value "new remarks" . - - a tern:Integer, - tern:Value ; - rdfs:label "individual-count" ; - rdf:value 2 . - - a tern:Integer, - tern:Value ; - rdfs:label "individual-count" ; - rdf:value 6 . - - a tern:IRI, - tern:Value ; - rdfs:label "lifeStage-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "lifeStage-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "occurrenceStatus = present" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "occurrenceStatus = new occurrence status" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdfs:label "organism-remarks" ; - rdf:value "Dried out leaf tips" . - - a tern:Text, - tern:Value ; - rdfs:label "organism-remarks" ; - rdf:value "Leaves brown" . - - a tern:IRI, - tern:Value ; - rdfs:label "preparations" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "preparations" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "reproductiveCondition-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "reproductiveCondition-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "sex-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "sex-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "taxon rank = species" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "taxon rank = new taxon rank" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation status = VU" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation status = new threat status" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "Calothamnus lateralis var. crassus" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia excelsa" . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates rounded to the nearest 10 km for conservation concern" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates rounded to the nearest 10 km for conservation concern" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates generalised" ; - tern:hasValue . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationQualifier." ; - skos:inScheme ; - skos:prefLabel "?" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationMethod." ; - skos:inScheme ; - skos:prefLabel "Visually identified in the field (sighting)" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationMethod." ; - skos:inScheme ; - skos:prefLabel "new identification method" ; - schema:citation "http://createme.org/dataset/Example-Incidental-Occurrence-Dataset"^^xsd:anyURI . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "CC123"^^ ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:Sampling ; - dcterms:identifier "1"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000000 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "10"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000012 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "11"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000014 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "12"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000016 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure . - - a tern:Sampling ; - dcterms:identifier "13"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000018 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "14"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000001a ; - geo:hasMetricSpatialAccuracy 2e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "8022FSJMJ079c5cf"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000001c ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "ABC123"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000001e ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "2"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000002 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "3"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000004 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "4"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000006 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "5"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000008 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "6"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000000a ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "7"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000000c ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "8022FSJMJ079c5cf"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe80000000e ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "9"^^ ; - void:inDataset ; - geo:hasGeometry _:N30f52e03159b6f6cc4242fe800000010 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:N317ab8bbf18681ee0a7cf3da00000001 ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "sequencing-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:N317ab8bbf18681ee0a7cf3da00000003 ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "sequencing-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Nfa1da1f14c83ce86c3b5bdbd00000001 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Nfa1da1f14c83ce86c3b5bdbd00000003 ; - geo:hasMetricSpatialAccuracy 2e+01 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Nfa1da1f14c83ce86c3b5bdbd00000005 ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Nfa1da1f14c83ce86c3b5bdbd00000007 ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-27"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "acceptedNameUsage-value" ; - void:inDataset ; - rdf:value "Caladenia excelsa Hopper & A.P.Br." ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "acceptedNameUsage-value" ; - void:inDataset ; - rdf:value "Caladenia excelsa Hopper & A.P.Br." ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "CC456"^^ ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "MR-456"^^ ; - void:inDataset ; - dwc:otherCatalogNumbers "BHP2012-7521"^^, - "M12378"^^ ; - dwc:recordNumber "PE:12:8832"^^ ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "MR-457"^^ ; - void:inDataset ; - dwc:otherCatalogNumbers "BHP2012-7522"^^, - "M12379"^^ ; - dwc:recordNumber "PE:12:8833"^^ ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "ARACH"^^ ; - dwc:collectionCode "32237" ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType ; - tern:hasAttribute . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "ARACH"^^ ; - dwc:collectionCode "32238" ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType ; - tern:hasAttribute . - - a tern:FeatureOfInterest ; - void:inDataset ; - geo:hasGeometry [ a geo:Geometry ; - geo:sfWithin ] ; - tern:featureType . - - a prov:Agent ; - schema:name "Stream Environment and Water Pty Ltd" . - - a tern:Dataset ; - schema:dateCreated "2020-01-01"^^xsd:date ; - schema:dateIssued "2020-01-01"^^xsd:date ; - schema:description "Example Incidental Occurrence Dataset by Gaia Resources" ; - schema:name "Example Incidental Occurrence Dataset" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N317ab8bbf18681ee0a7cf3da00000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N317ab8bbf18681ee0a7cf3da00000003 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000000 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000002 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000004 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000006 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000008 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000000a ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000000c ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000000e ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000010 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000012 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000014 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000016 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe800000018 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000001a ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000001c ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N30f52e03159b6f6cc4242fe80000001e ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nfa1da1f14c83ce86c3b5bdbd00000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nfa1da1f14c83ce86c3b5bdbd00000003 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nfa1da1f14c83ce86c3b5bdbd00000005 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nfa1da1f14c83ce86c3b5bdbd00000007 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -_:N30f52e03159b6f6cc4242fe800000000 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000002 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000004 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000006 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000008 a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000000a a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000000c a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000000e a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000010 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000012 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000014 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000016 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe800000018 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000001a a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000001c a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:N30f52e03159b6f6cc4242fe80000001e a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:N317ab8bbf18681ee0a7cf3da00000001 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:N317ab8bbf18681ee0a7cf3da00000003 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Nfa1da1f14c83ce86c3b5bdbd00000001 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Nfa1da1f14c83ce86c3b5bdbd00000003 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Nfa1da1f14c83ce86c3b5bdbd00000005 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Nfa1da1f14c83ce86c3b5bdbd00000007 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/incidental_occurrence_data.csv b/abis_mapping/templates/incidental_occurrence_data_v2/incidental_occurrence_data.csv deleted file mode 100644 index 746ab31a..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/incidental_occurrence_data.csv +++ /dev/null @@ -1 +0,0 @@ -providerRecordID,providerRecordIDSource,locality,decimalLatitude,decimalLongitude,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,eventDate,samplingProtocol,basisOfRecord,recordedBy,recordNumber,occurrenceStatus,habitat,establishmentMeans,organismRemarks,individualCount,organismQuantity,organismQuantityType,lifeStage,sex,reproductiveCondition,ownerRecordID,ownerRecordIDSource,collectionCode,catalogNumber,catalogNumberSource,otherCatalogNumbers,otherCatalogNumbersSource,preparations,preparedDate,associatedSequences,sequencingMethod,verbatimIdentification,dateIdentified,identifiedBy,identificationMethod,scientificName,identificationQualifier,identificationRemarks,acceptedNameUsage,kingdom,taxonRank,threatStatus,conservationJurisdiction,threatStatusCheckProtocol,threatStatusDateDetermined,threatStatusDeterminedBy diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/mapping.py b/abis_mapping/templates/incidental_occurrence_data_v2/mapping.py deleted file mode 100644 index a7fb6f5e..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/mapping.py +++ /dev/null @@ -1,3166 +0,0 @@ -# Third-Party -import frictionless -import rdflib - -# Local -from abis_mapping import base -from abis_mapping import utils -from abis_mapping import plugins -from abis_mapping import models -from abis_mapping import vocabs - -# Typing -from typing import Iterator, Optional, Any - - -# Constants and Shortcuts -# These constants are specific to this template, and as such are defined here -# rather than in a common `utils` module. -a = rdflib.RDF.type -CONCEPT_AUSTRALIA = rdflib.URIRef("https://sws.geonames.org/2077456/") -CONCEPT_TAXON = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/70646576-6dc7-4bc5-a9d8-c4c366850df0") -CONCEPT_SITE = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/5bf7ae21-a454-440b-bdd7-f2fe982d8de4") -CONCEPT_ID_UNCERTAINTY = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/54e40f12-8c13-495a-9f8d-838d78faa5a7") -CONCEPT_ID_REMARKS = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/45a86abc-43c7-4a30-ac73-fc8d62538140") -CONCEPT_PROCEDURE_SAMPLING = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/7930424c-f2e1-41fa-9128-61524b67dbd5") -CONCEPT_SCIENTIFIC_NAME = utils.rdf.uri("concept/scientificName", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_DATA_GENERALIZATIONS = utils.rdf.uri( - "concept/data-generalizations", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_TAXON_RANK = utils.rdf.uri("concept/taxonRank", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_INDIVIDUAL_COUNT = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/74c71500-0bae-43c9-8db0-bd6940899af1") -CONCEPT_ORGANISM_REMARKS = utils.rdf.uri("concept/organismRemarks", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_HABITAT = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/2090cfd9-8b6b-497b-9512-497456a18b99") -CONCEPT_BASIS_OF_RECORD = utils.rdf.uri("concept/basisOfRecord", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_OCCURRENCE_STATUS = utils.rdf.uri("concept/occurrenceStatus", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_PREPARATIONS = utils.rdf.uri("concept/preparations", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_ESTABLISHMENT_MEANS = utils.rdf.uri( - "concept/establishmentMeans", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_LIFE_STAGE = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/abb0ee19-b2e8-42f3-8a25-d1f39ca3ebc3") -CONCEPT_SEX = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/05cbf534-c233-4aa8-a08c-00b28976ed36") -CONCEPT_REPRODUCTIVE_CONDITION = utils.rdf.uri( - "concept/reproductiveCondition", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_ACCEPTED_NAME_USAGE = utils.rdf.uri( - "concept/acceptedNameUsage", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_NAME_CHECK_METHOD = utils.rdf.uri( - "methods/name-check-method", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_SEQUENCE = utils.rdf.uri("concept/sequence", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_CONSERVATION_STATUS = rdflib.URIRef( - "http://linked.data.gov.au/def/tern-cv/1466cc29-350d-4a23-858b-3da653fd24a6" -) -CONCEPT_CONSERVATION_JURISDICTION = rdflib.URIRef( - "http://linked.data.gov.au/def/tern-cv/755b1456-b76f-4d54-8690-10e41e25c5a7" -) - -# Roles -ROLE_ORIGINATOR = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/originator" -) -ROLE_RIGHTS_HOLDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/rightsHolder" -) -ROLE_RESOURCE_PROVIDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/resourceProvider" -) -ROLE_CUSTODIAN = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/custodian" -) -ROLE_STAKEHOLDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/stakeholder" -) -ROLE_OWNER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/owner" -) - - -class IncidentalOccurrenceMapper(base.mapper.ABISMapper): - """ABIS Mapper for `incidental_occurrence_data.csv` - version 2""" - - # Default Dataset Metadata - DATASET_DEFAULT_NAME = "Example Incidental Occurrence Dataset" - DATASET_DEFAULT_DESCRIPTION = "Example Incidental Occurrence Dataset by Gaia Resources" - - def apply_validation( - self, - data: base.types.ReadableType, - **kwargs: Any, - ) -> frictionless.Report: - """Applies Frictionless Validation for the `incidental_occurrence_data.csv` Template - - Args: - data (base.types.ReadableType): Raw data to be validated. - **kwargs (Any): Additional keyword arguments. - - Returns: - frictionless.Report: Validation report for the specified data. - """ - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Validate - report: frictionless.Report = resource.validate( - checklist=frictionless.Checklist( - checks=[ - # Extra Custom Checks - plugins.tabular.IsTabular(), - plugins.empty.NotEmpty(), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["threatStatus", "conservationJurisdiction"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["catalogNumber", "catalogNumberSource"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["otherCatalogNumbers", "otherCatalogNumbersSource"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["ownerRecordID", "ownerRecordIDSource"], - ), - ], - ), - ) - - # Return Validation Report - return report - - def apply_mapping( - self, - data: base.types.ReadableType, - dataset_iri: Optional[rdflib.URIRef] = None, - base_iri: Optional[rdflib.Namespace] = None, - **kwargs: Any, - ) -> Iterator[rdflib.Graph]: - """Applies Mapping for the `incidental_occurrence_data.csv` Template - - Args: - data (base.types.ReadableType): Valid raw data to be mapped. - dataset_iri (Optional[rdflib.URIRef]): Optional dataset IRI. - base_iri (Optional[rdflib.Namespace]): Optional mapping base IRI. - - Keyword Args: - chunk_size (Optional[int]): How many rows of the original data to - ingest before yielding a graph. `None` will ingest all rows. - - Yields: - rdflib.Graph: ABIS Conformant RDF Sub-Graph from Raw Data Chunk. - """ - # Extract keyword arguments - chunk_size = kwargs.get("chunk_size") - if not isinstance(chunk_size, int) or chunk_size < 1: - chunk_size = None - - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - extra_schema = self.extra_fields_schema( - data=data, - full_schema=False, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Initialise Graph - graph = utils.rdf.create_graph() - - # Check if Dataset IRI Supplied - if not dataset_iri: - # Create Dataset IRI - dataset_iri = utils.rdf.uri(f"dataset/{self.DATASET_DEFAULT_NAME}", base_iri) - - # Add Example Default Dataset if not Supplied - self.add_default_dataset( - uri=dataset_iri, - base_iri=base_iri, - graph=graph, - ) - - # Create Terminal Feature of Interest IRI - terminal_foi = utils.rdf.uri("location/Australia", base_iri) - - # Add Terminal Feature of Interest (Australia) - self.add_terminal_feature_of_interest( - uri=terminal_foi, - dataset=dataset_iri, - graph=graph, - ) - - # Open the Resource to allow row streaming - with resource.open() as r: - # Loop through Rows - for row in r.row_stream: - # Map Row - self.apply_mapping_row( - row=row, - dataset=dataset_iri, - terminal_foi=terminal_foi, - graph=graph, - extra_schema=extra_schema, - base_iri=base_iri, - ) - - # Check Whether to Yield a Chunk - # The row_number needs to be reduced by one as the numbering of rows - # in a Resource includes the header - if chunk_size is not None and (row.row_number - 1) % chunk_size == 0: - # Yield Chunk - yield graph - - # Initialise New Graph - graph = utils.rdf.create_graph() - - # Yield - yield graph - - def apply_mapping_row( - self, - row: frictionless.Row, - dataset: rdflib.URIRef, - terminal_foi: rdflib.URIRef, - graph: rdflib.Graph, - extra_schema: frictionless.Schema, - base_iri: Optional[rdflib.Namespace] = None, - ) -> rdflib.Graph: - """Applies Mapping for a Row in the `incidental_occurrence_data.csv` Template - - Args: - row (frictionless.Row): Row to be processed in the dataset. - dataset (rdflib.URIRef): Dataset uri this row is apart of. - terminal_foi (rdflib.URIRef): Terminal feature of interest. - graph (rdflib.Graph): Graph to map row into. - extra_schema (frictionless.Schema): Schema of extra fields. - base_iri (Optional[rdflib.Namespace]): Optional base IRI namespace - to use for mapping. - - Returns: - rdflib.Graph: Graph with row mapped into it. - """ - # Set the row number to relate to the data itself, excluding header - row_num = row.row_number - 1 - - # Create URIs - provider_provider_record_id_src = utils.rdf.uri(f"provider/{row['providerRecordIDSource']}", base_iri) - provider_identified = utils.rdf.uri(f"provider/{row['identifiedBy']}", base_iri) - sample_field = utils.rdf.uri(f"sample/field/{row_num}", base_iri) - sampling_field = utils.rdf.uri(f"sampling/field/{row_num}", base_iri) - sample_specimen = utils.rdf.uri(f"sample/specimen/{row_num}", base_iri) - sampling_specimen = utils.rdf.uri(f"sampling/specimen/{row_num}", base_iri) - text_scientific_name = utils.rdf.uri(f"scientificName/{row_num}", base_iri) - text_verbatim_id = utils.rdf.uri(f"verbatimID/{row_num}", base_iri) - observation_scientific_name = utils.rdf.uri(f"observation/scientificName/{row_num}", base_iri) - observation_verbatim_id = utils.rdf.uri(f"observation/verbatimID/{row_num}", base_iri) - id_qualifier_attribute = utils.rdf.uri(f"attribute/identificationQualifier/{row_num}", base_iri) - id_qualifier_value = utils.rdf.uri(f"value/identificationQualifier/{row_num}", base_iri) - id_remarks_attribute = utils.rdf.uri(f"attribute/identificationRemarks/{row_num}", base_iri) - id_remarks_value = utils.rdf.uri(f"value/identificationRemarks/{row_num}", base_iri) - data_generalizations_attribute = utils.rdf.uri(f"attribute/dataGeneralizations/{row_num}", base_iri) - data_generalizations_value = utils.rdf.uri(f"value/dataGeneralizations/{row_num}", base_iri) - taxon_rank_attribute = utils.rdf.uri(f"attribute/taxonRank/{row_num}", base_iri) - taxon_rank_value = utils.rdf.uri(f"value/taxonRank/{row_num}", base_iri) - individual_count_observation = utils.rdf.uri(f"observation/individualCount/{row_num}", base_iri) - individual_count_value = utils.rdf.uri(f"value/individualCount/{row_num}", base_iri) - organism_remarks_observation = utils.rdf.uri(f"observation/organismRemarks/{row_num}", base_iri) - organism_remarks_value = utils.rdf.uri(f"value/organismRemarks/{row_num}", base_iri) - habitat_attribute = utils.rdf.uri(f"attribute/habitat/{row_num}", base_iri) - habitat_value = utils.rdf.uri(f"value/habitat/{row_num}", base_iri) - basis_attribute = utils.rdf.uri(f"attribute/basisOfRecord/{row_num}", base_iri) - basis_value = utils.rdf.uri(f"value/basisOfRecord/{row_num}", base_iri) - occurrence_status_observation = utils.rdf.uri(f"observation/occurrenceStatus/{row_num}", base_iri) - occurrence_status_value = utils.rdf.uri(f"value/occurrenceStatus/{row_num}", base_iri) - preparations_attribute = utils.rdf.uri(f"attribute/preparations/{row_num}", base_iri) - preparations_value = utils.rdf.uri(f"value/preparations/{row_num}", base_iri) - establishment_means_observation = utils.rdf.uri(f"observation/establishmentMeans/{row_num}", base_iri) - establishment_means_value = utils.rdf.uri(f"value/establishmentMeans/{row_num}", base_iri) - life_stage_observation = utils.rdf.uri(f"observation/lifeStage/{row_num}", base_iri) - life_stage_value = utils.rdf.uri(f"value/lifeStage/{row_num}", base_iri) - sex_observation = utils.rdf.uri(f"observation/sex/{row_num}", base_iri) - sex_value = utils.rdf.uri(f"value/sex/{row_num}", base_iri) - reproductive_condition_observation = utils.rdf.uri(f"observation/reproductiveCondition/{row_num}", base_iri) - reproductive_condition_value = utils.rdf.uri(f"value/reproductiveCondition/{row_num}", base_iri) - accepted_name_usage_observation = utils.rdf.uri(f"observation/acceptedNameUsage/{row_num}", base_iri) - accepted_name_usage_value = utils.rdf.uri(f"value/acceptedNameUsage/{row_num}", base_iri) - sampling_sequencing = utils.rdf.uri(f"sampling/sequencing/{row_num}", base_iri) - sample_sequence = utils.rdf.uri(f"sample/sequence/{row_num}", base_iri) - threat_status_observation = utils.rdf.uri(f"observation/threatStatus/{row_num}", base_iri) - threat_status_value = utils.rdf.uri(f"value/threatStatus/{row_num}", base_iri) - conservation_jurisdiction_attribute = utils.rdf.uri(f"attribute/conservationJurisdiction/{row_num}", base_iri) - conservation_jurisdiction_value = utils.rdf.uri(f"value/conservationJurisdiction/{row_num}", base_iri) - provider_determined_by = utils.rdf.uri(f"provider/{row['threatStatusDeterminedBy']}", base_iri) - provider_record_id_datatype = utils.rdf.uri( - internal_id=f"datatype/providerRecordID/{row['providerRecordIDSource']}", - namespace=base_iri, - ) - provider_record_id_agent = utils.rdf.uri(f"agent/{row['providerRecordIDSource']}", base_iri) - - # Conditionally create uris dependent on ownerRecordIDSource field - if owner_record_id_source := row["ownerRecordIDSource"]: - owner_record_id_datatype = utils.rdf.uri(f"datatype/ownerRecordID/{owner_record_id_source}", base_iri) - owner_record_id_provider = utils.rdf.uri(f"provider/{row['ownerRecordIDSource']}", base_iri) - else: - owner_record_id_datatype = None - owner_record_id_provider = None - - # Conditionally create uri's dependent on recordedBy field. - if recorded_by := row["recordedBy"]: - record_number_datatype = utils.rdf.uri(f"datatype/recordNumber/{recorded_by}", base_iri) - provider_recorded_by = utils.rdf.uri(f"provider/{recorded_by}", base_iri) - else: - record_number_datatype = None - provider_recorded_by = None - - # Conditionally create uris dependent on catalogNumberSource field. - if catalog_number_source := row["catalogNumberSource"]: - catalog_number_datatype = utils.rdf.uri(f"datatype/catalogNumber/{catalog_number_source}", base_iri) - catalog_number_provider = utils.rdf.uri(f"provider/{catalog_number_source}", base_iri) - else: - catalog_number_datatype = None - catalog_number_provider = None - - # Conditionally create uris dependent on otherCatalogNumbersSource field. - if other_catalog_numbers_source := row["otherCatalogNumbersSource"]: - other_catalog_numbers_datatype = utils.rdf.uri( - internal_id=f"datatype/otherCatalogNumbers/{other_catalog_numbers_source}", - namespace=base_iri, - ) - other_catalog_numbers_provider = utils.rdf.uri(f"provider/{other_catalog_numbers_source}", base_iri) - else: - other_catalog_numbers_datatype = None - other_catalog_numbers_provider = None - - # Add Provider Identified By - self.add_provider_identified( - uri=provider_identified, - row=row, - graph=graph, - ) - - # Add Sample Field - self.add_sample_field( - uri=sample_field, - row=row, - dataset=dataset, - feature_of_interest=terminal_foi, - sampling_field=sampling_field, - owner_record_id_datatype=owner_record_id_datatype, - other_catalog_numbers_datatype=other_catalog_numbers_datatype, - record_number_datatype=record_number_datatype, - graph=graph, - ) - - # Add record number datatype - self.add_record_number_datatype( - uri=record_number_datatype, - provider=provider_recorded_by, - graph=graph, - ) - - # Add provider provider agent - self.add_provider_recorded_by_agent( - uri=provider_recorded_by, - row=row, - graph=graph, - ) - - # Add owner record id datatype - self.add_owner_record_id_datatype( - uri=owner_record_id_datatype, - provider=owner_record_id_provider, - graph=graph, - ) - - # Add the provider owner record id - self.add_owner_record_id_provider( - uri=owner_record_id_provider, - row=row, - graph=graph, - ) - - # Add Sampling Field - self.add_sampling_field( - uri=sampling_field, - row=row, - dataset=dataset, - provider_record_id_source=provider_record_id_datatype, - provider=provider_recorded_by, - feature_of_interest=terminal_foi, - sample_field=sample_field, - generalizations=data_generalizations_attribute, - habitat=habitat_attribute, - basis=basis_attribute, - graph=graph, - ) - - # Add provider record ID datatype - self.add_provider_record_id_datatype( - uri=provider_record_id_datatype, - agent=provider_record_id_agent, - graph=graph, - ) - - # Add provider agent - self.add_provider_record_id_agent( - uri=provider_record_id_agent, - row=row, - graph=graph, - ) - - # Add Sample Specimen - self.add_sample_specimen( - uri=sample_specimen, - row=row, - dataset=dataset, - sampling_specimen=sampling_specimen, - sample_field=sample_field, - preparations=preparations_attribute, - catalog_number_datatype=catalog_number_datatype, - graph=graph, - ) - - # Add catalog number datatype - self.add_catalog_number_datatype( - uri=catalog_number_datatype, - provider=catalog_number_provider, - graph=graph, - ) - - # Add catalog number provider - self.add_catalog_number_provider( - uri=catalog_number_provider, - row=row, - graph=graph, - ) - - # Add other catalog numbers datatype - self.add_other_catalog_numbers_datatype( - uri=other_catalog_numbers_datatype, - provider=other_catalog_numbers_provider, - graph=graph, - ) - - # Add other catalog numbers provider - self.add_other_catalog_numbers_provider( - uri=other_catalog_numbers_provider, - row=row, - graph=graph, - ) - - # Add Sampling Specimen - self.add_sampling_specimen( - uri=sampling_specimen, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - generalizations=data_generalizations_attribute, - basis=basis_attribute, - graph=graph, - ) - - # Add Text for Scientific Name - self.add_text_scientific_name( - uri=text_scientific_name, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add Identification Qualifier Attribute - self.add_id_qualifier_attribute( - uri=id_qualifier_attribute, - row=row, - dataset=dataset, - id_qualifier_value=id_qualifier_value, - graph=graph, - ) - - # Add Identification Qualifier Value - self.add_id_qualifier_value( - uri=id_qualifier_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Identification Remarks Attribute - self.add_id_remarks_attribute( - uri=id_remarks_attribute, - row=row, - dataset=dataset, - id_remarks_value=id_remarks_value, - graph=graph, - ) - - # Add Identification Remarks Value - self.add_id_remarks_value( - uri=id_remarks_value, - row=row, - graph=graph, - ) - - # Add Text for Verbatim ID - self.add_text_verbatim_id( - uri=text_verbatim_id, - row=row, - graph=graph, - ) - - # Add Observation for Scientific Name - self.add_observation_scientific_name( - uri=observation_scientific_name, - row=row, - dataset=dataset, - provider=provider_identified, - sample_field=sample_field, - sample_specimen=sample_specimen, - scientific_name=text_scientific_name, - qualifier=id_qualifier_attribute, - remarks=id_remarks_attribute, - taxon_rank=taxon_rank_attribute, - graph=graph, - ) - - # Add Observation for Verbatim ID - self.add_observation_verbatim_id( - uri=observation_verbatim_id, - row=row, - dataset=dataset, - provider=provider_identified, - sample_field=sample_field, - sample_specimen=sample_specimen, - verbatim_id=text_verbatim_id, - graph=graph, - ) - - # Add Data Generalizations Attribute - self.add_data_generalizations_attribute( - uri=data_generalizations_attribute, - row=row, - dataset=dataset, - data_generalizations_value=data_generalizations_value, - graph=graph, - ) - - # Add Data Generalizations Value - self.add_data_generalizations_value( - uri=data_generalizations_value, - row=row, - graph=graph, - ) - - # Add Taxon Rank Attribute - self.add_taxon_rank_attribute( - uri=taxon_rank_attribute, - row=row, - dataset=dataset, - taxon_rank_value=taxon_rank_value, - graph=graph, - ) - - # Add Taxon Rank Value - self.add_taxon_rank_value( - uri=taxon_rank_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Individual Count Observation - self.add_individual_count_observation( - uri=individual_count_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - individual_count_value=individual_count_value, - graph=graph, - ) - - # Add Individual Count Value - self.add_individual_count_value( - uri=individual_count_value, - row=row, - graph=graph, - ) - - # Add Organism Remarks Observation - self.add_organism_remarks_observation( - uri=organism_remarks_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - organism_remarks_value=organism_remarks_value, - graph=graph, - ) - - # Add Organism Remarks Value - self.add_organism_remarks_value( - uri=organism_remarks_value, - row=row, - graph=graph, - ) - - # Add Habitat Attribute - self.add_habitat_attribute( - uri=habitat_attribute, - row=row, - dataset=dataset, - habitat_value=habitat_value, - graph=graph, - ) - - # Add Habitat Value - self.add_habitat_value( - uri=habitat_value, - row=row, - graph=graph, - ) - - # Add Basis of Record Attribute - self.add_basis_attribute( - uri=basis_attribute, - row=row, - dataset=dataset, - basis_value=basis_value, - graph=graph, - ) - - # Add Basis of Record Value - self.add_basis_value( - uri=basis_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Owner Institution Provider - self.add_owner_institution_provider( - uri=owner_record_id_provider, - row=row, - graph=graph, - ) - - # Add provider record id provider - self.add_provider_record_id_provider( - uri=provider_provider_record_id_src, - row=row, - graph=graph, - ) - - # Add Occurrence Status Observation - self.add_occurrence_status_observation( - uri=occurrence_status_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - occurrence_status_value=occurrence_status_value, - graph=graph, - ) - - # Add Occurrence Status Value - self.add_occurrence_status_value( - uri=occurrence_status_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Preparations Attribute - self.add_preparations_attribute( - uri=preparations_attribute, - row=row, - dataset=dataset, - preparations_value=preparations_value, - graph=graph, - ) - - # Add Preparations Value - self.add_preparations_value( - uri=preparations_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Establishment Means Observation - self.add_establishment_means_observation( - uri=establishment_means_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - establishment_means_value=establishment_means_value, - graph=graph, - ) - - # Add Establishment Means Value - self.add_establishment_means_value( - uri=establishment_means_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Life Stage Observation - self.add_life_stage_observation( - uri=life_stage_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - life_stage_value=life_stage_value, - graph=graph, - ) - - # Add Life Stage Value - self.add_life_stage_value( - uri=life_stage_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Sex Observation - self.add_sex_observation( - uri=sex_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - sex_value=sex_value, - graph=graph, - ) - - # Add Sex Value - self.add_sex_value( - uri=sex_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Reproductive Condition Observation - self.add_reproductive_condition_observation( - uri=reproductive_condition_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - reproductive_condition_value=reproductive_condition_value, - graph=graph, - ) - - # Add Reproductive Condition Value - self.add_reproductive_condition_value( - uri=reproductive_condition_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Accepted Name Usage Observation - self.add_accepted_name_usage_observation( - uri=accepted_name_usage_observation, - row=row, - dataset=dataset, - scientific_name=text_scientific_name, - accepted_name_usage_value=accepted_name_usage_value, - graph=graph, - ) - - # Add Accepted Name Usage Value - self.add_accepted_name_usage_value( - uri=accepted_name_usage_value, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add Sampling Sequencing - self.add_sampling_sequencing( - uri=sampling_sequencing, - row=row, - dataset=dataset, - feature_of_interest=sample_specimen, - sample_sequence=sample_sequence, - graph=graph, - ) - - # Add Sample Sequence - self.add_sample_sequence( - uri=sample_sequence, - row=row, - dataset=dataset, - feature_of_interest=sample_specimen, - sampling_sequencing=sampling_sequencing, - graph=graph, - ) - - # Add Provider Threat Status Determined By - self.add_provider_determined_by( - uri=provider_determined_by, - row=row, - graph=graph, - ) - - # Add Threat Status Observation - self.add_threat_status_observation( - uri=threat_status_observation, - row=row, - dataset=dataset, - accepted_name_usage=accepted_name_usage_value, - scientific_name=text_scientific_name, - threat_status_value=threat_status_value, - jurisdiction_attribute=conservation_jurisdiction_attribute, - determined_by=provider_determined_by, - graph=graph, - ) - - # Add Threat Status Value - self.add_threat_status_value( - uri=threat_status_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Conservation Jurisdiction Attribute - self.add_conservation_jurisdiction_attribute( - uri=conservation_jurisdiction_attribute, - row=row, - dataset=dataset, - conservation_jurisdiction_value=conservation_jurisdiction_value, - graph=graph, - ) - - # Add Conservation Jurisdiction Value - self.add_conservation_jurisdiction_value( - uri=conservation_jurisdiction_value, - row=row, - graph=graph, - ) - - # Add extra fields JSON - self.add_extra_fields_json( - subject_uri=sampling_field, - row=row, - graph=graph, - extra_schema=extra_schema, - ) - - # Return - return graph - - def add_terminal_feature_of_interest( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds the Terminal Feature of Interest to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Add Terminal Feature of Interest to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SITE)) - - # Add Geometry - geometry = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry)) - graph.add((geometry, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry, utils.namespaces.GEO.sfWithin, CONCEPT_AUSTRALIA)) - - def add_provider_identified( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Identified By Provider to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for identifiedBy - if not row["identifiedBy"]: - return - - # Add to Graph - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["identifiedBy"]))) - - def add_observation_scientific_name( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - scientific_name: rdflib.URIRef, - qualifier: rdflib.URIRef, - remarks: rdflib.URIRef, - taxon_rank: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Observation Scientific Name to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider (rdflib.URIRef): Provider associated with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - qualifier (rdflib.URIRef): Identification Qualifier attribute - associated with this node - remarks (rdflib.URIRef): Identification Remarks attribute - associated with this node - taxon_rank (rdflib.URIRef): Taxon Rank attribute associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Get Timestamp - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve vocab for field - vocab = self.fields()["identificationMethod"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("scientificName-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, scientific_name)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["scientificName"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Check for identifiedBy - if row["identifiedBy"]: - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for dateIdentified - if not row["dateIdentified"]: - # Add comment to temporal entity - comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - # Check for identificationQualifier - if row["identificationQualifier"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, qualifier)) - - # Check for identificationRemarks - if row["identificationRemarks"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, remarks)) - - # Check for taxonRank - if row["taxonRank"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, taxon_rank)) - - def add_observation_verbatim_id( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - verbatim_id: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Observation Verbatim ID to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider (rdflib.URIRef): Provider associated with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - verbatim_id (rdflib.URIRef): Verbatim ID associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check for verbatimIdentification - if not row["verbatimIdentification"]: - return - - # Get Timestamp - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve vocab for field - vocab = self.fields()["identificationMethod"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("verbatimID-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, verbatim_id)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["verbatimIdentification"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Check for identifiedBy - if row["identifiedBy"]: - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for dateIdentified - if not row["dateIdentified"]: - # Add comment to temporal entity - comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - def add_provider_recorded_by_agent( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the provider agent to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Ensure data and URI passed in - if uri is None or not row["recordedBy"]: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["recordedBy"]))) - - def add_owner_record_id_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds the owner record id datatype to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - provider (rdflib.URIRef): Provider of the datatype. - graph (rdflid.Graph): Graph to be modified. - """ - # Check to see subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("ownerRecordID source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_owner_record_id_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the provider owner record id node. - - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified.: - """ - # Check that a subject uri was supplied - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["ownerRecordIDSource"]))) - - def add_sampling_field( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider_record_id_source: rdflib.URIRef, - provider: rdflib.URIRef | None, - feature_of_interest: rdflib.URIRef, - sample_field: rdflib.URIRef, - generalizations: rdflib.URIRef, - habitat: rdflib.URIRef, - basis: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Field to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider_record_id_source (rdflib.URIRef): Provider record id source - associated with this node. - provider (rdflib.URIRef | None): Provider associated with this node - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node. - sample_field (rdflib.URIRef): Sample Field associated with this - node - generalizations (rdflib.URIRef): Data Generalizations associated - with this node - habitat (rdflib.URIRef): Habitat associated with this node - basis (rdflib.URIRef): Basis Of Record associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Extract values from row - event_date: models.temporal.Timestamp = row["eventDate"] - - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(row["decimalLatitude"], row["decimalLongitude"]), datum=row["geodeticDatum"] - ) - - # Retrieve vocab for field - vocab = self.fields()["samplingProtocol"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["samplingProtocol"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("field-sampling"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, feature_of_interest)) - graph.add((uri, rdflib.SOSA.hasResult, sample_field)) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - - # Add 'supplied as' geometry - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Add temporal members - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Add Identifier - graph.add( - ( - uri, - rdflib.DCTERMS.identifier, - rdflib.Literal(row["providerRecordID"], datatype=provider_record_id_source), - ) - ) - - # Check for recordedBy - if row["recordedBy"] and provider is not None: - # Add Associated Provider - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for locality - if row["locality"]: - # Add Location Description - graph.add((uri, utils.namespaces.TERN.locationDescription, rdflib.Literal(row["locality"]))) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Check for dataGeneralizations - if row["dataGeneralizations"]: - # Add Data Generalizations Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, generalizations)) - - # Check for habitat - if row["habitat"]: - # Add Habitat Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, habitat)) - - # Check for basisOfRecord and if Row has no Specimen - if not has_specimen(row) and row["basisOfRecord"]: - # Add Basis Of Record Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, basis)) - - def add_provider_record_id_datatype( - self, - uri: rdflib.URIRef, - agent: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds the provider record id datatype to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - agent (rdflib.URIRef): Provider agent URI. - graph (rdflib.Graph): Graph to be modified. - """ - # Add the type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("providerRecordID source"))) - - # Add attribution - graph.add((uri, rdflib.PROV.wasAttributedTo, agent)) - - def add_provider_record_id_agent( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds provider record id agent to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["providerRecordIDSource"]))) - - def add_id_qualifier_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - id_qualifier_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Qualifier Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - id_qualifier_value (rdflib.URIRef): Identification Qualifier Value - associated with this node. - graph (rdflib.Graph): Graph to add to - """ - # Check identificationQualifier - if not row["identificationQualifier"]: - return - - # Identification Qualifier Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_ID_UNCERTAINTY)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["identificationQualifier"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, id_qualifier_value)) - - def add_id_qualifier_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Qualifier Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check identificationQualifier - if not row["identificationQualifier"]: - return - - # Retrieve vocab for field - vocab = self.fields()["identificationQualifier"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationQualifier"]) - - # Identification Qualifier Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("identificationQualifier"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_id_remarks_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - id_remarks_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Remarks Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - id_remarks_value (rdflib.URIRef): Identification Remarks Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check identificationRemarks - if not row["identificationRemarks"]: - return - - # Identification Remarks Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_ID_REMARKS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["identificationRemarks"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, id_remarks_value)) - - def add_id_remarks_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Remarks Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check identificationRemarks - if not row["identificationRemarks"]: - return - - # Identification Remarks Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["identificationRemarks"]))) - - def add_text_scientific_name( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Text Scientific Name to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset this belongs to - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("scientificName"))) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["scientificName"]))) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SCIENTIFIC_NAME)) - - def add_catalog_number_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds catalog number datatype to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - provider (rdflib.URIRef | None): Corresponding provider. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("catalogNumber source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_catalog_number_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the catalog number provider to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["catalogNumberSource"]))) - - def add_other_catalog_numbers_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds other catalog numbers datatype to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - provider (rdflib.URIRef | None): Corresponding provider. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("otherCatalogNumbers source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_other_catalog_numbers_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds other catalog numbers provider to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check that subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["otherCatalogNumbersSource"]))) - - def add_sampling_specimen( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - generalizations: rdflib.URIRef, - basis: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Specimen to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - generalizations (rdflib.URIRef): Data Generalizations associated - with this node - basis (rdflib.URIRef): Basis Of Record associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check if Row has a Specimen - if not has_specimen(row): - return - - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(row["decimalLatitude"], row["decimalLongitude"]), - datum=row["geodeticDatum"], - ) - - # Get Timestamp - timestamp: models.temporal.Timestamp = row["preparedDate"] or row["eventDate"] - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("specimen-sampling"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, sample_specimen)) - graph.add((uri, rdflib.SOSA.usedProcedure, CONCEPT_PROCEDURE_SAMPLING)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, timestamp.rdf_in_xsd, timestamp.to_rdf_literal())) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - spatial_comment = "Location unknown, location of field sampling used as proxy" - graph.add((geometry_node, rdflib.RDFS.comment, rdflib.Literal(spatial_comment))) - - # Add 'supplied as' geometry - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Check for preparedDate - if not row["preparedDate"]: - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Check for dataGeneralizations - if row["dataGeneralizations"]: - # Add Data Generalizations Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, generalizations)) - - # Check for basisOfRecord and if Row has a Specimen - if has_specimen(row) and row["basisOfRecord"]: - # Add Basis Of Record Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, basis)) - - def add_text_verbatim_id( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Text Verbatim ID to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for verbatimIdentification - if not row["verbatimIdentification"]: - return - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["verbatimIdentification"]))) - - def add_sample_field( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sampling_field: rdflib.URIRef, - owner_record_id_datatype: rdflib.URIRef | None, - other_catalog_numbers_datatype: rdflib.URIRef | None, - record_number_datatype: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Field to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node. - sampling_field (rdflib.URIRef): Sampling Field associated with this - node - owner_record_id_datatype (rdflib.URIRef | None): Source of owner ID - used as datatype. - other_catalog_numbers_datatype (rdflib.URIRef): Datatype to use - with other catalog numbers literals. - record_number_datatype (rdflib.URIRef | None): Datatype to use - with record number literal. - graph (rdflib.Graph): Graph to add to - """ - # Retrieve vocab for field - vocab = self.fields()["kingdom"].get_vocab("KINGDOM_OCCURRENCE") - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["kingdom"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("field-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_field)) - graph.add((uri, rdflib.SOSA.isSampleOf, feature_of_interest)) - graph.add((uri, utils.namespaces.TERN.featureType, term)) - - # Check for recordNumber - if row["recordNumber"]: - # Determine which datatype to use for literal - dt = record_number_datatype or rdflib.XSD.string - # Add to Graph - graph.add((uri, utils.namespaces.DWC.recordNumber, rdflib.Literal(row["recordNumber"], datatype=dt))) - - # Check for ownerRecordID - if (owner_record_id := row["ownerRecordID"]) and owner_record_id_datatype: - # Add to Graph - graph.add( - (uri, rdflib.DCTERMS.identifier, rdflib.Literal(owner_record_id, datatype=owner_record_id_datatype)) - ) - - # Check for otherCatalogNumbers - if (other_catalog_numbers := row["otherCatalogNumbers"]) and other_catalog_numbers_datatype is not None: - # Iterate through the catalog numbers - for num in other_catalog_numbers: - # Add catalog number literal - graph.add( - ( - uri, - utils.namespaces.DWC.otherCatalogNumbers, - rdflib.Literal(num, datatype=other_catalog_numbers_datatype), - ) - ) - - def add_record_number_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds record number datatype to the graph. - - Args: - uri (rdflib.URIRef | None): The subject of the node - or None if uri wasn't created. - provider (rdflib.URIRef | None): The corresponding - provider uri. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("recordNumber source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_sample_specimen( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sampling_specimen: rdflib.URIRef, - sample_field: rdflib.URIRef, - preparations: rdflib.URIRef, - catalog_number_datatype: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Specimen to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sampling_specimen (rdflib.URIRef): Sampling Specimen associated - with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - preparations (rdflib.URIRef): Preparations Attribute associated - with this node - catalog_number_datatype (rdflib.URIRef): Catalog number source - datatype. - graph (rdflib.Graph): Graph to add to - """ - # Check if Row has a Specimen - if not has_specimen(row): - return - - # Retrieve vocab for field - vocab = self.fields()["kingdom"].get_vocab("KINGDOM_SPECIMEN") - - # Retrieve Vocab or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["kingdom"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("specimen-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_specimen)) - graph.add((uri, rdflib.SOSA.isSampleOf, sample_field)) - graph.add((uri, utils.namespaces.TERN.featureType, term)) - - # Check for catalogNumber - if row["catalogNumber"]: - # Add to Graph - graph.add( - ( - uri, - utils.namespaces.DWC.catalogNumber, - rdflib.Literal(row["catalogNumber"], datatype=catalog_number_datatype), - ) - ) - - # Check for collectionCode - if row["collectionCode"]: - # Add to Graph - graph.add((uri, utils.namespaces.DWC.collectionCode, rdflib.Literal(row["collectionCode"]))) - - # Check for preparations - if row["preparations"]: - # Add Preparations - graph.add((uri, utils.namespaces.TERN.hasAttribute, preparations)) - - def add_data_generalizations_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - data_generalizations_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Data Generalizations Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - data_generalizations_value (rdflib.URIRef): Data Generalizations - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["dataGeneralizations"]: - return - - # Data Generalizations Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_DATA_GENERALIZATIONS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["dataGeneralizations"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, data_generalizations_value)) - - def add_data_generalizations_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Data Generalizations Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["dataGeneralizations"]: - return - - # Data Generalizations Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["dataGeneralizations"]))) - - def add_taxon_rank_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - taxon_rank_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Taxon Rank Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - taxon_rank_value (rdflib.URIRef): Taxon Rank Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["taxonRank"]: - return - - # Taxon Rank Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_TAXON_RANK)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["taxonRank"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, taxon_rank_value)) - - def add_taxon_rank_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Taxon Rank Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["taxonRank"]: - return - # Retrieve vocab for field - vocab = self.fields()["taxonRank"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["taxonRank"]) - - # Taxon Rank Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"taxon rank = {row['taxonRank']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_individual_count_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - individual_count_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Individual Count Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - individual_count_value (rdflib.URIRef): Individual Count Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["individualCount"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Individual Count Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("individualCount-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, individual_count_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["individualCount"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_INDIVIDUAL_COUNT)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add Method Qualifier comment - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_individual_count_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Individual Count Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["individualCount"]: - return - - # Individual Count Value - graph.add((uri, a, utils.namespaces.TERN.Integer)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("individual-count"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["individualCount"]))) - - def add_organism_remarks_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - organism_remarks_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Organism Remarks Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - organism_remarks_value (rdflib.URIRef): Organism Remarks Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["organismRemarks"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Organism Remarks Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("organismRemarks-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, organism_remarks_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["organismRemarks"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_ORGANISM_REMARKS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_organism_remarks_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Organism Remarks Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["organismRemarks"]: - return - - # Organism Remarks Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("organism-remarks"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["organismRemarks"]))) - - def add_habitat_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - habitat_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Habitat Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - habitat_value (rdflib.URIRef): Habitat Value associated with this - node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["habitat"]: - return - - # Habitat Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_HABITAT)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["habitat"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, habitat_value)) - - def add_habitat_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Habitat Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["habitat"]: - return - - # Habitat Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("habitat"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["habitat"]))) - - def add_basis_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - basis_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Basis of Record Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - basis_value (rdflib.URIRef): Basis of Record Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["basisOfRecord"]: - return - - # Basis of Record Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_BASIS_OF_RECORD)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["basisOfRecord"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, basis_value)) - - def add_basis_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Basis of Record Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["basisOfRecord"]: - return - - # Retrieve vocab for field - vocab = self.fields()["basisOfRecord"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["basisOfRecord"]) - - # Basis of Record Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("basisOfRecord"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_owner_institution_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Owner Institution Provider to the Graph - - Args: - uri (rdflib.URIRef | None): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # TODO -> Retrieve this from a known list of institutions - # Check Existence - if not row["ownerRecordIDSource"] or uri is None: - return - - # Owner Institution Provider - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["ownerRecordIDSource"]))) - - def add_provider_record_id_provider( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds provider record id provider to the graph. - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # TODO -> Retrieve this from a known list of institutions - # Institution Provider - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["providerRecordIDSource"]))) - - def add_occurrence_status_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - occurrence_status_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Occurrence Status Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - occurrence_status_value (rdflib.URIRef): Occurrence Status Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["occurrenceStatus"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Occurrence Status Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("occurrenceStatus-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, occurrence_status_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["occurrenceStatus"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_OCCURRENCE_STATUS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_occurrence_status_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Occurrence Status Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["occurrenceStatus"]: - return - - # Retrieve vocab for field - vocab = self.fields()["occurrenceStatus"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["occurrenceStatus"]) - - # Occurrence Status Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"occurrenceStatus = {row['occurrenceStatus']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_preparations_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - preparations_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Preparations Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - preparations_value (rdflib.URIRef): Preparations Value associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["preparations"]: - return - - # Preparations Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_PREPARATIONS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["preparations"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, preparations_value)) - - def add_preparations_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Preparations Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["preparations"]: - return - - # Retrieve vocab for field - vocab = self.fields()["preparations"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["preparations"]) - - # Preparations Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("preparations"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_establishment_means_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - establishment_means_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Establishment Means Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - establishment_means_value (rdflib.URIRef): Establishment Means - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["establishmentMeans"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Establishment Means Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("establishmentMeans-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, establishment_means_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["establishmentMeans"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_ESTABLISHMENT_MEANS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_establishment_means_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Establishment Means Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["establishmentMeans"]: - return - - # Retrieve vocab for field - vocab = self.fields()["establishmentMeans"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["establishmentMeans"]) - - # Establishment Means Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("establishmentMeans-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_life_stage_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - life_stage_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Life Stage Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - life_stage_value (rdflib.URIRef): Life Stage Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["lifeStage"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Life Stage Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("lifeStage-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, life_stage_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["lifeStage"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_LIFE_STAGE)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_life_stage_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Life Stage Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["lifeStage"]: - return - - # Retrieve vocab for field - vocab = self.fields()["lifeStage"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["lifeStage"]) - - # Life Stage Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("lifeStage-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_sex_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - sex_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sex Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - sex_value (rdflib.URIRef): Sex Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["sex"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Sex Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sex-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, sex_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["sex"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_SEX)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_sex_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sex Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["sex"]: - return - - # Retrieve vocab for field - vocab = self.fields()["sex"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["sex"]) - - # Sex Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("sex-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_reproductive_condition_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - reproductive_condition_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Reproductive Condition Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - reproductive_condition_value (rdflib.URIRef): Reproductive - Condition Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["reproductiveCondition"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Reproductive Condition Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("reproductiveCondition-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, reproductive_condition_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["reproductiveCondition"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_REPRODUCTIVE_CONDITION)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_reproductive_condition_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Reproductive Condition Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["reproductiveCondition"]: - return - - # Retrieve vocab for field - vocab = self.fields()["reproductiveCondition"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["reproductiveCondition"]) - - # Reproductive Condition Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("reproductiveCondition-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_accepted_name_usage_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - scientific_name: rdflib.URIRef, - accepted_name_usage_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Accepted Name Usage Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - accepted_name_usage_value (rdflib.URIRef): Accepted Name Usage - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["acceptedNameUsage"]: - return - - # Get Timestamp - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Accepted Name Usage Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("acceptedNameUsage-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, scientific_name)) - graph.add((uri, rdflib.SOSA.hasResult, accepted_name_usage_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["acceptedNameUsage"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - graph.add((uri, rdflib.SOSA.usedProcedure, CONCEPT_NAME_CHECK_METHOD)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - - # Add comment to temporal entity - timestamp_used = "dateIdentified" if row["dateIdentified"] else "eventDate" # Determine which field was used - temporal_comment = f"Date unknown, template {timestamp_used} used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - def add_accepted_name_usage_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Accepted Name Usage Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - dataset (rdflib.URIRef): Dataset this belongs to - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["acceptedNameUsage"]: - return - - # Accepted Name Usage Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("acceptedNameUsage-value"))) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["acceptedNameUsage"]))) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_ACCEPTED_NAME_USAGE)) - - def add_sampling_sequencing( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sample_sequence: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Sequencing to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node - sample_sequence (rdflib.URIRef): Sample Sequence associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Extract values from row - event_date: models.temporal.Timestamp = row["eventDate"] - - # Check Existence - if not row["associatedSequences"]: - return - - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(row["decimalLatitude"], row["decimalLongitude"]), - datum=row["geodeticDatum"], - ) - - # Retrieve vocab for field - vocab = self.fields()["sequencingMethod"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["sequencingMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sequencing-sampling"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, feature_of_interest)) - graph.add((uri, rdflib.SOSA.hasResult, sample_sequence)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - - # Add 'supplied as' geometry - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add comment to geometry - spatial_comment = "Location unknown, location of field sampling used as proxy" - graph.add((geometry_node, rdflib.RDFS.comment, rdflib.Literal(spatial_comment))) - - def add_sample_sequence( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sampling_sequencing: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Sequence to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node - sampling_sequencing (rdflib.URIRef): Sampling Sequencing associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["associatedSequences"]: - return - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sequence-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_sequencing)) - graph.add((uri, rdflib.SOSA.isSampleOf, feature_of_interest)) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SEQUENCE)) - - # Loop Through Associated Sequences - for identifier in row["associatedSequences"]: - # Add Identifier - graph.add((uri, rdflib.DCTERMS.identifier, rdflib.Literal(identifier))) - - def add_provider_determined_by( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Determined By Provider to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for threatStatusDeterminedBy - if not row["threatStatusDeterminedBy"]: - return - - # Add to Graph - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["threatStatusDeterminedBy"]))) - - def add_threat_status_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - accepted_name_usage: rdflib.URIRef, - scientific_name: rdflib.URIRef, - threat_status_value: rdflib.URIRef, - jurisdiction_attribute: rdflib.URIRef, - determined_by: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Threat Status Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - accepted_name_usage (rdflib.URIRef): Accepted Name Usage associated - with this node - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - threat_status_value (rdflib.URIRef): Threat Status Value associated - with this node - jurisdiction_attribute (rdflib.URIRef): Conservation Jurisdiction - Attribute associated with this node - determined_by (rdflib.URIRef): Determined By Provider associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["threatStatus"]: - return - - # Choose Feature of Interest - # Feature of Interest is the Accepted Name Usage Value if it exists, - # otherwise it is the Scientific Name Text - foi = accepted_name_usage if row["acceptedNameUsage"] else scientific_name - - # Get Timestamp - # Prefer `threatStatusDateDetermined` > `dateIdentified` > `eventDate` (fallback) - date_determined: models.temporal.Timestamp = ( - row["threatStatusDateDetermined"] or row["dateIdentified"] or row["preparedDate"] or row["eventDate"] - ) - - # Retrieve vocab for field - vocab = self.fields()["threatStatusCheckProtocol"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["threatStatusCheckProtocol"]) - - # Threat Status Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("threatStatus-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, threat_status_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["threatStatus"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_CONSERVATION_STATUS)) - graph.add((uri, rdflib.PROV.wasInfluencedBy, jurisdiction_attribute)) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_determined.rdf_in_xsd, date_determined.to_rdf_literal())) - - # Check for threatStatusDeterminedBy - if row["threatStatusDeterminedBy"]: - # Add wasAssociatedWith - graph.add((uri, rdflib.PROV.wasAssociatedWith, determined_by)) - - # Check for threatStatusDateDetermined - if not row["threatStatusDateDetermined"]: - # Determine Used Date Column - date_used = ( - "dateIdentified" if row["dateIdentified"] else "preparedDate" if row["preparedDate"] else "eventDate" - ) - - # Add comment to temporal entity - comment = f"Date unknown, template {date_used} used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - def add_threat_status_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Threat Status Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["threatStatus"]: - return - - # Combine conservationJurisdiction and threatStatus - value = f"{row['conservationJurisdiction']}/{row['threatStatus']}" - - # Retrieve vocab for field - vocab = self.fields()["threatStatus"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(value) - - # Threat Status Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"Conservation status = {row['threatStatus']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_conservation_jurisdiction_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - conservation_jurisdiction_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Conservation Jurisdiction Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - conservation_jurisdiction_value (rdflib.URIRef): Conservation - Jurisdiction Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["conservationJurisdiction"]: - return - - # Conservation Jurisdiction Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_CONSERVATION_JURISDICTION)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["conservationJurisdiction"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, conservation_jurisdiction_value)) - - def add_conservation_jurisdiction_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Conservation Jurisdiction Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["conservationJurisdiction"]: - return - - # Retrieve vocab for field - vocab = self.fields()["conservationJurisdiction"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph).get(row["conservationJurisdiction"]) - - # Construct Label - label = f"Conservation Jurisdiction = {row['conservationJurisdiction']}" - - # Conservation Jurisdiction Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(label))) - graph.add((uri, rdflib.RDF.value, term)) - - -# Helper Functions -# These utility helper functions are specific to this template, and as such are -# defined here instead of in a common utilities module. -def has_specimen(row: frictionless.Row) -> bool: - """Determines whether a row has a specimen associated with it or not. - - This method is used when determining whether to add the specimen specific - `/sampling/specimen/x` and `/sample/specimen/x` nodes to the graph. - - Args: - row (frictionless.Row): Row to retrieve data from. - - Returns: - bool: Whether this row has a specimen associated with it. - """ - # Check Specimen Rules - if row["preparations"] or row["catalogNumber"] or row["associatedSequences"]: - # If any of `preparations`, `catalogNumber` or `associatedSequences` - # are provided, regardless of the value of `basisOfRecord` we can infer - # that there is a specimen associated with the row. - specimen = True - - elif ( - not row["basisOfRecord"] # Blank - or vocabs.basis_of_record.HUMAN_OBSERVATION.match(row["basisOfRecord"]) # HumanObservation - or vocabs.basis_of_record.OCCURRENCE.match(row["basisOfRecord"]) # Occurrence - ): - # Otherwise, if none of `preparations`, `catalogNumber` or - # `associatedSequences` were provided, and the `basisOfRecord` is - # either blank or one of "HumanObservation" or "Occurrence", then we - # cannot infer that there is a specimen associated with the row. - specimen = False - - else: - # Finally, none of `preparations`, `catalogNumber` or - # `associatedSequences` were provided, but the `basisOfRecord` is a - # value that implies that there is a specimen associated with the row. - specimen = True - - # Return - return specimen - - -# Register Mapper -base.mapper.ABISMapper.register_mapper(IncidentalOccurrenceMapper) diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/metadata.json b/abis_mapping/templates/incidental_occurrence_data_v2/metadata.json deleted file mode 100644 index b1149835..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "incidental_occurrence_data", - "label": "Incidental Occurrence Data Template", - "version": "2.0.0", - "description": "A template to translate some Darwin Core fields", - "biodiversity_type": "Species Occurrences", - "spatial_type": "Point", - "file_type": "CSV", - "sampling_type": "incidental", - "template_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/incidental_occurrence_data_v2/incidental_occurrence_data.csv", - "schema_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/incidental_occurrence_data_v2/schema.json", - "template_lifecycle_status": "deprecated" -} diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/schema.json b/abis_mapping/templates/incidental_occurrence_data_v2/schema.json deleted file mode 100644 index efb9a224..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/schema.json +++ /dev/null @@ -1,679 +0,0 @@ -{ - "fields": [ - { - "name": "providerRecordID", - "title": "Provider Record ID", - "description": "The unique (within provider) identifier allocated to this record by the data provider e.g. when data is provided by an aggregator. It connects the record to the collection and storage of the specimens when these parts of the workflow may have been done by different parties.", - "example": "8022FSJMJ079c5cf", - "type": "string", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "providerRecordIDSource", - "title": "Provider Record ID Source", - "description": "Person or Organisation that generated the providerRecordID. For providers registered with the BDR, this field should contain your BDR registrationID. Populate only if the details are different from the dataset submission details.", - "example": "Western Australian Biodiversity Information Office", - "type": "string", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "locality", - "title": "Locality", - "description": "The specific description of the place.", - "example": "Cowaramup Bay Road", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:locality", - "constraints": { - "required": false - } - }, - { - "name": "decimalLatitude", - "title": "Decimal Latitude", - "description": "The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are north of the Equator, negative values are south of it. Valid coordinate ranges for the BDR system are within and inclusive of -90 to 0.", - "example": "-33.80", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLatitude", - "constraints": { - "required": true, - "minimum": -90.0, - "maximum": 0 - } - }, - { - "name": "decimalLongitude", - "title": "Decimal Longitude", - "description": "The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are east of the Greenwich Meridian, negative values are west of it. Valid coordinate ranges for the BDR system are within and inclusive of 0 to 180.", - "example": "115.21", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLongitude", - "constraints": { - "required": true, - "minimum": 0, - "maximum": 180.0 - } - }, - { - "name": "geodeticDatum", - "title": "Geodetic Datum", - "description": "The acronym for the ellipsoid, geodetic datum, or spatial reference system (SRS) upon which the geographic (non-projected) coordinates given in decimalLatitude and decimalLongitude as based.", - "example": "WGS84", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:geodeticDatum", - "constraints": { - "required": true, - "enum": [ - "AGD66", - "EPSG:4202", - "AGD84", - "EPSG:4203", - "GDA2020", - "EPSG:7844", - "GDA94", - "EPSG:4283", - "WGS84", - "EPSG:4326" - ] - }, - "vocabularies": [ - "GEODETIC_DATUM" - ] - }, - { - "name": "coordinateUncertaintyInMeters", - "title": "Coordinate Uncertainty In Meters", - "description": "The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Location. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.", - "example": "50.0", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters", - "constraints": { - "required": false, - "minimum": 0.0 - } - }, - { - "name": "dataGeneralizations", - "title": "Data Generalizations", - "description": "Actions taken to make the shared data less specific or complete than in its original form, due to restrictions around identifying locations of particular species. Suggests that alternative data of higher quality may be available on request.", - "example": "Coordinates rounded to the nearest 10 km for conservation concern", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:dataGeneralizations", - "constraints": { - "required": false - } - }, - { - "name": "eventDate", - "title": "Event Date", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T06:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) during which a species occurrence was observed. For occurrences, this is the date-time when the event was recorded. Not suitable for a time in a geological context", - "example": "2019-09-23T14:03+08:00", - "type": "timestamp", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:eventDate", - "constraints": { - "required": true - } - }, - { - "name": "samplingProtocol", - "title": "Sampling Protocol", - "description": "The sampling protocol is the method used to sample the locality to determine the presence (or absence) of the taxon referred to in this record at the indicated time. This may be a collecting method or a method to observe an organism without collection.\nRecommended best practice is to describe a species occurrence with no more than one sampling protocol. In the case of a summary, in which a specific protocol can not be attributed to specific species occurrences, the recommended best practice is to repeat the property for each IRI that denotes a different sampling protocol that applies to the occurrence.", - "example": "human observation", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:samplingProtocol", - "constraints": { - "required": false - }, - "vocabularies": [ - "SAMPLING_PROTOCOL" - ] - }, - { - "name": "basisOfRecord", - "title": "Basis Of Record", - "description": "The specific nature of the data record.", - "example": "Human Observation", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:basisOfRecord", - "constraints": { - "required": false - }, - "vocabularies": [ - "BASIS_OF_RECORD" - ] - }, - { - "name": "recordedBy", - "title": "Recorded By", - "description": "A person, group, or organisation responsible for recording the original Occurrence.", - "example": "Stream Environment and Water Pty Ltd", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:recordedBy", - "constraints": { - "required": false - } - }, - { - "name": "recordNumber", - "title": "Record Number", - "description": "An identifier given to the Occurrence at the time it was recorded. Often serves as a link between field notes and an Occurrence record, such as a specimen collector's number.", - "example": "PE:12:8832", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/recordNumber", - "constraints": { - "required": false - } - }, - { - "name": "occurrenceStatus", - "title": "Occurrence Status", - "description": "A statement about the presence or absence of a Taxon at a Location.", - "example": "present", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:occurrenceStatus", - "constraints": { - "required": false - }, - "vocabularies": [ - "OCCURRENCE_STATUS" - ] - }, - { - "name": "habitat", - "title": "Habitat", - "description": "A category or description of the habitat in which the event occurred.", - "example": "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/habitat", - "constraints": { - "required": false - }, - "vocabularies": [ - "TARGET_HABITAT_SCOPE" - ] - }, - { - "name": "establishmentMeans", - "title": "Establishment Means", - "description": "Statement about whether an organism or organisms have been introduced to a given place and time through the direct or indirect activity of modern humans.", - "example": "native", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:establishmentMeans", - "constraints": { - "required": false - }, - "vocabularies": [ - "ESTABLISHMENT_MEANS" - ] - }, - { - "name": "organismRemarks", - "title": "Organism Remarks", - "description": "Comments or notes about the Organism instance.", - "example": "Dried out leaf tips.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/organismRemarks", - "constraints": { - "required": false - } - }, - { - "name": "individualCount", - "title": "Individual Count", - "description": "The number of individuals present at the time of the Occurrence. 0 = none, no value = the specific number was not recorded.", - "example": "26", - "type": "integer", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:individualCount", - "constraints": { - "required": false - } - }, - { - "name": "organismQuantity", - "title": "Organism Quantity", - "description": "A number or enumeration value for the quantity of organisms.", - "example": "12.5", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/list/#dwc_organismQuantity", - "constraints": { - "required": false - } - }, - { - "name": "organismQuantityType", - "title": "Organism Quantity Type", - "description": "The type of quantification system used for the quantity organisms.", - "example": "% biomass", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/list/#dwc_organismQuantityType", - "constraints": { - "required": false - } - }, - { - "name": "lifeStage", - "title": "Life Stage", - "description": "The age class or life stage of the Organism(s) at the time the Occurrence was recorded.", - "example": "adult", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/lifeStage", - "constraints": { - "required": false - }, - "vocabularies": [ - "LIFE_STAGE" - ] - }, - { - "name": "sex", - "title": "Sex", - "description": "The sex of the biological individual(s) represented in the Occurrence.", - "example": "male", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:sex", - "constraints": { - "required": false - }, - "vocabularies": [ - "SEX" - ] - }, - { - "name": "reproductiveCondition", - "title": "Reproductive Condition", - "description": "The reproductive condition of the biological individual(s) represented in the Occurrence.", - "example": "No breeding evident", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:reproductiveCondition", - "constraints": { - "required": false - }, - "vocabularies": [ - "REPRODUCTIVE_CONDITION" - ] - }, - { - "name": "ownerRecordID", - "title": "Owner Record ID", - "description": "Identifier given to the occurrence by the owner of the data. Populate this field if the data owner is different to the data provider. Unique (within data owner) identifier for the record.", - "example": "12345NT521mc5h", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "ownerRecordIDSource", - "title": "Owner Record ID Source", - "description": "Person or Organisation that generated the ownerRecordID. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation who owns the data.", - "example": "WAM", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "collectionCode", - "title": "Collection Code", - "description": "The name, acronym, code, or initialism identifying the collection or data set from which the record was derived. It is associated with the catalogNumber.", - "example": "ARACH", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:collectionCode", - "constraints": { - "required": false - } - }, - { - "name": "catalogNumber", - "title": "Catalog Number", - "description": "An identifier (preferably unique) for the record within the data set or collection.", - "example": "1234568.1", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/catalogNumber", - "constraints": { - "required": false - } - }, - { - "name": "catalogNumberSource", - "title": "Catalog Number Source", - "description": "Organisation that generated the catalogNumber. In the BDR context, this is likely to be a collecting institution where a specimen or material sample is located. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.", - "example": "Western Australian Museum", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "otherCatalogNumbers", - "title": "Other Catalog Numbers", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of previous or alternate fully qualified catalog numbers or other human-used identifiers for the same Occurrence, whether in the current or any other data set or collection.", - "example": "BHP2012-7521 | M12378", - "type": "list", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/otherCatalogNumbers", - "constraints": { - "required": false - } - }, - { - "name": "otherCatalogNumbersSource", - "title": "Other Catalog Numbers Source", - "description": "Organisation that generated the otherCatalogNumbers. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.", - "example": "University of Western Australia", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "preparations", - "title": "Preparations", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of preparations and preservation methods for a specimen.", - "example": "Wet (in ethanol or some other preservative)", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/preparations", - "constraints": { - "required": false - }, - "vocabularies": [ - "PREPARATIONS" - ] - }, - { - "name": "preparedDate", - "title": "Prepared Date", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) representing the date or date-time the specimen was prepared.", - "example": "2019-09-25T10:02+08:00", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "associatedSequences", - "title": "Associated Sequences", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of identifiers (publication, global unique identifier, URI) of genetic sequence information associated with the Occurrence.", - "example": "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "type": "list", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/associatedSequences", - "constraints": { - "required": false - } - }, - { - "name": "sequencingMethod", - "title": "Sequencing Method", - "description": "The method used to obtain sequence data for example DNA, RNA, or protein from the sample.", - "example": "Sanger dideoxy sequencing", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "SEQUENCING_METHOD" - ] - }, - { - "name": "verbatimIdentification", - "title": "Verbatim Identification", - "description": "A string representing the taxonomic identification as it appeared in the original record. This term is meant to allow the capture of an unaltered original identification/determination, including identification qualifiers, hybrid formulas, uncertainties, etc. This term is meant to be used in addition to scientificName (and identificationQualifier etc.), not instead of it.", - "example": "Caladenia ?excelsa", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:verbatimIdentification", - "constraints": { - "required": false - } - }, - { - "name": "dateIdentified", - "title": "Date Identified", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which the subject was determined as representing the Taxon.", - "example": "2019-09-23T14:03+08:00", - "type": "timestamp", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/dateIdentified", - "constraints": { - "required": false - } - }, - { - "name": "identifiedBy", - "title": "Identified By", - "description": "Group of names, organisations who assigned the Taxon to the subject. For multiple names, use the pipe separator ( | ).", - "example": "Stream Environment and Water Pty Ltd", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/identifiedBy", - "constraints": { - "required": false - } - }, - { - "name": "identificationMethod", - "title": "Identification Method", - "description": "Method used to associate the organism with the scientificName label.", - "example": "Visually identified in the field (sighting)", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "IDENTIFICATION_METHOD" - ] - }, - { - "name": "scientificName", - "title": "Scientific Name", - "description": "The full scientific name, with authorship and date information if known. When forming part of an Identification, this should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the identificationQualifier column.\nNOTE: Phrase names such as Rhagodia sp. Hamersley (M.Trudgen 17794) are permitted in the scientificName field where those are in use.", - "example": "Caladenia excelsa", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/scientificName", - "constraints": { - "required": true - } - }, - { - "name": "identificationQualifier", - "title": "Identification Qualifier", - "description": "A brief phrase or a standard term (\"cf.\", \"aff.\") to express the determiner's doubts about the Identification.", - "example": "Species incerta", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:identificationQualifier", - "constraints": { - "required": false - }, - "vocabularies": [ - "IDENTIFICATION_QUALIFIER" - ] - }, - { - "name": "identificationRemarks", - "title": "Identification Remarks", - "description": "Comments or notes about the Identification.", - "example": "DNA evidence may indicate a new species. Further analysis required.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/identificationRemarks", - "constraints": { - "required": false - } - }, - { - "name": "acceptedNameUsage", - "title": "Accepted Name Usage", - "description": "The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) taxon.", - "example": "Occiperipatoides gilesii (Spencer, 1909)", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:acceptedNameUsage", - "constraints": { - "required": false - } - }, - { - "name": "kingdom", - "title": "Kingdom", - "description": "The full scientific name of the kingdom in which the taxon is classified.", - "example": "Plantae", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:kingdom", - "constraints": { - "required": true - }, - "vocabularies": [ - "KINGDOM_OCCURRENCE", - "KINGDOM_SPECIMEN" - ] - }, - { - "name": "taxonRank", - "title": "Taxon Rank", - "description": "The taxonomic rank of the most specific name in the scientificName.", - "example": "species", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/verbatimTaxonRank", - "constraints": { - "required": false - }, - "vocabularies": [ - "TAXON_RANK" - ] - }, - { - "name": "threatStatus", - "title": "Threat Status", - "description": "The conservation status (or code) assigned to an organism that is recognised in conjunction with a specific jurisdiction.", - "example": "VU", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "THREAT_STATUS" - ] - }, - { - "name": "conservationJurisdiction", - "title": "Conservation Jurisdiction", - "description": "The jurisdiction under which an organism is recognised to have a specific conservation status applied.", - "example": "WA", - "type": "string", - "format": "default", - "constraints": { - "required": false, - "enum": [ - "ACT", - "AUSTRALIAN CAPITAL TERRITORY", - "Australian Capital Territory", - "EPBC", - "ENVIRONMENT PROTECTION AND BIODIVERSITY CONSERVATION", - "Environment Protection And Biodiversity Conservation", - "NSW", - "NEW SOUTH WALES", - "New South Wales", - "NT", - "NORTHERN TERRITORY", - "Northern Territory", - "QLD", - "QUEENSLAND", - "Queensland", - "SA", - "SOUTH AUSTRALIA", - "South Australia", - "TAS", - "TASMANIA", - "Tasmania", - "VIC", - "VICTORIA", - "Victoria", - "WA", - "WESTERN AUSTRALIA", - "Western Australia" - ] - }, - "vocabularies": [ - "CONSERVATION_AUTHORITY" - ] - }, - { - "name": "threatStatusCheckProtocol", - "title": "Threat Status Check Protocol", - "description": "The method used to determine if the organism is listed under the relevant jurisdictional threatened species list.", - "example": "Species name check of the Department of Climate Change, Energy, the Environment and Water’s Species Profile and Threat Database http://www.environment.gov.au/cgi-bin/sprat/public/sprat.pl", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "CHECK_PROTOCOL" - ] - }, - { - "name": "threatStatusDateDetermined", - "title": "Threat Status Date Determined", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which this record of this organism was assigned to the nominated threatStatus and conservationJurisdiction", - "example": "30/08/2022", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "threatStatusDeterminedBy", - "title": "Threat Status Determined By", - "description": "The person and/organisation responsible for appending the threatStatus and conservationJurisdiction to this organism’s occurrence record.", - "example": "J. Bloggs, Department of Environment", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - } - ] -} diff --git a/abis_mapping/templates/incidental_occurrence_data_v2/templates/instructions.md b/abis_mapping/templates/incidental_occurrence_data_v2/templates/instructions.md deleted file mode 100644 index f35ddbd5..00000000 --- a/abis_mapping/templates/incidental_occurrence_data_v2/templates/instructions.md +++ /dev/null @@ -1,167 +0,0 @@ -{% extends "BASE_TEMPLATE base.md" %} -{% block body %} -# INCIDENTAL OCCURRENCE DATA TEMPLATE INSTRUCTIONS - -## OVERVIEW -Use this template to record occurrence data; that is the presence or absence of an organism -at a particular site locality at a point in time. - -Templates have been provided to facilitate integration of your data into the Biodiversity -Data Repository database. Not all types of data have been catered for in the available -templates at this stage; therefore, if you are unable to find a suitable template, please -contact to make us aware of your data needs. - -#### NEED TO KNOW: -For data validation, you will need your data file to: - -- be the correct **file format,** -- have **matching template fields** to the template downloaded (do not remove, or -change the order of fields), however -- additional fields may be added **after the templated fields** (noting that the -data type is not assumed and values will be encoded as strings), -- have values in **mandatory fields** (see Table 1), -- comply with data **value constraints** for example the geographic coordinates are -consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***{{values.geodetic_datum_count}}*** available -options, and -- align with existing controlled [vocabularies](#appendix-i-vocabulary-list) wherever possible (this is mandatory -for geodeticDatum), but new terms may be submitted for consideration amd will not cause a -validation error. - -### FILE FORMAT -- The incidental occurrence data template is a [UTF-8](#appendix-iii-utf-8) encoded csv (not Microsoft -Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as follows, -otherwise it will not pass the csv validation step upon upload. -
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > -Unicode (UTF-8)]` -- **Do not include empty rows**. - -#### FILE SIZE -MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the -header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character -limit on individual cells in a spreadsheet. These limits may be overcome by using or -editing CSV files with other software. - -Larger datasets may be more readily ingested using the API interface. Please contact - to make us aware of your data needs. - -## TEMPLATE FIELDS -The template contains the field names in the top row. Table 1 will assist you in transferring -your data to the template indicating: - -- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) -for that field where relevant); -- **Description** of the field; -- **Required** i.e. whether the field is **mandatory, -conditionally mandatory, or optional**; -- **Format** (datatype) required for the data values for example text (string), number - (integer, float), or date; -- **Example** of an entry or entries for that field; and -- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where -relevant. The fields that have suggested values options for the fields in Table 1 are -listed in Table 2 in alphabetical order of the field name. - -### ADDITIONAL FIELDS -Data that do not match the existing template fields may be added as additional columns in -the CSV files after the templated fields.
-E.g. eventRemarks, associatedTaxa, pathway. - -Table 1: Incidental occurrence data template fields with descriptions, conditions, -datatype format, and examples. - -{{tables.fields}} - -## CHANGELOG - -Changes from Incidental Occurrence Data Template v1.0.0 - -### CHANGED FIELDS - -* `recordID` is renamed [`providerRecordID`](#providerRecordID-field) and its value is now **mandatory** -* [`providerRecordIDSource`](#providerRecordIDSource-field) is an added field. Its type is string and its value is **mandatory**. -* [`organismQuantity`](#organismQuantity-field) is an added field. Its type is number. Can be blank. -* [`organismQuantityType`](#organismQuantityType-field) is an added field. Its type is string. Can be blank. -* `occurrenceID` is renamed [`ownerRecordID`](#ownerRecordID-field). Can be blank. -* `ownerInstitutionCode` is renamed [`ownerRecordIDSource`](#ownerRecordIDSource-field). Can be blank. -* `institutionCode` is replaced by [`catalogNumberSource`](#catalogNumberSource-field). Can be blank. -* [`otherCatalogNumbersSource`](#otherCatalogNumbersSource-field) is an added field. Its type is string. Can be blank. - -## APPENDICES -### APPENDIX-I: VOCABULARY LIST -Apart from geodeticDatum, the data validation does not require adherence to the below vocabularies -for each of the fields indicated as having vocabularies. These vocabularies are provided as a -means of assistance in developing consistent language within the database. New terms can be added -to more appropriately describe your data that goes beyond the current list. Table 2 provides some -suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), -[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information -System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity -era](https://doi.org/10.1111/2041-210X.12594). - -Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has -a preferred label with a definition to aid understanding of its meaning. For some terms, alternative -labels are provided that mean the same sort of thing. Note: geodeticDatum value -must come from one of five options in this table. - - - -{{tables.vocabularies}} - - -Table 2b: Suggested values for conditionally mandatory values for the threatStatus and -conservationJurisdiction in the template. State and Territory conservationJurisdictions spelt out -in words are also valid. For some threatStatus terms, alternative labels are provided that are also -valid for that conservationJurisdiction. - -{{tables.threat_status}} - -### APPENDIX-II: Timestamp -Following date and date-time formats are acceptable within the timestamp: - -| TYPE | FORMAT | -| --- |-------------------------------------------------------------------------------------------------------------------------------------| -| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| -| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | -| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | -| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | -| **xsd:gYear** | yyyy | - -Where:
-  yyyy = four-digit year
-  mm = two-digit month (01=January, etc.)
-  dd = two-digit day of month (01 through 31)
-  hh = two digits of hour (00 through 23) (am/pm NOT allowed)
-  mm = two digits of minute (00 through 59)
-  ss = two digits of second (00 through 59)
- - -### APPENDIX-III: UTF-8 -UTF-8 encoding is considered a best practice for handling character encoding, especially in -the context of web development, data exchange, and modern software systems. UTF-8 -(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of -encoding all possible characters (code points) in Unicode.
-Here are some reasons why UTF-8 is recommended:**Universal Character Support:** UTF-8 -can represent almost all characters from all writing systems in use today. This includes -characters from various languages, mathematical symbols, and other special characters. - -- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American -Standard Code for Information Interchange). The first 128 characters in UTF-8 are -identical to ASCII, making it easy to work with systems that use ASCII. -- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English -and many other languages). It uses one byte for ASCII characters and up to four -bytes for other characters. This variable-length encoding minimises storage and -bandwidth requirements. -- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is -widely supported by browsers, servers, and web-related technologies. -- **Globalisation:** As software applications become more globalised, supporting a wide -range of languages and scripts becomes crucial. UTF-8 is well-suited for -internationalisation and multilingual support. -- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many -programming languages, databases, and operating systems. Choosing UTF-8 helps -ensure compatibility across different platforms and technologies. - -When working with text data, it's generally a good idea to use UTF-8 encoding to avoid -issues related to character representation and ensure that your software can handle a -diverse set of characters and languages. - -For assistance, please contact: - -{% endblock %} diff --git a/abis_mapping/templates/survey_metadata/README.md b/abis_mapping/templates/survey_metadata/README.md deleted file mode 100644 index bce67b50..00000000 --- a/abis_mapping/templates/survey_metadata/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Template Description -TBC - -# Template Instructions -See `instructions.pdf` for more details diff --git a/abis_mapping/templates/survey_metadata/examples/minimal.csv b/abis_mapping/templates/survey_metadata/examples/minimal.csv deleted file mode 100644 index 4fc322c9..00000000 --- a/abis_mapping/templates/survey_metadata/examples/minimal.csv +++ /dev/null @@ -1,2 +0,0 @@ -surveyID,surveyName,surveyPurpose,surveyType,surveyStart,surveyEnd,targetTaxonomicScope,targetHabitatScope,spatialCoverageWKT,geodeticDatum,surveyOrgs,samplingPerformedBy,surveyMethodCitation,surveyMethodDescription,surveyMethodURL,samplingEffortValue,samplingEffortUnit,keywords -COL1,"Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer",Summer sampling for peak insect diversity.,Wet pitfall trapping,21/01/2015,3/02/2015,Coleoptera | Insecta,Woodland,"POLYGON ((146.363 -33.826, 148.499 -33.826, 148.499 -34.411, 146.363 -33.826))",GDA2020,"NSW Department of Planning, Industry and Environment | CSIRO",https://orcid.org/0000-0003-1092-9705 | https://orcid.org/0009-0004-5278-4238,"Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9""","Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location.",https://doi.org/10.1002/9781118945568.ch11 | https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf ,20 x 12,trapDays,ground beetle | habitat | morphology | traits | farmland | woodland | remnant vegetation | split-plot study diff --git a/abis_mapping/templates/survey_metadata/examples/minimal.ttl b/abis_mapping/templates/survey_metadata/examples/minimal.ttl deleted file mode 100644 index 6fd39b82..00000000 --- a/abis_mapping/templates/survey_metadata/examples/minimal.ttl +++ /dev/null @@ -1,175 +0,0 @@ -@prefix bdr: . -@prefix dcterms: . -@prefix geo: . -@prefix prov: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "20 x 12 trapDays" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Wet pitfall trapping" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Woodland" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coleoptera" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Insecta" ; - tern:hasValue . - - a rdfs:Datatype ; - skos:definition "An identifier for the dataset" ; - skos:prefLabel "Gaia Resources datasetID" ; - prov:wasAttributedTo . - - skos:prefLabel "surveyID source" ; - prov:qualifiedAttribution [ a prov:Attribution ; - prov:agent ; - prov:hadRole ] . - - skos:prefLabel "surveyID source" ; - prov:qualifiedAttribution [ a prov:Attribution ; - prov:agent ; - prov:hadRole ] . - - a bdr:Project ; - dcterms:identifier "COL1" ; - dcterms:title "Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer" ; - void:inDataset ; - schema:hasPart . - - a prov:Agent ; - schema:name "CSIRO" . - - a prov:Agent ; - schema:name "NSW Department of Planning, Industry and Environment" . - - a skos:Concept ; - skos:definition "In conjunction with the sampling effort value, the sampling effort unit gives an indication of the effort applied to the specified protocol." ; - skos:inScheme ; - skos:prefLabel "trapDays" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Metadata-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of targetTaxonomicScope" ; - skos:inScheme ; - skos:prefLabel "Coleoptera" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Metadata-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of targetTaxonomicScope" ; - skos:inScheme ; - skos:prefLabel "Insecta" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Metadata-Dataset"^^xsd:anyURI . - - a prov:Plan ; - prov:wasAssociatedWith "https://orcid.org/0000-0003-1092-9705"^^xsd:anyURI, - "https://orcid.org/0009-0004-5278-4238"^^xsd:anyURI ; - schema:citation "Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9\"" ; - schema:description "Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location." ; - schema:url "https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf"^^xsd:anyURI, - "https://doi.org/10.1002/9781118945568.ch11"^^xsd:anyURI ; - tern:hasAttribute , - , - , - . - - a prov:Plan ; - schema:citation "Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9\"" ; - schema:description "Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location." ; - schema:url "https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf"^^xsd:anyURI, - "https://doi.org/10.1002/9781118945568.ch11"^^xsd:anyURI . - - a tern:Text, - tern:Value ; - rdfs:label "samplingEffort" ; - rdf:value "20 x 12" ; - tern:unit . - - a tern:IRI, - tern:Value ; - rdfs:label "surveyType" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "targetHabitatScope" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "targetTaxonomicScope" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "targetTaxonomicScope" ; - rdf:value . - - a bdr:Survey ; - bdr:purpose "Summer sampling for peak insect diversity." ; - bdr:target "Coleoptera", - "Insecta" ; - dcterms:identifier "COL1"^^, - "COL1"^^ ; - dcterms:title "Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer" ; - geo:hasGeometry _:N3b433d680f13245b5cb163b000000000 ; - time:hasTime [ a time:TemporalEntity ; - time:hasBeginning [ a time:Instant ; - time:inXSDDate "2015-01-21"^^xsd:date ] ; - time:hasEnd [ a time:Instant ; - time:inXSDDate "2015-02-03"^^xsd:date ] ] ; - prov:hadPlan , - ; - schema:keywords "farmland", - "ground beetle", - "habitat", - "morphology", - "remnant vegetation", - "split-plot study", - "traits", - "woodland" . - - a tern:Dataset ; - schema:dateCreated "2020-01-01"^^xsd:date ; - schema:dateIssued "2020-01-01"^^xsd:date ; - schema:description "Example Systematic Survey Metadata Dataset by Gaia Resources" ; - schema:name "Example Systematic Survey Metadata Dataset" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POLYGON ((-33.826 146.363, -33.826 148.499, -34.411 148.499, -33.826 146.363))"^^geo:wktLiteral ] ; - rdf:object _:N3b433d680f13245b5cb163b000000000 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -_:N3b433d680f13245b5cb163b000000000 a geo:Geometry ; - geo:asWKT " POLYGON ((-33.826 146.363, -33.826 148.499, -34.411 148.499, -33.826 146.363))"^^geo:wktLiteral . - diff --git a/abis_mapping/templates/survey_metadata/examples/minimal_error_chronological_order.csv b/abis_mapping/templates/survey_metadata/examples/minimal_error_chronological_order.csv deleted file mode 100644 index 39b7d2a5..00000000 --- a/abis_mapping/templates/survey_metadata/examples/minimal_error_chronological_order.csv +++ /dev/null @@ -1,2 +0,0 @@ -surveyID,surveyName,surveyPurpose,surveyType,surveyStart,surveyEnd,targetTaxonomicScope,targetHabitatScope,spatialCoverageWKT,geodeticDatum,surveyOrgs,samplingPerformedBy,surveyMethodCitation,surveyMethodDescription,surveyMethodURL,samplingEffortValue,samplingEffortUnit,keywords -COL1,"Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer",Summer sampling for peak insect diversity.,Wet pitfall trapping,21/01/2015,3/02/2014,Coleoptera | Insecta,Woodland,"POLYGON ((146.363 -33.826, 148.499 -33.826, 148.499 -34.411, 146.363 -33.826))",GDA2020,"NSW Department of Planning, Industry and Environment | CSIRO",https://orcid.org/0000-0003-1092-9705 | https://orcid.org/0009-0004-5278-4238,"Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9""","Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location.",https://doi.org/10.1002/9781118945568.ch11 | https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf ,20 x 12,trapDays,ground beetle | habitat | morphology | traits | farmland | woodland | remnant vegetation | split-plot study diff --git a/abis_mapping/templates/survey_metadata/mapping.py b/abis_mapping/templates/survey_metadata/mapping.py deleted file mode 100644 index 1aff9cf0..00000000 --- a/abis_mapping/templates/survey_metadata/mapping.py +++ /dev/null @@ -1,1004 +0,0 @@ -"""Provides ABIS mapper for `survey_metadata.csv` template""" - -# Standard -import dataclasses - -# Third-party -import frictionless -import frictionless.checks -import rdflib - -# Local -from abis_mapping import base -from abis_mapping import plugins -from abis_mapping import models -from abis_mapping import utils - -# Typing -from typing import Optional, Iterator, Any - - -# Constants / shortcuts -a = rdflib.RDF.type -PRINCIPAL_INVESTIGATOR = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/" - "code/CI_RoleCode/principalInvestigator" -) -CONCEPT_SURVEY_TYPE = utils.rdf.uri("concept/surveyType", utils.namespaces.EXAMPLE) -CONCEPT_SAMPLING_EFFORT = utils.rdf.uri("concept/samplingEffort", utils.namespaces.EXAMPLE) -CONCEPT_TARGET_HABITAT_SCOPE = rdflib.URIRef("https://linked.data.gov.au/def/nrm/ae2c88be-63d5-44d3-95ac-54b14c4a4b28") -CONCEPT_TARGET_TAXONOMIC_SCOPE = rdflib.URIRef( - "https://linked.data.gov.au/def/nrm/7ea12fed-6b87-4c20-9ab4-600b32ce15ec", -) - - -# Dataclass used in mapping -@dataclasses.dataclass -class SurveyIDDatatype: - """Contains data items for a survey organisation""" - - name: str - datatype: rdflib.URIRef - agent: rdflib.URIRef - - -@dataclasses.dataclass -class AttributeValue: - """Contains data items to enable producing attribute and value nodes""" - - raw: str - attribute: rdflib.URIRef - value: rdflib.URIRef - - -class SurveyMetadataMapper(base.mapper.ABISMapper): - """ABIS mapper for `survey_metadata""" - - # Default Dataset Metadata - DATASET_DEFAULT_NAME = "Example Systematic Survey Metadata Dataset" - DATASET_DEFAULT_DESCRIPTION = "Example Systematic Survey Metadata Dataset by Gaia Resources" - - def apply_validation(self, data: base.types.ReadableType, **kwargs: Any) -> frictionless.Report: - """Applies Frictionless validation for the 'survey_metadata.csv' template - - Args: - data (base.types.ReadableType): Raw data to be validated - **kwargs (Any): Additional keyword arguments. - - Returns: - frictionless.Report: Validation report for the specified data. - """ - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Validate - report: frictionless.Report = resource.validate( - checklist=frictionless.Checklist( - checks=[ - # Enforces non-empty and maximum row count. - frictionless.checks.table_dimensions(max_rows=1, min_rows=1), - # Extra Custom Checks - plugins.tabular.IsTabular(), - plugins.chronological.ChronologicalOrder( - field_names=[ - "surveyStart", - "surveyEnd", - ] - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=[ - "spatialCoverageWKT", - "geodeticDatum", - ] - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=[ - "samplingEffortValue", - "samplingEffortUnit", - ] - ), - ], - ), - ) - - # Return validation report - return report - - def apply_mapping( - self, - data: base.types.ReadableType, - dataset_iri: Optional[rdflib.URIRef] = None, - base_iri: Optional[rdflib.Namespace] = None, - **kwargs: Any, - ) -> Iterator[rdflib.Graph]: - """Applies mapping for the `survey_metadata.csv` template. - - Args: - data (base.types.ReadableType): Valid raw data to be mapped. - dataset_iri (Optional[rdflib.URIRef]): Optional dataset IRI. - base_iri (Optional[rdflib.Namespace]): Optional mapping base IRI. - **kwargs (Any): Additional keyword arguments. - - Yields: - rdflib.Graph: ABIS conformant RDF sub-graph from raw data chunk. - """ - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - extra_schema = self.extra_fields_schema( - data=data, - full_schema=False, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Initialise Graph - graph = utils.rdf.create_graph() - - # Check if Dataset IRI Supplied - if not dataset_iri: - # Create Dataset IRI - dataset_iri = utils.rdf.uri(f"dataset/{self.DATASET_DEFAULT_NAME}", base_iri) - - # Add the default dataset - self.add_default_dataset( - uri=dataset_iri, - base_iri=base_iri, - graph=graph, - ) - - # Open the Resource to allow row streaming - with resource.open() as r: - # Loop through rows - for row in r.row_stream: - # Map row - self.apply_mapping_row( - row=row, - dataset=dataset_iri, - graph=graph, - extra_schema=extra_schema, - base_iri=base_iri, - ) - - yield graph - - def apply_mapping_row( - self, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - extra_schema: frictionless.Schema, - base_iri: Optional[rdflib.Namespace] = None, - ) -> None: - """Applies mapping for a row in the `survey_metadata.csv` template. - - Args: - row (frictionless.Row): Row to be processed in the dataset. - dataset (rdflib.URIRef): Dataset IRI this row is a part of. - graph (rdflib.URIRef): Graph to map row into. - extra_schema (frictionless.Schema): Schema of extra fields. - base_iri (Optional[rdflib.Namespace]): Optional base IRI - to use for mapping. - """ - # Set the row number to start from the data, excluding header - row_num = row.row_number - 1 - - # Create BDR project IRI - project = utils.rdf.uri(f"project/SSD-Survey-Project/{row_num}", base_iri) - - # Create BDR survey IRI - survey = utils.rdf.uri(f"survey/SSD-Survey/{row_num}", base_iri) - - # Create survey method procedure IRI - survey_method_procedure = utils.rdf.uri(f"survey/procedure/surveyMethod/{row_num}", base_iri) - - # Create survey plan IRI - survey_plan = utils.rdf.uri(f"survey/SSD-survey/{row_num}/plan") - - # Create survey type attribute IRI - survey_type_attribute = utils.rdf.uri(f"attribute/surveyType/{row_num}", base_iri) - - # Create survey type value IRI - survey_type_value = utils.rdf.uri(f"value/surveyType/{row_num}", base_iri) - - # Create sampling effort attribute IRI - sampling_effort_attribute = utils.rdf.uri(f"attribute/samplingEffort/{row_num}", base_iri) - - # Create sampling effort value IRI - sampling_effort_value = utils.rdf.uri(f"value/samplingEffort/{row_num}", base_iri) - - # Create target habitat scope attribute and value objects - target_habitat_objects: list[AttributeValue] = [] - if target_habitats := row["targetHabitatScope"]: - for i, target_habitat in enumerate(target_habitats, start=1): - target_habitat_objects.append( - AttributeValue( - raw=target_habitat, - attribute=utils.rdf.uri(f"attribute/targetHabitatScope/{row_num}/{i}", base_iri), - value=utils.rdf.uri(f"value/targetHabitatScope/{row_num}/{i}", base_iri), - ), - ) - - # Create target taxonomic scope attribute and value IRIs (list input) - target_taxonomic_objects: list[AttributeValue] = [] - if target_taxa := row["targetTaxonomicScope"]: - for i, target_taxon in enumerate(target_taxa, start=1): - target_taxonomic_objects.append( - AttributeValue( - raw=target_taxon, - attribute=utils.rdf.uri(f"attribute/targetTaxonomicScope/{row_num}/{i}", base_iri), - value=utils.rdf.uri(f"value/targetTaxonomicScope/{row_num}/{i}", base_iri), - ) - ) - - # Create survey orgs iris - survey_org_objects: list[SurveyIDDatatype] = [] - if survey_orgs := row["surveyOrgs"]: - for raw_org in survey_orgs: - survey_org_objects.append( - SurveyIDDatatype( - name=raw_org, - datatype=utils.rdf.uri( - internal_id=f"datatype/surveyID/{raw_org}", namespace=utils.namespaces.CREATEME - ), - agent=utils.rdf.uri(internal_id=f"agent/{raw_org}"), - ) - ) - - # Add BDR project - self.add_project( - uri=project, - survey=survey, - dataset=dataset, - graph=graph, - row=row, - ) - - # Add BDR survey - self.add_survey( - uri=survey, - survey_method=survey_method_procedure, - survey_plan=survey_plan, - survey_org_objects=survey_org_objects, - row=row, - graph=graph, - ) - - # Attach temporal coverage if present - self.add_temporal_coverage( - uri=survey, - row=row, - graph=graph, - ) - - # Add survey method urls - self.add_survey_methodologies( - uri=survey_method_procedure, - row=row, - graph=graph, - ) - - # Add spatial coverage values - self.add_spatial_coverage( - uri=survey, - row=row, - graph=graph, - ) - - for so_obj in survey_org_objects: - # Add survey ID source datatype nodes - self.add_survey_id_source_datatypes( - uri=so_obj.datatype, - agent=so_obj.agent, - graph=graph, - ) - - # Add agent - self.add_agent( - uri=so_obj.agent, - name=so_obj.name, - graph=graph, - ) - - # Add plan - self.add_plan( - uri=survey_plan, - row=row, - graph=graph, - ) - - # Add survey type attribute node - self.add_survey_type_attribute( - uri=survey_type_attribute, dataset=dataset, survey_type_value=survey_type_value, row=row, graph=graph - ) - - # Add survey type value node - self.add_survey_type_value( - uri=survey_type_value, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add sampling effort attribute node - self.add_sampling_effort_attribute( - uri=sampling_effort_attribute, - dataset=dataset, - sampling_effort_value=sampling_effort_value, - row=row, - graph=graph, - ) - - # Add sampling effort value node - self.add_sampling_effort_value( - uri=sampling_effort_value, - dataset=dataset, - row=row, - graph=graph, - ) - - # Iterate through target habitat objects - for th_obj in target_habitat_objects: - # Add target habitat scope attribute node - self.add_target_habitat_attribute( - uri=th_obj.attribute, - dataset=dataset, - target_habitat_value=th_obj.value, - raw_value=th_obj.raw, - graph=graph, - ) - - # Add target habitat scope value node - self.add_target_habitat_value( - uri=th_obj.value, - dataset=dataset, - raw_value=th_obj.raw, - graph=graph, - ) - - # Iterate through target taxonomic objects - for tt_obj in target_taxonomic_objects: - # Add target taxonomic scope attribute node - self.add_target_taxonomic_attribute( - uri=tt_obj.attribute, - dataset=dataset, - target_taxon_value=tt_obj.value, - raw_value=tt_obj.raw, - graph=graph, - ) - - # Add target taxonomic scope value node - self.add_target_taxonomic_value( - uri=tt_obj.value, - dataset=dataset, - raw_value=tt_obj.raw, - graph=graph, - ) - - # Add extra columns JSON - self.add_extra_fields_json( - subject_uri=survey, - row=row, - graph=graph, - extra_schema=extra_schema, - ) - - def add_project( - self, - uri: rdflib.URIRef, - survey: rdflib.URIRef, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - row: frictionless.Row, - ) -> None: - """Adds the BDR project to the graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - survey (rdflib.URIRef): BDR survey uri. - dataset (rdflib.URIRef): Dataset uri. - graph (rdflib.Graph): Graph to add to. - row (frictionless.Row): Row to be processed in dataset. - """ - # Extract relevant values from row - project_id = row["surveyID"] - project_name = row["surveyName"] - - # Add type and attach to dataset - graph.add((uri, a, utils.namespaces.BDR.Project)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add (required) project name, id (not required) and purpose (not required). - graph.add((uri, rdflib.DCTERMS.title, rdflib.Literal(project_name))) - if project_id: - graph.add((uri, rdflib.DCTERMS.identifier, rdflib.Literal(project_id))) - - # Attach survey - graph.add((uri, rdflib.SDO.hasPart, survey)) - - def add_survey( - self, - uri: rdflib.URIRef, - survey_method: rdflib.URIRef, - survey_plan: rdflib.URIRef, - survey_org_objects: list[SurveyIDDatatype], - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the BDR survey to the graph. - - Args: - uri (rdflib.URIRef): URI of the survey. - survey_method (rdflib.URIRef): URI of node associated with - survey method data. - survey_plan (rdflib.URIRef): URI of survey plan - survey_org_objects (list[SurveyIDDatatype]): Data objects - describing the survey organisations - row (frictionless.Row): Data row provided in the data csv - graph (rdflib.Graph): The graph to be modified. - """ - # Add type and dataset - graph.add((uri, a, utils.namespaces.BDR.Survey)) - - # Add survey method procedure node - graph.add((uri, rdflib.PROV.hadPlan, survey_method)) - - # Add survey name - graph.add((uri, rdflib.DCTERMS.title, rdflib.Literal(row["surveyName"]))) - - # Add survey ID - if (survey_id := row["surveyID"]) is not None: - # Add survey id literals per organisation - for survey_org in survey_org_objects: - id_literal = rdflib.Literal(lexical_or_value=survey_id, datatype=survey_org.datatype) - graph.add((uri, rdflib.DCTERMS.identifier, id_literal)) - - # Add survey id as type string if no organisation provided - if len(survey_org_objects) == 0: - id_literal = rdflib.Literal(survey_id) - graph.add((uri, rdflib.DCTERMS.identifier, id_literal)) - - # Add taxonomic coverage - if taxonomic_coverage := row["targetTaxonomicScope"]: - for taxa in taxonomic_coverage: - graph.add((uri, utils.namespaces.BDR.target, rdflib.Literal(taxa))) - - # Add purpose - if purpose := row["surveyPurpose"]: - graph.add((uri, utils.namespaces.BDR.purpose, rdflib.Literal(purpose))) - - # Add plan - graph.add((uri, rdflib.PROV.hadPlan, survey_plan)) - - # Add keywords - if keywords := row["keywords"]: - for keyword in keywords: - graph.add((uri, rdflib.SDO.keywords, rdflib.Literal(keyword))) - - def add_spatial_coverage( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the spatial coverage fields to the graph. - - Args: - uri (rdflib.URIRef): Base URI the spatial information will be attached - row (frictionless.Row): Data row provided in the data csv - graph (rdflib.Graph): Graph to be modified - """ - # Extract relevant values - datum = row["geodeticDatum"] - sc_geometry = row["spatialCoverageWKT"] - - if not (datum and sc_geometry): - return - - # Construct geometry - geometry = models.spatial.Geometry( - raw=sc_geometry, - datum=datum, - ) - - # Add spatial coverage - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - def add_temporal_coverage( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the temporal coverage fields to the graph. - - Args: - uri (rdflib.URIRef): Base URI the temporal information will be attached - row (frictionless.Row): Data row provided in the data csv - graph (rdflib.Graph): Graph to be modified - """ - # Determine if any dates are present in the row - start_date: models.temporal.Timestamp = row["surveyStart"] - end_date: models.temporal.Timestamp = row["surveyEnd"] - if not start_date and not end_date: - return - - # Create temporal coverage node - temporal_coverage = rdflib.BNode() - graph.add((temporal_coverage, a, rdflib.TIME.TemporalEntity)) - if start_date: - begin = rdflib.BNode() - graph.add((temporal_coverage, rdflib.TIME.hasBeginning, begin)) - graph.add((begin, a, rdflib.TIME.Instant)) - graph.add((begin, start_date.rdf_in_xsd, start_date.to_rdf_literal())) - if end_date: - end = rdflib.BNode() - graph.add((temporal_coverage, rdflib.TIME.hasEnd, end)) - graph.add((end, a, rdflib.TIME.Instant)) - graph.add((end, end_date.rdf_in_xsd, end_date.to_rdf_literal())) - - # Attach to survey node - graph.add((uri, rdflib.TIME.hasTime, temporal_coverage)) - - def add_survey_methodologies( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the survey methodology URIs to the graph. - - Args: - uri (rdflib.URIRef): Base URI the methodologies will be attached. - row (frictionless.Row): Row containing CSV data row contents. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract relevant values from row - survey_method_urls = row["surveyMethodURL"] - survey_method_description = row["surveyMethodDescription"] - survey_method_refs = row["surveyMethodCitation"] - - # If no relevant data provided then no change to graph - if not (survey_method_urls or survey_method_description or survey_method_refs): - return - - # Add type - graph.add((uri, a, rdflib.PROV.Plan)) - - # Attach survey methodologies - if survey_method_urls: - for survey_method_url in survey_method_urls: - # Add literal containing the method URL - graph.add((uri, rdflib.SDO.url, rdflib.Literal(survey_method_url, datatype=rdflib.XSD.anyURI))) - - if survey_method_description: - # Add literal containing the description - graph.add( - ( - uri, - rdflib.SDO.description, - rdflib.Literal(survey_method_description), - ) - ) - - if survey_method_refs: - for survey_method_ref in survey_method_refs: - # Add bibliographic reference - graph.add( - ( - uri, - rdflib.SDO.citation, - rdflib.Literal(survey_method_ref), - ) - ) - - def add_survey_id_source_datatypes( - self, - uri: rdflib.URIRef, - agent: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds the source datatype nodes to graph. - - Args: - uri (rdflib.URIRef): The reference uri. - agent (rdflib.URIRef): Agent uri. - graph (rdflib.Graph): Graph to be modified. - """ - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("surveyID source"))) - - # Add attribution - attribution = rdflib.BNode() - graph.add((attribution, a, rdflib.PROV.Attribution)) - graph.add((attribution, rdflib.PROV.agent, agent)) - graph.add((attribution, rdflib.PROV.hadRole, PRINCIPAL_INVESTIGATOR)) - graph.add((uri, rdflib.PROV.qualifiedAttribution, attribution)) - - def add_agent( - self, - uri: rdflib.URIRef, - name: str, - graph: rdflib.Graph, - ) -> None: - """Adds agent to graph. - - Args: - uri (rdflib.URIRef): Agent reference - name (str): Original name supplied - graph (rdflib.Graph): Graph to be modified - """ - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, utils.rdf.uri_or_string_literal(name))) - - def add_plan( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds plan to graph. - - Args: - uri (rdflib.URIRef): Plan reference. - row (frictionless.Row): Raw data row. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, rdflib.PROV.Plan)) - - # Add attributes - if row["surveyType"]: - graph.add( - ( - uri, - utils.namespaces.TERN.hasAttribute, - utils.rdf.uri("attribute/surveyType", utils.namespaces.CREATEME), - ) - ) - if row["samplingEffortValue"] and row["samplingEffortUnit"]: - graph.add( - ( - uri, - utils.namespaces.TERN.hasAttribute, - utils.rdf.uri("attribute/samplingEffort", utils.namespaces.CREATEME), - ) - ) - if row["targetHabitatScope"]: - graph.add( - ( - uri, - utils.namespaces.TERN.hasAttribute, - utils.rdf.uri("attribute/targetHabitatScope", utils.namespaces.CREATEME), - ) - ) - if row["targetTaxonomicScope"]: - graph.add( - ( - uri, - utils.namespaces.TERN.hasAttribute, - utils.rdf.uri("attribute/targetTaxa", utils.namespaces.CREATEME), - ) - ) - - # Add citation(s) - if citations := row["surveyMethodCitation"]: - for citation in citations: - graph.add((uri, rdflib.SDO.citation, rdflib.Literal(citation))) - - # Add description - if description := row["surveyMethodDescription"]: - graph.add((uri, rdflib.SDO.description, rdflib.Literal(description))) - - # Add method url(s) - if method_urls := row["surveyMethodURL"]: - for method_url in method_urls: - graph.add((uri, rdflib.SDO.url, rdflib.Literal(method_url, datatype=rdflib.XSD.anyURI))) - - # Add sampling performed by(s) - if sampling_peformed_bys := row["samplingPerformedBy"]: - for peformed_by in sampling_peformed_bys: - graph.add((uri, rdflib.PROV.wasAssociatedWith, utils.rdf.uri_or_string_literal(peformed_by))) - - def add_survey_type_attribute( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - survey_type_value: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds survey type attribute node. - - Args: - uri (rdflib.URIRef): Node reference - dataset (rdflib.URIRef): Dataset the data belongs. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract value - survey_type = row["surveyType"] - - # Non default field, return if not present - if not survey_type: - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add attribute - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_SURVEY_TYPE)) - - # Add value - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(survey_type))) - graph.add((uri, utils.namespaces.TERN.hasValue, survey_type_value)) - - def add_survey_type_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the survey type value node to graph. - - Args: - uri (rdflib.URIRef): Survey type value iri. - dataset (rdflib.URIRef): Dataset raw data belongs. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract value - survey_type = row["surveyType"] - - # Return if not a value - if survey_type is None: - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add label - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("surveyType"))) - - # Retrieve vocab for field - vocab = self.fields()["surveyType"].get_vocab() - - # Add value - term = vocab(graph=graph, source=dataset).get(survey_type) - graph.add((uri, rdflib.RDF.value, term)) - - def add_sampling_effort_attribute( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - sampling_effort_value: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds sampling effort attribute node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - sampling_effort_value (rdflib.URIRef): Corresponding value. - row (frictionless.Row): Raw data being processed. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values - effort_value = row["samplingEffortValue"] - effort_unit = row["samplingEffortUnit"] - - # Check that valid data available - if effort_value is None or effort_unit is None: - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add concept - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_SAMPLING_EFFORT)) - - # Add values - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(f"{effort_value} {effort_unit}"))) - graph.add((uri, utils.namespaces.TERN.hasValue, sampling_effort_value)) - - def add_sampling_effort_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds sampling effor value node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - row (frictionless.Row): Raw data being processed. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values - effort_value = row["samplingEffortValue"] - effort_unit = row["samplingEffortUnit"] - - # Check valid data available - if effort_value is None or effort_unit is None: - return - - # Add types - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add label - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("samplingEffort"))) - - # Retrieve vocab for field - vocab = self.fields()["samplingEffortUnit"].get_vocab() - - # Add value - term = vocab(graph=graph, source=dataset).get(effort_unit) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(effort_value))) - graph.add((uri, utils.namespaces.TERN.unit, term)) - - def add_target_habitat_attribute( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - target_habitat_value: rdflib.URIRef, - raw_value: str, - graph: rdflib.Graph, - ) -> None: - """Adds the target habitat scope attribute node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - target_habitat_value (rdflib.URIRef): Corresponding value. - raw_value (str): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add attribute concept - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_TARGET_HABITAT_SCOPE)) - - # Add value - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(raw_value))) - graph.add((uri, utils.namespaces.TERN.hasValue, target_habitat_value)) - - def add_target_habitat_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - raw_value: str, - graph: rdflib.Graph, - ) -> None: - """Add the target habitat scope value node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - raw_value (str): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add types - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add label - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("targetHabitatScope"))) - - # Retrieve vocab for field - vocab = self.fields()["targetHabitatScope"].get_vocab() - - # Add value - term = vocab(graph=graph, source=dataset).get(raw_value) - graph.add((uri, rdflib.RDF.value, term)) - - def add_target_taxonomic_attribute( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - target_taxon_value: rdflib.URIRef, - raw_value: str, - graph: rdflib.Graph, - ) -> None: - """Add the target taxonomic scope node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - target_taxon_value (rdflib.URIRef): Corresponding - value node. - raw_value (str): Raw data provided. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add attribute concept - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_TARGET_TAXONOMIC_SCOPE)) - - # Add values - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(raw_value))) - graph.add((uri, utils.namespaces.TERN.hasValue, target_taxon_value)) - - def add_target_taxonomic_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - raw_value: str, - graph: rdflib.Graph, - ) -> None: - """Adds the target toxonomic scope value node. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - raw_value (str): Raw data provided. - graph (rdflib.Graph): Graph to be modified. - """ - # Add types - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add label - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("targetTaxonomicScope"))) - - # Retrieve vocab for field - vocab = self.fields()["targetTaxonomicScope"].get_vocab() - - # Add value - term = vocab(graph=graph, source=dataset).get(raw_value) - graph.add((uri, rdflib.RDF.value, term)) - - -base.mapper.ABISMapper.register_mapper(SurveyMetadataMapper) diff --git a/abis_mapping/templates/survey_metadata/metadata.json b/abis_mapping/templates/survey_metadata/metadata.json deleted file mode 100644 index 4e35e046..00000000 --- a/abis_mapping/templates/survey_metadata/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "survey_metadata", - "label": "Systematic Survey Metadata Template", - "version": "1.0.0", - "description": "A template for systematic survey metadata", - "biodiversity_type": "Systematic Survey Metadata", - "spatial_type": "Point, line, polygon", - "file_type": "CSV", - "sampling_type": "systematic survey", - "template_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_metadata/survey_metadata.csv", - "schema_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_metadata/schema.json", - "template_lifecycle_status": "deprecated" -} diff --git a/abis_mapping/templates/survey_metadata/schema.json b/abis_mapping/templates/survey_metadata/schema.json deleted file mode 100644 index 8058af21..00000000 --- a/abis_mapping/templates/survey_metadata/schema.json +++ /dev/null @@ -1,230 +0,0 @@ -{ - "fields": [ - { - "name": "surveyID", - "title": "Survey ID", - "description": "The identifier for the survey. Important if more there is more than one survey a the project.", - "example": "COL1", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyName", - "title": "Survey Name", - "description": "Brief title for the survey.", - "type": "string", - "format": "default", - "example": "Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer", - "constraints": { - "required": true - } - }, - { - "name": "surveyPurpose", - "title": "Survey Purpose", - "description": "A description of the survey objective", - "type": "string", - "format": "default", - "example": "Summer sampling for peak insect diversity.", - "constraints": { - "required": false - } - }, - { - "name": "surveyType", - "title": "Survey Type", - "description": "Description of type of survey conducted", - "example": "Wet pitfall trapping", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "SURVEY_TYPE" - ] - }, - { - "name": "surveyStart", - "title": "Survey Start", - "description": "The date data collection commenced.", - "example": "21/09/2020", - "type": "timestamp", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "surveyEnd", - "title": "Survey End", - "description": "The date data collection was completed.", - "example": "23/09/2020", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "targetTaxonomicScope", - "title": "Target Taxonomic Scope", - "description": "The range of biological taxa covered by the survey. Multiple terms are allowed, separated by a vertical bar aka pipe |", - "example": "Coleoptera | Formicidae", - "type": "list", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "TARGET_TAXONOMIC_SCOPE" - ] - }, - { - "name": "targetHabitatScope", - "title": "Target Habitat Scope", - "description": "The habitats targeted for sampling during the survey. Multiple terms are allowed, separated by a vertical bar aka pipe |", - "example": "Woodland", - "type": "list", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "TARGET_HABITAT_SCOPE" - ] - }, - { - "name": "spatialCoverageWKT", - "title": "Spatial Coverage (WKT)", - "description": "Well Known Text (WKT) expression of the geographic coordinates that describe the survey's spatial extent.", - "example": "POLYGON ((146.363 -33.826, 148.499 -33.826, 148.499 -34.411, 146.363 -33.826))", - "type": "wkt", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "geodeticDatum", - "title": "Spatial Coverage (Geodetic Datum)", - "description": "The geodetic datum upon which the geographic coordinates in the Spatial coverage (WKT) are based.", - "example": "GDA2020", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:geodeticDatum", - "constraints": { - "required": false, - "enum": [ - "AGD66", - "EPSG:4202", - "AGD84", - "EPSG:4203", - "GDA2020", - "EPSG:7844", - "GDA94", - "EPSG:4283", - "WGS84", - "EPSG:4326" - ] - }, - "vocabularies": [ - "GEODETIC_DATUM" - ] - }, - { - "name": "surveyOrgs", - "title": "Survey Orgs", - "description": "Name of organisations or individuals for whom Survey is being conducted. Multiple terms are allowed, separated by a vertical bar aka pipe |", - "example": "NSW Department of Planning, Industry and Environment | CSIRO", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "samplingPerformedBy", - "title": "Sampling Performed By", - "description": "Similar to eco:samplingPerformedBy. Individual/s that carried out the survey. These can be represented by identifiers. Multiple values allare allowed, separated by a vertical bar aka pipe |", - "example": "https://orcid.org/0000-0003-1092-9705 | https://orcid.org/0009-0004-5278-4238", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyMethodCitation", - "title": "Survey Method Citation", - "description": "A citation or reference to the survey methods used.", - "example": "Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyMethodDescription", - "title": "Survey Method Description", - "description": "Free text description of the survey method used.", - "example": "Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location.", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyMethodURL", - "title": "Survey Method URL", - "description": "A DOI or link to the reference about the survey method, if available.", - "example": "https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf | https://doi.org/10.1002/9781118945568.ch11", - "type": "list", - "format": "uri", - "constraints": { - "required": false - } - }, - { - "name":"samplingEffortValue", - "title": "Sample Effort", - "description": "Similar to eco:samplingEffortValue. The total sampling effort value. A samplingEffortValue must have a corresponding samplingEffortUnit", - "example": "20 x 12", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "samplingEffortUnit", - "title": "Sampling Effort Units", - "description": "Similar to eco:samplingEffortUnit. The units associated with samplingEffortValue.", - "example": "trapDays", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "SAMPLING_EFFORT_UNIT" - ] - }, - { - "name": "keywords", - "title": "Keywords", - "description": "Terms, phrases or descriptors that highlight the key attributes of the study. Multiple terms are allowed, separated by a vertical bar aka pipe |", - "example": "ground beetle | habitat | morphology | traits | farmland | woodland | remnant vegetation | split-plot study", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - } - ] -} diff --git a/abis_mapping/templates/survey_metadata/survey_metadata.csv b/abis_mapping/templates/survey_metadata/survey_metadata.csv deleted file mode 100644 index b5da01e6..00000000 --- a/abis_mapping/templates/survey_metadata/survey_metadata.csv +++ /dev/null @@ -1 +0,0 @@ -surveyID,surveyName,surveyPurpose,surveyType,surveyStart,surveyEnd,targetTaxonomicScope,targetHabitatScope,spatialCoverageWKT,geodeticDatum,surveyOrgs,samplingPerformedBy,surveyMethodCitation,surveyMethodDescription,surveyMethodURL,samplingEffortValue,samplingEffortUnit,keywords diff --git a/abis_mapping/templates/survey_metadata/templates/instructions.md b/abis_mapping/templates/survey_metadata/templates/instructions.md deleted file mode 100644 index 70bb8fe5..00000000 --- a/abis_mapping/templates/survey_metadata/templates/instructions.md +++ /dev/null @@ -1,152 +0,0 @@ -{% extends "BASE_TEMPLATE base.md" %} -{% block body %} -# SYSTEMATIC SURVEY METADATA TEMPLATE INSTRUCTIONS - -## Intended Usage -Use the Systematic Survey Metadata template to record metadata relating to a Systematic Survey dataset. - -The Systematic Survey Metadata template must be used in combination with the Systematic -Survey Occurrence template, and in some cases the Systematic Survey Site template. - -Templates have been provided to facilitate integration of your data into the Biodiversity -Data Repository database. Not all types of data have been catered for in the available -templates at this stage; therefore, if you are unable to find a suitable template, please -contact to make us aware of your data needs. - -#### Data Validation Requirements: -For data validation, you will need your data file to: - -- be the correct **file format**, -- have **fields that match the template downloaded** (do not remove, or - change the order of fields), -- have extant values for **mandatory fields** (see Table 1), and -- comply with all **data value constraints**; for example the geographic coordinates are - consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***{{values.geodetic_datum_count}}*** available - options. - -Additional fields may be added **after the templated fields** (noting that the data type -is not assumed and values will be encoded as strings). - -### FILE FORMAT -- The systematic survey metadata template is a [UTF-8](#appendix-iv-utf-8) encoded csv (not Microsoft -Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as -follows, otherwise it will not pass the in-browser csv validation step upon upload. -
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > -Unicode (UTF-8)]` -- **Do not include empty rows.** - -#### FILE SIZE -MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the -header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character -limit on individual cells in a spreadsheet. These limits may be overcome by using or -editing CSV files with other software. - -Larger datasets may be more readily ingested using the API interface. Please contact - to make us aware of your data needs. - -## TEMPLATE FIELDS -The template file contains the field names in the top row that form part of the core Survey -data model. Table 1 will assist you in transferring your data to the template with the following -information: - -- **Field name** in the template (and an external link to the Darwin Core standard for that -field where available); -- **Description** of the field; -- **Required** i.e. whether the field is **mandatory, -conditionally mandatory, or optional**; -- **Datatype format** required for the data values for example text (string), number -(integer, float), or date; and -- **Example/s** of an entry for that field. -- **Vocabulary links** within this document (for example pick list values) where relevant. -The fields that have suggested values options for the fields in Table 1 are listed in -Table 2 in alphabetical order of field name. - -### ADDITIONAL FIELDS -Data that do not match the existing template fields may be added as additional columns in -the CSV files after the templated fields. -For example, `sampleSizeUnit`, `sampleSizeValue`. - -Table 1: Systematic Survey Metadata template fields with descriptions, conditions, -datatype format, and examples. - -{{tables.fields}} - -## APPENDICES -### APPENDIX-I: VOCABULARY LIST -With the exception of `geodeticDatum`, data validation -does not require adherence to the vocabularies for the various vocabularied fields.. These vocabularies are provided as a -means of assistance in developing consistent language within the database. New terms can be added -to more appropriately describe your data that goes beyond the current list. - -Table 2 provides some -suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), -[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information -System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity -era](https://doi.org/10.1111/2041-210X.12594). - -Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has -a preferred label with a definition to aid understanding of its meaning. For some terms, alternative -labels with similar semantics are provided.
Note: the value for `geodeticDatum` -must come from one of five options in this table.
- -{{tables.vocabularies}} - -### APPENDIX-II: Well Known Text (WKT) -For general information on how WKT coordinate reference data is formatted is available [here](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). -The length of a WKT string or of its components is not prescribed; however, MS Excel *does* has a -32,767 (32K) character limit on individual cells in a spreadsheet. - -It is possible to edit CSV files outside of Excel in order to include more than 32K characters. - -![Multipart geometries (2D) WKT](assets/multipart_geometries_2d_wkt.png) -
*Source: Mwtoews - CC BY-SA 3.0 - Wikipedia *
- -### APPENDIX-III: Timestamp -Following date and date-time formats are acceptable within the timestamp: - -| TYPE | FORMAT | -| --- |-------------------------------------------------------------------------------------------------------------------------------------| -| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| -| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | -| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | -| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | -| **xsd:gYear** | yyyy | - -Where:
-  `yyyy`: four-digit year
-  `mm`: two-digit month (01=January, etc.)
-  `dd`: two-digit day of month (01 through 31)
-  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
-  `mm`: two digits of minute (00 through 59)
-  `ss`: two digits of second (00 through 59)
- -### APPENDIX-IV: UTF-8 -UTF-8 encoding is considered a best practice for handling character encoding, especially in -the context of web development, data exchange, and modern software systems. UTF-8 -(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of -encoding all possible characters (code points) in Unicode.
-Here are some reasons why UTF-8 is recommended: -- **Universal Character Support:** UTF-8 can represent almost all characters from all writing - systems in use today. This includes characters from various languages, mathematical symbols, - and other special characters. -- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American - Standard Code for Information Interchange). The first 128 characters in UTF-8 are - identical to ASCII, making it easy to work with systems that use ASCII. -- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English - and many other languages). It uses one byte for ASCII characters and up to four - bytes for other characters. This variable-length encoding minimises storage and - bandwidth requirements. -- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is - widely supported by browsers, servers, and web-related technologies. -- **Globalisation:** As software applications become more globalised, supporting a wide - range of languages and scripts becomes crucial. UTF-8 is well-suited for - internationalisation and multilingual support. -- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many - programming languages, databases, and operating systems. Choosing UTF-8 helps - ensure compatibility across different platforms and technologies. - -When working with text data, UTF-8 encoding is recommended to avoid issues related to character -representation and ensure that a diverse set of characters and languages is supported. - -For assistance, please contact: -{% endblock %} diff --git a/abis_mapping/templates/survey_occurrence_data/README.md b/abis_mapping/templates/survey_occurrence_data/README.md deleted file mode 100644 index d2595b7c..00000000 --- a/abis_mapping/templates/survey_occurrence_data/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Template Description -A template to translate some Darwin Core fields - -# Template Instructions -See `instructions.pdf` for more details diff --git a/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.csv b/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.csv deleted file mode 100644 index afb08a0c..00000000 --- a/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.csv +++ /dev/null @@ -1,17 +0,0 @@ -providerRecordID,providerRecordIDSource,locality,decimalLatitude,decimalLongitude,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,eventDate,samplingProtocol,basisOfRecord,recordedBy,recordNumber,occurrenceStatus,habitat,establishmentMeans,organismRemarks,individualCount,organismQuantity,organismQuantityType,lifeStage,sex,reproductiveCondition,ownerRecordID,ownerRecordIDSource,collectionCode,catalogNumber,catalogNumberSource,otherCatalogNumbers,otherCatalogNumbersSource,preparations,preparedDate,associatedSequences,sequencingMethod,verbatimIdentification,dateIdentified,identifiedBy,identificationMethod,scientificName,identificationQualifier,identificationRemarks,acceptedNameUsage,kingdom,taxonRank,threatStatus,conservationJurisdiction,threatStatusCheckProtocol,threatStatusDateDetermined,threatStatusDeterminedBy,siteID,surveyID -A001,UFP,Cowaramup Bay Road,-33.8,115.21,WGS84,,,2019-09-24,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Calothamnus lateralis var. crassus,2019-09-24,Stream Environment and Water Pty Ltd,,Calothamnus lateralis var. crassus,,,,Plantae,,,,,,,, -A002,UFP,Cowaramup Bay Road,-33.86,115.01,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,2019-09-21,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,,,, -A003,UFP,Cowaramup Bay Road,-33.86,115.01,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,2019-09-21,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,,,, -A004,UFP,Cowaramup Bay Road,-33.86,115.01,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Boronia anceps,2019-09-21,Stream Environment and Water Pty Ltd,,Boronia anceps,,,,Plantae,,,,,,,, -A005,UFP,Cowaramup Bay Road,-33.86,114.99,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,2019-09-21,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,,,, -A006,UFP,Cowaramup Bay Road,-33.86,114.99,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,2019-09-21,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,,,, -A007,UFP,Cowaramup Bay Road,-33.86,114.99,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,2019-09-21,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,,,, -A008,UFP,Cowaramup Bay Road,-33.86,114.99,WGS84,,,2020-09-21,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Banksia sessilis var. cordata,2019-09-21,Stream Environment and Water Pty Ltd,,Banksia sessilis var. cordata,,,,Plantae,,,,,,,, -A009,UFP,Cowaramup Bay Road,-33.86,115.02,WGS84,,,2020-09-23,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,2019-09-23,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,,,, -A010,UFP,Cowaramup Bay Road,-33.86,115.02,WGS84,,,2020-09-23,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,2019-09-23,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,,,, -A011,UFP,Cowaramup Bay Road,-33.86,115.02,WGS84,,,2020-09-23,,,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,,,,,,,,,,Caladenia ?excelsa,2019-09-23,Stream Environment and Water Pty Ltd,,Caladenia excelsa,?,One unopened flower when recorded and one leaf only. ID not confirmed,,Plantae,,,,,,,, -A012,UFP,,-33.8,115.21,WGS84,,,2019-09-24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Caladenia excelsa,,,,Plantae,,,,,,,, -A013,UFP,Cowaramup Bay Road,-33.86,115.02,WGS84,,,2020-09-23,,PreservedSpecimen,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,CC123,,,,,,,,,,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,,,,Plantae,,,,,,,, -A014,UFP,Cowaramup Bay Road,-33.86,115.02,WGS84,20,Coordinates rounded to the nearest 10 km for conservation concern,2020-09-23,,HumanObservation,Stream Environment and Water Pty Ltd,,,,,,,,,,,,,,CC456,,,,,,,,,Caladenia ?excelsa,,Stream Environment and Water Pty Ltd,,Caladenia excelsa,?,Could not confirm the ID due to damaged flower,,Plantae,,,,,,,, -8022FSJMJ079c5cf,UFP,Cowaramup Bay Road,-33.8,115.21,WGS84,50,Coordinates rounded to the nearest 10 km for conservation concern,2019-09-24,human observation,PreservedSpecimen,Stream Environment and Water Pty Ltd,PE:12:8832,present,"Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.",native,Dried out leaf tips,2,,,adult,male,No breeding evident,MR-456,WAM,ARACH,32237,BHP,BHP2012-7521 | M12378,BHP,Wet (in ethanol or some other preservative),26/09/2019,https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1,Sanger dideoxy sequencing,Caladenia ?excelsa,2019-09-27T12:34+08:00,Stream Environment and Water Pty Ltd,Visually identified in the field (sighting),Caladenia excelsa,species incerta,no flowers present,Caladenia excelsa Hopper & A.P.Br.,Plantae,species,VU,WA,Check against Threatened and Priority Fauna List WA available from https://www.dpaw.wa.gov.au/plants-and-animals/threatened-species-and-communities/threatened-animals. Last updated 13 June 2022,2022-09-12,WA-BIO,, -ABC123,UFP,Cowaramup Bay Road,-33.8,115.21,WGS84,30,Coordinates generalised,2019-09-25,new sampling protocol,new basis of record,Stream Environment and Water Pty Ltd,PE:12:8833,new occurrence status,new habitat,new establishment means,Leaves brown,6,,,new life stage,new sex,new reproductiveCondition,MR-457,WAM,ARACH,32238,WAM,BHP2012-7522 | M12379,BHP,new preparations,27/09/2019,https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1,new sequencing method,Caladenia ?excelsa,2019-09-27T12:34+08:00,Stream Environment and Water Pty Ltd,new identification method,Caladenia excelsa,new identification qualifier,new remarks,Caladenia excelsa Hopper & A.P.Br.,new kingdom,new taxon rank,new threat status,WA,a random selection,,,, diff --git a/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.ttl b/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.ttl deleted file mode 100644 index c6838fe6..00000000 --- a/abis_mapping/templates/survey_occurrence_data/examples/margaret_river_flora/margaret_river_flora.ttl +++ /dev/null @@ -1,2072 +0,0 @@ -@prefix dcterms: . -@prefix dwc: . -@prefix geo: . -@prefix prov: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix sosa: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - - a rdfs:Datatype ; - skos:prefLabel "catalogNumber source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "catalogNumber source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:definition "An identifier for the dataset" ; - skos:prefLabel "Gaia Resources datasetID" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "otherCatalogNumbers source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "ownerRecordID source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "providerRecordID source" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "recordNumber source" ; - prov:wasAttributedTo . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "acceptedNameUsage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa Hopper & A.P.Br." ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "acceptedNameUsage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa Hopper & A.P.Br." ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "establishmentMeans-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "native" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "establishmentMeans-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new establishment means" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "individualCount-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult 2 ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "individualCount-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult 6 ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "lifeStage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "adult" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "lifeStage-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new life stage" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "occurrenceStatus-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "present" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "occurrenceStatus-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new occurrence status" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "organismRemarks-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Dried out leaf tips" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "organismRemarks-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Leaves brown" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "reproductiveCondition-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "No breeding evident" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "reproductiveCondition-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new reproductiveCondition" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Calothamnus lateralis var. crassus" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure ; - tern:hasAttribute , - , - . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "sex-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "male" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "sex-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new sex" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "threatStatus-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2022-09-12"^^xsd:date ] ; - prov:wasAssociatedWith ; - prov:wasInfluencedBy ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "VU" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "threatStatus-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template dateIdentified used as proxy" ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasInfluencedBy ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "new threat status" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Calothamnus lateralis var. crassus" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDateTimeStamp "2019-09-27T12:34:00+08:00"^^xsd:dateTimeStamp ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia ?excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Boronia anceps" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Banksia sessilis var. cordata" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "verbatimID-observation" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Caladenia excelsa" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a prov:Agent ; - schema:name "UFP" . - - a prov:Agent ; - schema:name "UFP" . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "PreservedSpecimen" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "HumanObservation" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "PreservedSpecimen" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new basis of record" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "WA" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "WA" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates rounded to the nearest 10 km for conservation concern" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam." ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new habitat" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "?" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "?" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "species incerta" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new identification qualifier" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "One unopened flower when recorded and one leaf only. ID not confirmed" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Could not confirm the ID due to damaged flower" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "no flowers present" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new remarks" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Wet (in ethanol or some other preservative)" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new preparations" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "species" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "new taxon rank" ; - tern:hasValue . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of basisOfRecord." ; - skos:inScheme ; - skos:prefLabel "new basis of record" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationQualifier." ; - skos:inScheme ; - skos:prefLabel "new identification qualifier" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of preparations." ; - skos:inScheme ; - skos:prefLabel "Wet (in ethanol or some other preservative)" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of preparations." ; - skos:inScheme ; - skos:prefLabel "new preparations" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of taxonRank." ; - skos:inScheme ; - skos:prefLabel "new taxon rank" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:definition "The existence of the organism from this kingdom sampled at a particular place at a particular time." ; - skos:inScheme ; - skos:prefLabel "new kingdom occurrence" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:definition "A specimen sampled from an organism of this kingdom." ; - skos:inScheme ; - skos:prefLabel "new kingdom specimen" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of samplingProtocol." ; - skos:inScheme ; - skos:prefLabel "new sampling protocol" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sequencingMethod." ; - skos:inScheme ; - skos:prefLabel "Sanger dideoxy sequencing" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sequencingMethod." ; - skos:inScheme ; - skos:prefLabel "new sequencing method" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatusCheckProtocol." ; - skos:inScheme ; - skos:prefLabel "Check against Threatened and Priority Fauna List WA available from https://www.dpaw.wa.gov.au/plants-and-animals/threatened-species-and-communities/threatened-animals. Last updated 13 June 2022" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatusCheckProtocol." ; - skos:inScheme ; - skos:prefLabel "a random selection" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of establishmentMeans." ; - skos:inScheme ; - skos:prefLabel "new establishment means" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of lifeStage." ; - skos:inScheme ; - skos:prefLabel "new life stage" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of occurrenceStatus." ; - skos:inScheme ; - skos:prefLabel "new occurrence status" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of reproductiveCondition." ; - skos:inScheme ; - skos:prefLabel "No breeding evident" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of reproductiveCondition." ; - skos:inScheme ; - skos:prefLabel "new reproductiveCondition" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of sex." ; - skos:inScheme ; - skos:prefLabel "new sex" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of threatStatus." ; - skos:inScheme ; - skos:prefLabel "WA/new threat status" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a prov:Agent ; - schema:name "WA-BIO" . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1" ; - void:inDataset ; - rdfs:comment "sequence-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1" ; - void:inDataset ; - rdfs:comment "sequence-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Calothamnus lateralis var. crassus" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Boronia anceps" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Banksia sessilis var. cordata" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "basisOfRecord" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation Jurisdiction = WA" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation Jurisdiction = WA" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates rounded to the nearest 10 km for conservation concern" . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates rounded to the nearest 10 km for conservation concern" . - - a tern:Text, - tern:Value ; - rdf:value "Coordinates generalised" . - - a tern:IRI, - tern:Value ; - rdfs:label "establishmentMeans-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "establishmentMeans-value" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdfs:label "habitat" ; - rdf:value "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam." . - - a tern:Text, - tern:Value ; - rdfs:label "habitat" ; - rdf:value "new habitat" . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "identificationQualifier" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "One unopened flower when recorded and one leaf only. ID not confirmed" . - - a tern:Text, - tern:Value ; - rdf:value "Could not confirm the ID due to damaged flower" . - - a tern:Text, - tern:Value ; - rdf:value "no flowers present" . - - a tern:Text, - tern:Value ; - rdf:value "new remarks" . - - a tern:Integer, - tern:Value ; - rdfs:label "individual-count" ; - rdf:value 2 . - - a tern:Integer, - tern:Value ; - rdfs:label "individual-count" ; - rdf:value 6 . - - a tern:IRI, - tern:Value ; - rdfs:label "lifeStage-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "lifeStage-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "occurrenceStatus = present" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "occurrenceStatus = new occurrence status" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdfs:label "organism-remarks" ; - rdf:value "Dried out leaf tips" . - - a tern:Text, - tern:Value ; - rdfs:label "organism-remarks" ; - rdf:value "Leaves brown" . - - a tern:IRI, - tern:Value ; - rdfs:label "preparations" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "preparations" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "reproductiveCondition-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "reproductiveCondition-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "sex-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "sex-value" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "taxon rank = species" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "taxon rank = new taxon rank" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation status = VU" ; - rdf:value . - - a tern:IRI, - tern:Value ; - rdfs:label "Conservation status = new threat status" ; - rdf:value . - - a tern:Text, - tern:Value ; - rdf:value "Calothamnus lateralis var. crassus" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia ?excelsa" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Boronia anceps" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Banksia sessilis var. cordata" . - - a tern:Text, - tern:Value ; - rdf:value "Caladenia excelsa" . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates rounded to the nearest 10 km for conservation concern" ; - tern:hasValue . - - a tern:Attribute ; - void:inDataset ; - tern:attribute ; - tern:hasSimpleValue "Coordinates generalised" ; - tern:hasValue . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationQualifier." ; - skos:inScheme ; - skos:prefLabel "?" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationMethod." ; - skos:inScheme ; - skos:prefLabel "Visually identified in the field (sighting)" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a skos:Concept ; - skos:broader ; - skos:definition "A type of identificationMethod." ; - skos:inScheme ; - skos:prefLabel "new identification method" ; - schema:citation "http://createme.org/dataset/Example-Systematic-Survey-Occurrence-Dataset"^^xsd:anyURI . - - a prov:Agent ; - schema:name "BHP" . - - a prov:Agent ; - schema:name "WAM" . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:collectionCode "CC123" ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:Sampling ; - dcterms:identifier "A001"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000001 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A010"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000013 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A011"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000015 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A012"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000017 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf . - - a tern:Sampling ; - dcterms:identifier "A013"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000019 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A014"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000001b ; - geo:hasMetricSpatialAccuracy 2e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:hasAttribute , - ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "8022FSJMJ079c5cf"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000001d ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:hasAttribute , - ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "ABC123"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000001f ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:hasAttribute , - ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A002"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000003 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A003"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000005 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A004"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000007 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A005"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000009 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A006"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000000b ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A007"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000000d ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A008"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac40000000f ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-21"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - dcterms:identifier "A009"^^ ; - void:inDataset ; - geo:hasGeometry _:Nd94ea7312c2d3e77d05abac400000011 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - prov:wasAssociatedWith ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Ne8d54e6bd1ad43a155c3634d00000001 ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "sequencing-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:Ne8d54e6bd1ad43a155c3634d00000003 ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "sequencing-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-25"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:N622b8266a06ee1d3a8413e6c00000001 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2020-09-23"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:N622b8266a06ee1d3a8413e6c00000003 ; - geo:hasMetricSpatialAccuracy 5e+01 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-26"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:Sampling ; - void:inDataset ; - geo:hasGeometry _:N622b8266a06ee1d3a8413e6c00000005 ; - geo:hasMetricSpatialAccuracy 3e+01 ; - rdfs:comment "specimen-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-27"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - tern:hasAttribute , - . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Caladenia excelsa" ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "acceptedNameUsage-value" ; - void:inDataset ; - rdf:value "Caladenia excelsa Hopper & A.P.Br." ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "acceptedNameUsage-value" ; - void:inDataset ; - rdf:value "Caladenia excelsa Hopper & A.P.Br." ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "MR-456"^^ ; - void:inDataset ; - dwc:otherCatalogNumbers "BHP2012-7521"^^, - "M12378"^^, - "['BHP2012-7521', 'M12378']" ; - dwc:recordNumber "PE:12:8832"^^ ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - dcterms:identifier "MR-457"^^ ; - void:inDataset ; - dwc:otherCatalogNumbers "BHP2012-7522"^^, - "M12379"^^, - "['BHP2012-7522', 'M12379']" ; - dwc:recordNumber "PE:12:8833"^^ ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "32237"^^ ; - dwc:collectionCode "ARACH" ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType ; - tern:hasAttribute . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - dwc:catalogNumber "32238"^^ ; - dwc:collectionCode "ARACH" ; - rdfs:comment "specimen-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType ; - tern:hasAttribute . - - a tern:FeatureOfInterest ; - void:inDataset ; - geo:hasGeometry [ a geo:Geometry ; - geo:sfWithin ] ; - tern:featureType . - - a prov:Agent ; - schema:name "Stream Environment and Water Pty Ltd" . - - a tern:Dataset ; - schema:dateCreated "2020-01-01"^^xsd:date ; - schema:dateIssued "2020-01-01"^^xsd:date ; - schema:description "Example Systematic Survey Occurrence Dataset by Gaia Resources" ; - schema:name "Example Systematic Survey Occurrence Dataset" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000003 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000005 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000007 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000009 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000000b ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000000d ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000000f ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000011 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000013 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000015 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000017 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac400000019 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000001b ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000001d ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Nd94ea7312c2d3e77d05abac40000001f ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ] ; - rdf:object _:N622b8266a06ee1d3a8413e6c00000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N622b8266a06ee1d3a8413e6c00000003 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N622b8266a06ee1d3a8413e6c00000005 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Ne8d54e6bd1ad43a155c3634d00000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:Ne8d54e6bd1ad43a155c3634d00000003 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -_:N622b8266a06ee1d3a8413e6c00000001 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:N622b8266a06ee1d3a8413e6c00000003 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:N622b8266a06ee1d3a8413e6c00000005 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Nd94ea7312c2d3e77d05abac400000001 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000003 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000005 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000007 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.01)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000009 a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000000b a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000000d a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000000f a geo:Geometry ; - geo:asWKT " POINT (-33.86 114.99)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000011 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000013 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000015 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000017 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac400000019 a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000001b a geo:Geometry ; - geo:asWKT " POINT (-33.86 115.02)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000001d a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:Nd94ea7312c2d3e77d05abac40000001f a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - -_:Ne8d54e6bd1ad43a155c3634d00000001 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - -_:Ne8d54e6bd1ad43a155c3634d00000003 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ; - rdfs:comment "Location unknown, location of field sampling used as proxy" . - diff --git a/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.csv b/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.csv deleted file mode 100644 index 280b1dd0..00000000 --- a/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.csv +++ /dev/null @@ -1,2 +0,0 @@ -providerRecordID,providerRecordIDSource,locality,decimalLatitude,decimalLongitude,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,eventDate,samplingProtocol,basisOfRecord,recordedBy,recordNumber,occurrenceStatus,habitat,establishmentMeans,organismRemarks,individualCount,organismQuantity,organismQuantityType,lifeStage,sex,reproductiveCondition,ownerRecordID,ownerRecordIDSource,collectionCode,catalogNumber,catalogNumberSource,otherCatalogNumbers,otherCatalogNumbersSource,preparations,preparedDate,associatedSequences,sequencingMethod,verbatimIdentification,dateIdentified,identifiedBy,identificationMethod,scientificName,identificationQualifier,identificationRemarks,acceptedNameUsage,kingdom,taxonRank,threatStatus,conservationJurisdiction,threatStatusCheckProtocol,threatStatusDateDetermined,threatStatusDeterminedBy,siteID,surveyID -A0010,Gaia Resources,Cowaramup Bay Road,-33.8,115.21,WGS84,,,24/09/2019,,,,,,,,,,0.05,percentageCoverage,,,,,,,,,,,,,,,,,,,Calothamnus lateralis var. crassus,,,,Plantae,,,,,,,P1, diff --git a/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.ttl b/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.ttl deleted file mode 100644 index 9d1d4842..00000000 --- a/abis_mapping/templates/survey_occurrence_data/examples/organism_qty.ttl +++ /dev/null @@ -1,118 +0,0 @@ -@prefix dcterms: . -@prefix dwc: . -@prefix geo: . -@prefix prov: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix sosa: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - - a rdfs:Datatype ; - skos:definition "An identifier for the dataset" ; - skos:prefLabel "Gaia Resources datasetID" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "providerRecordID source" ; - prov:wasAttributedTo . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "Observation method unknown, 'human observation' used as proxy", - "organismQuantity-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "0.05 percentageCoverage" ; - sosa:observedProperty dwc:organismQuantity ; - sosa:usedProcedure . - - a tern:Observation ; - void:inDataset ; - rdfs:comment "scientificName-observation" ; - time:hasTime [ a time:Instant ; - rdfs:comment "Date unknown, template eventDate used as proxy" ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:hasSimpleResult "Calothamnus lateralis var. crassus" ; - sosa:observedProperty ; - sosa:usedProcedure . - - a prov:Agent ; - schema:name "Gaia Resources" . - - a tern:FeatureOfInterest ; - void:inDataset ; - geo:hasGeometry [ a geo:Geometry ; - geo:sfWithin ] ; - tern:featureType . - - a prov:Agent ; - schema:name "Gaia Resources" . - - a tern:FeatureOfInterest, - tern:Text, - tern:Value ; - rdfs:label "scientificName" ; - void:inDataset ; - rdf:value "Calothamnus lateralis var. crassus" ; - tern:featureType . - - a tern:Float, - tern:Value ; - rdfs:label "organism-count" ; - rdf:value "0.05"^^xsd:float ; - tern:unit . - - a tern:FeatureOfInterest, - tern:Site ; - void:inDataset ; - sosa:isSampleOf ; - tern:featureType . - - a tern:Sampling ; - dcterms:identifier "A0010"^^ ; - void:inDataset ; - geo:hasGeometry _:N20e197c04c43c11f4167e9cd00000001 ; - rdfs:comment "field-sampling" ; - time:hasTime [ a time:Instant ; - time:inXSDDate "2019-09-24"^^xsd:date ] ; - sosa:hasFeatureOfInterest ; - sosa:hasResult ; - sosa:usedProcedure ; - schema:isPartOf ; - tern:locationDescription "Cowaramup Bay Road" . - - a tern:FeatureOfInterest, - tern:Sample ; - void:inDataset ; - rdfs:comment "field-sample" ; - sosa:isResultOf ; - sosa:isSampleOf ; - tern:featureType . - - a tern:Dataset ; - schema:dateCreated "2020-01-01"^^xsd:date ; - schema:dateIssued "2020-01-01"^^xsd:date ; - schema:description "Example Systematic Survey Occurrence Dataset by Gaia Resources" ; - schema:name "Example Systematic Survey Occurrence Dataset" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral ] ; - rdf:object _:N20e197c04c43c11f4167e9cd00000001 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -_:N20e197c04c43c11f4167e9cd00000001 a geo:Geometry ; - geo:asWKT " POINT (-33.8 115.21)"^^geo:wktLiteral . - diff --git a/abis_mapping/templates/survey_occurrence_data/mapping.py b/abis_mapping/templates/survey_occurrence_data/mapping.py deleted file mode 100644 index bb972e3f..00000000 --- a/abis_mapping/templates/survey_occurrence_data/mapping.py +++ /dev/null @@ -1,3488 +0,0 @@ -"""Provides ABIS Mapper for `survey_occurrence_data.csv` Template""" - -# Standard -import urllib.parse - -# Third-Party -import frictionless -import rdflib - -# Local -from abis_mapping import base -from abis_mapping import utils -from abis_mapping import plugins -from abis_mapping import models -from abis_mapping import vocabs - -# Typing -from typing import Iterator, Optional, Any - - -# Constants and Shortcuts -# These constants are specific to this template, and as such are defined here -# rather than in a common `utils` module. -a = rdflib.RDF.type -CONCEPT_AUSTRALIA = rdflib.URIRef("https://sws.geonames.org/2077456/") -CONCEPT_TAXON = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/70646576-6dc7-4bc5-a9d8-c4c366850df0") -CONCEPT_SITE = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/5bf7ae21-a454-440b-bdd7-f2fe982d8de4") -CONCEPT_ID_UNCERTAINTY = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/54e40f12-8c13-495a-9f8d-838d78faa5a7") -CONCEPT_ID_REMARKS = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/45a86abc-43c7-4a30-ac73-fc8d62538140") -CONCEPT_PROCEDURE_SAMPLING = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/7930424c-f2e1-41fa-9128-61524b67dbd5") -CONCEPT_SCIENTIFIC_NAME = utils.rdf.uri("concept/scientificName", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_DATA_GENERALIZATIONS = utils.rdf.uri( - "concept/data-generalizations", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_TAXON_RANK = utils.rdf.uri("concept/taxonRank", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_INDIVIDUAL_COUNT = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/74c71500-0bae-43c9-8db0-bd6940899af1") -CONCEPT_ORGANISM_REMARKS = utils.rdf.uri("concept/organismRemarks", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_HABITAT = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/2090cfd9-8b6b-497b-9512-497456a18b99") -CONCEPT_BASIS_OF_RECORD = utils.rdf.uri("concept/basisOfRecord", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_OCCURRENCE_STATUS = utils.rdf.uri("concept/occurrenceStatus", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_PREPARATIONS = utils.rdf.uri("concept/preparations", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_ESTABLISHMENT_MEANS = utils.rdf.uri( - "concept/establishmentMeans", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_LIFE_STAGE = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/abb0ee19-b2e8-42f3-8a25-d1f39ca3ebc3") -CONCEPT_SEX = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/05cbf534-c233-4aa8-a08c-00b28976ed36") -CONCEPT_REPRODUCTIVE_CONDITION = utils.rdf.uri( - "concept/reproductiveCondition", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_ACCEPTED_NAME_USAGE = utils.rdf.uri( - "concept/acceptedNameUsage", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_NAME_CHECK_METHOD = utils.rdf.uri( - "methods/name-check-method", utils.namespaces.EXAMPLE -) # TODO -> Need real URI -CONCEPT_SEQUENCE = utils.rdf.uri("concept/sequence", utils.namespaces.EXAMPLE) # TODO -> Need real URI -CONCEPT_CONSERVATION_STATUS = rdflib.URIRef( - "http://linked.data.gov.au/def/tern-cv/1466cc29-350d-4a23-858b-3da653fd24a6" -) -CONCEPT_CONSERVATION_JURISDICTION = rdflib.URIRef( - "http://linked.data.gov.au/def/tern-cv/755b1456-b76f-4d54-8690-10e41e25c5a7" -) - -# Roles -ROLE_ORIGINATOR = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/originator" -) -ROLE_RIGHTS_HOLDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/rightsHolder" -) -ROLE_RESOURCE_PROVIDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/resourceProvider" -) -ROLE_CUSTODIAN = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/custodian" -) -ROLE_STAKEHOLDER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/stakeholder" -) -ROLE_OWNER = rdflib.URIRef( - "http://def.isotc211.org/iso19115/-1/2018/CitationAndResponsiblePartyInformation/code/CI_RoleCode/owner" -) - -# Temporary -DEFAULT_SURVEY = rdflib.URIRef("http://createme.org/survey/SSD-Survey/1") # TODO -> Cross reference - - -class SurveyOccurrenceMapper(base.mapper.ABISMapper): - """ABIS Mapper for `survey_occurrence_data.csv`""" - - # Default Dataset Metadata - DATASET_DEFAULT_NAME = "Example Systematic Survey Occurrence Dataset" - DATASET_DEFAULT_DESCRIPTION = "Example Systematic Survey Occurrence Dataset by Gaia Resources" - - def apply_validation(self, data: base.types.ReadableType, **kwargs: Any) -> frictionless.Report: - """Applies Frictionless Validation for the `survey_occurrence_data.csv` Template - - Args: - data (base.types.ReadableType): Raw data to be validated. - **kwargs (Any): Additional keyword arguments. - - Keyword Args: - site_id_geometry_map (dict[str, str]): Default values to use for geometry - for given siteID. - - Returns: - frictionless.Report: Validation report for the specified data. - """ - # Extract kwargs - site_id_geometry_map = kwargs.get("site_id_geometry_map") - - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - - # Construct default Checklist - checklist = frictionless.Checklist( - checks=[ - # Extra Custom Checks - plugins.tabular.IsTabular(), - plugins.empty.NotEmpty(), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["threatStatus", "conservationJurisdiction"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["organismQuantity", "organismQuantityType"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["catalogNumber", "catalogNumberSource"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["otherCatalogNumbers", "otherCatalogNumbersSource"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["ownerRecordID", "ownerRecordIDSource"], - ), - ], - ) - - # Modify schema and checklist in the event default geometry map provided - if site_id_geometry_map is not None: - # We need to make sure that required is false from the lat long fields - # since this would override the default lookup checks - for field_name in ["decimalLatitude", "decimalLongitude", "geodeticDatum"]: - schema.get_field(field_name).constraints["required"] = False - - # Perform a default lookup check based on passed in map. - checklist.add_check( - plugins.default_lookup.DefaultLookup( - key_field="siteID", - value_field="decimalLatitude", - default_map=site_id_geometry_map, - ) - ) - # Mutual inclusion check to close out the possibility of one missing. - checklist.add_check( - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["decimalLatitude", "decimalLongitude", "geodeticDatum"] - ) - ) - - # Construct Resource (Table with Schema) - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Validate - report: frictionless.Report = resource.validate(checklist=checklist) - - # Return Validation Report - return report - - def extract_site_id_keys( - self, - data: base.types.ReadableType, - ) -> dict[str, bool]: - """Extract site id key values from the data. - - Args: - data (base.types.ReadableType): Raw data to be mapped. - - Returns: - dict[str, bool]: Keys are the site id values encountered - in the data, values are all 'True', - """ - # Construct schema - schema = frictionless.Schema.from_descriptor(self.schema()) - - # Construct resource - resource = frictionless.Resource( - source=data, - format="csv", - schema=schema, - encoding="utf-8", - ) - - # Iterate over rows to extract values - with resource.open() as r: - # Construct dictionary and return - return {row["siteID"]: True for row in r.row_stream if row["siteID"] is not None} - - def apply_mapping( - self, - data: base.types.ReadableType, - dataset_iri: Optional[rdflib.URIRef] = None, - base_iri: Optional[rdflib.Namespace] = None, - **kwargs: Any, - ) -> Iterator[rdflib.Graph]: - """Applies Mapping for the `survey_occurrence_data.csv` Template - - Args: - data (base.types.ReadableType): Valid raw data to be mapped. - dataset_iri (Optional[rdflib.URIRef]): Optional dataset IRI. - base_iri (Optional[rdflib.Namespace]): Optional mapping base IRI. - - Keyword Args: - chunk_size (Optional[int]): How many rows of the original data to - ingest before yielding a graph. `None` will ingest all rows. - site_id_geometry_map (dict[str, str]): Default values of geometry wkt - to use for a given site id. - - Yields: - rdflib.Graph: ABIS Conformant RDF Sub-Graph from Raw Data Chunk. - """ - # Extract keyword arguments - chunk_size = kwargs.get("chunk_size") - if not isinstance(chunk_size, int): - chunk_size = None - - site_id_geometry_map = kwargs.get("site_id_geometry_map") - - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - extra_schema = self.extra_fields_schema( - data=data, - full_schema=False, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Initialise Graph - graph = utils.rdf.create_graph() - - # Check if Dataset IRI Supplied - if not dataset_iri: - # Create Dataset IRI - dataset_iri = utils.rdf.uri(f"dataset/{self.DATASET_DEFAULT_NAME}", base_iri) - - # Add Example Default Dataset if not Supplied - self.add_default_dataset( - uri=dataset_iri, - base_iri=base_iri, - graph=graph, - ) - - # Create Terminal Feature of Interest IRI - terminal_foi = utils.rdf.uri("location/Australia", base_iri) - - # Add Terminal Feature of Interest (Australia) - self.add_terminal_feature_of_interest( - uri=terminal_foi, - dataset=dataset_iri, - graph=graph, - ) - - # Open the Resource to allow row streaming - with resource.open() as r: - # Loop through Rows - for row in r.row_stream: - # Map Row - self.apply_mapping_row( - row=row, - dataset=dataset_iri, - terminal_foi=terminal_foi, - graph=graph, - extra_schema=extra_schema, - base_iri=base_iri, - site_id_geometry_map=site_id_geometry_map, - ) - - # Check Whether to Yield a Chunk - # The row_number needs to be reduced by one as the numbering of rows - # in a Resource includes the header. - if chunk_size is not None and (row.row_number - 1) % chunk_size == 0: - # Yield Chunk - yield graph - - # Initialise New Graph - graph = utils.rdf.create_graph() - - # Yield - yield graph - - def apply_mapping_row( - self, - row: frictionless.Row, - dataset: rdflib.URIRef, - terminal_foi: rdflib.URIRef, - graph: rdflib.Graph, - extra_schema: frictionless.Schema, - base_iri: Optional[rdflib.Namespace] = None, - site_id_geometry_map: dict[str, str] | None = None, - ) -> rdflib.Graph: - """Applies Mapping for a Row in the `survey_occurrence_data.csv` Template - - Args: - row (frictionless.Row): Row to be processed in the dataset. - dataset (rdflib.URIRef): Dataset uri this row is a part of. - terminal_foi (rdflib.URIRef): Terminal feature of interest. - graph (rdflib.Graph): Graph to map row into. - extra_schema (frictionless.Schema): Schema of extra fields. - base_iri (Optional[rdflib.Namespace]): Optional base IRI namespace - to use for mapping. - site_id_geometry_map (dict[str, str] | None): Optional site id to geometry - default map. - - Returns: - rdflib.Graph: Graph with row mapped into it. - """ - # Set the row number to be based on the data itself, excluding header - row_num = row.row_number - 1 - - # Create URIs - provider_provider_record_id_src = utils.rdf.uri(f"provider/{row['providerRecordIDSource']}", base_iri) - provider_identified = utils.rdf.uri(f"provider/{row['identifiedBy']}", base_iri) - sample_field = utils.rdf.uri(f"sample/field/{row_num}", base_iri) - sampling_field = utils.rdf.uri(f"sampling/field/{row_num}", base_iri) - sample_specimen = utils.rdf.uri(f"sample/specimen/{row_num}", base_iri) - sampling_specimen = utils.rdf.uri(f"sampling/specimen/{row_num}", base_iri) - text_scientific_name = utils.rdf.uri(f"scientificName/{row_num}", base_iri) - text_verbatim_id = utils.rdf.uri(f"verbatimID/{row_num}", base_iri) - observation_scientific_name = utils.rdf.uri(f"observation/scientificName/{row_num}", base_iri) - observation_verbatim_id = utils.rdf.uri(f"observation/verbatimID/{row_num}", base_iri) - id_qualifier_attribute = utils.rdf.uri(f"attribute/identificationQualifier/{row_num}", base_iri) - id_qualifier_value = utils.rdf.uri(f"value/identificationQualifier/{row_num}", base_iri) - id_remarks_attribute = utils.rdf.uri(f"attribute/identificationRemarks/{row_num}", base_iri) - id_remarks_value = utils.rdf.uri(f"value/identificationRemarks/{row_num}", base_iri) - data_generalizations_attribute = utils.rdf.uri(f"attribute/dataGeneralizations/{row_num}", base_iri) - data_generalizations_value = utils.rdf.uri(f"value/dataGeneralizations/{row_num}", base_iri) - taxon_rank_attribute = utils.rdf.uri(f"attribute/taxonRank/{row_num}", base_iri) - taxon_rank_value = utils.rdf.uri(f"value/taxonRank/{row_num}", base_iri) - individual_count_observation = utils.rdf.uri(f"observation/individualCount/{row_num}", base_iri) - individual_count_value = utils.rdf.uri(f"value/individualCount/{row_num}", base_iri) - organism_remarks_observation = utils.rdf.uri(f"observation/organismRemarks/{row_num}", base_iri) - organism_remarks_value = utils.rdf.uri(f"value/organismRemarks/{row_num}", base_iri) - habitat_attribute = utils.rdf.uri(f"attribute/habitat/{row_num}", base_iri) - habitat_value = utils.rdf.uri(f"value/habitat/{row_num}", base_iri) - basis_attribute = utils.rdf.uri(f"attribute/basisOfRecord/{row_num}", base_iri) - basis_value = utils.rdf.uri(f"value/basisOfRecord/{row_num}", base_iri) - occurrence_status_observation = utils.rdf.uri(f"observation/occurrenceStatus/{row_num}", base_iri) - occurrence_status_value = utils.rdf.uri(f"value/occurrenceStatus/{row_num}", base_iri) - preparations_attribute = utils.rdf.uri(f"attribute/preparations/{row_num}", base_iri) - preparations_value = utils.rdf.uri(f"value/preparations/{row_num}", base_iri) - establishment_means_observation = utils.rdf.uri(f"observation/establishmentMeans/{row_num}", base_iri) - establishment_means_value = utils.rdf.uri(f"value/establishmentMeans/{row_num}", base_iri) - life_stage_observation = utils.rdf.uri(f"observation/lifeStage/{row_num}", base_iri) - life_stage_value = utils.rdf.uri(f"value/lifeStage/{row_num}", base_iri) - sex_observation = utils.rdf.uri(f"observation/sex/{row_num}", base_iri) - sex_value = utils.rdf.uri(f"value/sex/{row_num}", base_iri) - reproductive_condition_observation = utils.rdf.uri(f"observation/reproductiveCondition/{row_num}", base_iri) - reproductive_condition_value = utils.rdf.uri(f"value/reproductiveCondition/{row_num}", base_iri) - accepted_name_usage_observation = utils.rdf.uri(f"observation/acceptedNameUsage/{row_num}", base_iri) - accepted_name_usage_value = utils.rdf.uri(f"value/acceptedNameUsage/{row_num}", base_iri) - sampling_sequencing = utils.rdf.uri(f"sampling/sequencing/{row_num}", base_iri) - sample_sequence = utils.rdf.uri(f"sample/sequence/{row_num}", base_iri) - threat_status_observation = utils.rdf.uri(f"observation/threatStatus/{row_num}", base_iri) - threat_status_value = utils.rdf.uri(f"value/threatStatus/{row_num}", base_iri) - conservation_jurisdiction_attribute = utils.rdf.uri(f"attribute/conservationJurisdiction/{row_num}", base_iri) - conservation_jurisdiction_value = utils.rdf.uri(f"value/conservationJurisdiction/{row_num}", base_iri) - provider_determined_by = utils.rdf.uri(f"provider/{row['threatStatusDeterminedBy']}", base_iri) - organism_quantity_observation = utils.rdf.uri(f"observation/organismQuantity/{row_num}", base_iri) - organism_quantity_value = utils.rdf.uri(f"value/organismQuantity/{row_num}", base_iri) - site = dataset + f"/site/{urllib.parse.quote(row['siteID'], safe='')}" if row["siteID"] else None - - provider_record_id_datatype = utils.rdf.uri( - internal_id=f"datatype/providerRecordID/{row['providerRecordIDSource']}", - namespace=base_iri, - ) - provider_record_id_agent = utils.rdf.uri(f"agent/{row['providerRecordIDSource']}", base_iri) - - # Conditionally create uris dependent on ownerRecordIDSource field - if owner_record_id_source := row["ownerRecordIDSource"]: - owner_record_id_datatype = utils.rdf.uri(f"datatype/ownerRecordID/{owner_record_id_source}", base_iri) - owner_record_id_provider = utils.rdf.uri(f"provider/{row['ownerRecordIDSource']}", base_iri) - else: - owner_record_id_datatype = None - owner_record_id_provider = None - - # Conditionally create uri's dependent on recordedBy field. - if recorded_by := row["recordedBy"]: - record_number_datatype = utils.rdf.uri(f"datatype/recordNumber/{recorded_by}", base_iri) - provider_recorded_by = utils.rdf.uri(f"provider/{recorded_by}", base_iri) - else: - record_number_datatype = None - provider_recorded_by = None - - # Conditionally create uris dependent on catalogNumberSource field. - if catalog_number_source := row["catalogNumberSource"]: - catalog_number_datatype = utils.rdf.uri(f"datatype/catalogNumber/{catalog_number_source}", base_iri) - catalog_number_provider = utils.rdf.uri(f"provider/{catalog_number_source}", base_iri) - else: - catalog_number_datatype = None - catalog_number_provider = None - - # Conditionally create uris dependent on otherCatalogNumbersSource field. - if other_catalog_numbers_source := row["otherCatalogNumbersSource"]: - other_catalog_numbers_datatype = utils.rdf.uri( - internal_id=f"datatype/otherCatalogNumbers/{other_catalog_numbers_source}", - namespace=base_iri, - ) - other_catalog_numbers_provider = utils.rdf.uri(f"provider/{other_catalog_numbers_source}", base_iri) - else: - other_catalog_numbers_datatype = None - other_catalog_numbers_provider = None - - # Add Provider Identified By - self.add_provider_identified( - uri=provider_identified, - row=row, - graph=graph, - ) - - # Add Provider Recorded By - self.add_provider_recorded( - uri=provider_recorded_by, - row=row, - graph=graph, - ) - - # Add Sample Field - self.add_sample_field( - uri=sample_field, - row=row, - dataset=dataset, - feature_of_interest=terminal_foi, - sampling_field=sampling_field, - owner_record_id_datatype=owner_record_id_datatype, - other_catalog_numbers_datatype=other_catalog_numbers_datatype, - record_number_datatype=record_number_datatype, - site=site, - graph=graph, - ) - - # Add record number datatype - self.add_record_number_datatype( - uri=record_number_datatype, - provider=provider_recorded_by, - graph=graph, - ) - - # Add provider provider agent - self.add_provider_recorded_by_agent( - uri=provider_recorded_by, - row=row, - graph=graph, - ) - - # Add owner record id datatype - self.add_owner_record_id_datatype( - uri=owner_record_id_datatype, - provider=owner_record_id_provider, - graph=graph, - ) - - # Add the provider owner record id - self.add_owner_record_id_provider( - uri=owner_record_id_provider, - row=row, - graph=graph, - ) - - # Add Sampling Field - self.add_sampling_field( - uri=sampling_field, - row=row, - dataset=dataset, - provider_record_id_source=provider_record_id_datatype, - provider=provider_recorded_by, - feature_of_interest=terminal_foi, - sample_field=sample_field, - generalizations=data_generalizations_attribute, - habitat=habitat_attribute, - basis=basis_attribute, - site=site, - site_id_geometry_map=site_id_geometry_map, - graph=graph, - ) - - # Add provider record ID datatype - self.add_provider_record_id_datatype( - uri=provider_record_id_datatype, - agent=provider_record_id_agent, - graph=graph, - ) - - # Add provider agent - self.add_provider_record_id_agent( - uri=provider_record_id_agent, - row=row, - graph=graph, - ) - - # Add Sample Specimen - self.add_sample_specimen( - uri=sample_specimen, - row=row, - dataset=dataset, - sampling_specimen=sampling_specimen, - sample_field=sample_field, - preparations=preparations_attribute, - catalog_number_datatype=catalog_number_datatype, - graph=graph, - ) - - # Add catalog number datatype - self.add_catalog_number_datatype( - uri=catalog_number_datatype, - provider=catalog_number_provider, - graph=graph, - ) - - # Add catalog number provider - self.add_catalog_number_provider( - uri=catalog_number_provider, - row=row, - graph=graph, - ) - - # Add other catalog numbers datatype - self.add_other_catalog_numbers_datatype( - uri=other_catalog_numbers_datatype, - provider=other_catalog_numbers_provider, - graph=graph, - ) - - # Add other catalog numbers provider - self.add_other_catalog_numbers_provider( - uri=other_catalog_numbers_provider, - row=row, - graph=graph, - ) - - # Add Sampling Specimen - self.add_sampling_specimen( - uri=sampling_specimen, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - generalizations=data_generalizations_attribute, - basis=basis_attribute, - site_id_geometry_map=site_id_geometry_map, - graph=graph, - ) - - # Add Text for Scientific Name - self.add_text_scientific_name( - uri=text_scientific_name, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add Identification Qualifier Attribute - self.add_id_qualifier_attribute( - uri=id_qualifier_attribute, - row=row, - dataset=dataset, - id_qualifier_value=id_qualifier_value, - graph=graph, - ) - - # Add Identification Qualifier Value - self.add_id_qualifier_value( - uri=id_qualifier_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Identification Remarks Attribute - self.add_id_remarks_attribute( - uri=id_remarks_attribute, - row=row, - dataset=dataset, - id_remarks_value=id_remarks_value, - graph=graph, - ) - - # Add Identification Remarks Value - self.add_id_remarks_value( - uri=id_remarks_value, - row=row, - graph=graph, - ) - - # Add Text for Verbatim ID - self.add_text_verbatim_id( - uri=text_verbatim_id, - row=row, - graph=graph, - ) - - # Add Observation for Scientific Name - self.add_observation_scientific_name( - uri=observation_scientific_name, - row=row, - dataset=dataset, - provider=provider_identified, - sample_field=sample_field, - sample_specimen=sample_specimen, - scientific_name=text_scientific_name, - qualifier=id_qualifier_attribute, - remarks=id_remarks_attribute, - taxon_rank=taxon_rank_attribute, - graph=graph, - ) - - # Add Observation for Verbatim ID - self.add_observation_verbatim_id( - uri=observation_verbatim_id, - row=row, - dataset=dataset, - provider=provider_identified, - sample_field=sample_field, - sample_specimen=sample_specimen, - verbatim_id=text_verbatim_id, - graph=graph, - ) - - # Add Data Generalizations Attribute - self.add_data_generalizations_attribute( - uri=data_generalizations_attribute, - row=row, - dataset=dataset, - data_generalizations_value=data_generalizations_value, - graph=graph, - ) - - # Add Data Generalizations Value - self.add_data_generalizations_value( - uri=data_generalizations_value, - row=row, - graph=graph, - ) - - # Add Taxon Rank Attribute - self.add_taxon_rank_attribute( - uri=taxon_rank_attribute, - row=row, - dataset=dataset, - taxon_rank_value=taxon_rank_value, - graph=graph, - ) - - # Add Taxon Rank Value - self.add_taxon_rank_value( - uri=taxon_rank_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Individual Count Observation - self.add_individual_count_observation( - uri=individual_count_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - individual_count_value=individual_count_value, - graph=graph, - ) - - # Add Individual Count Value - self.add_individual_count_value( - uri=individual_count_value, - row=row, - graph=graph, - ) - - # Add Organism Remarks Observation - self.add_organism_remarks_observation( - uri=organism_remarks_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - organism_remarks_value=organism_remarks_value, - graph=graph, - ) - - # Add Organism Remarks Value - self.add_organism_remarks_value( - uri=organism_remarks_value, - row=row, - graph=graph, - ) - - # Add Habitat Attribute - self.add_habitat_attribute( - uri=habitat_attribute, - row=row, - dataset=dataset, - habitat_value=habitat_value, - graph=graph, - ) - - # Add Habitat Value - self.add_habitat_value( - uri=habitat_value, - row=row, - graph=graph, - ) - - # Add Basis of Record Attribute - self.add_basis_attribute( - uri=basis_attribute, - row=row, - dataset=dataset, - basis_value=basis_value, - graph=graph, - ) - - # Add Basis of Record Value - self.add_basis_value( - uri=basis_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Owner Institution Provider - self.add_owner_institution_provider( - uri=owner_record_id_provider, - row=row, - graph=graph, - ) - - # Add provider record id provider - self.add_provider_record_id_provider( - uri=provider_provider_record_id_src, - row=row, - graph=graph, - ) - - # Add Occurrence Status Observation - self.add_occurrence_status_observation( - uri=occurrence_status_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - occurrence_status_value=occurrence_status_value, - graph=graph, - ) - - # Add Occurrence Status Value - self.add_occurrence_status_value( - uri=occurrence_status_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Preparations Attribute - self.add_preparations_attribute( - uri=preparations_attribute, - row=row, - dataset=dataset, - preparations_value=preparations_value, - graph=graph, - ) - - # Add Preparations Value - self.add_preparations_value( - uri=preparations_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Establishment Means Observation - self.add_establishment_means_observation( - uri=establishment_means_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - establishment_means_value=establishment_means_value, - graph=graph, - ) - - # Add Establishment Means Value - self.add_establishment_means_value( - uri=establishment_means_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Life Stage Observation - self.add_life_stage_observation( - uri=life_stage_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - life_stage_value=life_stage_value, - graph=graph, - ) - - # Add Life Stage Value - self.add_life_stage_value( - uri=life_stage_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Sex Observation - self.add_sex_observation( - uri=sex_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - sex_value=sex_value, - graph=graph, - ) - - # Add Sex Value - self.add_sex_value( - uri=sex_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Reproductive Condition Observation - self.add_reproductive_condition_observation( - uri=reproductive_condition_observation, - row=row, - dataset=dataset, - sample_field=sample_field, - sample_specimen=sample_specimen, - reproductive_condition_value=reproductive_condition_value, - graph=graph, - ) - - # Add Reproductive Condition Value - self.add_reproductive_condition_value( - uri=reproductive_condition_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Accepted Name Usage Observation - self.add_accepted_name_usage_observation( - uri=accepted_name_usage_observation, - row=row, - dataset=dataset, - scientific_name=text_scientific_name, - accepted_name_usage_value=accepted_name_usage_value, - graph=graph, - ) - - # Add Accepted Name Usage Value - self.add_accepted_name_usage_value( - uri=accepted_name_usage_value, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add Sampling Sequencing - self.add_sampling_sequencing( - uri=sampling_sequencing, - row=row, - dataset=dataset, - feature_of_interest=sample_specimen, - sample_sequence=sample_sequence, - site_id_geometry_map=site_id_geometry_map, - graph=graph, - ) - - # Add Sample Sequence - self.add_sample_sequence( - uri=sample_sequence, - row=row, - dataset=dataset, - feature_of_interest=sample_specimen, - sampling_sequencing=sampling_sequencing, - graph=graph, - ) - - # Add Provider Threat Status Determined By - self.add_provider_determined_by( - uri=provider_determined_by, - row=row, - graph=graph, - ) - - # Add Threat Status Observation - self.add_threat_status_observation( - uri=threat_status_observation, - row=row, - dataset=dataset, - accepted_name_usage=accepted_name_usage_value, - scientific_name=text_scientific_name, - threat_status_value=threat_status_value, - jurisdiction_attribute=conservation_jurisdiction_attribute, - determined_by=provider_determined_by, - graph=graph, - ) - - # Add Threat Status Value - self.add_threat_status_value( - uri=threat_status_value, - row=row, - dataset=dataset, - graph=graph, - ) - - # Add Conservation Jurisdiction Attribute - self.add_conservation_jurisdiction_attribute( - uri=conservation_jurisdiction_attribute, - row=row, - dataset=dataset, - conservation_jurisdiction_value=conservation_jurisdiction_value, - graph=graph, - ) - - # Add Conservation Jurisdiction Value - self.add_conservation_jurisdiction_value( - uri=conservation_jurisdiction_value, - row=row, - graph=graph, - ) - - # Add organism quantity observation - self.add_organism_quantity_observation( - uri=organism_quantity_observation, - sample_field=sample_field, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add organism quantity value - self.add_organism_quantity_value( - uri=organism_quantity_value, - organism_qty_observation=organism_quantity_observation, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add site - self.add_site( - uri=site, - dataset=dataset, - terminal_foi=terminal_foi, - graph=graph, - ) - - # Add extra fields JSON - self.add_extra_fields_json( - subject_uri=sampling_field, - row=row, - graph=graph, - extra_schema=extra_schema, - ) - - # Return - return graph - - def add_terminal_feature_of_interest( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds the Terminal Feature of Interest to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Add Terminal Feature of Interest to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SITE)) - - # Add Geometry - geometry = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry)) - graph.add((geometry, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry, utils.namespaces.GEO.sfWithin, CONCEPT_AUSTRALIA)) - - def add_provider_identified( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Identified By Provider to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for identifiedBy - if not row["identifiedBy"]: - return - - # Add to Graph - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["identifiedBy"]))) - - def add_provider_recorded( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Recorded By Provider to the Graph - - Args: - uri (rdflib.URIRef | None): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for valid subject and data - if not row["recordedBy"] or uri is None: - return - - # Add to Graph - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["recordedBy"]))) - - def add_observation_scientific_name( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - scientific_name: rdflib.URIRef, - qualifier: rdflib.URIRef, - remarks: rdflib.URIRef, - taxon_rank: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Observation Scientific Name to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider (rdflib.URIRef): Provider associated with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - qualifier (rdflib.URIRef): Identification Qualifier attribute - associated with this node - remarks (rdflib.URIRef): Identification Remarks attribute - associated with this node - taxon_rank (rdflib.URIRef): Taxon Rank attribute associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Get Timestamps - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve vocab for field - vocab = self.fields()["identificationMethod"].get_vocab() - - # Retrieve Vocab or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("scientificName-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, scientific_name)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["scientificName"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Check for identifiedBy - if row["identifiedBy"]: - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for dateIdentified - if not row["dateIdentified"]: - # Add comment to temporal entity - comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - # Check for identificationQualifier - if row["identificationQualifier"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, qualifier)) - - # Check for identificationRemarks - if row["identificationRemarks"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, remarks)) - - # Check for taxonRank - if row["taxonRank"]: - graph.add((uri, utils.namespaces.TERN.hasAttribute, taxon_rank)) - - def add_observation_verbatim_id( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - verbatim_id: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Observation Verbatim ID to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider (rdflib.URIRef): Provider associated with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - verbatim_id (rdflib.URIRef): Verbatim ID associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check for verbatimIdentification - if not row["verbatimIdentification"]: - return - - # Get Timestamp - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve vocab for field - vocab = self.fields()["identificationMethod"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("verbatimID-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, verbatim_id)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["verbatimIdentification"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Check for identifiedBy - if row["identifiedBy"]: - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for dateIdentified - if not row["dateIdentified"]: - # Add comment to temporal entity - comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - def add_provider_recorded_by_agent( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the provider agent to the graph. - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Ensure data and URI passed in - if uri is None or not row["recordedBy"]: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["recordedBy"]))) - - def add_owner_record_id_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds the owner record id datatype to the graph. - Args: - uri (rdflib.URIRef): Subject of the node. - provider (rdflib.URIRef): Provider of the datatype. - graph (rdflid.Graph): Graph to be modified. - """ - # Check to see subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("ownerRecordID source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_owner_record_id_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the provider owner record id node. - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified.: - """ - # Check that a subject uri was supplied - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["ownerRecordIDSource"]))) - - def add_sampling_field( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - provider_record_id_source: rdflib.URIRef, - provider: rdflib.URIRef | None, - feature_of_interest: rdflib.URIRef, - sample_field: rdflib.URIRef, - generalizations: rdflib.URIRef, - habitat: rdflib.URIRef, - basis: rdflib.URIRef, - site: rdflib.URIRef | None, - site_id_geometry_map: dict[str, str] | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Field to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - provider_record_id_source (rdflib.URIRef): Provider record id source - associated with this node. - provider (rdflib.URIRef | None): Provider associated with this node - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node. - sample_field (rdflib.URIRef): Sample Field associated with this - node - generalizations (rdflib.URIRef): Data Generalizations associated - with this node - habitat (rdflib.URIRef): Habitat associated with this node - basis (rdflib.URIRef): Basis Of Record associated with this node - site (rdflib.URIRef | None): Site if one was provided else None. - site_id_geometry_map (dict[str, str] | None): Default geometry value to use - if none available for given site id. - graph (rdflib.Graph): Graph to add to - """ - # Extract values - latitude = row["decimalLatitude"] - longitude = row["decimalLongitude"] - site_id = row["siteID"] - event_date: models.temporal.Timestamp = row["eventDate"] - - if latitude is not None and longitude is not None: - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(row["decimalLatitude"], row["decimalLongitude"]), - datum=row["geodeticDatum"], - ) - - elif site_id_geometry_map is not None and (default_geometry := site_id_geometry_map.get(site_id)) is not None: - # Create geometry from literal - geometry = models.spatial.Geometry.from_geosparql_wkt_literal(default_geometry) - - else: - # Should not reach this as data is already validated included for completeness - return - - # Add survey - graph.add((uri, rdflib.SDO.isPartOf, DEFAULT_SURVEY)) # TODO -> Cross reference - - # Retrieve vocab for field - vocab = self.fields()["samplingProtocol"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["samplingProtocol"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("field-sampling"))) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - graph.add((uri, rdflib.SOSA.hasResult, sample_field)) - - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Add site if one provided - if site is not None: - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, site)) - else: - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, feature_of_interest)) - - # Add Identifier - graph.add( - ( - uri, - rdflib.DCTERMS.identifier, - rdflib.Literal(row["providerRecordID"], datatype=provider_record_id_source), - ) - ) - - # Check for recordedBy - if row["recordedBy"] and provider is not None: - # Add Associated Provider - graph.add((uri, rdflib.PROV.wasAssociatedWith, provider)) - - # Check for locality - if row["locality"]: - # Add Location Description - graph.add((uri, utils.namespaces.TERN.locationDescription, rdflib.Literal(row["locality"]))) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Check for dataGeneralizations - if row["dataGeneralizations"]: - # Add Data Generalizations Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, generalizations)) - - # Check for habitat - if row["habitat"]: - # Add Habitat Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, habitat)) - - # Check for basisOfRecord and if Row has no Specimen - if not has_specimen(row) and row["basisOfRecord"]: - # Add Basis Of Record Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, basis)) - - def add_provider_record_id_datatype( - self, - uri: rdflib.URIRef, - agent: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds the provider record id datatype to the graph. - Args: - uri (rdflib.URIRef): Subject of the node. - agent (rdflib.URIRef): Provider agent URI. - graph (rdflib.Graph): Graph to be modified. - """ - # Add the type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("providerRecordID source"))) - - # Add attribution - graph.add((uri, rdflib.PROV.wasAttributedTo, agent)) - - def add_provider_record_id_agent( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds provider record id agent to the graph. - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["providerRecordIDSource"]))) - - def add_id_qualifier_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - id_qualifier_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Qualifier Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - id_qualifier_value (rdflib.URIRef): Identification Qualifier Value - associated with this node. - graph (rdflib.Graph): Graph to add to - """ - # Check identificationQualifier - if not row["identificationQualifier"]: - return - - # Identification Qualifier Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_ID_UNCERTAINTY)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["identificationQualifier"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, id_qualifier_value)) - - def add_id_qualifier_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Qualifier Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check identificationQualifier - if not row["identificationQualifier"]: - return - - # Retrieve vocab for field - vocab = self.fields()["identificationQualifier"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["identificationQualifier"]) - - # Identification Qualifier Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("identificationQualifier"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_id_remarks_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - id_remarks_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Remarks Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - id_remarks_value (rdflib.URIRef): Identification Remarks Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check identificationRemarks - if not row["identificationRemarks"]: - return - - # Identification Remarks Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_ID_REMARKS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["identificationRemarks"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, id_remarks_value)) - - def add_id_remarks_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Identification Remarks Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check identificationRemarks - if not row["identificationRemarks"]: - return - - # Identification Remarks Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["identificationRemarks"]))) - - def add_text_scientific_name( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Text Scientific Name to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset this belongs to - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("scientificName"))) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["scientificName"]))) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SCIENTIFIC_NAME)) - - def add_catalog_number_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds catalog number datatype to the graph. - Args: - uri (rdflib.URIRef | None): Subject of the node. - provider (rdflib.URIRef | None): Corresponding provider. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("catalogNumber source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_catalog_number_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the catalog number provider to the graph. - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionlee.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["catalogNumberSource"]))) - - def add_other_catalog_numbers_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds other catalog numbers datatype to the graph. - Args: - uri (rdflib.URIRef | None): Subject of the node. - provider (rdflib.URIRef | None): Corresponding provider. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("otherCatalogNumbers source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_other_catalog_numbers_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds other catalog numbers provider to the graph. - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check that subject was provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["otherCatalogNumbersSource"]))) - - def add_sampling_specimen( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - generalizations: rdflib.URIRef, - basis: rdflib.URIRef, - site_id_geometry_map: dict[str, str] | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Specimen to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - generalizations (rdflib.URIRef): Data Generalizations associated - with this node - basis (rdflib.URIRef): Basis Of Record associated with this node - site_id_geometry_map (dict[str, str] | None): Map with default wkt - string for a given site id. - graph (rdflib.Graph): Graph to add to - """ - # Check if Row has a Specimen - if not has_specimen(row): - return - - # Extract values - latitude = row["decimalLatitude"] - longitude = row["decimalLongitude"] - geodetic_datum = row["geodeticDatum"] - site_id = row["siteID"] - - if latitude is not None and longitude is not None: - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(latitude, longitude), - datum=geodetic_datum, - ) - - elif site_id_geometry_map is not None and (default_geometry := site_id_geometry_map.get(site_id)) is not None: - # Create geometry from geosparql wkt literal - geometry = models.spatial.Geometry.from_geosparql_wkt_literal(default_geometry) - - else: - # Should not reach here since validated data provided, however if - # it does come to it the corresponding node will be omitted - return - - # Get Timestamp - timestamp: models.temporal.Timestamp = row["preparedDate"] or row["eventDate"] - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("specimen-sampling"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, sample_specimen)) - graph.add((uri, rdflib.SOSA.usedProcedure, CONCEPT_PROCEDURE_SAMPLING)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, timestamp.rdf_in_xsd, timestamp.to_rdf_literal())) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Add comment to geometry - spatial_comment = "Location unknown, location of field sampling used as proxy" - graph.add((geometry_node, rdflib.RDFS.comment, rdflib.Literal(spatial_comment))) - - # Check for preparedDate - if not row["preparedDate"]: - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Check for dataGeneralizations - if row["dataGeneralizations"]: - # Add Data Generalizations Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, generalizations)) - - # Check for basisOfRecord and if Row has a Specimen - if has_specimen(row) and row["basisOfRecord"]: - # Add Basis Of Record Attribute - graph.add((uri, utils.namespaces.TERN.hasAttribute, basis)) - - def add_text_verbatim_id( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Text Verbatim ID to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for verbatimIdentification - if not row["verbatimIdentification"]: - return - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["verbatimIdentification"]))) - - def add_sample_field( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sampling_field: rdflib.URIRef, - owner_record_id_datatype: rdflib.URIRef | None, - other_catalog_numbers_datatype: rdflib.URIRef | None, - record_number_datatype: rdflib.URIRef | None, - site: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Field to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node. - sampling_field (rdflib.URIRef): Sampling Field associated with this - node - owner_record_id_datatype (rdflib.URIRef | None): Source of owner ID - used as datatype. - other_catalog_numbers_datatype (rdflib.URIRef | None): Datatype to use - with other catalog numbers literals. - record_number_datatype (rdflib.URIRef | None): Datatype to use - with record number literal. - site (rdflib.URIRef | None): Site associated with this node if - provided else None. - graph (rdflib.Graph): Graph to add to - """ - # Retrieve vocab for field (multiple exists for kingdom) - vocab = self.fields()["kingdom"].get_vocab("KINGDOM_OCCURRENCE") - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["kingdom"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("field-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_field)) - graph.add((uri, utils.namespaces.TERN.featureType, term)) - - if site is not None: - graph.add((uri, rdflib.SOSA.isSampleOf, site)) - else: - graph.add((uri, rdflib.SOSA.isSampleOf, feature_of_interest)) - - # Check for recordNumber - if row["recordNumber"]: - # Determine which datatype to use for literal - dt = record_number_datatype or rdflib.XSD.string - # Add to Graph - graph.add((uri, utils.namespaces.DWC.recordNumber, rdflib.Literal(row["recordNumber"], datatype=dt))) - - # Check for otherCatalogNumbers - if other_catalog_numbers := row["otherCatalogNumbers"]: - # Add to Graph - graph.add((uri, utils.namespaces.DWC.otherCatalogNumbers, rdflib.Literal(other_catalog_numbers))) - - # Check for ownerRecordID - if (owner_record_id := row["ownerRecordID"]) and owner_record_id_datatype: - # Add to graph - graph.add( - (uri, rdflib.DCTERMS.identifier, rdflib.Literal(owner_record_id, datatype=owner_record_id_datatype)) - ) - - # Check for otherCatalogNumbers - if (other_catalog_numbers := row["otherCatalogNumbers"]) and other_catalog_numbers_datatype is not None: - # Iterate through the catalog numbers - for num in other_catalog_numbers: - # Add catalog number literal - graph.add( - ( - uri, - utils.namespaces.DWC.otherCatalogNumbers, - rdflib.Literal(num, datatype=other_catalog_numbers_datatype), - ) - ) - - def add_record_number_datatype( - self, - uri: rdflib.URIRef | None, - provider: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds record number datatype to the graph. - Args: - uri (rdflib.URIRef | None): The subject of the node - or None if uri wasn't created. - provider (rdflib.URIRef | None): The corresponding - provider uri. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("recordNumber source"))) - - # Add attribution - if provider is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, provider)) - - def add_sample_specimen( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sampling_specimen: rdflib.URIRef, - sample_field: rdflib.URIRef, - preparations: rdflib.URIRef, - catalog_number_datatype: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Specimen to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sampling_specimen (rdflib.URIRef): Sampling Specimen associated - with this node - sample_field (rdflib.URIRef): Sample Field associated with this - node - preparations (rdflib.URIRef): Preparations Attribute associated - with this node - catalog_number_datatype (rdflib.URIRef | None): Catalog number source - datatype. - graph (rdflib.Graph): Graph to add to - """ - # Check if Row has a Specimen - if not has_specimen(row): - return - - # Retrieve vocab for field (multiple exists for kingdom) - vocab = self.fields()["kingdom"].get_vocab("KINGDOM_SPECIMEN") - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["kingdom"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("specimen-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_specimen)) - graph.add((uri, rdflib.SOSA.isSampleOf, sample_field)) - graph.add((uri, utils.namespaces.TERN.featureType, term)) - - # Check for catalogNumber - if row["catalogNumber"]: - # Add to Graph - graph.add( - ( - uri, - utils.namespaces.DWC.catalogNumber, - rdflib.Literal(row["catalogNumber"], datatype=catalog_number_datatype), - ) - ) - - # Check for collectionCode - if row["collectionCode"]: - # Add to Graph - graph.add((uri, utils.namespaces.DWC.collectionCode, rdflib.Literal(row["collectionCode"]))) - - # Check for preparations - if row["preparations"]: - # Add Preparations - graph.add((uri, utils.namespaces.TERN.hasAttribute, preparations)) - - def add_data_generalizations_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - data_generalizations_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Data Generalizations Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - data_generalizations_value (rdflib.URIRef): Data Generalizations - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["dataGeneralizations"]: - return - - # Data Generalizations Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_DATA_GENERALIZATIONS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["dataGeneralizations"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, data_generalizations_value)) - - def add_data_generalizations_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Data Generalizations Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["dataGeneralizations"]: - return - - # Data Generalizations Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["dataGeneralizations"]))) - - def add_taxon_rank_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - taxon_rank_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Taxon Rank Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - taxon_rank_value (rdflib.URIRef): Taxon Rank Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["taxonRank"]: - return - - # Taxon Rank Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_TAXON_RANK)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["taxonRank"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, taxon_rank_value)) - - def add_taxon_rank_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Taxon Rank Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["taxonRank"]: - return - - # Retrieve vocab for field - vocab = self.fields()["taxonRank"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["taxonRank"]) - - # Taxon Rank Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"taxon rank = {row['taxonRank']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_individual_count_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - individual_count_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Individual Count Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - individual_count_value (rdflib.URIRef): Individual Count Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["individualCount"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Individual Count Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("individualCount-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, individual_count_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["individualCount"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_INDIVIDUAL_COUNT)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_individual_count_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Individual Count Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["individualCount"]: - return - - # Individual Count Value - graph.add((uri, a, utils.namespaces.TERN.Integer)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("individual-count"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["individualCount"]))) - - def add_organism_remarks_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - organism_remarks_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Organism Remarks Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - organism_remarks_value (rdflib.URIRef): Organism Remarks Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["organismRemarks"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Organism Remarks Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("organismRemarks-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, organism_remarks_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["organismRemarks"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_ORGANISM_REMARKS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_organism_remarks_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Organism Remarks Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["organismRemarks"]: - return - - # Organism Remarks Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("organism-remarks"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["organismRemarks"]))) - - def add_habitat_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - habitat_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Habitat Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - habitat_value (rdflib.URIRef): Habitat Value associated with this - node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["habitat"]: - return - - # Habitat Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_HABITAT)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["habitat"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, habitat_value)) - - def add_habitat_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Habitat Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["habitat"]: - return - - # Habitat Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("habitat"))) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["habitat"]))) - - def add_basis_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - basis_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Basis of Record Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - basis_value (rdflib.URIRef): Basis of Record Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["basisOfRecord"]: - return - - # Basis of Record Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_BASIS_OF_RECORD)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["basisOfRecord"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, basis_value)) - - def add_basis_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Basis of Record Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["basisOfRecord"]: - return - - # Retrieve vocab for field - vocab = self.fields()["basisOfRecord"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["basisOfRecord"]) - - # Basis of Record Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("basisOfRecord"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_owner_institution_provider( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Owner Institution Provider to the Graph - - Args: - uri (rdflib.URIRef | None): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # TODO -> Retrieve this from a known list of institutions - # Check Existence - if not row["ownerRecordIDSource"] or uri is None: - return - - # Owner Institution Provider - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["ownerRecordIDSource"]))) - - def add_provider_record_id_provider( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds provider record id provider to the graph. - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # TODO -> Retrieve this from a known list of institutions - # Institution Provider - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["providerRecordIDSource"]))) - - def add_occurrence_status_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - occurrence_status_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Occurrence Status Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - occurrence_status_value (rdflib.URIRef): Occurrence Status Value - associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["occurrenceStatus"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Occurrence Status Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("occurrenceStatus-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, occurrence_status_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["occurrenceStatus"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_OCCURRENCE_STATUS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_occurrence_status_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Occurrence Status Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["occurrenceStatus"]: - return - - # Retrieve vocab for field - vocab = self.fields()["occurrenceStatus"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["occurrenceStatus"]) - - # Occurrence Status Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"occurrenceStatus = {row['occurrenceStatus']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_preparations_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - preparations_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Preparations Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - preparations_value (rdflib.URIRef): Preparations Value associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["preparations"]: - return - - # Preparations Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_PREPARATIONS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["preparations"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, preparations_value)) - - def add_preparations_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Preparations Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["preparations"]: - return - - # Retrieve vocab for field - vocab = self.fields()["preparations"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["preparations"]) - - # Preparations Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("preparations"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_establishment_means_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - establishment_means_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Establishment Means Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - establishment_means_value (rdflib.URIRef): Establishment Means - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["establishmentMeans"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Establishment Means Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("establishmentMeans-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.SOSA.hasResult, establishment_means_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["establishmentMeans"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_ESTABLISHMENT_MEANS)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_establishment_means_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Establishment Means Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["establishmentMeans"]: - return - - # Retrieve vocab for field - vocab = self.fields()["establishmentMeans"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["establishmentMeans"]) - - # Establishment Means Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("establishmentMeans-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_life_stage_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - life_stage_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Life Stage Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - life_stage_value (rdflib.URIRef): Life Stage Value associated with - this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["lifeStage"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Life Stage Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("lifeStage-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, life_stage_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["lifeStage"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_LIFE_STAGE)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_life_stage_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Life Stage Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["lifeStage"]: - return - - # Retrieve vocab for field - vocab = self.fields()["lifeStage"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["lifeStage"]) - - # Life Stage Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("lifeStage-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_sex_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - sex_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sex Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - sex_value (rdflib.URIRef): Sex Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["sex"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Sex Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sex-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, sex_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["sex"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_SEX)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_sex_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sex Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["sex"]: - return - - # Retrieve vocab for field - vocab = self.fields()["sex"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["sex"]) - - # Sex Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("sex-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_reproductive_condition_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - sample_specimen: rdflib.URIRef, - reproductive_condition_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Reproductive Condition Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - sample_field (rdflib.URIRef): Sample Field associated with this - node - sample_specimen (rdflib.URIRef): Sample Specimen associated with - this node - reproductive_condition_value (rdflib.URIRef): Reproductive - Condition Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["reproductiveCondition"]: - return - - # Get Timestamp - event_date: models.temporal.Timestamp = row["eventDate"] - - # Choose Feature of Interest - # The Feature of Interest is the Specimen Sample if it is determined - # that this row has a specimen, otherwise it is Field Sample - foi = sample_specimen if has_specimen(row) else sample_field - - # Retrieve Vocab or Create on the Fly - vocab = vocabs.sampling_protocol.HUMAN_OBSERVATION.iri # Always Human Observation - - # Reproductive Condition Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("reproductiveCondition-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, reproductive_condition_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["reproductiveCondition"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_REPRODUCTIVE_CONDITION)) - graph.add((uri, rdflib.SOSA.usedProcedure, vocab)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add method comment to node - method_comment = "Observation method unknown, 'human observation' used as proxy" - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal(method_comment))) - - def add_reproductive_condition_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Reproductive Condition Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["reproductiveCondition"]: - return - - # Retrieve vocab for field - vocab = self.fields()["reproductiveCondition"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["reproductiveCondition"]) - - # Reproductive Condition Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("reproductiveCondition-value"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_accepted_name_usage_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - scientific_name: rdflib.URIRef, - accepted_name_usage_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Accepted Name Usage Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - accepted_name_usage_value (rdflib.URIRef): Accepted Name Usage - Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["acceptedNameUsage"]: - return - - # Get Timestamp - date_identified: models.temporal.Timestamp = row["dateIdentified"] or row["eventDate"] - - # Accepted Name Usage Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("acceptedNameUsage-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, scientific_name)) - graph.add((uri, rdflib.SOSA.hasResult, accepted_name_usage_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["acceptedNameUsage"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_TAXON)) - graph.add((uri, rdflib.SOSA.usedProcedure, CONCEPT_NAME_CHECK_METHOD)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_identified.rdf_in_xsd, date_identified.to_rdf_literal())) - - # Add comment to temporal entity - timestamp_used = "dateIdentified" if row["dateIdentified"] else "eventDate" # Determine which field was used - temporal_comment = f"Date unknown, template {timestamp_used} used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - def add_accepted_name_usage_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Accepted Name Usage Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - dataset (rdflib.URIRef): Dataset this belongs to - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["acceptedNameUsage"]: - return - - # Accepted Name Usage Value - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("acceptedNameUsage-value"))) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["acceptedNameUsage"]))) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_ACCEPTED_NAME_USAGE)) - - def add_sampling_sequencing( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sample_sequence: rdflib.URIRef, - site_id_geometry_map: dict[str, str] | None, - graph: rdflib.Graph, - ) -> None: - """Adds Sampling Sequencing to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node - sample_sequence (rdflib.URIRef): Sample Sequence associated with - this node - site_id_geometry_map (dict[str, str] | None): Map of default geometry - string values for a given site id. - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["associatedSequences"]: - return - - # Extract values - latitude = row["decimalLatitude"] - longitude = row["decimalLongitude"] - geodetic_datum = row["geodeticDatum"] - site_id = row["siteID"] - event_date: models.temporal.Timestamp = row["eventDate"] - - if latitude is not None and longitude is not None: - # Create geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(latitude, longitude), - datum=geodetic_datum, - ) - - elif site_id_geometry_map is not None and (default_geometry := site_id_geometry_map.get(site_id)) is not None: - # Create geometry from wkt literal - geometry = models.spatial.Geometry.from_geosparql_wkt_literal(default_geometry) - - else: - # Should not be able to reach here if validated data provided, - # but if it does then node will be ommitted from graph. - return - - # Retrieve vocab for field - vocab = self.fields()["sequencingMethod"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["sequencingMethod"]) - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.Sampling)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sequencing-sampling"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, feature_of_interest)) - graph.add((uri, rdflib.SOSA.hasResult, sample_sequence)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - - # Add geometry - geometry_node = rdflib.BNode() - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - # Check for coordinateUncertaintyInMeters - if row["coordinateUncertaintyInMeters"]: - # Add Spatial Accuracy - accuracy = rdflib.Literal(row["coordinateUncertaintyInMeters"], datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Add comment to temporal entity - temporal_comment = "Date unknown, template eventDate used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(temporal_comment))) - - # Add comment to geometry - spatial_comment = "Location unknown, location of field sampling used as proxy" - graph.add((geometry_node, rdflib.RDFS.comment, rdflib.Literal(spatial_comment))) - - def add_sample_sequence( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - feature_of_interest: rdflib.URIRef, - sampling_sequencing: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Sample Sequence to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - feature_of_interest (rdflib.URIRef): Feature of Interest associated - with this node - sampling_sequencing (rdflib.URIRef): Sampling Sequencing associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["associatedSequences"]: - return - - # Add to Graph - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, a, utils.namespaces.TERN.Sample)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("sequence-sample"))) - graph.add((uri, rdflib.SOSA.isResultOf, sampling_sequencing)) - graph.add((uri, rdflib.SOSA.isSampleOf, feature_of_interest)) - graph.add((uri, utils.namespaces.TERN.featureType, CONCEPT_SEQUENCE)) - - # Loop Through Associated Sequences - for identifier in row["associatedSequences"]: - # Add Identifier - graph.add((uri, rdflib.DCTERMS.identifier, rdflib.Literal(identifier))) - - def add_provider_determined_by( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Determined By Provider to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check for threatStatusDeterminedBy - if not row["threatStatusDeterminedBy"]: - return - - # Add to Graph - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["threatStatusDeterminedBy"]))) - - def add_threat_status_observation( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - accepted_name_usage: rdflib.URIRef, - scientific_name: rdflib.URIRef, - threat_status_value: rdflib.URIRef, - jurisdiction_attribute: rdflib.URIRef, - determined_by: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Threat Status Observation to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - accepted_name_usage (rdflib.URIRef): Accepted Name Usage associated - with this node - scientific_name (rdflib.URIRef): Scientific Name associated with - this node - threat_status_value (rdflib.URIRef): Threat Status Value associated - with this node - jurisdiction_attribute (rdflib.URIRef): Conservation Jurisdiction - Attribute associated with this node - determined_by (rdflib.URIRef): Determined By Provider associated - with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["threatStatus"]: - return - - # Choose Feature of Interest - # Feature of Interest is the Accepted Name Usage Value if it exists, - # otherwise it is the Scientific Name Text - foi = accepted_name_usage if row["acceptedNameUsage"] else scientific_name - - # Get Timestamp - # Prefer `threatStatusDateDetermined` > `dateIdentified` > `eventDate` (fallback) - date_determined: models.temporal.Timestamp = ( - row["threatStatusDateDetermined"] or row["dateIdentified"] or row["preparedDate"] or row["eventDate"] - ) - - # Retrieve vocab for field - vocab = self.fields()["threatStatusCheckProtocol"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(row["threatStatusCheckProtocol"]) - - # Threat Status Observation - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("threatStatus-observation"))) - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, foi)) - graph.add((uri, rdflib.SOSA.hasResult, threat_status_value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(row["threatStatus"]))) - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_CONSERVATION_STATUS)) - graph.add((uri, rdflib.PROV.wasInfluencedBy, jurisdiction_attribute)) - graph.add((uri, rdflib.SOSA.usedProcedure, term)) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, date_determined.rdf_in_xsd, date_determined.to_rdf_literal())) - - # Check for threatStatusDeterminedBy - if row["threatStatusDeterminedBy"]: - # Add wasAssociatedWith - graph.add((uri, rdflib.PROV.wasAssociatedWith, determined_by)) - - # Check for threatStatusDateDetermined - if not row["threatStatusDateDetermined"]: - # Determine Used Date Column - date_used = ( - "dateIdentified" if row["dateIdentified"] else "preparedDate" if row["preparedDate"] else "eventDate" - ) - - # Add comment to temporal entity - comment = f"Date unknown, template {date_used} used as proxy" - graph.add((temporal_entity, rdflib.RDFS.comment, rdflib.Literal(comment))) - - def add_threat_status_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Threat Status Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["threatStatus"]: - return - - # Combine conservationJurisdiction and threatStatus - value = f"{row['conservationJurisdiction']}/{row['threatStatus']}" - - # Retrieve vocab for field - vocab = self.fields()["threatStatus"].get_vocab() - - # Retrieve term or Create on the Fly - term = vocab(graph=graph, source=dataset).get(value) - - # Threat Status Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(f"Conservation status = {row['threatStatus']}"))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_conservation_jurisdiction_attribute( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - dataset: rdflib.URIRef, - conservation_jurisdiction_value: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds Conservation Jurisdiction Attribute to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node. - row (frictionless.Row): Row to retrieve data from - dataset (rdflib.URIRef): Dataset this belongs to - conservation_jurisdiction_value (rdflib.URIRef): Conservation - Jurisdiction Value associated with this node - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["conservationJurisdiction"]: - return - - # Conservation Jurisdiction Attribute - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_CONSERVATION_JURISDICTION)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(row["conservationJurisdiction"]))) - graph.add((uri, utils.namespaces.TERN.hasValue, conservation_jurisdiction_value)) - - def add_conservation_jurisdiction_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds Conservation Jurisdiction Value to the Graph - - Args: - uri (rdflib.URIRef): URI to use for this node - row (frictionless.Row): Row to retrieve data from - graph (rdflib.Graph): Graph to add to - """ - # Check Existence - if not row["conservationJurisdiction"]: - return - - # Retrieve vocab for field - vocab = self.fields()["conservationJurisdiction"].get_vocab() - - # Retrieve term - term = vocab(graph=graph).get(row["conservationJurisdiction"]) - - # Construct Label - label = f"Conservation Jurisdiction = {row['conservationJurisdiction']}" - - # Conservation Jurisdiction Value - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal(label))) - graph.add((uri, rdflib.RDF.value, term)) - - def add_organism_quantity_observation( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - sample_field: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds observation organism quantity to the graph. - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset which data belongs. - sample_field (rdflib.URIRef): URI for the sample field node. - row (frictionless.Row): Row to retrieve data from. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values - event_date: models.temporal.Timestamp = row["eventDate"] - organism_qty = row["organismQuantity"] - organism_qty_type = row["organismQuantityType"] - - # Check if organism quantity values were provided - if not organism_qty or not organism_qty_type: - return - - # Attach node to sample field and dataset - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, sample_field)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Observation)) - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("organismQuantity-observation"))) - graph.add((uri, rdflib.SOSA.observedProperty, utils.namespaces.DWC.organismQuantity)) - - # Add event date(time) - temporal_entity = rdflib.BNode() - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - graph.add((temporal_entity, a, rdflib.TIME.Instant)) - graph.add((temporal_entity, event_date.rdf_in_xsd, event_date.to_rdf_literal())) - - # Add Human observation as proxy for observation method - human_observation = rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/ea1d6342-1901-4f88-8482-3111286ec157") - graph.add((uri, rdflib.SOSA.usedProcedure, human_observation)) - - # Add organism quantity and type values - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(f"{organism_qty} {organism_qty_type}"))) - - # Add method comment to node - graph.add( - (uri, rdflib.RDFS.comment, rdflib.Literal("Observation method unknown, 'human observation' used as proxy")) - ) - - # Add comment to temporal entity - graph.add( - (temporal_entity, rdflib.RDFS.comment, rdflib.Literal("Date unknown, template eventDate used as proxy")) - ) - - def add_organism_quantity_value( - self, - uri: rdflib.URIRef, - organism_qty_observation: rdflib.URIRef, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds organism quantity value to graph. - - Args: - uri (rdflib.URIRef): URI to use for this node. - organism_qty_observation (rdflib.URIRef): Observation URI. - dataset (rdflib.URIRef): Dataset this is a part of. - row (frictionless.Row): Row to retrieve data from. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values if any - organism_qty = row["organismQuantity"] - organism_qty_type = row["organismQuantityType"] - - # Check for values - if not (organism_qty and organism_qty_type): - return - - # Retrieve vocab for field - vocab = self.fields()["organismQuantityType"].get_vocab() - - # Get term or create on the fly - term = vocab(graph=graph, source=dataset).get(organism_qty_type) - - # Add to graph - graph.add((organism_qty_observation, rdflib.SOSA.hasResult, uri)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - graph.add((uri, a, utils.namespaces.TERN.Float)) - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("organism-count"))) - graph.add((uri, utils.namespaces.TERN.unit, term)) - graph.add((uri, rdflib.RDF.value, rdflib.Literal(organism_qty, datatype=rdflib.XSD.float))) - - def add_site( - self, - uri: rdflib.URIRef | None, - dataset: rdflib.URIRef, - terminal_foi: rdflib.URIRef, - graph: rdflib.Graph, - ) -> None: - """Adds site to the graph. - - Args: - uri (rdflib.URIRef | None): URI to use if site provided else None. - dataset (rdflib.URIRef): The dataset which the data belongs. - terminal_foi (rdflib.URIRef): Terminal feature of interest. - graph (rdflib.URIRef): Graph to be modified. - """ - # Check site uri exists - if uri is None: - return - - # Add site information to graph - graph.add((uri, a, utils.namespaces.TERN.Site)) - graph.add((uri, a, utils.namespaces.TERN.FeatureOfInterest)) - graph.add((uri, rdflib.VOID.inDataset, dataset)) - graph.add((uri, utils.namespaces.TERN.featureType, vocabs.site_type.SITE.iri)) - graph.add((uri, rdflib.SOSA.isSampleOf, terminal_foi)) - - -# Helper Functions -# These utility helper functions are specific to this template, and as such are -# defined here instead of in a common utilities module. -def has_specimen(row: frictionless.Row) -> bool: - """Determines whether a row has a specimen associated with it or not. - - This method is used when determining whether to add the specimen specific - `/sampling/specimen/x` and `/sample/specimen/x` nodes to the graph. - - Args: - row (frictionless.Row): Row to retrieve data from. - - Returns: - bool: Whether this row has a specimen associated with it. - """ - # Check Specimen Rules - if row["preparations"] or row["catalogNumber"] or row["associatedSequences"]: - # If any of `preparations`, `catalogNumber` or `associatedSequences` - # are provided, regardless of the value of `basisOfRecord` we can infer - # that there is a specimen associated with the row. - specimen = True - - elif ( - not row["basisOfRecord"] # Blank - or vocabs.basis_of_record.HUMAN_OBSERVATION.match(row["basisOfRecord"]) # HumanObservation - or vocabs.basis_of_record.OCCURRENCE.match(row["basisOfRecord"]) # Occurrence - ): - # Otherwise, if none of `preparations`, `catalogNumber` or - # `associatedSequences` were provided, and the `basisOfRecord` is - # either blank or one of "HumanObservation" or "Occurrence", then we - # cannot infer that there is a specimen associated with the row. - specimen = False - - else: - # Finally, none of `preparations`, `catalogNumber` or - # `associatedSequences` were provided, but the `basisOfRecord` is a - # value that implies that there is a specimen associated with the row. - specimen = True - - # Return - return specimen - - -# Register Mapper -base.mapper.ABISMapper.register_mapper(SurveyOccurrenceMapper) diff --git a/abis_mapping/templates/survey_occurrence_data/metadata.json b/abis_mapping/templates/survey_occurrence_data/metadata.json deleted file mode 100644 index b3d89129..00000000 --- a/abis_mapping/templates/survey_occurrence_data/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "survey_occurrence_data", - "label": "Systematic Survey Occurrence Data Template", - "version": "1.0.0", - "description": "A template to translate some Darwin Core fields", - "biodiversity_type": "Systematic Survey Species Occurrences", - "spatial_type": "Point", - "file_type": "CSV", - "sampling_type": "systematic survey", - "template_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_occurrence_data/survey_occurrence_data.csv", - "schema_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_occurrence_data/schema.json", - "template_lifecycle_status": "deprecated" -} diff --git a/abis_mapping/templates/survey_occurrence_data/schema.json b/abis_mapping/templates/survey_occurrence_data/schema.json deleted file mode 100644 index 31b2f371..00000000 --- a/abis_mapping/templates/survey_occurrence_data/schema.json +++ /dev/null @@ -1,710 +0,0 @@ -{ - "fields": [ - { - "name": "providerRecordID", - "title": "Provider Record ID", - "description": "Unique (within provider) identifier for the record.", - "example": "8022FSJMJ079c5cf", - "type": "string", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "providerRecordIDSource", - "title": "Provider Record ID Source", - "description": "Person or Organisation that generated the providerRecordID. For providers registered with the BDR, this field should contain your BDR registrationID. Populate only if the details are different from the dataset submission details.", - "example": "Western Australian Biodiversity Information Office", - "type": "string", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "locality", - "title": "Locality", - "description": "The specific description of the place.", - "example": "Cowaramup Bay Road", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:locality", - "constraints": { - "required": false - } - }, - { - "name": "decimalLatitude", - "title": "Decimal Latitude", - "description": "The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are north of the Equator, negative values are south of it. Valid coordinate ranges for the BDR system are within and inclusive of -90 to 0.", - "example": "-33.812314", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLatitude", - "constraints": { - "required": true, - "minimum": -90.0, - "maximum": 0 - } - }, - { - "name": "decimalLongitude", - "title": "Decimal Longitude", - "description": "The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are east of the Greenwich Meridian, negative values are west of it. Valid coordinate ranges for the BDR system are within and inclusive of 0 to 180.", - "example": "115.231512", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLongitude", - "constraints": { - "required": true, - "minimum": 0, - "maximum": 180.0 - } - }, - { - "name": "geodeticDatum", - "title": "Geodetic Datum", - "description": "The acronym for the ellipsoid, geodetic datum, or spatial reference system (SRS) upon which the geographic (non-projected) coordinates given in decimalLatitude and decimalLongitude as based.", - "example": "WGS84", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:geodeticDatum", - "constraints": { - "required": true, - "enum": [ - "AGD66", - "EPSG:4202", - "AGD84", - "EPSG:4203", - "GDA2020", - "EPSG:7844", - "GDA94", - "EPSG:4283", - "WGS84", - "EPSG:4326" - ] - }, - "vocabularies": [ - "GEODETIC_DATUM" - ] - }, - { - "name": "coordinateUncertaintyInMeters", - "title": "Coordinate Uncertainty In Meters", - "description": "The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Location. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.", - "example": "50.0", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters", - "constraints": { - "required": false, - "minimum": 0.0 - } - }, - { - "name": "dataGeneralizations", - "title": "Data Generalizations", - "description": "Actions taken to make the shared data less specific or complete than in its original form, due to restrictions around identifying locations of particular species. Suggests that alternative data of higher quality may be available on request.", - "example": "Coordinates rounded to the nearest 10 km for conservation concern", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:dataGeneralizations", - "constraints": { - "required": false - } - }, - { - "name": "eventDate", - "title": "Event Date", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T06:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) during which a species occurrence was observed. For occurrences, this is the date-time when the event was recorded. Not suitable for a time in a geological context.", - "example": "2019-09-23T14:03+08:00", - "type": "timestamp", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:eventDate", - "constraints": { - "required": true - } - }, - { - "name": "samplingProtocol", - "title": "Sampling Protocol", - "description": "The sampling protocol is the method used to sample the locality to determine the presence (or absence) of the taxon referred to in this record at the indicated time. This may be a collecting method or a method to observe an organism without collection.\nRecommended best practice is to describe a species occurrence with no more than one sampling protocol. In the case of a summary, in which a specific protocol can not be attributed to specific species occurrences, the recommended best practice is to repeat the property for each IRI that denotes a different sampling protocol that applies to the occurrence.", - "example": "Human Observation", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:samplingProtocol", - "constraints": { - "required": false - }, - "vocabularies": [ - "SAMPLING_PROTOCOL" - ] - }, - { - "name": "basisOfRecord", - "title": "Basis Of Record", - "description": "The specific nature of the data record.", - "example": "Preserved Specimen", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:basisOfRecord", - "constraints": { - "required": false - }, - "vocabularies": [ - "BASIS_OF_RECORD" - ] - }, - { - "name": "recordedBy", - "title": "Recorded By", - "description": "A person, group, or organisation responsible for recording the original Occurrence.", - "example": "Stream Environment and Water Pty Ltd", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:recordedBy", - "constraints": { - "required": false - } - }, - { - "name": "recordNumber", - "title": "Record Number", - "description": "An identifier given to the Occurrence at the time it was recorded. Often serves as a link between field notes and an Occurrence record, such as a specimen collector's number.", - "example": "PE:12:8832", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/recordNumber", - "constraints": { - "required": false - } - }, - { - "name": "occurrenceStatus", - "title": "Occurrence Status", - "description": "A statement about the presence or absence of a Taxon at a Location.", - "example": "Present", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:occurrenceStatus", - "constraints": { - "required": false - }, - "vocabularies": [ - "OCCURRENCE_STATUS" - ] - }, - { - "name": "habitat", - "title": "Habitat", - "description": "A category or description of the habitat in which the event occurred.", - "example": "Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/habitat", - "constraints": { - "required": false - } - }, - { - "name": "establishmentMeans", - "title": "Establishment Means", - "description": "Statement about whether an organism or organisms have been introduced to a given place and time through the direct or indirect activity of modern humans.", - "example": "Native", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:establishmentMeans", - "constraints": { - "required": false - }, - "vocabularies": [ - "ESTABLISHMENT_MEANS" - ] - }, - { - "name": "organismRemarks", - "title": "Organism Remarks", - "description": "Comments or notes about the Organism instance.", - "example": "Dried out leaf tips.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/organismRemarks", - "constraints": { - "required": false - } - }, - { - "name": "individualCount", - "title": "Individual Count", - "description": "The number of individuals present at the time of the Occurrence. 0 = none, no value = the specific number was not recorded.", - "example": "26", - "type": "integer", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:individualCount", - "constraints": { - "required": false - } - }, - { - "name": "organismQuantity", - "title": "Organism Quantity", - "description": "A number or enumeration value for the quantity of organisms.", - "example": "12.5", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/list/#dwc_organismQuantity", - "constraints": { - "required": false - } - }, - { - "name": "organismQuantityType", - "title": "Organism Quantity Type", - "description": "The type of quantification system used for the quantity organisms.", - "example": "% biomass", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/list/#dwc_organismQuantityType", - "constraints": { - "required": false - }, - "vocabularies": [ - "ORGANISM_QUANTITY_TYPE" - ] - }, - { - "name": "lifeStage", - "title": "Life Stage", - "description": "The age class or life stage of the Organism(s) at the time the Occurrence was recorded.", - "example": "adult", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/lifeStage", - "constraints": { - "required": false - }, - "vocabularies": [ - "LIFE_STAGE" - ] - }, - { - "name": "sex", - "title": "Sex", - "description": "The sex of the biological individual(s) represented in the Occurrence.", - "example": "Unspecified", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwciri:sex", - "constraints": { - "required": false - }, - "vocabularies": [ - "SEX" - ] - }, - { - "name": "reproductiveCondition", - "title": "Reproductive Condition", - "description": "The reproductive condition of the biological individual(s) represented in the Occurrence.", - "example": "No breeding evident", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:reproductiveCondition", - "constraints": { - "required": false - }, - "vocabularies": [ - "REPRODUCTIVE_CONDITION" - ] - }, - { - "name": "ownerRecordID", - "title": "Owner Record ID", - "description": "Identifier given to the occurrence by the owner of the data. Populate this field if the data owner is different to the data provider. Unique (within data owner) identifier for the record.", - "example": "12345NT521mc5h", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "ownerRecordIDSource", - "title": "Owner Record ID Source", - "description": "Person or Organisation that generated the ownerRecordID. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation who owns the data.", - "example": "WAM", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "collectionCode", - "title": "Collection Code", - "description": "The name, acronym, code, or initialism identifying the collection or data set from which the record was derived. It is associated with the catalogNumber.", - "example": "ARACH", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:collectionCode", - "constraints": { - "required": false - } - }, - { - "name": "catalogNumber", - "title": "Catalog Number", - "description": "An identifier (preferably unique) for the record within the data set or collection.", - "example": "145732, 145732a, 2008.1334, R-4313", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/catalogNumber", - "constraints": { - "required": false - } - }, - { - "name": "catalogNumberSource", - "title": "Catalog Number Source", - "description": "Organisation that generated the catalogNumber. In the BDR context, this is likely to be a collecting institution where a specimen or material sample is located. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.", - "example": "Western Australian Museum", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "otherCatalogNumbers", - "title": "Other Catalog Numbers", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of previous or alternate fully qualified catalog numbers or other human-used identifiers for the same Occurrence, whether in the current or any other data set or collection.", - "example": "BHP2012-7521 | M12378", - "type": "list", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/otherCatalogNumbers", - "constraints": { - "required": false - } - }, - { - "name": "otherCatalogNumbersSource", - "title": "Other Catalog Numbers Source", - "description": "Organisation that generated the otherCatalogNumbers. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.", - "example": "University of Western Australia", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "preparations", - "title": "Preparations", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of preparations and preservation methods for a specimen.", - "example": "alcohol", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/preparations", - "constraints": { - "required": false - }, - "vocabularies": [ - "PREPARATIONS" - ] - }, - { - "name": "preparedDate", - "title": "Prepared Date", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) representing the date or date-time the specimen was prepared.", - "example": "2019-09-24", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "associatedSequences", - "title": "Associated Sequences", - "description": "A list (concatenated and separated with a space vertical bar space ( | )) of identifiers (publication, global unique identifier, URI) of genetic sequence information associated with the Occurrence.", - "example": "https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 | https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1", - "type": "list", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/associatedSequences", - "constraints": { - "required": false - } - }, - { - "name": "sequencingMethod", - "title": "Sequencing Method", - "description": "The method used to obtain sequence data for example DNA, RNA, or protein from the sample.", - "example": "Sanger-dideoxy-sequencing", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "SEQUENCING_METHOD" - ] - }, - { - "name": "verbatimIdentification", - "title": "Verbatim Identification", - "description": "A string representing the taxonomic identification as it appeared in the original record. This term is meant to allow the capture of an unaltered original identification/determination, including identification qualifiers, hybrid formulas, uncertainties, etc. This term is meant to be used in addition to scientificName (and identificationQualifier etc.), not instead of it.", - "example": "Caladenia ?excelsa", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:verbatimIdentification", - "constraints": { - "required": false - } - }, - { - "name": "dateIdentified", - "title": "Date Identified", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which the subject was determined as representing the Taxon.", - "example": "2019-09-24", - "type": "timestamp", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/dateIdentified", - "constraints": { - "required": false - } - }, - { - "name": "identifiedBy", - "title": "Identified By", - "description": "Group of names, organisations who assigned the Taxon to the subject. For multiple names, use the pipe separator ( | ).", - "example": "J. Doe | WAM", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/identifiedBy", - "constraints": { - "required": false - } - }, - { - "name": "identificationMethod", - "title": "Identification Method", - "description": "Method used to associate the organism with the scientificName label.", - "example": "DNA", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "IDENTIFICATION_METHOD" - ] - }, - { - "name": "scientificName", - "title": "Scientific Name", - "description": "The full scientific name, with authorship and date information if known. When forming part of an Identification, this should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the identificationQualifier column.\nNOTE: Phrase names such as Rhagodia sp. Hamersley (M.Trudgen 17794) are permitted in the scientificName field where those are in use.", - "example": "Caladenia excelsa", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/scientificName", - "constraints": { - "required": true - } - }, - { - "name": "identificationQualifier", - "title": "Identification Qualifier", - "description": "A brief phrase or a standard term (\"cf.\", \"aff.\") to express the determiner's doubts about the Identification.", - "example": "Species incerta", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:identificationQualifier", - "constraints": { - "required": false - }, - "vocabularies": [ - "IDENTIFICATION_QUALIFIER" - ] - }, - { - "name": "identificationRemarks", - "title": "Identification Remarks", - "description": "Comments or notes about the Identification.", - "example": "DNA evidence may indicate a new species. Further analysis required.", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/identificationRemarks", - "constraints": { - "required": false - } - }, - { - "name": "acceptedNameUsage", - "title": "Accepted Name Usage", - "description": "The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) taxon.", - "example": "Occiperipatoides gilesii (Spencer, 1909)", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:acceptedNameUsage", - "constraints": { - "required": false - } - }, - { - "name": "kingdom", - "title": "Kingdom", - "description": "The full scientific name of the kingdom in which the taxon is classified.", - "example": "Plantae", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:kingdom", - "constraints": { - "required": true - }, - "vocabularies": [ - "KINGDOM_OCCURRENCE", - "KINGDOM_SPECIMEN" - ] - }, - { - "name": "taxonRank", - "title": "Taxon Rank", - "description": "The taxonomic rank of the most specific name in the scientificName.", - "example": "Species", - "type": "string", - "format": "default", - "url": "http://rs.tdwg.org/dwc/terms/verbatimTaxonRank", - "constraints": { - "required": false - }, - "vocabularies": [ - "TAXON_RANK" - ] - }, - { - "name": "threatStatus", - "title": "Threat Status", - "description": "The conservation status (or code) assigned to an organism that is recognised in conjunction with a specific jurisdiction.", - "example": "EN", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "THREAT_STATUS" - ] - }, - { - "name": "conservationJurisdiction", - "title": "Conservation Jurisdiction", - "description": "The jurisdiction under which an organism is recognised to have a specific conservation status applied.", - "example": "EPBC, WA", - "type": "string", - "format": "default", - "constraints": { - "required": false, - "enum": [ - "ACT", - "AUSTRALIAN CAPITAL TERRITORY", - "Australian Capital Territory", - "EPBC", - "ENVIRONMENT PROTECTION AND BIODIVERSITY CONSERVATION", - "Environment Protection And Biodiversity Conservation", - "NSW", - "NEW SOUTH WALES", - "New South Wales", - "NT", - "NORTHERN TERRITORY", - "Northern Territory", - "QLD", - "QUEENSLAND", - "Queensland", - "SA", - "SOUTH AUSTRALIA", - "South Australia", - "TAS", - "TASMANIA", - "Tasmania", - "VIC", - "VICTORIA", - "Victoria", - "WA", - "WESTERN AUSTRALIA", - "Western Australia" - ] - }, - "vocabularies": [ - "CONSERVATION_AUTHORITY" - ] - }, - { - "name": "threatStatusCheckProtocol", - "title": "Threat Status Check Protocol", - "description": "The method used to determine if the organism is listed under the relevant jurisdictional threatened species list.", - "example": "Species name check of the Department of Climate Change, Energy, the Environment and Water’s Species Profile and Threat Database http://www.environment.gov.au/cgi-bin/sprat/public/sprat.pl", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "CHECK_PROTOCOL" - ] - }, - { - "name": "threatStatusDateDetermined", - "title": "Threat Status Date Determined", - "description": "The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which this record of this organism was assigned to the nominated threatStatus and conservationJurisdiction", - "example": "30/08/2022", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "threatStatusDeterminedBy", - "title": "Threat Status Determined By", - "description": "The person and/organisation responsible for appending the threatStatus and conservationJurisdiction to this organism’s occurrence record.", - "example": "WA-BIO", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "siteID", - "title": "Site ID", - "description": "Corresponds to a unique site identifier, provided within accompanying survey_site_data.csv template.", - "example": "P1", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyID", - "title": "Survey ID", - "description": "The identifier of the Survey that the occurrence comes from. This field should be completed if it is ambiguous as to which survey the occurrence belongs to.", - "example": "AR220-01", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - } - ], - "foreignKeys": [ - { - "fields": "siteID", - "reference": { - "resource": "survey_site_data.csv", - "fields": "siteID" - } - } - ] -} diff --git a/abis_mapping/templates/survey_occurrence_data/survey_occurrence_data.csv b/abis_mapping/templates/survey_occurrence_data/survey_occurrence_data.csv deleted file mode 100644 index 56e58eec..00000000 --- a/abis_mapping/templates/survey_occurrence_data/survey_occurrence_data.csv +++ /dev/null @@ -1 +0,0 @@ -providerRecordID,providerRecordIDSource,locality,decimalLatitude,decimalLongitude,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,eventDate,samplingProtocol,basisOfRecord,recordedBy,recordNumber,occurrenceStatus,habitat,establishmentMeans,organismRemarks,individualCount,organismQuantity,organismQuantityType,lifeStage,sex,reproductiveCondition,ownerRecordID,ownerRecordIDSource,collectionCode,catalogNumber,catalogNumberSource,otherCatalogNumbers,otherCatalogNumbersSource,preparations,preparedDate,associatedSequences,sequencingMethod,verbatimIdentification,dateIdentified,identifiedBy,identificationMethod,scientificName,identificationQualifier,identificationRemarks,acceptedNameUsage,kingdom,taxonRank,threatStatus,conservationJurisdiction,threatStatusCheckProtocol,threatStatusDateDetermined,threatStatusDeterminedBy,siteID,surveyID diff --git a/abis_mapping/templates/survey_occurrence_data/templates/instructions.md b/abis_mapping/templates/survey_occurrence_data/templates/instructions.md deleted file mode 100644 index e1d10a91..00000000 --- a/abis_mapping/templates/survey_occurrence_data/templates/instructions.md +++ /dev/null @@ -1,155 +0,0 @@ -{% extends "BASE_TEMPLATE base.md" %} -{% block body %} -# SYSTEMATIC SURVEY OCCURRENCES DATA TEMPLATE INSTRUCTIONS - -## Intended Usage -This template is used to record occurrence data; that is, the presence or absence of an organism -at a particular site locality at a point in time. - -The Systematic Survey Occurrences template **must be used in combination** with the -Systematic Survey Metadata template, and in some cases the Systematic Survey Sites -template. - -Templates have been provided to facilitate integration of your data into the Biodiversity -Data Repository database. Not all types of data have been catered for in the available -templates at this stage; therefore, if you are unable to find a suitable template, please -contact to make us aware of your data needs. - -#### Data Validation Requirements: -For data validation, you will need your data file to: - -- be in the correct **file format,** -- have **fields that match the template downloaded** (do not remove, or - change the order of fields), -- have extant values for **mandatory fields** (see Table 1), -- comply with all **data value constraints**; for example the geographic coordinates are - consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***{{values.geodetic_datum_count}}*** available - options, and -- align with existing controlled [vocabularies](#appendix-i-vocabulary-list) wherever possible (this is mandatory - for geodeticDatum), but new terms may be submitted for consideration amd will not cause a - validation error. - -Additional fields may be added **after the templated fields** (noting that the data type -is not assumed and values will be encoded as strings). - -### FILE FORMAT -- The systematic survey occurrence data template is a [UTF-8](#appendix-iii-utf-8) encoded csv (that is, not Microsoft - Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8): -
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > - Unicode (UTF-8)]`
- otherwise it will not pass the csv validation step upon upload. -- **Do not include empty rows**. - -#### FILE SIZE -MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the -header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767-character -limit on individual cells in a spreadsheet. These limits may be overcome by using or -editing CSV files with other software. - -Larger datasets may be more readily ingested using the API interface. Please contact - to make us aware of your data needs. - -## TEMPLATE FIELDS -The template contains the field names in the top row. Table 1 will assist you in transferring -your data to the template by providing guidance on: - -- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) - for that field where relevant); -- **Description** of the field; -- **Required** i.e. whether the field is **mandatory, -conditionally mandatory, or optional**; -- **Format** (datatype) required for the data values for example text (string), number - (integer, float), or date; -- **Example** of an entry or entries for that field; and -- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where - relevant. The fields that have suggested values options for the fields in Table 1 are - listed in Table 2 in alphabetical order of the field name. - -### ADDITIONAL FIELDS -Data that does not match the existing template fields may be added as -additional columns in the CSV files after the templated fields. -For example: `eventRemarks`, `associatedTaxa`, `pathway`. - -Table 1: Systematic Survey Occurrence data template fields with descriptions, conditions, -datatype format, and examples. - -{{tables.fields}} - -## APPENDICES -### APPENDIX-I: VOCABULARY LIST -With the exception of `geodeticDatum`, data validation does not require fields to adhere to the -vocabularies specified for the various vocabularied fields. These vocabularies are merely provided as a -means of assistance in developing a consistent language within the database. New terms may be added -to more appropriately describe your data that goes beyond the current list. Table 2 provides some -suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), -[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information -System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity -era](https://doi.org/10.1111/2041-210X.12594). - -Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has -a preferred label with a definition to aid understanding of its meaning. For some terms, alternative -labels with similar semantics are provided. Note: `geodeticDatum` value -**must** come from one of five options in this table. - - - -{{tables.vocabularies}} - - -Table 2b: Suggested values for conditionally mandatory values for the `threatStatus` and -`conservationJurisdiction` fields in the template. State and Territory `conservationJurisdictions` -spelt out as words are also valid. For some `threatStatus` terms, alternative labels are provided -that are also valid for that `conservationJurisdiction`. - -{{tables.threat_status}} - -### APPENDIX-II: Timestamp -Following date and date-time formats are acceptable within the timestamp: - -| TYPE | FORMAT | -| --- |-------------------------------------------------------------------------------------------------------------------------------------| -| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| -| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | -| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | -| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | -| **xsd:gYear** | yyyy | - -Where
-  `yyyy`: four-digit year
-  `mm`: two-digit month (01=January, etc.)
-  `dd`: two-digit day of month (01 through 31)
-  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
-  `mm`: two digits of minute (00 through 59)
-  `ss`: two digits of second (00 through 59)
- - -### APPENDIX-III: UTF-8 -UTF-8 encoding is considered a best practice for handling character encoding, especially in -the context of web development, data exchange, and modern software systems. UTF-8 -(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of -encoding all possible characters (code points) in Unicode.
-Here are some reasons why UTF-8 is recommended: -- **Universal Character Support:** UTF-8 can represent almost all characters from all writing - systems in use today. This includes characters from various languages, mathematical symbols, - and other special characters. -- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American - Standard Code for Information Interchange). The first 128 characters in UTF-8 are - identical to ASCII, making it easy to work with systems that use ASCII. -- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English - and many other languages). It uses one byte for ASCII characters and up to four - bytes for other characters. This variable-length encoding minimises storage and - bandwidth requirements. -- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is - widely supported by browsers, servers, and web-related technologies. -- **Globalisation:** As software applications become more globalised, supporting a wide - range of languages and scripts becomes crucial. UTF-8 is well-suited for - internationalisation and multilingual support. -- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many - programming languages, databases, and operating systems. Choosing UTF-8 helps - ensure compatibility across different platforms and technologies. - -When working with text data, UTF-8 encoding is recommended to avoid issues related to character -representation and ensure that a diverse set of characters and languages is supported. - -For assistance, please contact: -{% endblock %} diff --git a/abis_mapping/templates/survey_site_data/README.md b/abis_mapping/templates/survey_site_data/README.md deleted file mode 100644 index bce67b50..00000000 --- a/abis_mapping/templates/survey_site_data/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Template Description -TBC - -# Template Instructions -See `instructions.pdf` for more details diff --git a/abis_mapping/templates/survey_site_data/examples/minimal.csv b/abis_mapping/templates/survey_site_data/examples/minimal.csv deleted file mode 100644 index 8ed8b90c..00000000 --- a/abis_mapping/templates/survey_site_data/examples/minimal.csv +++ /dev/null @@ -1,2 +0,0 @@ -siteID,siteIDSource,siteType,siteName,siteDescription,habitat,relatedSiteID,relationshipToRelatedSite,decimalLatitude,decimalLongitude,footprintWKT,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,surveyID,siteVisitID,siteVisitStart,siteVisitEnd,visitOrgs,visitObservers,condition -P1,WAM,Plot,Plot 1,Fine woody debris.,,,,-34.036,146.363,"LINESTRING (146.363 -34.036, 146.363 -34.037)",WGS84,50,,,,2016-02-28,2016-02-28,,, diff --git a/abis_mapping/templates/survey_site_data/examples/minimal.ttl b/abis_mapping/templates/survey_site_data/examples/minimal.ttl deleted file mode 100644 index c1b4e2d6..00000000 --- a/abis_mapping/templates/survey_site_data/examples/minimal.ttl +++ /dev/null @@ -1,73 +0,0 @@ -@prefix dcterms: . -@prefix geo: . -@prefix prov: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - - a rdfs:Datatype ; - skos:definition "An identifier for the dataset" ; - skos:prefLabel "Gaia Resources datasetID" ; - prov:wasAttributedTo . - - a rdfs:Datatype ; - skos:prefLabel "siteID source" ; - prov:wasAttributedTo . - - a prov:Agent ; - schema:name "WAM" . - - a tern:SiteVisit ; - void:inDataset ; - time:hasTime [ a time:TemporalEntity ; - time:hasBeginning [ a time:Instant ; - time:inXSDDate "2016-02-28"^^xsd:date ] ; - time:hasEnd [ a time:Instant ; - time:inXSDDate "2016-02-28"^^xsd:date ] ] ; - schema:isPartOf . - - a tern:Dataset ; - schema:dateCreated "2020-01-01"^^xsd:date ; - schema:dateIssued "2020-01-01"^^xsd:date ; - schema:description "Example Systematic Survey Site Dataset by Gaia Resources" ; - schema:name "Example Systematic Survey Site Dataset" . - - a tern:Site ; - dcterms:identifier "P1"^^ ; - dcterms:type ; - void:inDataset ; - geo:hasGeometry _:N37427f90dd24537af087917a00000000, - _:N4c8ca862a85a27910679928500000000 ; - geo:hasMetricSpatialAccuracy 5e+01 ; - schema:description "Fine woody debris." ; - schema:name "Plot 1" ; - tern:featureType ; - tern:hasSiteVisit . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " LINESTRING (-34.036 146.363, -34.037 146.363)"^^geo:wktLiteral ] ; - rdf:object _:N4c8ca862a85a27910679928500000000 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -[] a rdf:Statement ; - geo:hasGeometry [ a geo:Geometry ; - geo:asWKT " POINT (-34.036 146.363)"^^geo:wktLiteral ] ; - rdf:object _:N37427f90dd24537af087917a00000000 ; - rdf:predicate geo:hasGeometry ; - rdf:subject ; - rdfs:comment "supplied as" . - -_:N37427f90dd24537af087917a00000000 a geo:Geometry ; - geo:asWKT " POINT (-34.036 146.363)"^^geo:wktLiteral . - -_:N4c8ca862a85a27910679928500000000 a geo:Geometry ; - geo:asWKT " LINESTRING (-34.036 146.363, -34.037 146.363)"^^geo:wktLiteral . - diff --git a/abis_mapping/templates/survey_site_data/mapping.py b/abis_mapping/templates/survey_site_data/mapping.py deleted file mode 100644 index 65cb981d..00000000 --- a/abis_mapping/templates/survey_site_data/mapping.py +++ /dev/null @@ -1,987 +0,0 @@ -"""Provides ABIS Mapper for `survey_site_data.csv` Template""" - -# Standard -import decimal -import urllib.parse -import dataclasses - -# Third-party -import rdflib -import frictionless -import shapely -import shapely.geometry - -# Local -from abis_mapping import base -from abis_mapping import plugins -from abis_mapping import models -from abis_mapping import utils -from abis_mapping import vocabs - -# Typing -from typing import Any, Optional, Iterator - - -# Constants and shortcuts -a = rdflib.RDF.type -HABITAT_DESCRIPTION = rdflib.URIRef("https://linked.data.gov.au/def/nrm/aa4c96f6-9ea8-4bd3-8800-0bfddcd8a37c") -CONCEPT_DATA_GENERALIZATIONS = utils.rdf.uri("concept/data-generalizations", utils.namespaces.EXAMPLE) -CONCEPT_VEGETATION_CONDITION = rdflib.URIRef( - "http://linked.data.gov.au/def/ausplots-cv/ff69c254-e549-45e8-a320-e28ead5092c8" -) -DEFAULT_SURVEY = utils.rdf.uri("survey/SSD-Survey/1", utils.namespaces.CREATEME) # TODO: Cross reference -UNSPECIFIED_CONDITION_METHOD = utils.rdf.uri("bdr-cv/methods/conditionMethod/Unspecified", utils.namespaces.CREATEME) - - -# Dataclasses used in mapping -@dataclasses.dataclass -class AttributeValue: - """Contains data items to enable producing attribute and value nodes""" - - raw: str - attribute: rdflib.URIRef - value: rdflib.URIRef - - -@dataclasses.dataclass -class Agent: - """Contains data items to enable producing agent nodes""" - - raw: str - uri: rdflib.URIRef - - -class SurveySiteMapper(base.mapper.ABISMapper): - """ABIS Mapper for `survey_site_data.csv`""" - - # Default Dataset Metadata - DATASET_DEFAULT_NAME = "Example Systematic Survey Site Dataset" - DATASET_DEFAULT_DESCRIPTION = "Example Systematic Survey Site Dataset by Gaia Resources" - - def apply_validation( - self, - data: base.types.ReadableType, - **kwargs: Any, - ) -> frictionless.Report: - """Applies Frictionless Validation for the `survey_site_data.csv` Template - - Args: - data (base.types.ReadableType): Raw data to be validated. - **kwargs (Any): Additional keyword arguments. - - Keyword Args: - site_id_map (dict[str, bool]): Site ids present in the occurrence template. - - Returns: - frictionless.Report: Validation report for the specified data. - """ - # Extract keyword arguments - site_id_map: dict[str, bool] = kwargs.get("site_id_map", {}) - - # Construct schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - - # Construct resource - resource = frictionless.Resource( - source=data, - format="csv", - schema=schema, - encoding="utf-8", - ) - - # Validate - report = resource.validate( - checklist=frictionless.Checklist( - checks=[ - # Extra custom checks - plugins.tabular.IsTabular(), - plugins.empty.NotEmpty(), - plugins.sites_geometry.SitesGeometry( - occurrence_site_ids=set(site_id_map), - ), - plugins.chronological.ChronologicalOrder( - field_names=["siteVisitStart", "siteVisitEnd"], - ), - plugins.mutual_inclusion.MutuallyInclusive( - field_names=["relatedSiteID", "relationshipToRelatedSite"], - ), - ], - ) - ) - - # Return validation report - return report - - def extract_geometry_defaults( - self, - data: base.types.ReadableType, - ) -> dict[str, str]: - """Constructs a dictionary mapping site id to default WKT. - - The resulting string WKT returned can then be used as the missing - geometry for other related templates i.e. the site occurrences - - Args: - data (base.types.ReadableType): Raw data to be mapped. - - Returns: - dict[str, str]: Keys are the site id; values are the - appropriate point WKT serialized string. If none then - there is no siteID key created. Values include the geodetic - datum uri. - """ - # Construct schema - schema = frictionless.Schema.from_descriptor(self.schema()) - - # Construct resource - resource = frictionless.Resource( - source=data, - format="csv", - schema=schema, - encoding="utf-8", - ) - - # Context manager for row streaming - with resource.open() as r: - # Create empty dictionary to hold mapping values - result: dict[str, str] = {} - for row in r.row_stream: - # Extract values - site_id: str | None = row["siteID"] - - # Check for siteID, even though siteID is a mandatory field, it can be missing here - # because this method is called for cross-validation, regardless of if this template is valid. - if not site_id: - continue - - footprint_wkt: shapely.geometry.base.BaseGeometry = row["footprintWKT"] - longitude: decimal.Decimal = row["decimalLongitude"] - latitude: decimal.Decimal = row["decimalLatitude"] - datum: str = row["geodeticDatum"] - - # if no valid datum for row then don't add to map. - if datum is None: - continue - - try: - # Default to using the footprint wkt + geodetic datum - if footprint_wkt is not None: - # Create string and add to map for site id - result[site_id] = str( - models.spatial.Geometry( - raw=footprint_wkt.centroid, - datum=datum, - ).to_rdf_literal() - ) - continue - - # If not footprint then we revert to using supplied longitude & latitude - if longitude is not None and latitude is not None: - # Create string and add to map for site id - result[site_id] = str( - models.spatial.Geometry( - raw=shapely.Point([longitude, latitude]), - datum=datum, - ).to_rdf_literal() - ) - except models.spatial.GeometryError: - continue - - return result - - def apply_mapping( - self, - data: base.types.ReadableType, - dataset_iri: Optional[rdflib.URIRef] = None, - base_iri: Optional[rdflib.Namespace] = None, - **kwargs: Any, - ) -> Iterator[rdflib.Graph]: - """Applies Mapping for the `survey_site_data.csv` Template. - - Args: - data (base.types.ReadableType): Valid raw data to be mapped. - dataset_iri (Optional[rdflib.URIRef]): Optional dataset IRI. - base_iri (Optional[rdflib.Namespace]): Optional mapping base IRI. - - Keyword Args: - chunk_size (Optional[int]): How many rows of the original data to - ingest before yielding a graph. `None` will ingest all rows. - - Yields: - rdflib.Graph: ABIS Conformant RDF Sub-Graph from Raw Data Chunk. - """ - # Construct Schema - schema = self.extra_fields_schema( - data=data, - full_schema=True, - ) - extra_schema = self.extra_fields_schema( - data=data, - full_schema=False, - ) - - # Construct Resource - resource = frictionless.Resource( - source=data, - format="csv", # TODO -> Hardcoded to csv for now - schema=schema, - encoding="utf-8", - ) - - # Initialise Graph - graph = utils.rdf.create_graph() - - # Check if Dataset IRI Supplied - if not dataset_iri: - # Create Dataset IRI - dataset_iri = utils.rdf.uri(f"dataset/{self.DATASET_DEFAULT_NAME}", base_iri) - - # Add the default dataset - self.add_default_dataset( - uri=dataset_iri, - base_iri=base_iri, - graph=graph, - ) - - # Open the Resource to allow row streaming - with resource.open() as r: - # Loop through rows - for row in r.row_stream: - # Map row - self.apply_mapping_row( - row=row, - dataset=dataset_iri, - graph=graph, - extra_schema=extra_schema, - base_iri=base_iri, - ) - - yield graph - - def apply_mapping_row( - self, - row: frictionless.Row, - dataset: rdflib.URIRef, - graph: rdflib.Graph, - extra_schema: frictionless.Schema, - base_iri: Optional[rdflib.Namespace], - ) -> None: - """Applies mapping for a row in the `survey_site_data.csv` template. - - Args: - row (frictionless.Row): Row to be processed in the dataset. - dataset (rdflib.URIRef): Dataset IRI this row is a part of. - graph (rdflib.URIRef): Graph to map row into. - extra_schema (frictionless.Schema): Schema of extra fields. - base_iri (Optional[rdflib.Namespace]): Optional base IRI - to use for mapping. - """ - # Set the row number to start from the data, excluding header - row_num = row.row_number - 1 - - site_visit = utils.rdf.uri(f"visit/site/{row_num}", base_iri) - site_id = urllib.parse.quote(row["siteID"], safe="") - site = dataset + f"/Site/{site_id}" - condition_site_observation = utils.rdf.uri(f"observation/site/condition/{row_num}", base_iri) - condition_value = utils.rdf.uri(f"value/condition/{row_num}") - - # Conditionally create uris dependent on siteIDSource - if site_id_src := row["siteIDSource"]: - site_id_datatype = utils.rdf.uri(f"datatype/siteID/{site_id_src}", base_iri) - site_id_agent = utils.rdf.uri(f"agent/{site_id_src}", base_iri) - else: - site_id_datatype = None - site_id_agent = None - - # Conditionally create uris dependent on dataGeneralizations - if row["dataGeneralizations"]: - data_generalizations_attribute = utils.rdf.uri(f"attribute/dataGeneralizations/site/{row_num}", base_iri) - data_generalizations_value = utils.rdf.uri(f"value/dataGeneralizations/site/{row_num}", base_iri) - else: - data_generalizations_attribute = None - data_generalizations_value = None - - # Create habitat attribute and value objects - habitat_objects: list[AttributeValue] = [] - if habitats := row["habitat"]: - for i, habitat in enumerate(habitats, start=1): - habitat_objects.append( - AttributeValue( - raw=habitat, - attribute=utils.rdf.uri(f"attribute/habitat/site/{row_num}/{i}", base_iri), - value=utils.rdf.uri(f"value/habitat/site/{row_num}/{i}", base_iri), - ) - ) - - # Create organization agent objects - org_agent_objects: list[Agent] = [] - if organization_agents := row["visitOrgs"]: - for organizations_agent in organization_agents: - org_agent_objects.append( - Agent( - raw=organizations_agent, - uri=utils.rdf.uri(f"agent/{organizations_agent}", base_iri), - ) - ) - - # Create observer agent objects - observer_agent_objects: list[Agent] = [] - if observer_agents := row["visitObservers"]: - for observer_agent in observer_agents: - observer_agent_objects.append( - Agent( - raw=observer_agent, - uri=utils.rdf.uri(f"agent/{observer_agent}", base_iri), - ) - ) - - # Add site - self.add_site( - uri=site, - dataset=dataset, - site_visit=site_visit, - site_id_datatype=site_id_datatype, - habitat_attributes=[h.attribute for h in habitat_objects], - data_generalizations_attribute=data_generalizations_attribute, - row=row, - graph=graph, - ) - - # Add site id datatype - self.add_site_id_datatype( - uri=site_id_datatype, - agent=site_id_agent, - graph=graph, - ) - - # Add site id agent - self.add_site_id_agent( - uri=site_id_agent, - row=row, - graph=graph, - ) - - # Iterate through habitat objects - for habitat_object in habitat_objects: - # Add habitat attribute - self.add_habitat_attribute( - uri=habitat_object.attribute, - value=habitat_object.value, - dataset=dataset, - raw=habitat_object.raw, - graph=graph, - ) - - # Add habitat value - self.add_habitat_value( - uri=habitat_object.value, - dataset=dataset, - raw=habitat_object.raw, - graph=graph, - ) - - # Add data generalizations attribute - self.add_data_generalizations_attribute( - uri=data_generalizations_attribute, - value=data_generalizations_value, - dataset=dataset, - row=row, - graph=graph, - ) - - # Add data generalizations value - self.add_data_generalizations_value( - uri=data_generalizations_value, - row=row, - graph=graph, - ) - - # Add site visit - self.add_site_visit( - uri=site_visit, - dataset=dataset, - agents=[agent.uri for agent in org_agent_objects + observer_agent_objects], - row=row, - graph=graph, - ) - - # Add organization agents - for org_agent in org_agent_objects: - self.add_organization_agent( - uri=org_agent.uri, - raw=org_agent.raw, - graph=graph, - ) - - # Add observer agents - for obs_agent in observer_agent_objects: - self.add_observer_agent( - uri=obs_agent.uri, - raw=obs_agent.raw, - graph=graph, - ) - - # Add site condition - self.add_site_condition( - uri=condition_site_observation, - dataset=dataset, - site=site, - value=condition_value, - row=row, - graph=graph, - ) - - # TODO: Add condition value - self.add_condition_value( - uri=condition_value, - row=row, - graph=graph, - ) - - # Add geometry - self.add_footprint_geometry( - uri=site, - row=row, - graph=graph, - ) - - self.add_point_geometry( - uri=site, - row=row, - graph=graph, - ) - - # Add extra fields - self.add_extra_fields_json( - subject_uri=site, - row=row, - graph=graph, - extra_schema=extra_schema, - ) - - def add_site( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - site_visit: rdflib.URIRef, - site_id_datatype: rdflib.URIRef | None, - habitat_attributes: list[rdflib.URIRef], - data_generalizations_attribute: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds site to the graph. - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset to which data belongs. - site_visit (rdflib.URIRef): Site visit the site corresponds to. - site_id_datatype (rdflib.URIRef | None): Datatype to use for - the site id literal. - habitat_attributes (list[rdflib.URIRef]): List of habitat attribute - iris. - data_generalizations_attribute (rdflib.URIRef | None): Data generalization - the site corresponds. - row (frictionless.Row): Row to retrieve data from. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract relevant values - site_id = row["siteID"] - site_name = row["siteName"] - site_type = row["siteType"] - site_description = row["siteDescription"] - coordinate_uncertainty = row["coordinateUncertaintyInMeters"] - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Site)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add habitat attributes - for habitat_attribute in habitat_attributes: - graph.add((uri, utils.namespaces.TERN.hasAttribute, habitat_attribute)) - - # Link to site visit - graph.add((uri, utils.namespaces.TERN.hasSiteVisit, site_visit)) - - # Add siteID - dt = site_id_datatype if site_id_datatype is not None else rdflib.XSD.string - graph.add((uri, rdflib.DCTERMS.identifier, rdflib.Literal(site_id, datatype=dt))) - - # Add related site if available - if (relationship_to_related_site := row["relationshipToRelatedSite"]) and ( - related_site := row["relatedSiteID"] - ): - # Retrieve vocab for field - relationship_to_related_site_vocab = self.fields()["relationshipToRelatedSite"].get_vocab() - - # Retrieve term - relationship_to_related_site_term = relationship_to_related_site_vocab(graph=graph).get( - relationship_to_related_site - ) - - # Assign triple based on related site string - if (related_site_literal := utils.rdf.uri_or_string_literal(related_site)).datatype == rdflib.XSD.string: - graph.add((uri, relationship_to_related_site_term, related_site_literal)) - else: - graph.add((uri, relationship_to_related_site_term, rdflib.URIRef(related_site))) - - # Add site tern featuretype - graph.add((uri, utils.namespaces.TERN.featureType, vocabs.site_type.SITE.iri)) - - if site_type: - # Retrieve vocab for field - site_type_vocab = self.fields()["siteType"].get_vocab() - - # Retrieve term or create on the fly - site_type_term = site_type_vocab(graph=graph, source=dataset).get(site_type) - else: - site_type_term = vocabs.site_type.SITE.iri - - # Add to site type graph - graph.add((uri, rdflib.DCTERMS.type, site_type_term)) - - # Add site name if available - if site_name: - graph.add((uri, rdflib.SDO.name, rdflib.Literal(site_name))) - - # Add site description if available - if site_description: - graph.add((uri, rdflib.SDO.description, rdflib.Literal(site_description))) - - # Add coordinate uncertainty if available - if coordinate_uncertainty: - accuracy = rdflib.Literal(coordinate_uncertainty, datatype=rdflib.XSD.double) - graph.add((uri, utils.namespaces.GEO.hasMetricSpatialAccuracy, accuracy)) - - # Add data generalizations attribute if available - if data_generalizations_attribute is not None: - graph.add((uri, utils.namespaces.TERN.hasAttribute, data_generalizations_attribute)) - - def add_site_id_datatype( - self, - uri: rdflib.URIRef | None, - agent: rdflib.URIRef | None, - graph: rdflib.Graph, - ) -> None: - """Adds site id datatype to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - agent (rdflib.URIRef | None): Agent that the datatype - corresponds. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.RDFS.Datatype)) - - # Add label - graph.add((uri, rdflib.SKOS.prefLabel, rdflib.Literal("siteID source"))) - - # Add attribution - if agent is not None: - graph.add((uri, rdflib.PROV.wasAttributedTo, agent)) - - def add_site_id_agent( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds the site id agent to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(row["siteIDSource"]))) - - def add_habitat_attribute( - self, - uri: rdflib.URIRef, - value: rdflib.URIRef, - dataset: rdflib.URIRef, - raw: str, - graph: rdflib.Graph, - ) -> None: - """Adds a habitat attribute to the graph. - - Args: - uri (rdflib.URIRef): Subjcet of the node. - value (rdflib.URIRef): Corresponding value reference. - dataset (rdflib.URIRef): Dataset raw data belongs. - raw (str): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add tern values - graph.add((uri, utils.namespaces.TERN.attribute, HABITAT_DESCRIPTION)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, rdflib.Literal(raw))) - graph.add((uri, utils.namespaces.TERN.hasValue, value)) - - def add_habitat_value( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - raw: str, - graph: rdflib.Graph, - ) -> None: - """Add a habitat value node to graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset data belongs. - raw (str): Raw data provided. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, utils.namespaces.TERN.IRI)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add label - graph.add((uri, rdflib.RDFS.label, rdflib.Literal("Site habitat"))) - - # Retrieve vocab for field - vocab = self.fields()["habitat"].get_vocab() - - # Add flexible vocab term - term = vocab(graph=graph, source=dataset).get(raw) - graph.add((uri, rdflib.RDF.value, term)) - - def add_data_generalizations_attribute( - self, - uri: rdflib.URIRef | None, - value: rdflib.URIRef | None, - dataset: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Add the data generalizations attribute node to the graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - value (rdflib.URIRef | None): Corresponding value. - dataset (rdflib.URIRef): Corresponding dataset data belongs. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Attribute)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add tern values - graph.add((uri, utils.namespaces.TERN.attribute, CONCEPT_DATA_GENERALIZATIONS)) - graph.add((uri, utils.namespaces.TERN.hasSimpleValue, row["dataGeneralizations"])) - if value is not None: - graph.add((uri, utils.namespaces.TERN.hasValue, value)) - - def add_data_generalizations_value( - self, - uri: rdflib.URIRef | None, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Add data generalizations value node to graph. - - Args: - uri (rdflib.URIRef | None): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified.: - """ - # Check subject provided - if uri is None: - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add raw value - graph.add((uri, rdflib.RDF.value, rdflib.Literal(row["dataGeneralizations"]))) - - def add_site_visit( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - agents: list[rdflib.URIRef], - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds site visit to the graph. - - Args: - uri (rdflib.URIRef): URI to use for this node. - dataset (rdflib.URIRef): Dataset to which data belongs. - agents (list[rdflib.URIRef]): Agents involved in the site visit. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, utils.namespaces.TERN.SiteVisit)) - - # Add to dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # TODO: Cross reference - # Add survey - graph.add((uri, rdflib.SDO.isPartOf, DEFAULT_SURVEY)) - - # Add site visit id - if site_visit_id := row["siteVisitID"]: - graph.add((uri, rdflib.DCTERMS.identifier, rdflib.Literal(site_visit_id))) - - # Add temporal information - site_visit_start: models.temporal.Timestamp = row["siteVisitStart"] - start_instant = rdflib.BNode() - graph.add((start_instant, a, rdflib.TIME.Instant)) - graph.add((start_instant, site_visit_start.rdf_in_xsd, site_visit_start.to_rdf_literal())) - - temporal_entity = rdflib.BNode() - graph.add((temporal_entity, a, rdflib.TIME.TemporalEntity)) - graph.add((temporal_entity, rdflib.TIME.hasBeginning, start_instant)) - - site_visit_end: models.temporal.Timestamp | None = row["siteVisitEnd"] - if site_visit_end is not None: - end_instant = rdflib.BNode() - graph.add((end_instant, a, rdflib.TIME.Instant)) - graph.add((end_instant, site_visit_end.rdf_in_xsd, site_visit_end.to_rdf_literal())) - graph.add((temporal_entity, rdflib.TIME.hasEnd, end_instant)) - - graph.add((uri, rdflib.TIME.hasTime, temporal_entity)) - - # Add agents - for agent in agents: - graph.add((uri, rdflib.PROV.wasAssociatedWith, agent)) - - def add_organization_agent( - self, - uri: rdflib.URIRef, - raw: str, - graph: rdflib.Graph, - ) -> None: - """Adds organization agent node to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - raw (str): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, a, rdflib.PROV.Organization)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(raw))) - - def add_observer_agent( - self, - uri: rdflib.URIRef, - raw: str, - graph: rdflib.Graph, - ) -> None: - """Adds observer agent node to the graph - - Args: - uri (rdflib.URIRef): Subject of the node. - raw (str): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Add type - graph.add((uri, a, rdflib.PROV.Agent)) - graph.add((uri, a, rdflib.PROV.Person)) - - # Add name - graph.add((uri, rdflib.SDO.name, rdflib.Literal(raw))) - - def add_site_condition( - self, - uri: rdflib.URIRef, - dataset: rdflib.URIRef, - site: rdflib.URIRef, - value: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds site condition node to the graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - dataset (rdflib.URIRef): Dataset raw data belongs. - site (rdflib.URIRef): Site that condition references. - value (rdflib.URIRef): Corresponding value node reference. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check to see if a condition was supplied - if not (condition := row["condition"]): - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Observation)) - - # Add dataset - graph.add((uri, rdflib.VOID.inDataset, dataset)) - - # Add comment - graph.add((uri, rdflib.RDFS.comment, rdflib.Literal("site-condition"))) - - # Add feature of interest - graph.add((uri, rdflib.SOSA.hasFeatureOfInterest, site)) - - # Add result - graph.add((uri, rdflib.SOSA.hasResult, value)) - graph.add((uri, rdflib.SOSA.hasSimpleResult, rdflib.Literal(condition))) - - # Add observed property - graph.add((uri, rdflib.SOSA.observedProperty, CONCEPT_VEGETATION_CONDITION)) - - # Add temporal information - site_visit_start: models.temporal.Timestamp = row["siteVisitStart"] - start_instant = rdflib.BNode() - graph.add((start_instant, a, rdflib.TIME.Instant)) - graph.add((start_instant, site_visit_start.rdf_in_xsd, site_visit_start.to_rdf_literal())) - graph.add((uri, rdflib.SOSA.phenomenonTime, start_instant)) - - graph.add((uri, utils.namespaces.TERN.resultDateTime, site_visit_start.to_rdf_literal())) - - # Add method - graph.add((uri, rdflib.SOSA.usedProcedure, UNSPECIFIED_CONDITION_METHOD)) - - def add_condition_value( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds condition value node to graph. - - Args: - uri (rdflib.URIRef): Subject of the node. - row (frictionless.Row): Raw data. - graph (rdflib.Graph): Graph to be modified. - """ - # Check to ensure value for condition provided. - if not (condition := row["condition"]): - return - - # Add type - graph.add((uri, a, utils.namespaces.TERN.Text)) - graph.add((uri, a, utils.namespaces.TERN.Value)) - - # Add value - graph.add((uri, rdflib.RDF.value, condition)) - - def add_footprint_geometry( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds footprint geometry details to the graph. - - Args: - uri (rdflib.URIRef): URI to attach. - row (frictionless.Row): Row to retrieve data from. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values - geodetic_datum = row["geodeticDatum"] - footprint_wkt = row["footprintWKT"] - - if footprint_wkt is None or geodetic_datum is None: - return - - # Construct geometry - geometry = models.spatial.Geometry( - raw=footprint_wkt, - datum=geodetic_datum, - ) - - # Construct node - geometry_node = rdflib.BNode() - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - - # Add original geometry supplied as statement - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - def add_point_geometry( - self, - uri: rdflib.URIRef, - row: frictionless.Row, - graph: rdflib.Graph, - ) -> None: - """Adds site point geometry details to the graph. - - Args: - uri (rdflib.URIRef): URI to attach. - row (frictionless.Row): Row to retrieve data from. - graph (rdflib.Graph): Graph to be modified. - """ - # Extract values - decimal_latitude = row["decimalLatitude"] - decimal_longitude = row["decimalLongitude"] - geodetic_datum = row["geodeticDatum"] - - if decimal_latitude is None or decimal_longitude is None or geodetic_datum is None: - return - - # Construct geometry - geometry = models.spatial.Geometry( - raw=models.spatial.LatLong(decimal_latitude, decimal_longitude), - datum=geodetic_datum, - ) - - # Construct node - geometry_node = rdflib.BNode() - graph.add((geometry_node, a, utils.namespaces.GEO.Geometry)) - graph.add((geometry_node, utils.namespaces.GEO.asWKT, geometry.to_transformed_crs_rdf_literal())) - graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) - - # Add original geometry supplied as statement - self.add_geometry_supplied_as( - subj=uri, - pred=utils.namespaces.GEO.hasGeometry, - obj=geometry_node, - geom=geometry, - graph=graph, - ) - - -# Register Mapper -base.mapper.ABISMapper.register_mapper(SurveySiteMapper) diff --git a/abis_mapping/templates/survey_site_data/metadata.json b/abis_mapping/templates/survey_site_data/metadata.json deleted file mode 100644 index 8f284b86..00000000 --- a/abis_mapping/templates/survey_site_data/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "survey_site_data", - "label": "Systematic Survey Site Data Template", - "version": "1.0.0", - "description": "A template for systematic survey site data", - "biodiversity_type": "Systematic Survey Site Data", - "spatial_type": "Point, line, polygon", - "file_type": "CSV", - "sampling_type": "systematic survey", - "template_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_site_data/survey_site_data.csv", - "schema_url": "https://raw.githubusercontent.com/gaiaresources/abis-mapping/main/abis_mapping/templates/survey_site_data/schema.json", - "template_lifecycle_status": "deprecated" -} diff --git a/abis_mapping/templates/survey_site_data/schema.json b/abis_mapping/templates/survey_site_data/schema.json deleted file mode 100644 index 0d5d1dcf..00000000 --- a/abis_mapping/templates/survey_site_data/schema.json +++ /dev/null @@ -1,281 +0,0 @@ -{ - "fields": [ - { - "name": "siteID", - "title": "Site ID", - "description": "A unique within dataset string identifier for the site. Valid values include strings that are used specifically for this survey or URIs from BDR Sites that have been established in previous surveys.", - "example": "P1", - "type": "string", - "format": "default", - "constraints": { - "required": true, - "unique": true - } - }, - { - "name": "siteIDSource", - "title": "Site ID Source", - "description": "The organisation that assigned the SiteID to this Site", - "example": "TERN", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "siteType", - "title": "Site Type", - "description": "The type of site that relates to its sampling type and/or dimensions.", - "example": "Plot", - "type": "string", - "format": "default", - "constraints": { - "required": false - }, - "vocabularies": [ - "SITE_TYPE" - ] - }, - { - "name": "siteName", - "title": "Site Name", - "description": "A name for the site that may be more descriptive than the siteID.", - "example": "Plot 1", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "siteDescription", - "title": "Site Description", - "description": "The site (plot) description covers important aspects of the site (generally of the land surface). Some overlap in collected information does occur due to the modular nature of the survey processes. The description provides significant background information to gain an appreciation of the plot history, topography, position in the landscape and for understanding the likely relationship between the soils, vegetation and fauna.", - "example": "Fine woody debris.", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "habitat", - "title": "Habitat", - "description": "A collection of habitat types representing the dominant vegetation structural formation class adopted by the National Vegetation Information System (NVIS).", - "example": "Chenopod Shrubland | Closed Fernland", - "type": "list", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:habitat", - "constraints": { - "required": false - }, - "vocabularies": [ - "TARGET_HABITAT_SCOPE" - ] - }, - { - "name": "relatedSiteID", - "title": "Related SiteID", - "description": "Identifier of a related site to the specified site e.g. parent site, same site with different identifier.", - "example": "Same as within dataset or existing URI", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "relationshipToRelatedSite", - "title": "Relationship To Related Site", - "description": "Relationship between the site and the related site. This field can be used to record Site identifiers for the same site from different custodians through the use of URIs.", - "example": "Same as within dataset or existing URI", - "type": "string", - "format": "default", - "constraints": { - "required": false, - "enum": [ - "partOf", - "sameAs", - "part of", - "same as", - "Part of", - "Same as" - ] - }, - "vocabularies": [ - "RELATIONSHIP_TO_RELATED_SITE" - ] - }, - { - "name": "decimalLatitude", - "title": "Decimal Latitude", - "description": "The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic origin of a Site. Positive values are north of the Equator, negative values are south of it. Legal values lie between -90 and 0, inclusive for Southern hemisphere.", - "example": "-34.036", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLatitude", - "constraints": { - "required": false, - "minimum": -90, - "maximum": 0 - } - }, - { - "name": "decimalLongitude", - "title": "Decimal Longitude", - "description": "The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic origin of a Site. Positive values are east of the Greenwich Meridian, negative values are west of it. Legal values lie between 0 and 180, inclusive for the BDR use case.", - "example": "146.363", - "type": "number", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:decimalLongitude", - "constraints": { - "required": false, - "minimum": 0, - "maximum": 180 - } - }, - { - "name": "footprintWKT", - "title": "Footprint WKT", - "description": "A Well-Known Text (WKT) representation of the shape (footprint, geometry) that defines the Site. A Site may have both a point-radius representation and a footprint representation, and they may differ from each other.", - "example": "LINESTRING (146.363 -34.036, 146.363 -34.037)", - "type": "wkt", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:footprintWKT", - "constraints": { - "required": false - } - }, - { - "name": "geodeticDatum", - "title": "Geodetic Datum", - "description": "The geodetic datum, or spatial reference system (SRS) upon which the geographic coordinates given for the Site are based.", - "example": "WGS84", - "type": "string", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:geodeticDatum", - "constraints": { - "required": false, - "enum": [ - "AGD66", - "EPSG:4202", - "AGD84", - "EPSG:4203", - "GDA2020", - "EPSG:7844", - "GDA94", - "EPSG:4283", - "WGS84", - "EPSG:4326" - ] - }, - "vocabularies": [ - "GEODETIC_DATUM" - ] - }, - { - "name": "coordinateUncertaintyInMeters", - "title": "Coordinate Uncertainty in Meters", - "description": "The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Site. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.", - "example": "50", - "type": "integer", - "format": "default", - "url": "https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters", - "constraints": { - "required": false, - "minimum": 1 - } - }, - { - "name": "dataGeneralizations", - "title": "Data Generalizations", - "description": "Actions taken to make the shared data less specific or complete than in its original form.", - "example": "Coordinates given in decimalLatitude, decimalLongitude, easting and northing have been rounded to 0.1 DEG. The observer name has been changed to a unique User ID.", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "surveyID", - "title": "SurveyID", - "description": "The identifier of the Survey that the Site is related to in this dataset.", - "example": "AR220-01", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "siteVisitID", - "title": "Site Visit ID", - "description": "The unique key assigned to a visit. A visit is a time distinct assessment conducted within a survey at a designated site.", - "example": "CPXEI0000001", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "siteVisitStart", - "title": "Site Visit Start", - "description": "The temporal start of when the Site was being used to collect data for the survey. Expected values include date, dateTime, dateTimeStamp.", - "example": "2016-02-28", - "type": "timestamp", - "format": "default", - "constraints": { - "required": true - } - }, - { - "name": "siteVisitEnd", - "title": "Site Visit End", - "description": "The temporal end of when the Site was being used to collect data for the survey. Expected values include date, dateTime, dateTimeStamp.", - "example": "2016-02-28", - "type": "timestamp", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "visitOrgs", - "title": "Visit Orgs", - "description": "The names of the organisations responsible for recording the original Occurrence.", - "example": "NSW Dept of Planning, Industry and Environment.", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "visitObservers", - "title": "Visit Observers", - "description": "A list (concatenated and separated using |) of names of people, groups, or organisations responsible for recording the original Occurrence.", - "example": "Oliver P. Pearson | Anita K. Pearson", - "type": "list", - "format": "default", - "constraints": { - "required": false - } - }, - { - "name": "condition", - "title": "Condition", - "description": "The state of a patch of vegetation at the time of sampling relative to some specified standard or benchmark (where available).", - "example": "Burnt", - "type": "string", - "format": "default", - "constraints": { - "required": false - } - } - ], - "primaryKey": "siteID" -} - diff --git a/abis_mapping/templates/survey_site_data/survey_site_data.csv b/abis_mapping/templates/survey_site_data/survey_site_data.csv deleted file mode 100644 index 7784838a..00000000 --- a/abis_mapping/templates/survey_site_data/survey_site_data.csv +++ /dev/null @@ -1 +0,0 @@ -siteID,siteIDSource,siteType,siteName,siteDescription,habitat,relatedSiteID,relationshipToRelatedSite,decimalLatitude,decimalLongitude,footprintWKT,geodeticDatum,coordinateUncertaintyInMeters,dataGeneralizations,surveyID,siteVisitID,siteVisitStart,siteVisitEnd,visitOrgs,visitObservers,condition diff --git a/abis_mapping/templates/survey_site_data/templates/instructions.md b/abis_mapping/templates/survey_site_data/templates/instructions.md deleted file mode 100644 index 457f44f4..00000000 --- a/abis_mapping/templates/survey_site_data/templates/instructions.md +++ /dev/null @@ -1,150 +0,0 @@ -{% extends "BASE_TEMPLATE base.md" %} -{% block body %} -# SYSTEMATIC SURVEY SITE DATA TEMPLATE INSTRUCTIONS - -## Intended Usage -This Systematic Survey Site Data template should be used to record data about a -Site area where species occurrences have been sampled during a systematic survey. - -This Systematic Survey Site template **must be used in combination** with the -`Systematic Survey Occurrence` template and the `Systematic Survey Metadata` template. - -Templates have been provided to facilitate integration of data into the Biodiversity Data -Repository (BDR) database. Not all types of data have been catered for in the available -templates at this stage - if you are unable to find a suitable template, please -contact to make us aware of your data needs. - -#### Data Validation Requirements: -For data validation, you will need your data file to: - -- be the correct **file format**, -- have **fields that match the template downloaded** (do not remove, or - change the order of fields), -- have extant values for **mandatory fields** (see Table 1), and -- comply with all **data value constraints**; for example the geographic coordinates are - consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the - ***{{values.geodetic_datum_count}}*** available options. - -Additional fields may be added **after the templated fields** (noting that the data type -is not assumed and values will be encoded as strings). - -### FILE FORMAT -- The systematic survey site data template is a [UTF-8](#appendix-iv-utf-8) encoded csv (not Microsoft - Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as follows, - otherwise it will not pass the csv validation step upon upload. -
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > - Unicode (UTF-8)]`
- otherwise it will not pass the csv validation step upon upload. -- **Do not include empty rows**. - -#### FILE SIZE -MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the -header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character -limit on individual cells in a spreadsheet. These limits may be overcome by using or -editing CSV files with other software. - -Larger datasets may be more readily ingested using the API interface. Please contact - to make us aware of your data needs. - -## TEMPLATE FIELDS -The template contains the field names in the top row. Table 1 will assist you in transferring -your data to the template indicating: - -- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) - for that field where relevant); -- **Description** of the field; -- **Required** i.e. whether the field is **mandatory, -conditionally mandatory, or optional**; -- **Format** (datatype) required for the data values for example text (string), number - (integer, float), or date; -- **Example** of an entry or entries for that field; and -- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where - relevant. The fields that have suggested values options for the fields in Table 1 are - listed in Table 2 in alphabetical order of the field name. - -### ADDITIONAL FIELDS -Data that does not match the existing template fields may be added as additional columns in -the CSV files after the templated fields. -For example, `fieldNotes`, `continent`, `country`, `countryCode`, `stateProvince`, `georeferencedDate`, -`landformPattern`, `landformElement`, `aspect`, `slope`, `visitNo`. - -Table 1: Systematic Survey Site data template fields with descriptions, conditions, datatype format, and examples. - -{{tables.fields}} - -## APPENDICES -### APPENDIX-I: VOCABULARY LIST -With the exception of `geodeticDatum` and `relationshipToRelatedSite`, data validation -does not require adherence to the vocabularies for the various vocabularied fields. -These vocabularies are merely provided as a means of assistance in developing consistent language -within the database. New terms may be added to more appropriately describe your data that goes -beyond the current list. - -Table 2: Suggested values for controlled vocabulary fields in the template. Each term has a preferred label with a definition to aid understanding -of its meaning. For some terms, alternative -labels with similar semantics are provided. -
**Note:** The values for `geodeticDatum` and `relationshipToRelatedSite` must come from one of the Preferred labels or Alternate Labels in this -table. - -{{tables.vocabularies}} - -### APPENDIX-II: Well Known Text (WKT) -For general information on how WKT coordinate reference data is formatted is available [here](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). -The length of a WKT string or of its components is not prescribed; however, MS Excel *does* has a -32,767 (32K) character limit on individual cells in a spreadsheet. - -It is possible to edit CSV files outside of Excel in order to include more than 32K characters. - -![Multipart geometries (2D) WKT](assets/multipart_geometries_2d_wkt.png) -
*Source: Mwtoews - CC BY-SA 3.0 - Wikipedia *
- -### APPENDIX-III: Timestamp -Following date and date-time formats are acceptable within the timestamp: - -| TYPE | FORMAT | -| --- |-------------------------------------------------------------------------------------------------------------------------------------| -| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| -| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | -| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | -| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | -| **xsd:gYear** | yyyy | - -Where:
-  `yyyy`: four-digit year
-  `mm`: two-digit month (01=January, etc.)
-  `dd`: two-digit day of month (01 through 31)
-  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
-  `mm`: two digits of minute (00 through 59)
-  `ss`: two digits of second (00 through 59)
- - -### APPENDIX-IV: UTF-8 -UTF-8 encoding is considered a best practice for handling character encoding, especially in -the context of web development, data exchange, and modern software systems. UTF-8 -(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of -encoding all possible characters (code points) in Unicode.
-Here are some reasons why UTF-8 is recommended: -- **Universal Character Support:** UTF-8 can represent almost all characters from all writing - systems in use today. This includes characters from various languages, mathematical symbols, - and other special characters. -- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American - Standard Code for Information Interchange). The first 128 characters in UTF-8 are - identical to ASCII, making it easy to work with systems that use ASCII. -- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English - and many other languages). It uses one byte for ASCII characters and up to four - bytes for other characters. This variable-length encoding minimises storage and - bandwidth requirements. -- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is - widely supported by browsers, servers, and web-related technologies. -- **Globalisation:** As software applications become more globalised, supporting a wide - range of languages and scripts becomes crucial. UTF-8 is well-suited for - internationalisation and multilingual support. -- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many - programming languages, databases, and operating systems. Choosing UTF-8 helps - ensure compatibility across different platforms and technologies. - -When working with text data, UTF-8 encoding is recommended to avoid issues related to character -representation and ensure that a diverse set of characters and languages is supported. - -For assistance, please contact: -{% endblock %} diff --git a/abis_mapping/templates/survey_site_data/validators/shaping.py b/abis_mapping/templates/survey_site_data/validators/shaping.py deleted file mode 100644 index 63cf964e..00000000 --- a/abis_mapping/templates/survey_site_data/validators/shaping.py +++ /dev/null @@ -1,288 +0,0 @@ -"""Generates a SHACL shape graph for the survey_site_data template.""" - -# Third-party -import rdflib -import rdflib.term -import rdflib.collection -import pyshacl - -# Local -from abis_mapping import utils -from abis_mapping import vocabs - - -# Constants -a = rdflib.RDF.type -SH = rdflib.Namespace("http://www.w3.org/ns/shacl#") -TEMPORAL_DATATYPES = [ - (rdflib.TIME.inXSDDate, rdflib.XSD.date), - (rdflib.TIME.inXSDDateTime, rdflib.XSD.dateTime), - (rdflib.TIME.inXSDDateTimeStamp, rdflib.XSD.dateTimeStamp), - (rdflib.TIME.inXSDgYearMonth, rdflib.XSD.gYearMonth), - (rdflib.TIME.inXSDgYear, rdflib.XSD.gYear), -] - - -def main() -> None: - """Implementation of the SHACL generation.""" - - # Create graph and bind shape namespace - g = utils.rdf.create_graph() - g.bind("sh", SH) - - # Call each of the major shape constructions - dataset_shape = create_dataset_shape(g) - add_site_shape(g, dataset_shape) - add_site_visit_shape(g, dataset_shape) - - # Perform a validation - d = rdflib.Graph().parse(source="abis_mapping/templates/survey_site_data/examples/minimal.ttl") - s = rdflib.Graph().parse(data=g.serialize()) - valid, rgraph, rtext = pyshacl.validate(data_graph=d, shacl_graph=s) - - # Print report to stdout. - print(rtext) - - # Raise exception if not valid. - if not valid: - raise AssertionError("not valid") - - # Write out to file - g.serialize("abis_mapping/templates/survey_site_data/validators/validator.ttl") - - -def add_site_visit_shape(graph: rdflib.Graph, dataset_shape: rdflib.term.Node) -> rdflib.term.Node: - """Defines and adds site visit shape to graph. - - Args: - graph (rdflib.Graph): Graph to add site visit - dataset_shape (rdflib.term.Node): Dataset reference node: - - Returns: - rdflib.term.Node: Site visit shape node reference - """ - - # Declare shape uri - site_visit_shape = utils.namespaces.BDR.SiteVisitShape - - # Add type and target class - graph.add((site_visit_shape, a, SH.NodeShape)) - graph.add((site_visit_shape, SH.targetClass, utils.namespaces.TERN.SiteVisit)) - - # Add dataset prop - graph.add((site_visit_shape, SH.property, dataset_shape)) - - # Add temporal entity prop - temporal_entity_prop = rdflib.BNode() - graph.add((temporal_entity_prop, SH["class"], rdflib.TIME.TemporalEntity)) - graph.add((temporal_entity_prop, SH.path, rdflib.TIME.hasTime)) - # # Add dates - begin_prop = rdflib.BNode() - graph.add((begin_prop, SH["class"], rdflib.TIME.Instant)) - graph.add((begin_prop, SH.path, rdflib.TIME.hasBeginning)) - temporal_type_opts = temporal_type_list(graph) - graph.add((begin_prop, SH["or"], temporal_type_opts)) - graph.add((temporal_entity_prop, SH.property, begin_prop)) - end_prop = rdflib.BNode() - graph.add((end_prop, SH["class"], rdflib.TIME.Instant)) - graph.add((end_prop, SH.path, rdflib.TIME.hasEnd)) - graph.add((end_prop, SH["or"], temporal_type_opts)) - graph.add((temporal_entity_prop, SH.property, end_prop)) - graph.add((site_visit_shape, SH.property, temporal_entity_prop)) - - # Return reference uri - return site_visit_shape - - -def temporal_type_list(graph: rdflib.Graph) -> rdflib.term.Node: - """Creates an rdf list of temporal types. - - Args: - graph (rdflib.Graph): Graph the list will be added: - - Returns: - rdflib.term.Node: Reference to the list - """ - # Declare temporal type list uri - temporal_type_opts = utils.namespaces.BDR.TemporalTypesList - - # Empty list to hold the temporal datatypes - temporal_type_nodes: list[rdflib.term.Node] = [] - for in_xsd, data_type in TEMPORAL_DATATYPES: - new_node = rdflib.BNode() - graph.add((new_node, SH.path, in_xsd)) - graph.add((new_node, SH.datatype, data_type)) - temporal_type_nodes.append(new_node) - - # Create a collection and add to the graph - rdflib.collection.Collection(graph, temporal_type_opts, temporal_type_nodes) - - # Return the top reference uri - return temporal_type_opts - - -def create_dataset_shape(graph: rdflib.Graph) -> rdflib.term.Node: - """Creates the dataset shape and adds to graph. - - Args: - graph (rdflib.Graph): Graph to be added to. - - Returns: - rdflib.term.Node: Reference to the dataset shape. - """ - # Add the dataset prop - dataset_prop = utils.namespaces.BDR.DatasetShape - graph.add((dataset_prop, a, SH.PropertyShape)) - graph.add((dataset_prop, SH.path, rdflib.VOID.inDataset)) - graph.add((dataset_prop, SH["class"], utils.namespaces.TERN.Dataset)) - graph.add((dataset_prop, SH.minCount, rdflib.Literal(1))) - graph.add((dataset_prop, SH.maxCount, rdflib.Literal(1))) - - # Return reference uri - return dataset_prop - - -def add_site_shape(g: rdflib.Graph, dataset_shape: rdflib.term.Node) -> rdflib.term.Node: - """Adds the site shape to the graph. - - Args: - g (rdflib.Graph): Graph to be modified. - dataset_shape (rdflib.term.Node): Reference to the dataset shape - - Returns: - rdflib.term.Node: Reference to the site shape. - - """ - # Declare the shape uri - site_shape = utils.namespaces.BDR.SiteShape - - # Set the target class - g.add((site_shape, a, SH.NodeShape)) - g.add((site_shape, SH.targetClass, utils.namespaces.TERN.Site)) - - # Add the dataset prop - g.add((site_shape, SH.property, dataset_shape)) - - # Add the site visit prop - site_visit_prop = rdflib.BNode() - g.add((site_visit_prop, SH["class"], utils.namespaces.TERN.SiteVisit)) - g.add((site_visit_prop, SH.path, utils.namespaces.TERN.hasSiteVisit)) - g.add((site_visit_prop, SH.minCount, rdflib.Literal(1))) - g.add((site_visit_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, site_visit_prop)) - - # Add the site id property - site_id_prop = rdflib.BNode() - g.add((site_id_prop, SH.path, rdflib.DCTERMS.identifier)) - g.add((site_id_prop, SH.datatype, rdflib.XSD.string)) - g.add((site_id_prop, SH.minCount, rdflib.Literal(1))) - g.add((site_id_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, site_id_prop)) - - # Add the feature type prop - feature_type_prop = rdflib.BNode() - g.add((feature_type_prop, SH.path, utils.namespaces.TERN.featureType)) - g.add((feature_type_prop, SH.hasValue, vocabs.site_type.SITE.iri)) - g.add((feature_type_prop, SH.minCount, rdflib.Literal(1))) - g.add((feature_type_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, feature_type_prop)) - - # Add the dcterms type prop - dcterms_type_prop = rdflib.BNode() - terms_list = rdflib.BNode() - terms_list_shape = rdflib.BNode() - dcterms_type_opts = rdflib.BNode() - g.add((dcterms_type_prop, SH.path, rdflib.DCTERMS.type)) - site_type_vocab_values: list[rdflib.term.Node] = [v.iri for v in vocabs.site_type.SiteType.terms if v is not None] - rdflib.collection.Collection(g, terms_list, site_type_vocab_values) - g.add((terms_list_shape, SH["in"], terms_list)) - site_type_concept_shape = site_type_concept(g) - rdflib.collection.Collection(g, dcterms_type_opts, [terms_list_shape, site_type_concept_shape]) - g.add((dcterms_type_prop, SH.xone, dcterms_type_opts)) - g.add((dcterms_type_prop, SH.minCount, rdflib.Literal(1))) - g.add((dcterms_type_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, dcterms_type_prop)) - - # Add SDO name prop - sdo_name_prop = rdflib.BNode() - g.add((sdo_name_prop, SH.path, rdflib.SDO.name)) - g.add((sdo_name_prop, SH.datatype, rdflib.XSD.string)) - g.add((sdo_name_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, sdo_name_prop)) - - # Add SDO description prop - sdo_description_prop = rdflib.BNode() - g.add((sdo_description_prop, SH.path, rdflib.SDO.description)) - g.add((sdo_description_prop, SH.datatype, rdflib.XSD.string)) - g.add((sdo_description_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, sdo_description_prop)) - - # Add coord uncertainty prop - coord_uncert_prop = rdflib.BNode() - g.add((coord_uncert_prop, SH.path, utils.namespaces.GEO.hasMetricSpatialAccuracy)) - g.add((coord_uncert_prop, SH.datatype, rdflib.XSD.double)) - g.add((coord_uncert_prop, SH.maxCount, rdflib.Literal(1))) - g.add((site_shape, SH.property, coord_uncert_prop)) - - # Add geometry prop - site_geometry_prop = rdflib.BNode() - g.add((site_geometry_prop, SH.path, utils.namespaces.GEO.hasGeometry)) - g.add((site_geometry_prop, SH["class"], utils.namespaces.GEO.Geometry)) - g.add((site_geometry_prop, SH.maxCount, rdflib.Literal(2))) # Both point and footprintWKT supplied - wkt_prop = rdflib.BNode() - g.add((wkt_prop, SH.path, utils.namespaces.GEO.asWKT)) - g.add((wkt_prop, SH.datatype, utils.namespaces.GEO.wktLiteral)) - g.add((wkt_prop, SH.minCount, rdflib.Literal(1))) - g.add((wkt_prop, SH.minCount, rdflib.Literal(1))) - g.add((site_geometry_prop, SH.property, wkt_prop)) - g.add((site_shape, SH.property, site_geometry_prop)) - - # Return ref to site shape - return site_shape - - -def site_type_concept(g: rdflib.Graph) -> rdflib.term.Node: - """Site type concept shape. - - Args: - g (rdflib.Graph): Graph to be added to. - - Returns: - rdflib.term.Node: Site type concept shape reference. - - """ - # Add SKOS concept shapetype - concept_shape = utils.namespaces.BDR.SiteTypeConceptShape - g.add((concept_shape, a, SH.NodeShape)) - g.add((concept_shape, SH.targetClass, rdflib.SKOS.Concept)) - - # Add definition prop - definition_prop = rdflib.BNode() - g.add((definition_prop, SH.path, rdflib.SKOS.definition)) - g.add((definition_prop, SH.hasValue, rdflib.Literal("A type of site."))) - g.add((concept_shape, SH.property, definition_prop)) - - # Add scheme - scheme_prop = rdflib.BNode() - g.add((scheme_prop, SH.path, rdflib.SKOS.inScheme)) - g.add( - ( - scheme_prop, - SH.hasValue, - rdflib.URIRef("http://linked.data.gov.au/def/tern-cv/74aa68d3-28fd-468d-8ff5-7e791d9f7159"), - ) - ) - g.add((concept_shape, SH.property, scheme_prop)) - - # Add preflabel - pref_label_prop = rdflib.BNode() - g.add((pref_label_prop, SH.path, rdflib.SKOS.prefLabel)) - g.add((pref_label_prop, SH.datatype, rdflib.XSD.string)) - g.add((concept_shape, SH.property, pref_label_prop)) - - # Return reference - return concept_shape - - -if __name__ == "__main__": - main() diff --git a/abis_mapping/templates/survey_site_data/validators/validator.ttl b/abis_mapping/templates/survey_site_data/validators/validator.ttl deleted file mode 100644 index eb18c222..00000000 --- a/abis_mapping/templates/survey_site_data/validators/validator.ttl +++ /dev/null @@ -1,82 +0,0 @@ -@prefix bdr: . -@prefix dcterms: . -@prefix geo: . -@prefix rdf: . -@prefix schema: . -@prefix sh: . -@prefix skos: . -@prefix tern: . -@prefix time: . -@prefix void: . -@prefix xsd: . - -bdr:SiteShape a sh:NodeShape ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:path dcterms:identifier ], - [ sh:class geo:Geometry ; - sh:maxCount 2 ; - sh:path geo:hasGeometry ; - sh:property [ sh:datatype geo:wktLiteral ; - sh:minCount 1 ; - sh:path geo:asWKT ] ], - [ sh:hasValue ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:path tern:featureType ], - [ sh:maxCount 1 ; - sh:minCount 1 ; - sh:path dcterms:type ; - sh:xone ( [ sh:in ( ) ] bdr:SiteTypeConceptShape ) ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:path schema:description ], - [ sh:class tern:SiteVisit ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:path tern:hasSiteVisit ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:path schema:name ], - [ sh:datatype xsd:double ; - sh:maxCount 1 ; - sh:path geo:hasMetricSpatialAccuracy ], - bdr:DatasetShape ; - sh:targetClass tern:Site . - -bdr:SiteVisitShape a sh:NodeShape ; - sh:property [ sh:class time:TemporalEntity ; - sh:path time:hasTime ; - sh:property [ sh:class time:Instant ; - sh:or bdr:TemporalTypesList ; - sh:path time:hasEnd ], - [ sh:class time:Instant ; - sh:or bdr:TemporalTypesList ; - sh:path time:hasBeginning ] ], - bdr:DatasetShape ; - sh:targetClass tern:SiteVisit . - -bdr:SiteTypeConceptShape a sh:NodeShape ; - sh:property [ sh:datatype xsd:string ; - sh:path skos:prefLabel ], - [ sh:hasValue "A type of site." ; - sh:path skos:definition ], - [ sh:hasValue ; - sh:path skos:inScheme ] ; - sh:targetClass skos:Concept . - -bdr:DatasetShape a sh:PropertyShape ; - sh:class tern:Dataset ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:path void:inDataset . - -bdr:TemporalTypesList rdf:first [ sh:datatype xsd:date ; - sh:path time:inXSDDate ] ; - rdf:rest ( [ sh:datatype xsd:dateTime ; - sh:path time:inXSDDateTime ] [ sh:datatype xsd:dateTimeStamp ; - sh:path time:inXSDDateTimeStamp ] [ sh:datatype xsd:gYearMonth ; - sh:path time:inXSDgYearMonth ] [ sh:datatype xsd:gYear ; - sh:path time:inXSDgYear ] ) . - diff --git a/abis_mapping/templates/survey_site_data_v2/mapping.py b/abis_mapping/templates/survey_site_data_v2/mapping.py index 359cf294..74fda456 100644 --- a/abis_mapping/templates/survey_site_data_v2/mapping.py +++ b/abis_mapping/templates/survey_site_data_v2/mapping.py @@ -841,7 +841,6 @@ def add_footprint_geometry( # Extract values geodetic_datum = row["geodeticDatum"] footprint_wkt = row["footprintWKT"] - coordinate_uncertainty = row["coordinateUncertaintyInMeters"] if footprint_wkt is None or geodetic_datum is None: return @@ -859,6 +858,7 @@ def add_footprint_geometry( graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) # Add coordinate uncertainty if available + coordinate_uncertainty = row["coordinateUncertaintyInMeters"] if coordinate_uncertainty: spatial_accuracy = rdflib.Literal(coordinate_uncertainty, datatype=rdflib.XSD.double) graph.add((geometry_node, utils.namespaces.GEO.hasMetricSpatialAccuracy, spatial_accuracy)) @@ -892,7 +892,6 @@ def add_point_geometry( decimal_latitude = row["decimalLatitude"] decimal_longitude = row["decimalLongitude"] geodetic_datum = row["geodeticDatum"] - coordinate_uncertainty = row["coordinateUncertaintyInMeters"] if decimal_latitude is None or decimal_longitude is None or geodetic_datum is None: return @@ -910,6 +909,7 @@ def add_point_geometry( graph.add((uri, utils.namespaces.GEO.hasGeometry, geometry_node)) # Add coordinate uncertainty if available + coordinate_uncertainty = row["coordinateUncertaintyInMeters"] if coordinate_uncertainty: spatial_accuracy = rdflib.Literal(coordinate_uncertainty, datatype=rdflib.XSD.double) graph.add((geometry_node, utils.namespaces.GEO.hasMetricSpatialAccuracy, spatial_accuracy)) diff --git a/docs/contexts/__init__.py b/docs/contexts/__init__.py index b23df24d..1f147d63 100644 --- a/docs/contexts/__init__.py +++ b/docs/contexts/__init__.py @@ -2,12 +2,8 @@ # Local from . import base -from . import incidental_occurrence_data_v2 from . import incidental_occurrence_data_v3 -from . import survey_occurrence_data from . import survey_occurrence_data_v2 -from . import survey_metadata from . import survey_metadata_v2 -from . import survey_site_data from . import survey_site_data_v2 from . import survey_site_visit_data_v2 diff --git a/docs/contexts/incidental_occurrence_data_v2.py b/docs/contexts/incidental_occurrence_data_v2.py deleted file mode 100644 index 0955056d..00000000 --- a/docs/contexts/incidental_occurrence_data_v2.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Declares and registers the incidental occurrence data instruction rendering context.""" - -# Local -from abis_mapping import base -from abis_mapping import vocabs -from docs import contexts -from docs import tables - - -# Constants -mapper_id = "incidental_occurrence_data-v2.0.0.csv" - -# Retrieve mapper -mapper = base.mapper.get_mapper(mapper_id) - -# Create context -_ctx = { - "tables": { - "fields": tables.fields.OccurrenceFieldTabler(template_id=mapper_id, format="markdown").generate_table(), - "vocabularies": tables.vocabs.VocabTabler(template_id=mapper_id, format="markdown").generate_table(), - "threat_status": tables.threat_status.ThreatStatusTabler( - template_id=mapper_id, format="markdown" - ).generate_table(), - }, - "values": { - "geodetic_datum_count": len(vocabs.geodetic_datum.GeodeticDatum.terms), - }, - "metadata": mapper.metadata() if mapper is not None else None, -} - -# Register -contexts.base.register(mapper_id, _ctx) diff --git a/docs/contexts/survey_metadata.py b/docs/contexts/survey_metadata.py deleted file mode 100644 index 40957f3d..00000000 --- a/docs/contexts/survey_metadata.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Declares and registers the survey metadata instruction rendering context.""" - -# Local -from abis_mapping import base -from abis_mapping import vocabs -from docs import contexts -from docs import tables - - -# Constants -mapper_id = "survey_metadata-v1.0.0.csv" - -# Retrieve mapper -mapper = base.mapper.get_mapper(mapper_id) - -# Create context -_ctx = { - "tables": { - "fields": tables.fields.FieldTabler(template_id=mapper_id, format="markdown").generate_table(), - "vocabularies": tables.vocabs.VocabTabler(template_id=mapper_id, format="markdown").generate_table(), - }, - "values": { - "geodetic_datum_count": len(vocabs.geodetic_datum.GeodeticDatum.terms), - }, - "metadata": mapper.metadata() if mapper is not None else None, -} - -# Register -contexts.base.register(mapper_id, _ctx) diff --git a/docs/contexts/survey_occurrence_data.py b/docs/contexts/survey_occurrence_data.py deleted file mode 100644 index 5cb5add5..00000000 --- a/docs/contexts/survey_occurrence_data.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Declares and registers the survey occurrence data instruction rendering context.""" - -# Local -from abis_mapping import base -from abis_mapping import vocabs -from docs import contexts -from docs import tables - - -# Constants -mapper_id = "survey_occurrence_data-v1.0.0.csv" - -# Retrieve mapper -mapper = base.mapper.get_mapper(mapper_id) - -# Create context -_ctx = { - "tables": { - "fields": tables.fields.OccurrenceFieldTabler(template_id=mapper_id, format="markdown").generate_table(), - "vocabularies": tables.vocabs.VocabTabler( - template_id=mapper_id, - format="markdown", - ).generate_table(), - "threat_status": tables.threat_status.ThreatStatusTabler( - template_id=mapper_id, - format="markdown", - ).generate_table(), - }, - "values": { - "geodetic_datum_count": len(vocabs.geodetic_datum.GeodeticDatum.terms), - }, - "metadata": mapper.metadata() if mapper is not None else None, -} - -# Register -contexts.base.register(mapper_id, _ctx) diff --git a/docs/contexts/survey_site_data.py b/docs/contexts/survey_site_data.py deleted file mode 100644 index 3ed09f3d..00000000 --- a/docs/contexts/survey_site_data.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Declares and registers the survey site data instruction rendering context.""" - -# Local -from abis_mapping import base -from docs import contexts -from docs import tables -from abis_mapping import vocabs - - -# Constants -mapper_id = "survey_site_data-v1.0.0.csv" - -# Retrieve mapper -mapper = base.mapper.get_mapper(mapper_id) - - -# Declare context -_ctx = { - "tables": { - "vocabularies": tables.vocabs.VocabTabler( - template_id=mapper_id, - format="markdown", - ).generate_table(), - "fields": tables.fields.FieldTabler( - template_id=mapper_id, - format="markdown", - ).generate_table(), - }, - "values": { - "geodetic_datum_count": len(vocabs.geodetic_datum.GeodeticDatum.terms), - }, - "metadata": mapper.metadata() if mapper is not None else None, -} - - -# Register -contexts.base.register(mapper_id, _ctx) diff --git a/docs/pages/archived_templates/incidental_occurrence_data-v1.0.0.md b/docs/pages/archived_templates/incidental_occurrence_data-v1.0.0.md index 46a769aa..d215b0bc 100644 --- a/docs/pages/archived_templates/incidental_occurrence_data-v1.0.0.md +++ b/docs/pages/archived_templates/incidental_occurrence_data-v1.0.0.md @@ -1,3 +1,19 @@ -# Incidental Occurrence Data v1.0.0 - ARCHIVED +--- +title: Incidental Occurrence Data Template - v1.0.0 + - Archived + +summary: A template to translate some Darwin Core fields +--- + +**incidental_occurrence_data** v1.0.0 + + + +!!! failure "Template Archived" + + This Template is archived, and is no longer available for use. + + +# INCIDENTAL OCCURRENCE DATA TEMPLATE INSTRUCTIONS Instructions for this template are available as a pdf here. diff --git a/docs/pages/archived_templates/incidental_occurrence_data-v2.0.0.csv.md b/docs/pages/archived_templates/incidental_occurrence_data-v2.0.0.csv.md new file mode 100644 index 00000000..73aa675a --- /dev/null +++ b/docs/pages/archived_templates/incidental_occurrence_data-v2.0.0.csv.md @@ -0,0 +1,584 @@ +--- +title: Incidental Occurrence Data Template - v2.0.0 + - Archived + +summary: A template to translate some Darwin Core fields +--- + +**incidental_occurrence_data** v2.0.0 + + + +!!! failure "Template Archived" + + This Template is archived, and is no longer available for use. + + +# INCIDENTAL OCCURRENCE DATA TEMPLATE INSTRUCTIONS + +## OVERVIEW +Use this template to record occurrence data; that is the presence or absence of an organism +at a particular site locality at a point in time. + +Templates have been provided to facilitate integration of your data into the Biodiversity +Data Repository database. Not all types of data have been catered for in the available +templates at this stage; therefore, if you are unable to find a suitable template, please +contact to make us aware of your data needs. + +#### NEED TO KNOW: +For data validation, you will need your data file to: + +- be the correct **file format,** +- have **matching template fields** to the template downloaded (do not remove, or +change the order of fields), however +- additional fields may be added **after the templated fields** (noting that the +data type is not assumed and values will be encoded as strings), +- have values in **mandatory fields** (see Table 1), +- comply with data **value constraints** for example the geographic coordinates are +consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***5*** available +options, and +- align with existing controlled [vocabularies](#appendix-i-vocabulary-list) wherever possible (this is mandatory +for geodeticDatum), but new terms may be submitted for consideration amd will not cause a +validation error. + +### FILE FORMAT +- The incidental occurrence data template is a [UTF-8](#appendix-iii-utf-8) encoded csv (not Microsoft +Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as follows, +otherwise it will not pass the csv validation step upon upload. +
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > +Unicode (UTF-8)]` +- **Do not include empty rows**. + +#### FILE SIZE +MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the +header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character +limit on individual cells in a spreadsheet. These limits may be overcome by using or +editing CSV files with other software. + +Larger datasets may be more readily ingested using the API interface. Please contact + to make us aware of your data needs. + +## TEMPLATE FIELDS +The template contains the field names in the top row. Table 1 will assist you in transferring +your data to the template indicating: + +- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) +for that field where relevant); +- **Description** of the field; +- **Required** i.e. whether the field is **mandatory, +conditionally mandatory, or optional**; +- **Format** (datatype) required for the data values for example text (string), number + (integer, float), or date; +- **Example** of an entry or entries for that field; and +- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where +relevant. The fields that have suggested values options for the fields in Table 1 are +listed in Table 2 in alphabetical order of the field name. + +### ADDITIONAL FIELDS +Data that do not match the existing template fields may be added as additional columns in +the CSV files after the templated fields.
+E.g. eventRemarks, associatedTaxa, pathway. + +Table 1: Incidental occurrence data template fields with descriptions, conditions, +datatype format, and examples. + +|Field #|Name|Description|Mandatory / Optional|Datatype Format|Examples| +|:---:|:---|:---|:---:|:---:|:---| +|1|providerRecordID|The unique (within provider) identifier allocated to this record by the data provider e.g. when data is provided by an aggregator. It connects the record to the collection and storage of the specimens when these parts of the workflow may have been done by different parties.|**Mandatory**|String|8022FSJMJ079c5cf| +|2|providerRecordIDSource|Person or Organisation that generated the providerRecordID. For providers registered with the BDR, this field should contain your BDR registrationID. Populate only if the details are different from the dataset submission details.|**Mandatory**|String|Western Australian Biodiversity Information Office| +|3|[locality](https://dwc.tdwg.org/terms/#dwc:locality)|The specific description of the place.|Optional|String|Cowaramup Bay Road| +|4|[decimalLatitude](https://dwc.tdwg.org/terms/#dwc:decimalLatitude)|The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are north of the Equator, negative values are south of it. Valid coordinate ranges for the BDR system are within and inclusive of -90 to 0.|**Mandatory**|Number|-33.80| +|5|[decimalLongitude](https://dwc.tdwg.org/terms/#dwc:decimalLongitude)|The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are east of the Greenwich Meridian, negative values are west of it. Valid coordinate ranges for the BDR system are within and inclusive of 0 to 180.|**Mandatory**|Number|115.21| +|6|[geodeticDatum](https://dwc.tdwg.org/terms/#dwc:geodeticDatum)|The acronym for the ellipsoid, geodetic datum, or spatial reference system (SRS) upon which the geographic (non-projected) coordinates given in decimalLatitude and decimalLongitude as based.|**Mandatory**|String|WGS84
([Vocabulary link](#geodeticDatum-vocabularies))| +|7|[coordinateUncertaintyInMeters](https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters)|The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Location. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.|Optional|Number|50.0| +|8|[dataGeneralizations](https://dwc.tdwg.org/terms/#dwciri:dataGeneralizations)|Actions taken to make the shared data less specific or complete than in its original form, due to restrictions around identifying locations of particular species. Suggests that alternative data of higher quality may be available on request.|Optional|String|Coordinates rounded to the nearest 10 km for conservation concern| +|9|[eventDate](https://dwc.tdwg.org/terms/#dwc:eventDate)|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T06:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) during which a species occurrence was observed. For occurrences, this is the date-time when the event was recorded. Not suitable for a time in a geological context|**Mandatory**|Timestamp|2019-09-23T14:03+08:00| +|10|[samplingProtocol](https://dwc.tdwg.org/terms/#dwciri:samplingProtocol)|The sampling protocol is the method used to sample the locality to determine the presence (or absence) of the taxon referred to in this record at the indicated time. This may be a collecting method or a method to observe an organism without collection.
Recommended best practice is to describe a species occurrence with no more than one sampling protocol. In the case of a summary, in which a specific protocol can not be attributed to specific species occurrences, the recommended best practice is to repeat the property for each IRI that denotes a different sampling protocol that applies to the occurrence.|Optional|String|human observation
([Vocabulary link](#samplingProtocol-vocabularies))| +|11|[basisOfRecord](https://dwc.tdwg.org/terms/#dwc:basisOfRecord)|The specific nature of the data record.|Optional|String|Human Observation
([Vocabulary link](#basisOfRecord-vocabularies))| +|12|[recordedBy](https://dwc.tdwg.org/terms/#dwciri:recordedBy)|A person, group, or organisation responsible for recording the original Occurrence.|Optional|String|Stream Environment and Water Pty Ltd| +|13|[recordNumber](http://rs.tdwg.org/dwc/terms/recordNumber)|An identifier given to the Occurrence at the time it was recorded. Often serves as a link between field notes and an Occurrence record, such as a specimen collector's number.|Optional|String|PE:12:8832| +|14|[occurrenceStatus](https://dwc.tdwg.org/terms/#dwc:occurrenceStatus)|A statement about the presence or absence of a Taxon at a Location.|Optional|String|present
([Vocabulary link](#occurrenceStatus-vocabularies))| +|15|[habitat](http://rs.tdwg.org/dwc/terms/habitat)|A category or description of the habitat in which the event occurred.|Optional|String|Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.
([Vocabulary link](#habitat-vocabularies))| +|16|[establishmentMeans](https://dwc.tdwg.org/terms/#dwc:establishmentMeans)|Statement about whether an organism or organisms have been introduced to a given place and time through the direct or indirect activity of modern humans.|Optional|String|native
([Vocabulary link](#establishmentMeans-vocabularies))| +|17|[organismRemarks](http://rs.tdwg.org/dwc/terms/organismRemarks)|Comments or notes about the Organism instance.|Optional|String|Dried out leaf tips.| +|18|[individualCount](https://dwc.tdwg.org/terms/#dwc:individualCount)|The number of individuals present at the time of the Occurrence. 0 = none, no value = the specific number was not recorded.|Optional|Integer|26| +|19|[organismQuantity](https://dwc.tdwg.org/list/#dwc_organismQuantity)|A number or enumeration value for the quantity of organisms.|Optional|Number|12.5| +|20|[organismQuantityType](https://dwc.tdwg.org/list/#dwc_organismQuantityType)|The type of quantification system used for the quantity organisms.|Optional|String|% biomass| +|21|[lifeStage](http://rs.tdwg.org/dwc/terms/lifeStage)|The age class or life stage of the Organism(s) at the time the Occurrence was recorded.|Optional|String|adult
([Vocabulary link](#lifeStage-vocabularies))| +|22|[sex](https://dwc.tdwg.org/terms/#dwciri:sex)|The sex of the biological individual(s) represented in the Occurrence.|Optional|String|male
([Vocabulary link](#sex-vocabularies))| +|23|[reproductiveCondition](https://dwc.tdwg.org/terms/#dwc:reproductiveCondition)|The reproductive condition of the biological individual(s) represented in the Occurrence.|Optional|String|No breeding evident| +|24|ownerRecordID|Identifier given to the occurrence by the owner of the data. Populate this field if the data owner is different to the data provider. Unique (within data owner) identifier for the record.|**Conditionally mandatory with ownerRecordIDSource**|String|12345NT521mc5h| +|25|ownerRecordIDSource|Person or Organisation that generated the ownerRecordID. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation who owns the data.|**Conditionally mandatory with ownerRecordID**|String|WAM| +|26|[collectionCode](https://dwc.tdwg.org/terms/#dwc:collectionCode)|The name, acronym, code, or initialism identifying the collection or data set from which the record was derived. It is associated with the catalogNumber.|Optional|String|ARACH| +|27|[catalogNumber](http://rs.tdwg.org/dwc/terms/catalogNumber)|An identifier (preferably unique) for the record within the data set or collection.|**Conditionally mandatory with catalogNumberSource**|String|1234568.1| +|28|catalogNumberSource|Organisation that generated the catalogNumber. In the BDR context, this is likely to be a collecting institution where a specimen or material sample is located. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.|**Conditionally mandatory with catalogNumber**|String|Western Australian Museum| +|29|[otherCatalogNumbers](http://rs.tdwg.org/dwc/terms/otherCatalogNumbers)|A list (concatenated and separated with a space vertical bar space ( \| )) of previous or alternate fully qualified catalog numbers or other human-used identifiers for the same Occurrence, whether in the current or any other data set or collection.|**Conditionally mandatory with otherCatalogNumbersSource**|List|BHP2012-7521 \| M12378| +|30|otherCatalogNumbersSource|Organisation that generated the otherCatalogNumbers. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.|**Conditionally mandatory with otherCatalogNumbers**|String|University of Western Australia| +|31|[preparations](http://rs.tdwg.org/dwc/terms/preparations)|A list (concatenated and separated with a space vertical bar space ( \| )) of preparations and preservation methods for a specimen.|Optional|String|Wet (in ethanol or some other preservative)
([Vocabulary link](#preparations-vocabularies))| +|32|preparedDate|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) representing the date or date-time the specimen was prepared.|Optional|Timestamp|2019-09-25T10:02+08:00| +|33|[associatedSequences](http://rs.tdwg.org/dwc/terms/associatedSequences)|A list (concatenated and separated with a space vertical bar space ( \| )) of identifiers (publication, global unique identifier, URI) of genetic sequence information associated with the Occurrence.|Optional|List|https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 \| https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1| +|34|sequencingMethod|The method used to obtain sequence data for example DNA, RNA, or protein from the sample.|Optional|String|Sanger dideoxy sequencing
([Vocabulary link](#sequencingMethod-vocabularies))| +|35|[verbatimIdentification](https://dwc.tdwg.org/terms/#dwc:verbatimIdentification)|A string representing the taxonomic identification as it appeared in the original record. This term is meant to allow the capture of an unaltered original identification/determination, including identification qualifiers, hybrid formulas, uncertainties, etc. This term is meant to be used in addition to scientificName (and identificationQualifier etc.), not instead of it.|Optional|String|Caladenia ?excelsa| +|36|[dateIdentified](http://rs.tdwg.org/dwc/terms/dateIdentified)|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which the subject was determined as representing the Taxon.|Optional|Timestamp|2019-09-23T14:03+08:00| +|37|[identifiedBy](http://rs.tdwg.org/dwc/terms/identifiedBy)|Group of names, organisations who assigned the Taxon to the subject. For multiple names, use the pipe separator ( \| ).|Optional|String|Stream Environment and Water Pty Ltd| +|38|identificationMethod|Method used to associate the organism with the scientificName label.|Optional|String|Visually identified in the field (sighting)
([Vocabulary link](#identificationMethod-vocabularies))| +|39|[scientificName](http://rs.tdwg.org/dwc/terms/scientificName)|The full scientific name, with authorship and date information if known. When forming part of an Identification, this should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the identificationQualifier column.
NOTE: Phrase names such as Rhagodia sp. Hamersley (M.Trudgen 17794) are permitted in the scientificName field where those are in use.|**Mandatory**|String|Caladenia excelsa| +|40|[identificationQualifier](https://dwc.tdwg.org/terms/#dwc:identificationQualifier)|A brief phrase or a standard term ("cf.", "aff.") to express the determiner's doubts about the Identification.|Optional|String|Species incerta
([Vocabulary link](#identificationQualifier-vocabularies))| +|41|[identificationRemarks](http://rs.tdwg.org/dwc/terms/identificationRemarks)|Comments or notes about the Identification.|Optional|String|DNA evidence may indicate a new species. Further analysis required.| +|42|[acceptedNameUsage](https://dwc.tdwg.org/terms/#dwc:acceptedNameUsage)|The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) taxon.|Optional|String|Occiperipatoides gilesii (Spencer, 1909)| +|43|[kingdom](https://dwc.tdwg.org/terms/#dwc:kingdom)|The full scientific name of the kingdom in which the taxon is classified.|**Mandatory**|String|Plantae
([Vocabulary link](#kingdom-vocabularies))| +|44|[taxonRank](http://rs.tdwg.org/dwc/terms/verbatimTaxonRank)|The taxonomic rank of the most specific name in the scientificName.|Optional|String|species
([Vocabulary link](#taxonRank-vocabularies))| +|45|threatStatus|The conservation status (or code) assigned to an organism that is recognised in conjunction with a specific jurisdiction.|**Conditionally mandatory with conservationJurisdiction**|String|VU
([Vocabulary link](#threatStatus-vocabularies))| +|46|conservationJurisdiction|The jurisdiction under which an organism is recognised to have a specific conservation status applied.|**Conditionally mandatory with threatStatus**|String|WA
([Vocabulary link](#conservationJurisdiction-vocabularies))| +|47|threatStatusCheckProtocol|The method used to determine if the organism is listed under the relevant jurisdictional threatened species list.|Optional|String|Species name check of the Department of Climate Change, Energy, the Environment and Water’s Species Profile and Threat Database http://www.environment.gov.au/cgi-bin/sprat/public/sprat.pl
([Vocabulary link](#threatStatusCheckProtocol-vocabularies))| +|48|threatStatusDateDetermined|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which this record of this organism was assigned to the nominated threatStatus and conservationJurisdiction|Optional|Timestamp|30/08/2022| +|49|threatStatusDeterminedBy|The person and/organisation responsible for appending the threatStatus and conservationJurisdiction to this organism’s occurrence record.|Optional|String|J. Bloggs, Department of Environment| + + +## CHANGELOG + +Changes from Incidental Occurrence Data Template v1.0.0 + +### CHANGED FIELDS + +* `recordID` is renamed [`providerRecordID`](#providerRecordID-field) and its value is now **mandatory** +* [`providerRecordIDSource`](#providerRecordIDSource-field) is an added field. Its type is string and its value is **mandatory**. +* [`organismQuantity`](#organismQuantity-field) is an added field. Its type is number. Can be blank. +* [`organismQuantityType`](#organismQuantityType-field) is an added field. Its type is string. Can be blank. +* `occurrenceID` is renamed [`ownerRecordID`](#ownerRecordID-field). Can be blank. +* `ownerInstitutionCode` is renamed [`ownerRecordIDSource`](#ownerRecordIDSource-field). Can be blank. +* `institutionCode` is replaced by [`catalogNumberSource`](#catalogNumberSource-field). Can be blank. +* [`otherCatalogNumbersSource`](#otherCatalogNumbersSource-field) is an added field. Its type is string. Can be blank. + +## APPENDICES +### APPENDIX-I: VOCABULARY LIST +Apart from geodeticDatum, the data validation does not require adherence to the below vocabularies +for each of the fields indicated as having vocabularies. These vocabularies are provided as a +means of assistance in developing consistent language within the database. New terms can be added +to more appropriately describe your data that goes beyond the current list. Table 2 provides some +suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), +[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information +System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity +era](https://doi.org/10.1111/2041-210X.12594). + +Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has +a preferred label with a definition to aid understanding of its meaning. For some terms, alternative +labels are provided that mean the same sort of thing. Note: geodeticDatum value +must come from one of five options in this table. + + + +|Template field name|Preferred label|Definition|Alternate label| +|:---|:---|:---|:---| +|basisOfRecord|FOSSIL SPECIMEN|A preserved specimen that is a fossil.|| +|basisOfRecord|HUMAN OBSERVATION|An output of a human observation.|| +|basisOfRecord|LIVING SPECIMEN|A specimen that is alive.|| +|basisOfRecord|MACHINE OBSERVATION|An output of a machine observation process.|| +|basisOfRecord|MATERIAL SAMPLE|A physical result of a sampling (or subsampling) event. In biological collections, the material sample is typically collected, and either preserved or destructively processed.|| +|basisOfRecord|OCCURRENCE|An existence of an Organism (sensu http://rs.tdwg.org/dwc/terms/Organism) at a particular place at a particular time.|| +|basisOfRecord|PRESERVED SPECIMEN|A specimen that has been preserved.|| +|establishmentMeans|INTRODUCED|Establishment of a taxon by numan agency into an area that is not part of its natural range.|| +|establishmentMeans|INTRODUCED ASSISTED COLONISATION|Establishment of a taxon specifically with the intention of creating a self-sustaining wild population in an area that is not part of the taxon's natural range.|ASSISTED COLONISATION| +|establishmentMeans|NATIVE|A taxon occurring within its natural range.|NATIVE (INDIGENOUS)| +|establishmentMeans|NATIVE REINTRODUCED|A taxon re-established by direct introduction by humans into an area that is not part of its natural range, but from where it had become extinct.|NATIVE: REINTRODUCED| +|establishmentMeans|UNCERTAIN|The origin of the occurrence of the taxon in an area is obscure.|UNKNOWN, CRYPTOGENIC| +|establishmentMeans|VAGRANT|The temporary occurrence of a taxon far outside its natural or migratory range.|CASUAL| +|geodeticDatum|AGD66|Australian Geodetic Datum 1966|EPSG:4202| +|geodeticDatum|AGD84|Australian Geodetic Datum 1984|EPSG:4203| +|geodeticDatum|GDA2020|Geocentric Datum of Australia 2020|EPSG:7844| +|geodeticDatum|GDA94|Geocentric Datum of Australia 1994|EPSG:4283| +|geodeticDatum|WGS84|World Geodetic System 1984, used in GPS|EPSG:4326| +|habitat|BEACH|Type of Landform Element, which is usually short; low; very wide slope; gently or moderately inclined; built up or eroded by waves; forming the shore of a lake or sea.|| +|habitat|BILLABONG OR SWAMP|A swamp is a wetland that features temporary or permanent inundation of large areas of land by shallow bodies of water, generally with a substantial number of hammocks, or dry-land protrusions, and covered by aquatic vegetation, or vegetation that tolerates periodical inundation.|| +|habitat|CAVE|The type of habitat representative of a naturally formed, subterranean open area or chamber.|| +|habitat|CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Chenopodiaceae.|| +|habitat|CLOSED CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Chenopodiaceae.|| +|habitat|CLOSED FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Fern and Fern-allies.|| +|habitat|CLOSED FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|habitat|CLOSED FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|habitat|CLOSED HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of heath shrubs (e.g., members of Ericaceae, Myrtaceae).|| +|habitat|CLOSED HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of hummock (e.g., Triodia) grasses.|| +|habitat|CLOSED LICHENLAND|Refers to the type of habitat characterised by lichenised tree trunks and rocks.|| +|habitat|CLOSED LIVERWORTLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|CLOSED MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tree mallee (e.g., some members of Eucalyptus).|| +|habitat|CLOSED MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of mallee shrubs (e.g., some members of Eucalyptus).|| +|habitat|CLOSED MOSSLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|CLOSED RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Rushes (e.g., Juncaceae).|| +|habitat|CLOSED SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|habitat|CLOSED SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|habitat|CLOSED SOD GRASSLAND|Refers to the type of habitat representative of a characteristic sod-like (turf) grass.|| +|habitat|CLOSED TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tussock grasses (e.g., Poa).|| +|habitat|CLOSED VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|habitat|COASTAL WATERS|Refers to the type of habitat representative of an aquatic body typically characterized by a shallow continental shelf, gently sloping seaward to a continental slope, which drops relatively abruptly to the deep ocean.|| +|habitat|CROP LAND|Refers to the type of habitat representative of a cultivated land or land on which agricultural crops are grown or land that is set aside or temporarily not being used for crop production.|| +|habitat|ESTUARY|Type of Landform Element which has a stream channel close to its junction with a sea or lake; where the action of channelled stream flow is modified by tide and waves. The width typically increases downstream.|| +|habitat|FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Fern and Fern-allies.|| +|habitat|FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Forbs or herbaceous plants other than grasses.|| +|habitat|FRESHWATER LAKE|Refers to the type of habitat representative of an enclosed aquatic body having a relatively low mineral content, generally less than 500 mg/l of dissolved solids.|| +|habitat|GRAZING LAND|Refers to the type of habitat representative of a land predominantly used for grazing.|| +|habitat|HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Heath (e.g., Ericaceae, Myrtaceae).|| +|habitat|HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of hummock grasses (e.g., Triodia).|| +|habitat|ISOLATED CHENOPOD SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% members of Chenopodiaceae.|| +|habitat|ISOLATED CLUMP OF CHENOPOD SHRUBS|Refers to the type of habitat characterised by isolated clumps of chenopod shrubs.|| +|habitat|ISOLATED CLUMP OF HEATH SHRUBS|Refers to the type of habitat characterised by isolated clumps of heath or heath-like shrubs.|| +|habitat|ISOLATED CLUMP OF HUMMOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of hummocky grass (e.g., Triodia spp., Spinifex spp.).|| +|habitat|ISOLATED CLUMP OF LIVERWORTS|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|habitat|ISOLATED CLUMP OF MALLEE SHRUBS|Refers to the type of habitat characterised by isolated clumps of mallee shrubs (members of Eucalyptus spp., multistemmed from base).|| +|habitat|ISOLATED CLUMP OF MALLEE TREES|Refers to the type of habitat characterised by isolated clumps of tree mallee (members of Eucalyptus spp., multistemmed from base).|| +|habitat|ISOLATED CLUMP OF MOSSES|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|habitat|ISOLATED CLUMP OF RUSHES|Refers to the type of habitat characterised by isolated clumps of rushes.|| +|habitat|ISOLATED CLUMP OF SEDGES|Refers to the type of habitat characterised by isolated clumps of sedges.|| +|habitat|ISOLATED CLUMP OF SHRUBS|Refers to the type of habitat characterised by isolated clumps of shrubs.|| +|habitat|ISOLATED CLUMP OF SOD GRASSES|Refers to the type of habitat characterised by isolated clumps of sod grass.|| +|habitat|ISOLATED CLUMP OF TREES|Refers to the type of habitat characterised by isolated clumps of trees.|| +|habitat|ISOLATED CLUMP OF TUSSOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of tussock grasses (e.g., Poa spp).|| +|habitat|ISOLATED CLUMP OF VINES|Refers to the type of habitat characterised by isolated clumps of vines.|| +|habitat|ISOLATED CLUMPS OF FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Fern and Fern-allies.|| +|habitat|ISOLATED CLUMPS OF FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Forbs or herbs other than grasses.|| +|habitat|ISOLATED CLUP OF LICHENS|Refers to the type of habitat characterised by isolated clumps of lichens.|| +|habitat|ISOLATED FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of fern and fern allies.|| +|habitat|ISOLATED FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of forbs or herbs other than grasses.|| +|habitat|ISOLATED HEATH SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of heath shrubs (e.g., Ericaceae, Myrtaceae).|| +|habitat|ISOLATED HUMMOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of hummock grasses (e.g., Triodia).|| +|habitat|ISOLATED LICHENS|Refers to the type of habitat characterised by isolated or sparse lichens.|| +|habitat|ISOLATED LIVERWORTS|Refers to the type of habitat characterised by isolated or sparse liverworts.|| +|habitat|ISOLATED MALLEE SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of mallee shrubs (e.g., some multistemmed individuals from base of Eucalyptus).|| +|habitat|ISOLATED MALLEE TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tree mallee (e.g., some multistemmed individuals from base of Eucalyptus).|| +|habitat|ISOLATED MOSSES|Refers to the type of habitat characterised by isolated mosses, including bryophytes and liverworts.|| +|habitat|ISOLATED RUSHES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of rushes (e.g., Juncaceae).|| +|habitat|ISOLATED SEDGES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of sedges (e.g., Cyperaceae).|| +|habitat|ISOLATED SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of shrubs including cycads, grass-tree and tree-fern.|| +|habitat|ISOLATED SOD GRASSES|Refers to the type of habitat characterised by isolated or sparse sod or turf-like grasses.|| +|habitat|ISOLATED TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of trees including palms.|| +|habitat|ISOLATED TUSSOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tussock grass (e.g. Poa species).|| +|habitat|ISOLATED VINES|Refers to the type of habitat characterised by isolated or sparse stragglers or climbing woody vines.|| +|habitat|LICHENLAND|Refers to the type of habitat predominated by lichens on rocks, trees or tree stumps, etc.|| +|habitat|LIVERWORTLAND|Refers to the type of habitat predominated by liverworts.|| +|habitat|MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrub mallee (e.g., individuals of some Eucalypts multistemmed from base).|| +|habitat|MALLEE WOODLAND|Refers to the dominant vegetation structural formation, with a percent cover of about 20-50% of Tree Mallee.|| +|habitat|MOSSLAND|Refers to the type of habitat dominated by mosses.|| +|habitat|MUDFLAT|Refers to the type of habitat characterised by a wetland that forms when mud is deposited by the tides, rivers, sea or oceans.|| +|habitat|OPEN CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of members of Chenopodiaceae.|| +|habitat|OPEN FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of ferns and fern allies.|| +|habitat|OPEN FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of forbs or herbs other than grasses.|| +|habitat|OPEN FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of trees including palms.|| +|habitat|OPEN HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of heaths (e.g., Ericaceae, Myrtaceae).|| +|habitat|OPEN HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of hummock grasses (e.g., Triodia).|| +|habitat|OPEN LICHENLAND|Refers to the type of habitat represented by open or sparse (i.e., 10-30%) hummocky grasses (e.g., Spinifex spp., Triodia spp.).|| +|habitat|OPEN LIVERWORTLAND|Refers to the type of habitat characterised by open or sparse lichenised tree trunks and rocks.|| +|habitat|OPEN MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tree Mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of Mallee shrubs (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MALLEE WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tree mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MOSSLAND|Refers to the type of habitat characterised by open or sparse members of lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|OPEN OCEAN|Refers to the type of habitat surrounded by ocean, i.e., a continuous saline-water bodies that surround the continents and fill the Earth's great depressions.|| +|habitat|OPEN RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of rushes (e.g. Juncaceae).|| +|habitat|OPEN SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of sedges (e.g. Cyperaceae).|| +|habitat|OPEN SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of shrubs (e.g. shrubs, cycads, grass-tree, tree-fern).|| +|habitat|OPEN SOD GRASSLAND|Refers to the type of habitat characterised by open or sparse (10-30% ground cover) of a characteristic sod-like (turf) grass.|| +|habitat|OPEN TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of tussock grasses (e.g. Poa species).|| +|habitat|OPEN VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|habitat|OPEN WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of trees including palms.|| +|habitat|ROCK OUTCROP|Refers to the type of habitat characterised by rocks, which protrudes through the surface layer.|| +|habitat|RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of rushes (e.g. Juncaceae).|| +|habitat|SALTWATER LAKE|Refers to the type of habitat representative of an aquatic body filled with water (with high salinity) of considerable size contained in a depression on a landmass.|| +|habitat|SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of sedges (e.g., Cyperaceae).|| +|habitat|SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrubs (e.g., shrub, cycad, grass-tree, tree-fern).|| +|habitat|SOD GRASSLAND|Refers to the type of habitat characterised by mid-dense (30-70% cover) sod or turf-like grasses.|| +|habitat|SPARSE CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of Chenopodiaceae.|| +|habitat|SPARSE FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of fern and fern-allies.|| +|habitat|SPARSE FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of forbs and herbs other than grasses.|| +|habitat|SPARSE GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of grasses.|| +|habitat|SPARSE HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of heath (e.g., Ericaceae, Myrtaceae).|| +|habitat|SPARSE LICHENLAND|Refers to the type of habitat characterised by very sparse (<10% cover) lichens.|| +|habitat|SPARSE LIVERWORTLAND|Refers to the type of habitat characterised by very sparse (<10% cover) liverworts.|| +|habitat|SPARSE MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of shrub Mallee.|| +|habitat|SPARSE MOSSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) mosses.|| +|habitat|SPARSE RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of rushes (e.g., Juncaceae).|| +|habitat|SPARSE SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of sedges (e.g., Cyperaceae).|| +|habitat|SPARSE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of shrubs, including cycad, grass-tree, tree-fern.|| +|habitat|SPARSE SOD GRASSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) sod or turf-like grasses.|| +|habitat|SPARSE TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tussock grass (e.g., Poa species).|| +|habitat|SPARSE VINELAND|Refers to the type of habitat characterised by well separated or very sparse crown stragglers or woody vines.|| +|habitat|STREAM OR RIVER|Refers to the type of habitat representative of an aquatic body with a watercourse which is linear and flows across the solid portion of a planetary surface.|| +|habitat|TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tussock grass (e.g., Poa species).|| +|habitat|URBAN|Refers to the type of habitat relating to, located in, or characteristic of a city or densely populated area.|| +|habitat|VINELAND|Refers to the type of habitat characterised by woody climbers/straggling vines.|| +|habitat|WOODLAND|Refers to the type of habitat characterised by a low-density forest forming open habitats with plenty of sunlight and limited shade.|| +|identificationMethod|TBC|TBC|| +|identificationQualifier|ANIMALIA CETERA|It groups all the unidentified specimens that are not listed as separate taxa. The term cetera (abbreviated c. or cet.) may be applied to a given high-rank taxon, meaning that identification at a lower taxonomic level has not been attempted (see also stetit) but explicitly not including subordinate taxa that may have been identified.|A.C.| +|identificationQualifier|CONFER|"Compare with". Specimens should be compared to reference material, since most of the diagnostic characters correspond to a given species but some are unclear. Also used in the sense of affinis and species incerta (these usages are discouraged).|CF., CFR., CONF., SP. CF.| +|identificationQualifier|EX GREGE|"Of the group including". The specimen has some affinity to a known species or it belongs to a species group or species complex; see also affinis and species proxima.|EX GR., GR.| +|identificationQualifier|FAMILIA GENUS SPECIES|The specimen has not been attributed to any known species nor family; see also species.|FAM. GEN. SP.| +|identificationQualifier|GENUS ET SPECIES NOVA|The specimen is considered to belong to a new species and a new genus; for more details, see species nova.|GEN. ET SP., GEN. NOV., SP. NOV., NOV. GEN. ET SP.| +|identificationQualifier|GENUS NOVUM|The specimen is considered to belong to a new species and a new genus; for more details, see species nova|GEN. NOV., G. NOV., GEN. N., G. N., NOV. GEN| +|identificationQualifier|GENUS SPECIES|The specimen has not been related to any known species nor genus; also species.|GEN. SP., G. SP.| +|identificationQualifier|SPECIES|The specimen has not been identified, nor it has been related to any known species; the uncertainty is potentially provisional: it could be due to the lack of suitable dichotomous keys, or to the occurrence of a species not previously described. Also used in the sense of species indeterminabilis and stetit (these usages are discouraged.|SP| +|identificationQualifier|SPECIES AFFINIS|"Has affinity with". The specimen has some affinity to a known species but it is not identical to it; it generally implies distinction more than a possible identity, in contrast with the qualifier confer; see also species Proxima and ex grege. It is often used in combination with the ON qualifier species nova. Also used in the sense of confer (this usage is discouraged).|AFF., SP. AFF.| +|identificationQualifier|SPECIES INCERTA|The identification is uncertain; it usually indicates a higher reliability with ?, sp. Inc respect to confer. The sign "sp. inc." is also used in the sense of species, species indeterminabilis and species inquirenda (these usages are discouraged).|SP. INC.| +|identificationQualifier|SPECIES INDETERMINABILIS|The specimen is indeterminable beyond a certain taxonomic level due to the deterioration or lack of diagnostic characters. Also used in the sense of species and stetit (these usages are discouraged.|INDET., IND., SP. INDET., SP. IND.| +|identificationQualifier|SPECIES NOVA|The specimen is considered to belong to a new, previously undescribed (1) When describing a new species, the use of the qualifier is required by the ICZN (1999) to explicitly indicate the taxa name as intentionally new. (2) Used as ON qualifier to refer to a new, still unnamed species before the formal publication of the description.|SP. NOV., SPEC. NOV., SP. N., NOV. SP., NOV. SPEC., N. SP.| +|identificationQualifier|SPECIES PROXIMA|The specimen is near to a known species but it is not identical to it; see also affinis and ex grege.|PROX., SP. PROX., NR., SP.NR.| +|identificationQualifier|STETIT|Identification at a lower taxonomic level has not been attempted, even if allowed by the sample conditions. It may also be used when more records with different ON qualifiers need to be merged at a safe taxonomic level.|STET.| +|identificationQualifier|SUBSPECIES|The only infraspecific rank regulated by the ICZN (1999). As ON qualifier, it indicates that the specimen probably belongs to a subspecies but it has not been related to any known one; see also species.|SSP., SUBSP.| +|kingdom|ANIMALIA|Kingdom Animalia|| +|kingdom|FUNGI|Kingdom (taxonRank: Regnum) Fungi|| +|kingdom|PLANTAE|Kingdom (taxonRank: Regnum) Plantae|PLANTAE HAECKEL| +|lifeStage|ADULT|An adult is a plant, animal, or person who has reached full growth or alternatively is capable of reproduction.|IMAGO| +|lifeStage|EMBRYO|An embryo is a multicellular diploid eukaryote in its earliest stage of development, from the time of first cell division until birth, hatching, or germination.|EGG, SEED| +|lifeStage|GAMETE|A gamete is a cell that fuses with another gamete during fertilisation in organisms that reproduce sexually. In species that produce two morphologically distinct types of gametes, and in which each individual produces only one type, a female is any individual that produces the larger type of gamete — called an ovum (or egg) — and a male produces the smaller tadpole-like type — called a sperm. This is an example of anisogamy or heterogamy, the condition wherein females and males produce gametes of different sizes. In contrast, isogamy is the state of gametes from both sexes being the same size and shape, and given arbitrary designators for mating type. Gametes carry half the genetic information of an individual, one chromosome of each type.|OVUM, SPERM, POLLEN| +|lifeStage|GAMETOPHYTE|In plants and algae that undergo alternation of generations, a gametophyte is the multicellular structure, or phase, that is haploid, containing a single set of chromosomes. The gametophyte produces male or female gametes (or both), by a process of cell division called mitosis. In mosses, liverworts and hornworts (bryophytes), the gametophyte is the commonly known phase of the plant. An early developmental stage in the gametophyte of mosses (immediately following germination of the meiospore) is called the protonema. In most other land plants the gametophyte is very small (as in ferns and their relatives) or even reduced as in flowering plants (angiosperms), where the female gametophyte (ovule) is known as a megagametophyte and the male gametophyte (pollen) is called a microgametophyte.|GAMONT, PROTONEMA, POLLEN, OVULE| +|lifeStage|JUVENILE|A juvenile is an individual organism that has not yet reached its adult form, sexual maturity or size. Juveniles sometimes look very different from the adult form, particularly in terms of their colour. In many organisms the juvenile has a different name from the adult.|SEEDLING, EFT, CALF, HATCHLING, INFANT, FOAL, KITTEN, KIT, CHICK, NYMPH, FAWN, WHELP, PUP, ELVER, FRY| +|lifeStage|LARVA|A larva (Latin; plural larvae) is a young (juvenile) form of animal with indirect development, going through or undergoing metamorphosis (for example, insects, amphibians, or cnidarians). The larva can look completely different from the adult form, for example, a caterpillar differs from a butterfly. Larvae often have special (larval) organs which do not occur in the adult form. The larvae of some species can become pubescent and not further develop into the adult form (for example, in some newts). This is a type of neoteny. It is a misunderstanding that the larval form always reflects the group's evolutionary history. It could be the case, but often the larval stage has evolved secondarily, as in insects. In these cases the larval form might differ more from the group's common origin than the adult form. The early life stages of most fish species are considerably different from juveniles and adults of their species and are called larvae.|LARVAE, TADPOLE, POLLIWOG, POLLYWOG, POLLIWIG, POLEWIG, POLWIG, PLANULA, NAUPLIUS, ZOEA, NYMPH, CATERPILLAR| +|lifeStage|PUPA|A pupa is the life stage of some insects undergoing transformation between immature and mature stages. The pupal stage is found only in holometabolous insects, those that undergo a complete metamorphosis, with four life stages: egg (-> embryo), larva, pupa, and imago (-> adult).|PUPPE| +|lifeStage|SPORE|A spore is a reproductive structure that is adapted for dispersal and surviving for extended periods of time in unfavorable conditions. Spores form part of the life cycles of many bacteria, plants, algae, fungi and some protozoans. A chief difference between spores and seeds as dispersal units is that spores have very little stored food resources compared with seeds. Spores are usually haploid and unicellular and are produced by meiosis in the sporangium by the sporophyte. Once conditions are favorable, the spore can develop into a new organism using mitotic division, producing a multicellular gametophyte, which eventually goes on to produce gametes. Many ferns, especially those adapted to dry conditions, produce diploid spores. In this case spores are the units of asexual reproduction, because a single spore develops into a new organism. By contrast, gametes are the units of sexual reproduction, as two gametes need to fuse to create a new organism.|| +|lifeStage|SPOROPHYTE|All land plants, and some algae, have life cycles in which a haploid gametophyte generation alternates with a diploid sporophyte, the generation of a plant or alga that has a double set of chromosomes. A multicellular sporophyte generation or phase is present in the life cycle of all land plants and in some green algae. For common flowering plants (Angiosperms), the sporophyte generation comprises almost their whole life cycle (that is whole green plant, roots etc), except phases of small reproductive structures (pollen and ovule).|AGAMONT| +|lifeStage|ZYGOTE|A zygote (or zygocyte) describes the first stage of a new unique organism blastomere when it consists of just a single cell. The term is also used more loosely to refer to the group of cells formed by the first few cell divisions, although this is properly referred to as a blastomere. A zygote is usually produced by a fertilisation event between two haploid cells - an ovum from a female and a sperm cell from a male - which combine to form the single diploid cell. Thus the zygote contains DNA originating from both mother and father and this provides all the genetic information necessary to form a new individual|BLASTOMERE| +|occurrenceStatus|ABSENT|The occurrence was not present at the location and time of the observation.|| +|occurrenceStatus|PRESENT|The occurrence was present at the location and time of the observation.|| +|preparations|ALCOHOL|Alcohol|| +|preparations|DEEP FROZEN|Deep frozen|| +|preparations|DRIED|Dried|| +|preparations|DRIED AND PRESSED|Dried and pressed|| +|preparations|FORMALIN|Formalin|| +|preparations|FREEZE DRIED|Freeze-dried|| +|preparations|GLYCERIN|Glycerin|| +|preparations|GUM ARABIC|Gum arabic|| +|preparations|MICROSCOPIC PREPARATION|Microscopic preparation|| +|preparations|MOUNTED|Mounted|| +|preparations|NO TREATMENT|No treatment|| +|preparations|OTHER|Other|| +|preparations|PINNED|Pinned|| +|preparations|REFRIGERATED|Refrigerated|| +|samplingProtocol|ACOUSTIC RECORDING|An acoustic recorder is a device that emits a soundwave at a range of frequencies, and are used to detect and monitor biodiversity in a given area.|| +|samplingProtocol|ANIMAL CARCASS (WHOLE)|Refers to the fauna observation method, i.e., any observations made on a carcass (whole), i.e., dead and or decaying animal., Refers to the type of voucher specimen sample, i.e., an animal carcass (full/complete).|| +|samplingProtocol|ANIMAL DIGGINGS|The type of evidence of a pest animal presence in the form of 'diggings'.|| +|samplingProtocol|ANIMAL GUT (WITHIN)|Animal gut is the portions of the alimentary canal, particularly the stomach and the intestines.|| +|samplingProtocol|ANIMAL HAIR/FUR|Animal fur are densely packed hairs on the skin of mammals.|| +|samplingProtocol|ANIMAL PELLET|Pellets are fecal droppings of animals such as goat, rats, rabbits, wombats, etc., and are often used as a sign/evidence of the presence of the species in the environment.|| +|samplingProtocol|ANIMAL SKIN|Skin is the outermost protective layer and the largest organ covering the body of vertebrate animal.|| +|samplingProtocol|ANIMAL TRACKING (STATELLITE)|A method of tracking the movements of fauna species facilitated by the assistance from satellite (i.e., imagery for example).|| +|samplingProtocol|ANIMAL TRACKS|Animal tracks are signs in the form of marks or imprints left behind on soil, ground or any related surface indicating the presence of a fauna species., Refers to the fauna observation method, i.e., any signs of a fauna detected from observations of tracks.|| +|samplingProtocol|BONE/TEETH|Bones/teeth are non-perishable remains of mammals that are often divided into skeleton (bones) and dentition (teeth).|| +|samplingProtocol|BURROW|A burrow is a hole or tunnel excavated into the ground by an animal to create a space suitable for habitation, temporary refuge, or as a byproduct of locomotion., Burrow is a small tunnel or a hole made by certain ground-dwelling mammals as a place of refuge., Refers to the microhabitat where the targeted fauna was observed. A burrow is a hole or tunnel excavated into the ground by an animal to create a space suitable for habitation, temporary refuge, or as a byproduct of locomotion.|| +|samplingProtocol|CAGE TRAP|A cage trap is a trap made of metal or galvanised mesh, normally used for trapping mammals., The equipment/method used during a passive, 'targeted fauna survey'. A cage trap is a trap made of metal or galvanised mesh and used in trapping mammals.|| +|samplingProtocol|DNA|DNA, or deoxyribonucleic acid, is the hereditary material in almost all living organisms that carries the genetic instructions used in growth, development, functioning, and reproduction. It consists of two long chains of nucleotides twisted into a double helix, with sequences of four types of nitrogen bases (adenine, thymine, cytosine, and guanine) that encode genetic information.|| +|samplingProtocol|EDNA|Environment DNA (eDNA) are the DNA that contains genetic information of living organisms representing a specific environmental and is usually sourced from soil, water, etc. , Refers to the method of identification of Vertebrate fauna. Taxon is identified using DNA sequencing techniques from environmental samples (eDNA).|| +|samplingProtocol|EGGS/EGGSHELL|An animal egg, or ovum, is the female reproductive cell (gamete) in many animals and vay in shape, size and structure. Egg shells are outer protctive layer that surrounds the egg of many animals. The animal eggs/egg shells here represent particular life stage of animal and often used as a sign/evidence to detect their presence in its habitat.|| +|samplingProtocol|ELLIOTT TRAP|The equipment/method used during a passive, 'fauna survey'. Elliott trapping is a technique used to trap small to medium sized mammals. The are usually hinged design that allows trapping to be conducted by folding into a compact panel and easy transport to field locations and storage., The equipment/method used during a passive, 'targeted fauna survey'. Elliott trapping is a technique used to trap small to medium sized mammals. The are usually hinged design that allows trapping to be conducted by folding into a compact panel and easy transport to field locations and storage.|| +|samplingProtocol|EXOSKELETON|Exoskeleton is the outer rigid covering of an invertebrate fauna with its structural features generally intact.|| +|samplingProtocol|FEATHER|Feathers are light, upright epidermal outgrowths that form the external covering of the body of birds. Feathers include the smaller down feathers and the larger contour and flight feathers., Refers to the type of voucher specimen sample. Feathers are one of the epidermal growths that form the distinctive outer covering, or plumage, on birds.|| +|samplingProtocol|FOSSIL/SUBFOSSIL|Fossils are preserved remains of animal or plant parts, usually of a prehistoric origin. Whereas, a sub-fossil are remains (usually skeletal) of animals that are not ancient enough to qualify as a fossil.|| +|samplingProtocol|FUNNEL TRAP|The equipment/method used in a 'fauna survey'. Funnel trap is a trapping method used in trapping insects/invertebrates. Funnel traps are made of nested black funnels (up to as many as 12). Insects fall through the funnels to a cup that is filled with a preservative., The equipment/method used in a 'targeted fauna survey'. Funnel trap is a trapping method used in trapping insects/invertebrates. Funnel traps are made of nested black funnels (up to as many as 12). Insects fall through the funnels to a cup that is filled with a preservative.|| +|samplingProtocol|GPS TRACKING|Geospatial tracking devices are portable units designed to monitor and track location. They use satellite navigation to determine movement and establish geographic positions.|| +|samplingProtocol|HAIR TUBE|Hair Tubes are short sections of PVC pipe lined with pieces of double-sided sticky-tape and useful to obtain hair/fur samples of animals., Refers to the targeted fauna observation method, i.e., any observations on a fauna made using 'Hair Tubes', which are short sections of PVC pipe lined with pieces of double-sided sticky-tape.|| +|samplingProtocol|HARP TRAP|Refers to the fauna observation method, i.e., any observations made on a fauna captured in a 'Harp trap' (especially designed for bats). They are particularly useful in situations where bats in flight can be channeled through a natural funnel such as above a water course, a cave or mine entrance or a clear area within a forest.|| +|samplingProtocol|HEARD|The method of bird sighting in the form of calls, or acoustic signals., The method of fauna sighting in the form of calls, or acoustic signals.|| +|samplingProtocol|HUMAN OBSERVATION|An observation performed by a human.|| +|samplingProtocol|LIGHT TRAP|Light trapping is designed for collecting flying insects attracted to ultra violet light and is useful for sampling insect populations., The equipment/method used during a passive, 'targeted fauna survey'. Light trapping is designed for collecting flying insects attracted to ultra violet light and is useful for sampling insect populations.|| +|samplingProtocol|MALAISE TRAP|A Malaise trap is a type of insect trap primarily used to capture invertebrates. They are large, tent-like structure effective in capturing flying insects (e.g., members of Hymenoptera and Diptera)., Refers to the targeted fauna observation method, i.e., any observations on a fauna captured using a malaise trap. A Malaise trap is a type of insect trap primarily used to capture invertebrates. They are large, tent-like structure effective in capturing flying insects (e.g., members of Hymenoptera and Diptera).|| +|samplingProtocol|MIST NET|Refers to the fauna observation method, i.e., any observations on a fauna captured using mist nets. The net is made of a very fine diameter cord, which is almost invisible when set up and is often used to capture birds, because they fail to see it, and fly straight into it., Refers to the targeted fauna observation method, i.e., any observations on a fauna captured using mist nets. The net is made of a very fine diameter cord, which is almost invisible when set up and is often used to capture birds, because they fail to see it, and fly straight into it.|| +|samplingProtocol|NEST|A nest is a place of refuge to hold an animal's eggs or provide a place to live or raise offspring.|| +|samplingProtocol|NO STATED METHOD|Refers to NO recognised method of observation stated for a target fauna.|UNSPECIFIED| +|samplingProtocol|NONE|Refers to No observation method of a target fauna., Refers to the targeted fauna observation method, i.e., 'No' standard observation methods were applied.|| +|samplingProtocol|OBSERVATION METHOD - AFTER CALL PLAYBACK|After call playback, is a method used for fauna observations (usually birds) and involves pre-recorded call playback to detect the presence of a target species in the survey area.|| +|samplingProtocol|OBSERVATION METHOD - ANIMAL DEN|A den is a place of refuge for many mammals and are usually either buried deep underground or built by the animal to create a secret shelter., Refers to the microhabitat where the fauna was observed. A den is a place of refuge for many mammals and are usually either buried deep underground or built by the animal to create a secret shelter.|| +|samplingProtocol|OBSERVATION METHOD - ANIMAL ODOUR|Animal odour or pheromones are distinct secretions of animals, often used as a sign/evidence of their presence in its habitat., Refers to the type of fauna observation method, which involves detection of a fauna species via its odour or pheromones.|| +|samplingProtocol|OTHER (SPECIFY)|Other types of liquid preservative used to store invertebrate samples., Refers to the any Other type of substrate/s used for fauna signs-based observation., Represents any 'Other' categorical collection NOT listed in the given collection., Represents any 'other' categorical collection NOT listed.|| +|samplingProtocol|PAN TRAP|A pan trap is a type of insect trap primarily used to capture small invertebrates (e.g., members of Hymenoptera) and often used to sample the abundance and diversity of insects., Refers to the targeted fauna observation method, i.e., any observations made from fauna captures in a pan trap. A pan trap is a type of insect trap primarily used to capture small invertebrates (e.g., members of Hymenoptera) and often used to sample the abundance and diversity of insects., The type/method of invertebrate fauna sampling implemented. Pan trapping consists of small, coloured bowls placed on the ground, either filled with water and a small amount of dishwashing liquid for sampling over one day, or propylene glycol for sampling over a longer duration.|| +|samplingProtocol|PELLET (WITHIN)|Pellets are fecal droppings of animals such as goat, rats, rabbits, wombats, etc., and are often used as a sign/evidence of the presence of the species in the environment. 'Within pellet' here represents an observation method (tier-2) that involves searching for any signs/evidence of a fauna species within a scat.|| +|samplingProtocol|PITFALL TRAP|Refers to the fauna observation method, i.e., any observations made from fauna captures in a pitfall trap. A pitfall trap is a simple device used to catch small animals , particularly insects and other invertebrates , that spend most of their time on the ground., Refers to the targeted fauna observation method, i.e., any observations made from fauna captures in a pitfall trap. A pitfall trap is a simple device used to catch small animals , particularly insects and other invertebrates , that spend most of their time on the ground.|| +|samplingProtocol|RADIO TRACKING|Refers to the fauna observation method, i.e., any signs of a fauna with the assistance of radio tracking device/s.|| +|samplingProtocol|REMOTE CAMERA DEVICE|Remote camera device are special devices that can be programmed to capture media (picture, videos) in places where humans cannot be physically present, and can be controlled remotely over a wireless network.|| +|samplingProtocol|SCATS|Faeces/faecal pellets/dung/droppings of animals. Often individual or scattered pellets (e.g. rabbit), or clumped pellet groups (e.g. deer). Their deposition will be influenced by diet (wet diet often causes clumping of pellets) and their size can reflect age (adult/juvenile). Scat surveys provide an estimate of relative abundances suitable for both herbivores and predators.|| +|samplingProtocol|SCATS (WITHIN)|Scats are fecal droppings of animals and are often represented by most to mark their territory. 'Within scats' here represents an observation method (tier-2) that involves searching for any signs/evidence of a fauna species within a scat.|| +|samplingProtocol|SCENT PAD|Scent pads are specific pads that are used as lures duing fauna observations.|| +|samplingProtocol|SCRATCHINGS (ARBOREAL)|Refers to the fauna observation method, i.e., any signs of a fauna detected from observations of scratchings on a tree.|| +|samplingProtocol|SCRATCHINGS (GROUND)|Scratchings are common traits of certain mammals leaving scars on trees, rocks etc.|| +|samplingProtocol|SHELL|A shell is a hard, rigid outer layer, which has evolved in a very wide variety of different animals, including molluscs, crustaceans, turtles and tortoises.|| +|samplingProtocol|SIGHTING|An observation method made by direct sighting of fauna in its habitat.|| +|samplingProtocol|SPOTLIGHTING|Spotlighting technique is a method used for fauna observations during the night and assists surveyors target nocturnal animals, using off-road vehicles and high-powered lights, spotlights, lamps or flashlights.|| +|samplingProtocol|SWEEP NET|Sweep nets are usually used for capturing insects using a number of sweeps. The net is made of fine diameter mesh fitted to a metal handle to trap invertebrates in air., The equipment/method used during a passive, 'targeted fauna survey'. Sweep nets are usually used for capturing insects using a number of sweeps. The net is made of fine diameter mesh fitted to a metal handle to trap invertebrates in air.|| +|samplingProtocol|TRACKING PAD|A tracking pad is an artificial pad made of loose material (such as sand for example) that are used to study and observe animal tracks. These pads are often designed to be delpoyed in habitats where animal activity/movements are high., Refers to the type of substrate used for fauna signs-based observation. A tracking pad is an artificial pad made of loose material (such as sand for example) that are used to study animal tracks in a fauna survey.|| +|samplingProtocol|ULTRASONIC RECORDING DEVICE|Ultrasound recorders are devices that send high-frequency sound waves in the environment to create images or detect objects and movements within various mediums, such as a mammalian body or other environments. They are popular for wildlife monitoring, biodiversity surveys, habitat assessments and echolocation studies (e.g., bats).|| +|samplingProtocol|UNKNOWN|Refers to the fire history of the plot, unknown., Unknown (unable to be determined)., Unknown capture status., Unknown position., Unknown- unable to be determined., Unknown/unable to be determined.|| +|samplingProtocol|UNKNOWN TRAP TYPE|Refers to the fire history of the plot, unknown., Unknown (unable to be determined)., Unknown capture status., Unknown position., Unknown, unable to be determined., Unknown/unable to be determined.|| +|samplingProtocol|WALLOW|A wallow is a depression containing mud or shallow water, formed by wallowing of large mammals., Wallow is a depression containing mud or shallow water, formed by the wallowing of large mammals such as a buffallo for example.|| +|samplingProtocol|WATER SAMPLE|Water samples are representative samples of a given habitat that serve as a source to study the chemical composition and detect the presence of fauna species (DNA).|| +|samplingProtocol|WET PITFALL TRAP|Refers to the fauna observation method, i.e., any observations made from fauna captures using a wet pitfall trap.|| +|sequencingMethod|TBC|TBC|| +|sex|FEMALE|Female (♀) is the sex of an organism, or a part of an organism, which produces mobile ova (egg cells).|F, ♀| +|sex|HERMAPHRODITE|One organism having both male and female sexual characteristics and organs; at birth an unambiguous assignment of male or female cannot be made|ZWITTER| +|sex|MALE|Male (♂) refers to the sex of an organism, or part of an organism, which produces small mobile gametes, called spermatozoa.|M, ♂| +|sex|UNDETERMINED|If the sex of an organism can't be determined for some reason.|UNDET., UNKNOWN| +|taxonRank|CLASS|Class|| +|taxonRank|CULTIVAR|The epithet is usually output in single quotes and may contain multiple words, see ICBN §28. Examples: Taxus baccata 'Variegata', Juniperus ×pfitzeriana 'Wilhelm Pfitzer'; Magnolia 'Elizabeth' (= a hybrid, no species epithet).|| +|taxonRank|CULTIVAR GROUP|Cultivar group|GREX| +|taxonRank|FAMILY|Family|| +|taxonRank|FORM|Form|FORMA| +|taxonRank|GENUS|Genus|| +|taxonRank|INFORMAL|Informal|| +|taxonRank|INFRAGENERIC NAME|Used for any other unspecific rank below genera and above species.|| +|taxonRank|INFRAORDER|Infraorder|| +|taxonRank|INFRASPECIFIC NAME|Used for any other unspecific rank below genera and above species.|| +|taxonRank|INFRASUBSPECIFIC NAME|Used for any other unspecific rank below subspecies.|| +|taxonRank|KINGDOM|Kingdom|REGNUM| +|taxonRank|ORDER|Order|ALLIANCE| +|taxonRank|PHYLUM|Phylum|DIVISION| +|taxonRank|SECTION|Section within a genus. In Zoology a section sometimes refers to a group above family level, this is NOT meant|| +|taxonRank|SERIES|Series within a genus.|| +|taxonRank|SPECIES|Species|| +|taxonRank|SPECIES AGGREGATE|A loosely defined group of species. Zoology: 'Aggregate - a group of species, other than a subgenus, within a genus. An aggregate may be denoted by a group name interpolated in parentheses.' -- The Berlin/MoreTax model notes:'[these] aren't taxonomic ranks but circumscriptions because on the one hand they are necessary for the concatenation of the fullname and on the other hand they are necessary for distinguishing the aggregate or species group from the microspecies.' Compare subspecific aggregate for a group of subspecies within a species.|AGGREGATE, SPECIES GROUP, SPECIES COMPLEX| +|taxonRank|SUBFAMILY|Subfamily|| +|taxonRank|SUBFORM|Subform|SUBFORMA| +|taxonRank|SUBGENUS|Subgenus|| +|taxonRank|SUBKINGDOM|Subkingdom|| +|taxonRank|SUBORDER|Suborder|| +|taxonRank|SUBSECTION|Subsection within a genus.|| +|taxonRank|SUBSERIES|Subseries within a genus.|| +|taxonRank|SUBSPECIES|Subspecies|| +|taxonRank|SUBSPECIFIC AGGREGATE|A loosely defined group of subspecies. Zoology:'Aggregate - a group of subspecies within a species. An aggregate may be denoted by a group name interpolated in parentheses.'|| +|taxonRank|SUBTRIBE|Subtribe|| +|taxonRank|SUBVARIETY|Subvariety|SUBVARIETAS| +|taxonRank|SUPERFAMILY|Superfamily|| +|taxonRank|SUPRAGENERIC NAME|Used for any other unspecific rank above genera.|| +|taxonRank|TRIBE|Tribe|| +|taxonRank|UNRANKED|Unranked|| +|taxonRank|VARIETY|Variety|VARIETAS| +|threatStatusCheckProtocol|UNSPECIFIED|Unspecified|| + + + +Table 2b: Suggested values for conditionally mandatory values for the threatStatus and +conservationJurisdiction in the template. State and Territory conservationJurisdictions spelt out +in words are also valid. For some threatStatus terms, alternative labels are provided that are also +valid for that conservationJurisdiction. + +|conservationJurisdiction|threatStatus|threatStatus alternative labels| +|:---:|:---|:---| +|ACT|CRITICALLY ENDANGERED|| +|ACT|ENDANGERED|| +|ACT|EXTINCT|| +|ACT|EXTINCT IN THE WILD|| +|ACT|REGIONALLY CONSERVATION DEPENDENT|| +|ACT|VULNERABLE|| +|EPBC|CAMBA|| +|EPBC|CD|CONSERVATION DEPENDENT| +|EPBC|CE|CRITICALLY ENDANGERED, CR| +|EPBC|CITES|| +|EPBC|E|EN, ENDANGERED| +|EPBC|EX|EXTINCT| +|EPBC|JAMBA|| +|EPBC|KAMBA|| +|EPBC|V|VULNERABLE, VU| +|EPBC|XW|EXTINCT IN THE WILD, EW| +|NSW|CE|CRITICALLY ENDANGERED| +|NSW|EN|ENDANGERED| +|NSW|EX|EXTINCT| +|NSW|V|VULNERABLE| +|NT|CE|CRITICALLY ENDANGERED| +|NT|DD|DATA DEFICIENT| +|NT|EN|ENDANGERED| +|NT|EN EXTINCT IN NT|ENDANGERED EXTINCT IN NT| +|NT|EN EXTINCT IN WILD IN NT|ENDANGERED EXTINCT IN WILD IN NT| +|NT|EW|CRITICALLY ENDANGERED POSSIBLY EXTINCT| +|NT|EX|EXTINCT| +|NT|LC|LEAST CONCERN| +|NT|LC EXTINCT IN NT|LEAST CONCERN EXTINCT IN NT| +|NT|NE|NOT EVALUATED| +|NT|NT|NEAR THREATENED| +|NT|VU|VULNERABLE| +|NT|VU EXTINCT IN NT|VULNERABLE EXTINCT IN NT| +|QLD|C|LEAST CONCERN WILDLIFE| +|QLD|CR|CRITICALLY ENDANGERED WILDLIFE| +|QLD|E|ENDANGERED WILDLIFE| +|QLD|EX|EXTINCT WILDLIFE| +|QLD|I|INTERNATIONAL WILDLIFE| +|QLD|NT|NEAR THREATENED WILDLIFE| +|QLD|PE|EXTINCT IN THE WILD WILDLIFE| +|QLD|SL|SPECIAL LEAST CONCERN WILDLIFE| +|QLD|V|VULNERABLE WILDLIFE| +|SA|E|ENDANGERED| +|SA|R|RARE| +|SA|SP|INDICATES THAT A RATING HAS BEEN APPLIED TO THE SPECIES LEVEL THE STATUS HAS NOT BEEN ASSESSED AT THE SUBSPECIES LEVEL| +|SA|SSP|INDICATES THAT AT LEAST ONE SUBSPECIES FOR THIS SPECIES HAS BEEN GIVEN A CONSERVATION RATING| +|SA|V|VULNERABLE| +|TAS|E|ENDANGERED| +|TAS|R|RARE| +|TAS|V|VULNERABLE| +|TAS|X|EXTINCT| +|VIC|CONSERVATION DEPENDENT|| +|VIC|CRITICALLY ENDANGERED|| +|VIC|ENDANGERED|| +|VIC|ENDANGERED EXTINCT IN VICTORIA|| +|VIC|EXTINCT|| +|VIC|EXTINCT IN THE WILD|| +|VIC|RESTRICTED|| +|VIC|VULNERABLE|| +|WA|CD|CONSERVATION DEPENDENT, SPECIES OF SPECIAL CONSERVATION INTEREST CONSERVATION DEPENDENT FAUNA| +|WA|CR|CRITICALLY ENDANGERED, CRITICALLY ENDANGERED SPECIES| +|WA|EN|ENDANGERED, ENDANGERED SPECIES| +|WA|EW|EXTINCT IN THE WILD| +|WA|EX|EXTINCT SPECIES, EXTINCT| +|WA|MI|MIGRATORY, MIGRATORY SPECIES| +|WA|OS|OTHER SPECIFICALLY PROTECTED FAUNA| +|WA|P1|PRIORITY 1 POORLY KNOWN, PRIORITY 1 POORLY KNOWN SPECIES| +|WA|P2|PRIORITY 2 POORLY KNOWN SPECIES, PRIORITY 2 POORLY KNOWN| +|WA|P3|PRIORITY 3 POORLY KNOWN SPECIES, PRIORITY 3 POORLY KNOWN| +|WA|P4|PRIORITY 4 RARE NEAR THREATENED AND OTHER SPECIES IN NEED OF MONITORING| +|WA|SPECIALLY PROTECTED|SPECIALLY PROTECTED SPECIES| +|WA|T|THREATENED, THREATENED SPECIES| +|WA|VU|VULNERABLE, VULNERABLE SPECIES| + + +### APPENDIX-II: Timestamp +Following date and date-time formats are acceptable within the timestamp: + +| TYPE | FORMAT | +| --- |-------------------------------------------------------------------------------------------------------------------------------------| +| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| +| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | +| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | +| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | +| **xsd:gYear** | yyyy | + +Where:
+  yyyy = four-digit year
+  mm = two-digit month (01=January, etc.)
+  dd = two-digit day of month (01 through 31)
+  hh = two digits of hour (00 through 23) (am/pm NOT allowed)
+  mm = two digits of minute (00 through 59)
+  ss = two digits of second (00 through 59)
+ + +### APPENDIX-III: UTF-8 +UTF-8 encoding is considered a best practice for handling character encoding, especially in +the context of web development, data exchange, and modern software systems. UTF-8 +(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of +encoding all possible characters (code points) in Unicode.
+Here are some reasons why UTF-8 is recommended:**Universal Character Support:** UTF-8 +can represent almost all characters from all writing systems in use today. This includes +characters from various languages, mathematical symbols, and other special characters. + +- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American +Standard Code for Information Interchange). The first 128 characters in UTF-8 are +identical to ASCII, making it easy to work with systems that use ASCII. +- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English +and many other languages). It uses one byte for ASCII characters and up to four +bytes for other characters. This variable-length encoding minimises storage and +bandwidth requirements. +- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is +widely supported by browsers, servers, and web-related technologies. +- **Globalisation:** As software applications become more globalised, supporting a wide +range of languages and scripts becomes crucial. UTF-8 is well-suited for +internationalisation and multilingual support. +- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many +programming languages, databases, and operating systems. Choosing UTF-8 helps +ensure compatibility across different platforms and technologies. + +When working with text data, it's generally a good idea to use UTF-8 encoding to avoid +issues related to character representation and ensure that your software can handle a +diverse set of characters and languages. + +For assistance, please contact: + + diff --git a/docs/pages/archived_templates/survey_metadata-v1.0.0.csv.md b/docs/pages/archived_templates/survey_metadata-v1.0.0.csv.md new file mode 100644 index 00000000..1a492aba --- /dev/null +++ b/docs/pages/archived_templates/survey_metadata-v1.0.0.csv.md @@ -0,0 +1,325 @@ +--- +title: Systematic Survey Metadata Template - v1.0.0 + - Archived + +summary: A template for systematic survey metadata +--- + +**survey_metadata** v1.0.0 + + + +!!! failure "Template Archived" + + This Template is archived, and is no longer available for use. + + +# SYSTEMATIC SURVEY METADATA TEMPLATE INSTRUCTIONS + +## Intended Usage +Use the Systematic Survey Metadata template to record metadata relating to a Systematic Survey dataset. + +The Systematic Survey Metadata template must be used in combination with the Systematic +Survey Occurrence template, and in some cases the Systematic Survey Site template. + +Templates have been provided to facilitate integration of your data into the Biodiversity +Data Repository database. Not all types of data have been catered for in the available +templates at this stage; therefore, if you are unable to find a suitable template, please +contact to make us aware of your data needs. + +#### Data Validation Requirements: +For data validation, you will need your data file to: + +- be the correct **file format**, +- have **fields that match the template downloaded** (do not remove, or + change the order of fields), +- have extant values for **mandatory fields** (see Table 1), and +- comply with all **data value constraints**; for example the geographic coordinates are + consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***5*** available + options. + +Additional fields may be added **after the templated fields** (noting that the data type +is not assumed and values will be encoded as strings). + +### FILE FORMAT +- The systematic survey metadata template is a [UTF-8](#appendix-iv-utf-8) encoded csv (not Microsoft +Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as +follows, otherwise it will not pass the in-browser csv validation step upon upload. +
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > +Unicode (UTF-8)]` +- **Do not include empty rows.** + +#### FILE SIZE +MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the +header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character +limit on individual cells in a spreadsheet. These limits may be overcome by using or +editing CSV files with other software. + +Larger datasets may be more readily ingested using the API interface. Please contact + to make us aware of your data needs. + +## TEMPLATE FIELDS +The template file contains the field names in the top row that form part of the core Survey +data model. Table 1 will assist you in transferring your data to the template with the following +information: + +- **Field name** in the template (and an external link to the Darwin Core standard for that +field where available); +- **Description** of the field; +- **Required** i.e. whether the field is **mandatory, +conditionally mandatory, or optional**; +- **Datatype format** required for the data values for example text (string), number +(integer, float), or date; and +- **Example/s** of an entry for that field. +- **Vocabulary links** within this document (for example pick list values) where relevant. +The fields that have suggested values options for the fields in Table 1 are listed in +Table 2 in alphabetical order of field name. + +### ADDITIONAL FIELDS +Data that do not match the existing template fields may be added as additional columns in +the CSV files after the templated fields. +For example, `sampleSizeUnit`, `sampleSizeValue`. + +Table 1: Systematic Survey Metadata template fields with descriptions, conditions, +datatype format, and examples. + +|Field #|Name|Description|Mandatory / Optional|Datatype Format|Examples| +|:---:|:---|:---|:---:|:---:|:---| +|1|surveyID|The identifier for the survey. Important if more there is more than one survey a the project.|Optional|String|COL1| +|2|surveyName|Brief title for the survey.|**Mandatory**|String|Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits - Summer| +|3|surveyPurpose|A description of the survey objective|Optional|String|Summer sampling for peak insect diversity.| +|4|surveyType|Description of type of survey conducted|Optional|String|Wet pitfall trapping
([Vocabulary link](#surveyType-vocabularies))| +|5|surveyStart|The date data collection commenced.|**Mandatory**|Timestamp|21/09/2020| +|6|surveyEnd|The date data collection was completed.|Optional|Timestamp|23/09/2020| +|7|targetTaxonomicScope|The range of biological taxa covered by the survey. Multiple terms are allowed, separated by a vertical bar aka pipe \||Optional|List|Coleoptera \| Formicidae
([Vocabulary link](#targetTaxonomicScope-vocabularies))| +|8|targetHabitatScope|The habitats targeted for sampling during the survey. Multiple terms are allowed, separated by a vertical bar aka pipe \||Optional|List|Woodland
([Vocabulary link](#targetHabitatScope-vocabularies))| +|9|spatialCoverageWKT|Well Known Text (WKT) expression of the geographic coordinates that describe the survey's spatial extent.|**Conditionally mandatory with geodeticDatum**|WKT|POLYGON ((146.363 -33.826, 148.499 -33.826, 148.499 -34.411, 146.363 -33.826))
([WKT notes](#appendix-ii-well-known-text-wkt))| +|10|[geodeticDatum](https://dwc.tdwg.org/terms/#dwc:geodeticDatum)|The geodetic datum upon which the geographic coordinates in the Spatial coverage (WKT) are based.|**Conditionally mandatory with spatialCoverageWKT**|String|GDA2020
([Vocabulary link](#geodeticDatum-vocabularies))| +|11|surveyOrgs|Name of organisations or individuals for whom Survey is being conducted. Multiple terms are allowed, separated by a vertical bar aka pipe \||Optional|List|NSW Department of Planning, Industry and Environment \| CSIRO| +|12|samplingPerformedBy|Similar to eco:samplingPerformedBy. Individual/s that carried out the survey. These can be represented by identifiers. Multiple values allare allowed, separated by a vertical bar aka pipe \||Optional|List|https://orcid.org/0000-0003-1092-9705 \| https://orcid.org/0009-0004-5278-4238| +|13|surveyMethodCitation|A citation or reference to the survey methods used.|Optional|List|Ng, K., Barton, P.S., Blanchard, W. et al. Disentangling the effects of farmland use, habitat edges, and vegetation structure on ground beetle morphological traits. Oecologia 188, 645–657 (2018). https://doi.org/10.1007/s00442-018-4180-9| +|14|surveyMethodDescription|Free text description of the survey method used.|Optional|String|Our experimental design consisted of four 400 m transects running from inside each woodland patch out into four adjoining farmland uses (crop, rested, woody debris application, revegetation plantings). To quantify potential edge efects on beetle species traits, we sampled beetles at five locations along each transect: 200 and 20 m inside woodlands, 200 and 20 m inside farmlands, and at the woodland–farmland edge (0 m). Each sampling location comprised a pair of wet invertebrate pitfall traps. separated by a drift fence (60 cm long x 10 cm high) to help direct arthropods into traps. We opened a total of 220 pairs of traps for 14 days during spring (Oct–Nov 2014), and repeated sampling during summer (January–February 2015). Beetle samples from each pitfall trap pair, and across the two time periods, were pooled to provide one sample per sampling location.| +|15|surveyMethodURL|A DOI or link to the reference about the survey method, if available.|Optional|List|https://biocollect.ala.org.au/document/download/2022-01/202201%20CBR%20Flora%20and%20Vegetation%20report_draftv1.pdf \| https://doi.org/10.1002/9781118945568.ch11| +|16|samplingEffortValue|Similar to eco:samplingEffortValue. The total sampling effort value. A samplingEffortValue must have a corresponding samplingEffortUnit|**Conditionally mandatory with samplingEffortUnit**|String|20 x 12| +|17|samplingEffortUnit|Similar to eco:samplingEffortUnit. The units associated with samplingEffortValue.|**Conditionally mandatory with samplingEffortValue**|String|trapDays
([Vocabulary link](#samplingEffortUnit-vocabularies))| +|18|keywords|Terms, phrases or descriptors that highlight the key attributes of the study. Multiple terms are allowed, separated by a vertical bar aka pipe \||Optional|List|ground beetle \| habitat \| morphology \| traits \| farmland \| woodland \| remnant vegetation \| split-plot study| + + +## APPENDICES +### APPENDIX-I: VOCABULARY LIST +With the exception of `geodeticDatum`, data validation +does not require adherence to the vocabularies for the various vocabularied fields.. These vocabularies are provided as a +means of assistance in developing consistent language within the database. New terms can be added +to more appropriately describe your data that goes beyond the current list. + +Table 2 provides some +suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), +[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information +System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity +era](https://doi.org/10.1111/2041-210X.12594). + +Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has +a preferred label with a definition to aid understanding of its meaning. For some terms, alternative +labels with similar semantics are provided.
Note: the value for `geodeticDatum` +must come from one of five options in this table.
+ +|Template field name|Preferred label|Definition|Alternate label| +|:---|:---|:---|:---| +|geodeticDatum|AGD66|Australian Geodetic Datum 1966|EPSG:4202| +|geodeticDatum|AGD84|Australian Geodetic Datum 1984|EPSG:4203| +|geodeticDatum|GDA2020|Geocentric Datum of Australia 2020|EPSG:7844| +|geodeticDatum|GDA94|Geocentric Datum of Australia 1994|EPSG:4283| +|geodeticDatum|WGS84|World Geodetic System 1984, used in GPS|EPSG:4326| +|samplingEffortUnit|Hectares|The total area surveyed or sampled, measured in hectares.|| +|samplingEffortUnit|Hours|The total time spent actively surveying using the specified protocol, expressed in hours.|| +|samplingEffortUnit|Metre Hours|The distance (metres) and time (hours) of specific survey activities such as walking or transect surveys (measure of effort across both space and time).|| +|samplingEffortUnit|Metres|A measure of linear distance, to describe the length of transects or areas covered.|| +|samplingEffortUnit|Minutes|The total time spent actively surveying using the specified protocol, expressed in minutes.|| +|samplingEffortUnit|Person Hours|The cumulative amount of time spent by individuals conducting the survey using the specified protocol. For example, if two people survey for 2 hours each, the total would be 4 person-hours.|| +|samplingEffortUnit|Trap Nights|The total number of nights traps are left in the field. One trap night refers to one trap set for one night.|| +|samplingEffortUnit|kHz|The frequency of sound is measured in kilohertz, for acoustic monitoring.|| +|surveyType|WET PITFALL TRAPPING|The type/method of invertebrate fauna sampling implemented. Wet pitfall trapping consists of a grid of 20 traps (specimen containers), dug into the ground so they are flush with the soil surface, and partially filled with a liquid preservative to rapidly kill the invertebrates that fall in. The trap grid is established anywhere within the plot, consisting of 4 north-south rows of 5 traps, spaced 10 m apart.|| +|targetHabitatScope|BEACH|Type of Landform Element, which is usually short; low; very wide slope; gently or moderately inclined; built up or eroded by waves; forming the shore of a lake or sea.|| +|targetHabitatScope|BILLABONG OR SWAMP|A swamp is a wetland that features temporary or permanent inundation of large areas of land by shallow bodies of water, generally with a substantial number of hammocks, or dry-land protrusions, and covered by aquatic vegetation, or vegetation that tolerates periodical inundation.|| +|targetHabitatScope|CAVE|The type of habitat representative of a naturally formed, subterranean open area or chamber.|| +|targetHabitatScope|CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Chenopodiaceae.|| +|targetHabitatScope|CLOSED CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Chenopodiaceae.|| +|targetHabitatScope|CLOSED FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Fern and Fern-allies.|| +|targetHabitatScope|CLOSED FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|targetHabitatScope|CLOSED FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|targetHabitatScope|CLOSED HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of heath shrubs (e.g., members of Ericaceae, Myrtaceae).|| +|targetHabitatScope|CLOSED HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of hummock (e.g., Triodia) grasses.|| +|targetHabitatScope|CLOSED LICHENLAND|Refers to the type of habitat characterised by lichenised tree trunks and rocks.|| +|targetHabitatScope|CLOSED LIVERWORTLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|targetHabitatScope|CLOSED MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tree mallee (e.g., some members of Eucalyptus).|| +|targetHabitatScope|CLOSED MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of mallee shrubs (e.g., some members of Eucalyptus).|| +|targetHabitatScope|CLOSED MOSSLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|targetHabitatScope|CLOSED RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Rushes (e.g., Juncaceae).|| +|targetHabitatScope|CLOSED SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|targetHabitatScope|CLOSED SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|targetHabitatScope|CLOSED SOD GRASSLAND|Refers to the type of habitat representative of a characteristic sod-like (turf) grass.|| +|targetHabitatScope|CLOSED TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tussock grasses (e.g., Poa).|| +|targetHabitatScope|CLOSED VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|targetHabitatScope|COASTAL WATERS|Refers to the type of habitat representative of an aquatic body typically characterized by a shallow continental shelf, gently sloping seaward to a continental slope, which drops relatively abruptly to the deep ocean.|| +|targetHabitatScope|CROP LAND|Refers to the type of habitat representative of a cultivated land or land on which agricultural crops are grown or land that is set aside or temporarily not being used for crop production.|| +|targetHabitatScope|ESTUARY|Type of Landform Element which has a stream channel close to its junction with a sea or lake; where the action of channelled stream flow is modified by tide and waves. The width typically increases downstream.|| +|targetHabitatScope|FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Fern and Fern-allies.|| +|targetHabitatScope|FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Forbs or herbaceous plants other than grasses.|| +|targetHabitatScope|FRESHWATER LAKE|Refers to the type of habitat representative of an enclosed aquatic body having a relatively low mineral content, generally less than 500 mg/l of dissolved solids.|| +|targetHabitatScope|GRAZING LAND|Refers to the type of habitat representative of a land predominantly used for grazing.|| +|targetHabitatScope|HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Heath (e.g., Ericaceae, Myrtaceae).|| +|targetHabitatScope|HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of hummock grasses (e.g., Triodia).|| +|targetHabitatScope|ISOLATED CHENOPOD SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% members of Chenopodiaceae.|| +|targetHabitatScope|ISOLATED CLUMP OF CHENOPOD SHRUBS|Refers to the type of habitat characterised by isolated clumps of chenopod shrubs.|| +|targetHabitatScope|ISOLATED CLUMP OF HEATH SHRUBS|Refers to the type of habitat characterised by isolated clumps of heath or heath-like shrubs.|| +|targetHabitatScope|ISOLATED CLUMP OF HUMMOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of hummocky grass (e.g., Triodia spp., Spinifex spp.).|| +|targetHabitatScope|ISOLATED CLUMP OF LIVERWORTS|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|targetHabitatScope|ISOLATED CLUMP OF MALLEE SHRUBS|Refers to the type of habitat characterised by isolated clumps of mallee shrubs (members of Eucalyptus spp., multistemmed from base).|| +|targetHabitatScope|ISOLATED CLUMP OF MALLEE TREES|Refers to the type of habitat characterised by isolated clumps of tree mallee (members of Eucalyptus spp., multistemmed from base).|| +|targetHabitatScope|ISOLATED CLUMP OF MOSSES|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|targetHabitatScope|ISOLATED CLUMP OF RUSHES|Refers to the type of habitat characterised by isolated clumps of rushes.|| +|targetHabitatScope|ISOLATED CLUMP OF SEDGES|Refers to the type of habitat characterised by isolated clumps of sedges.|| +|targetHabitatScope|ISOLATED CLUMP OF SHRUBS|Refers to the type of habitat characterised by isolated clumps of shrubs.|| +|targetHabitatScope|ISOLATED CLUMP OF SOD GRASSES|Refers to the type of habitat characterised by isolated clumps of sod grass.|| +|targetHabitatScope|ISOLATED CLUMP OF TREES|Refers to the type of habitat characterised by isolated clumps of trees.|| +|targetHabitatScope|ISOLATED CLUMP OF TUSSOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of tussock grasses (e.g., Poa spp).|| +|targetHabitatScope|ISOLATED CLUMP OF VINES|Refers to the type of habitat characterised by isolated clumps of vines.|| +|targetHabitatScope|ISOLATED CLUMPS OF FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Fern and Fern-allies.|| +|targetHabitatScope|ISOLATED CLUMPS OF FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Forbs or herbs other than grasses.|| +|targetHabitatScope|ISOLATED CLUP OF LICHENS|Refers to the type of habitat characterised by isolated clumps of lichens.|| +|targetHabitatScope|ISOLATED FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of fern and fern allies.|| +|targetHabitatScope|ISOLATED FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of forbs or herbs other than grasses.|| +|targetHabitatScope|ISOLATED HEATH SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of heath shrubs (e.g., Ericaceae, Myrtaceae).|| +|targetHabitatScope|ISOLATED HUMMOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of hummock grasses (e.g., Triodia).|| +|targetHabitatScope|ISOLATED LICHENS|Refers to the type of habitat characterised by isolated or sparse lichens.|| +|targetHabitatScope|ISOLATED LIVERWORTS|Refers to the type of habitat characterised by isolated or sparse liverworts.|| +|targetHabitatScope|ISOLATED MALLEE SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of mallee shrubs (e.g., some multistemmed individuals from base of Eucalyptus).|| +|targetHabitatScope|ISOLATED MALLEE TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tree mallee (e.g., some multistemmed individuals from base of Eucalyptus).|| +|targetHabitatScope|ISOLATED MOSSES|Refers to the type of habitat characterised by isolated mosses, including bryophytes and liverworts.|| +|targetHabitatScope|ISOLATED RUSHES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of rushes (e.g., Juncaceae).|| +|targetHabitatScope|ISOLATED SEDGES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of sedges (e.g., Cyperaceae).|| +|targetHabitatScope|ISOLATED SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of shrubs including cycads, grass-tree and tree-fern.|| +|targetHabitatScope|ISOLATED SOD GRASSES|Refers to the type of habitat characterised by isolated or sparse sod or turf-like grasses.|| +|targetHabitatScope|ISOLATED TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of trees including palms.|| +|targetHabitatScope|ISOLATED TUSSOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tussock grass (e.g. Poa species).|| +|targetHabitatScope|ISOLATED VINES|Refers to the type of habitat characterised by isolated or sparse stragglers or climbing woody vines.|| +|targetHabitatScope|LICHENLAND|Refers to the type of habitat predominated by lichens on rocks, trees or tree stumps, etc.|| +|targetHabitatScope|LIVERWORTLAND|Refers to the type of habitat predominated by liverworts.|| +|targetHabitatScope|MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrub mallee (e.g., individuals of some Eucalypts multistemmed from base).|| +|targetHabitatScope|MALLEE WOODLAND|Refers to the dominant vegetation structural formation, with a percent cover of about 20-50% of Tree Mallee.|| +|targetHabitatScope|MOSSLAND|Refers to the type of habitat dominated by mosses.|| +|targetHabitatScope|MUDFLAT|Refers to the type of habitat characterised by a wetland that forms when mud is deposited by the tides, rivers, sea or oceans.|| +|targetHabitatScope|OPEN CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of members of Chenopodiaceae.|| +|targetHabitatScope|OPEN FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of ferns and fern allies.|| +|targetHabitatScope|OPEN FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of forbs or herbs other than grasses.|| +|targetHabitatScope|OPEN FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of trees including palms.|| +|targetHabitatScope|OPEN HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of heaths (e.g., Ericaceae, Myrtaceae).|| +|targetHabitatScope|OPEN HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of hummock grasses (e.g., Triodia).|| +|targetHabitatScope|OPEN LICHENLAND|Refers to the type of habitat represented by open or sparse (i.e., 10-30%) hummocky grasses (e.g., Spinifex spp., Triodia spp.).|| +|targetHabitatScope|OPEN LIVERWORTLAND|Refers to the type of habitat characterised by open or sparse lichenised tree trunks and rocks.|| +|targetHabitatScope|OPEN MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tree Mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|targetHabitatScope|OPEN MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of Mallee shrubs (e.g., certain individuals of Eucalypts multistemmed from base).|| +|targetHabitatScope|OPEN MALLEE WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tree mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|targetHabitatScope|OPEN MOSSLAND|Refers to the type of habitat characterised by open or sparse members of lower plant groups such as moss, liverworts and bryophytes.|| +|targetHabitatScope|OPEN OCEAN|Refers to the type of habitat surrounded by ocean, i.e., a continuous saline-water bodies that surround the continents and fill the Earth's great depressions.|| +|targetHabitatScope|OPEN RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of rushes (e.g. Juncaceae).|| +|targetHabitatScope|OPEN SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of sedges (e.g. Cyperaceae).|| +|targetHabitatScope|OPEN SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of shrubs (e.g. shrubs, cycads, grass-tree, tree-fern).|| +|targetHabitatScope|OPEN SOD GRASSLAND|Refers to the type of habitat characterised by open or sparse (10-30% ground cover) of a characteristic sod-like (turf) grass.|| +|targetHabitatScope|OPEN TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of tussock grasses (e.g. Poa species).|| +|targetHabitatScope|OPEN VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|targetHabitatScope|OPEN WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of trees including palms.|| +|targetHabitatScope|ROCK OUTCROP|Refers to the type of habitat characterised by rocks, which protrudes through the surface layer.|| +|targetHabitatScope|RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of rushes (e.g. Juncaceae).|| +|targetHabitatScope|SALTWATER LAKE|Refers to the type of habitat representative of an aquatic body filled with water (with high salinity) of considerable size contained in a depression on a landmass.|| +|targetHabitatScope|SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of sedges (e.g., Cyperaceae).|| +|targetHabitatScope|SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrubs (e.g., shrub, cycad, grass-tree, tree-fern).|| +|targetHabitatScope|SOD GRASSLAND|Refers to the type of habitat characterised by mid-dense (30-70% cover) sod or turf-like grasses.|| +|targetHabitatScope|SPARSE CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of Chenopodiaceae.|| +|targetHabitatScope|SPARSE FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of fern and fern-allies.|| +|targetHabitatScope|SPARSE FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of forbs and herbs other than grasses.|| +|targetHabitatScope|SPARSE GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of grasses.|| +|targetHabitatScope|SPARSE HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of heath (e.g., Ericaceae, Myrtaceae).|| +|targetHabitatScope|SPARSE LICHENLAND|Refers to the type of habitat characterised by very sparse (<10% cover) lichens.|| +|targetHabitatScope|SPARSE LIVERWORTLAND|Refers to the type of habitat characterised by very sparse (<10% cover) liverworts.|| +|targetHabitatScope|SPARSE MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of shrub Mallee.|| +|targetHabitatScope|SPARSE MOSSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) mosses.|| +|targetHabitatScope|SPARSE RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of rushes (e.g., Juncaceae).|| +|targetHabitatScope|SPARSE SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of sedges (e.g., Cyperaceae).|| +|targetHabitatScope|SPARSE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of shrubs, including cycad, grass-tree, tree-fern.|| +|targetHabitatScope|SPARSE SOD GRASSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) sod or turf-like grasses.|| +|targetHabitatScope|SPARSE TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tussock grass (e.g., Poa species).|| +|targetHabitatScope|SPARSE VINELAND|Refers to the type of habitat characterised by well separated or very sparse crown stragglers or woody vines.|| +|targetHabitatScope|STREAM OR RIVER|Refers to the type of habitat representative of an aquatic body with a watercourse which is linear and flows across the solid portion of a planetary surface.|| +|targetHabitatScope|TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tussock grass (e.g., Poa species).|| +|targetHabitatScope|URBAN|Refers to the type of habitat relating to, located in, or characteristic of a city or densely populated area.|| +|targetHabitatScope|VINELAND|Refers to the type of habitat characterised by woody climbers/straggling vines.|| +|targetHabitatScope|WOODLAND|Refers to the type of habitat characterised by a low-density forest forming open habitats with plenty of sunlight and limited shade.|| +|targetTaxonomicScope|AMPHIBIAN|Refers to the target taxa studied in a fauna survey. Amphibians are vertebrates belonging to the class amphibia such as frogs, toads, newts and salamanders that live in a semi-aquatic environment.|| +|targetTaxonomicScope|BIRD|Refers to the target taxa studied in a fauna survey.Warm-blooded vertebrates possessing feather and belonging to the class Aves.|| +|targetTaxonomicScope|INVERTEBRATE|Refers to the target taxa studied in a fauna survey.Animals that have no spinal column (e.g., insects, molluscs, spiders).|| +|targetTaxonomicScope|MAMMALS|Refers to the target taxa studied in a fauna survey. Warm-blooded vertebrate animals belonging to the class Mammalia, including all that possess hair and suckle their young. Warm-blooded vertebrate animals belonging to the class Mammalia, including all that possess hair and suckle their young.|| +|targetTaxonomicScope|NON-VASCULAR PLANT|Refers to the target taxa studied in a fauna survey. Non-vascular plants are plants that do not possess a true vascular tissue (such as xylem-water conducting, phloem-sugar transport). Instead, they may possess simpler tissues that have specialized functions for the internal transport of food and water. They are members of bryophytes for example.|| +|targetTaxonomicScope|REPTILE|Refers to the target taxa studied in a fauna survey.Cold-blooded, air-breathing Vertebrates belonging to the class Reptilia, usually covered with external scales or bony plates.|| +|targetTaxonomicScope|VASCULAR PLANT|Refers to the target taxa studied in a fauna survey. Vascular plants are plants that possess a true vascular tissue (such as xylem-water conducting, phloem-sugar transport). Examples include some members mosses, such as club moss, horsetails, and pteridophytes such as ferns an fern-allies, gymnosperms (including conifers), and angiosperms (flowering plants).|| + + +### APPENDIX-II: Well Known Text (WKT) +For general information on how WKT coordinate reference data is formatted is available [here](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). +The length of a WKT string or of its components is not prescribed; however, MS Excel *does* has a +32,767 (32K) character limit on individual cells in a spreadsheet. + +It is possible to edit CSV files outside of Excel in order to include more than 32K characters. + +![Multipart geometries (2D) WKT](../assets/multipart_geometries_2d_wkt.png) +
*Source: Mwtoews - CC BY-SA 3.0 - Wikipedia *
+ +### APPENDIX-III: Timestamp +Following date and date-time formats are acceptable within the timestamp: + +| TYPE | FORMAT | +| --- |-------------------------------------------------------------------------------------------------------------------------------------| +| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| +| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | +| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | +| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | +| **xsd:gYear** | yyyy | + +Where:
+  `yyyy`: four-digit year
+  `mm`: two-digit month (01=January, etc.)
+  `dd`: two-digit day of month (01 through 31)
+  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
+  `mm`: two digits of minute (00 through 59)
+  `ss`: two digits of second (00 through 59)
+ +### APPENDIX-IV: UTF-8 +UTF-8 encoding is considered a best practice for handling character encoding, especially in +the context of web development, data exchange, and modern software systems. UTF-8 +(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of +encoding all possible characters (code points) in Unicode.
+Here are some reasons why UTF-8 is recommended: +- **Universal Character Support:** UTF-8 can represent almost all characters from all writing + systems in use today. This includes characters from various languages, mathematical symbols, + and other special characters. +- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American + Standard Code for Information Interchange). The first 128 characters in UTF-8 are + identical to ASCII, making it easy to work with systems that use ASCII. +- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English + and many other languages). It uses one byte for ASCII characters and up to four + bytes for other characters. This variable-length encoding minimises storage and + bandwidth requirements. +- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is + widely supported by browsers, servers, and web-related technologies. +- **Globalisation:** As software applications become more globalised, supporting a wide + range of languages and scripts becomes crucial. UTF-8 is well-suited for + internationalisation and multilingual support. +- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many + programming languages, databases, and operating systems. Choosing UTF-8 helps + ensure compatibility across different platforms and technologies. + +When working with text data, UTF-8 encoding is recommended to avoid issues related to character +representation and ensure that a diverse set of characters and languages is supported. + +For assistance, please contact: + diff --git a/docs/pages/archived_templates/survey_occurrence_data-v1.0.0.csv.md b/docs/pages/archived_templates/survey_occurrence_data-v1.0.0.csv.md new file mode 100644 index 00000000..63c42c6d --- /dev/null +++ b/docs/pages/archived_templates/survey_occurrence_data-v1.0.0.csv.md @@ -0,0 +1,470 @@ +--- +title: Systematic Survey Occurrence Data Template - v1.0.0 + - Archived + +summary: A template to translate some Darwin Core fields +--- + +**survey_occurrence_data** v1.0.0 + + + +!!! failure "Template Archived" + + This Template is archived, and is no longer available for use. + + +# SYSTEMATIC SURVEY OCCURRENCES DATA TEMPLATE INSTRUCTIONS + +## Intended Usage +This template is used to record occurrence data; that is, the presence or absence of an organism +at a particular site locality at a point in time. + +The Systematic Survey Occurrences template **must be used in combination** with the +Systematic Survey Metadata template, and in some cases the Systematic Survey Sites +template. + +Templates have been provided to facilitate integration of your data into the Biodiversity +Data Repository database. Not all types of data have been catered for in the available +templates at this stage; therefore, if you are unable to find a suitable template, please +contact to make us aware of your data needs. + +#### Data Validation Requirements: +For data validation, you will need your data file to: + +- be in the correct **file format,** +- have **fields that match the template downloaded** (do not remove, or + change the order of fields), +- have extant values for **mandatory fields** (see Table 1), +- comply with all **data value constraints**; for example the geographic coordinates are + consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the ***5*** available + options, and +- align with existing controlled [vocabularies](#appendix-i-vocabulary-list) wherever possible (this is mandatory + for geodeticDatum), but new terms may be submitted for consideration amd will not cause a + validation error. + +Additional fields may be added **after the templated fields** (noting that the data type +is not assumed and values will be encoded as strings). + +### FILE FORMAT +- The systematic survey occurrence data template is a [UTF-8](#appendix-iii-utf-8) encoded csv (that is, not Microsoft + Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8): +
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > + Unicode (UTF-8)]`
+ otherwise it will not pass the csv validation step upon upload. +- **Do not include empty rows**. + +#### FILE SIZE +MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the +header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767-character +limit on individual cells in a spreadsheet. These limits may be overcome by using or +editing CSV files with other software. + +Larger datasets may be more readily ingested using the API interface. Please contact + to make us aware of your data needs. + +## TEMPLATE FIELDS +The template contains the field names in the top row. Table 1 will assist you in transferring +your data to the template by providing guidance on: + +- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) + for that field where relevant); +- **Description** of the field; +- **Required** i.e. whether the field is **mandatory, +conditionally mandatory, or optional**; +- **Format** (datatype) required for the data values for example text (string), number + (integer, float), or date; +- **Example** of an entry or entries for that field; and +- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where + relevant. The fields that have suggested values options for the fields in Table 1 are + listed in Table 2 in alphabetical order of the field name. + +### ADDITIONAL FIELDS +Data that does not match the existing template fields may be added as +additional columns in the CSV files after the templated fields. +For example: `eventRemarks`, `associatedTaxa`, `pathway`. + +Table 1: Systematic Survey Occurrence data template fields with descriptions, conditions, +datatype format, and examples. + +|Field #|Name|Description|Mandatory / Optional|Datatype Format|Examples| +|:---:|:---|:---|:---:|:---:|:---| +|1|providerRecordID|Unique (within provider) identifier for the record.|**Mandatory**|String|8022FSJMJ079c5cf| +|2|providerRecordIDSource|Person or Organisation that generated the providerRecordID. For providers registered with the BDR, this field should contain your BDR registrationID. Populate only if the details are different from the dataset submission details.|**Mandatory**|String|Western Australian Biodiversity Information Office| +|3|[locality](https://dwc.tdwg.org/terms/#dwc:locality)|The specific description of the place.|Optional|String|Cowaramup Bay Road| +|4|[decimalLatitude](https://dwc.tdwg.org/terms/#dwc:decimalLatitude)|The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are north of the Equator, negative values are south of it. Valid coordinate ranges for the BDR system are within and inclusive of -90 to 0.|**Mandatory**|Number|-33.812314| +|5|[decimalLongitude](https://dwc.tdwg.org/terms/#dwc:decimalLongitude)|The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic centre of a Location. Positive values are east of the Greenwich Meridian, negative values are west of it. Valid coordinate ranges for the BDR system are within and inclusive of 0 to 180.|**Mandatory**|Number|115.231512| +|6|[geodeticDatum](https://dwc.tdwg.org/terms/#dwc:geodeticDatum)|The acronym for the ellipsoid, geodetic datum, or spatial reference system (SRS) upon which the geographic (non-projected) coordinates given in decimalLatitude and decimalLongitude as based.|**Mandatory**|String|WGS84
([Vocabulary link](#geodeticDatum-vocabularies))| +|7|[coordinateUncertaintyInMeters](https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters)|The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Location. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.|Optional|Number|50.0| +|8|[dataGeneralizations](https://dwc.tdwg.org/terms/#dwciri:dataGeneralizations)|Actions taken to make the shared data less specific or complete than in its original form, due to restrictions around identifying locations of particular species. Suggests that alternative data of higher quality may be available on request.|Optional|String|Coordinates rounded to the nearest 10 km for conservation concern| +|9|[eventDate](https://dwc.tdwg.org/terms/#dwc:eventDate)|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T06:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) during which a species occurrence was observed. For occurrences, this is the date-time when the event was recorded. Not suitable for a time in a geological context.|**Mandatory**|Timestamp|2019-09-23T14:03+08:00| +|10|[samplingProtocol](https://dwc.tdwg.org/terms/#dwciri:samplingProtocol)|The sampling protocol is the method used to sample the locality to determine the presence (or absence) of the taxon referred to in this record at the indicated time. This may be a collecting method or a method to observe an organism without collection.
Recommended best practice is to describe a species occurrence with no more than one sampling protocol. In the case of a summary, in which a specific protocol can not be attributed to specific species occurrences, the recommended best practice is to repeat the property for each IRI that denotes a different sampling protocol that applies to the occurrence.|Optional|String|Human Observation
([Vocabulary link](#samplingProtocol-vocabularies))| +|11|[basisOfRecord](https://dwc.tdwg.org/terms/#dwc:basisOfRecord)|The specific nature of the data record.|Optional|String|Preserved Specimen
([Vocabulary link](#basisOfRecord-vocabularies))| +|12|[recordedBy](https://dwc.tdwg.org/terms/#dwciri:recordedBy)|A person, group, or organisation responsible for recording the original Occurrence.|Optional|String|Stream Environment and Water Pty Ltd| +|13|[recordNumber](http://rs.tdwg.org/dwc/terms/recordNumber)|An identifier given to the Occurrence at the time it was recorded. Often serves as a link between field notes and an Occurrence record, such as a specimen collector's number.|Optional|String|PE:12:8832| +|14|[occurrenceStatus](https://dwc.tdwg.org/terms/#dwc:occurrenceStatus)|A statement about the presence or absence of a Taxon at a Location.|Optional|String|Present
([Vocabulary link](#occurrenceStatus-vocabularies))| +|15|[habitat](http://rs.tdwg.org/dwc/terms/habitat)|A category or description of the habitat in which the event occurred.|Optional|String|Closed forest of Melaleuca lanceolata. White, grey or brown sand, sandy loam.| +|16|[establishmentMeans](https://dwc.tdwg.org/terms/#dwc:establishmentMeans)|Statement about whether an organism or organisms have been introduced to a given place and time through the direct or indirect activity of modern humans.|Optional|String|Native
([Vocabulary link](#establishmentMeans-vocabularies))| +|17|[organismRemarks](http://rs.tdwg.org/dwc/terms/organismRemarks)|Comments or notes about the Organism instance.|Optional|String|Dried out leaf tips.| +|18|[individualCount](https://dwc.tdwg.org/terms/#dwc:individualCount)|The number of individuals present at the time of the Occurrence. 0 = none, no value = the specific number was not recorded.|Optional|Integer|26| +|19|[organismQuantity](https://dwc.tdwg.org/list/#dwc_organismQuantity)|A number or enumeration value for the quantity of organisms.|**Conditionally mandatory with organismQuantityType**|Number|12.5| +|20|[organismQuantityType](https://dwc.tdwg.org/list/#dwc_organismQuantityType)|The type of quantification system used for the quantity organisms.|**Conditionally mandatory with organismQuantity**|String|% biomass
([Vocabulary link](#organismQuantityType-vocabularies))| +|21|[lifeStage](http://rs.tdwg.org/dwc/terms/lifeStage)|The age class or life stage of the Organism(s) at the time the Occurrence was recorded.|Optional|String|adult
([Vocabulary link](#lifeStage-vocabularies))| +|22|[sex](https://dwc.tdwg.org/terms/#dwciri:sex)|The sex of the biological individual(s) represented in the Occurrence.|Optional|String|Unspecified
([Vocabulary link](#sex-vocabularies))| +|23|[reproductiveCondition](https://dwc.tdwg.org/terms/#dwc:reproductiveCondition)|The reproductive condition of the biological individual(s) represented in the Occurrence.|Optional|String|No breeding evident| +|24|ownerRecordID|Identifier given to the occurrence by the owner of the data. Populate this field if the data owner is different to the data provider. Unique (within data owner) identifier for the record.|**Conditionally mandatory with ownerRecordIDSource**|String|12345NT521mc5h| +|25|ownerRecordIDSource|Person or Organisation that generated the ownerRecordID. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation who owns the data.|**Conditionally mandatory with ownerRecordID**|String|WAM| +|26|[collectionCode](https://dwc.tdwg.org/terms/#dwc:collectionCode)|The name, acronym, code, or initialism identifying the collection or data set from which the record was derived. It is associated with the catalogNumber.|Optional|String|ARACH| +|27|[catalogNumber](http://rs.tdwg.org/dwc/terms/catalogNumber)|An identifier (preferably unique) for the record within the data set or collection.|**Conditionally mandatory with catalogNumberSource**|String|145732, 145732a, 2008.1334, R-4313| +|28|catalogNumberSource|Organisation that generated the catalogNumber. In the BDR context, this is likely to be a collecting institution where a specimen or material sample is located. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.|**Conditionally mandatory with catalogNumber**|String|Western Australian Museum| +|29|[otherCatalogNumbers](http://rs.tdwg.org/dwc/terms/otherCatalogNumbers)|A list (concatenated and separated with a space vertical bar space ( \| )) of previous or alternate fully qualified catalog numbers or other human-used identifiers for the same Occurrence, whether in the current or any other data set or collection.|**Conditionally mandatory with otherCatalogNumbersSource**|List|BHP2012-7521 \| M12378| +|30|otherCatalogNumbersSource|Organisation that generated the otherCatalogNumbers. For organisations registered with the BDR, this field should contain the BDR registrationID. For all others, please provide the name of Person or Organisation.|**Conditionally mandatory with otherCatalogNumbers**|String|University of Western Australia| +|31|[preparations](http://rs.tdwg.org/dwc/terms/preparations)|A list (concatenated and separated with a space vertical bar space ( \| )) of preparations and preservation methods for a specimen.|Optional|String|alcohol
([Vocabulary link](#preparations-vocabularies))| +|32|preparedDate|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) representing the date or date-time the specimen was prepared.|Optional|Timestamp|2019-09-24| +|33|[associatedSequences](http://rs.tdwg.org/dwc/terms/associatedSequences)|A list (concatenated and separated with a space vertical bar space ( \| )) of identifiers (publication, global unique identifier, URI) of genetic sequence information associated with the Occurrence.|Optional|List|https://www.ncbi.nlm.nih.gov/nuccore/MH040669.1 \| https://www.ncbi.nlm.nih.gov/nuccore/MH040616.1| +|34|sequencingMethod|The method used to obtain sequence data for example DNA, RNA, or protein from the sample.|Optional|String|Sanger-dideoxy-sequencing
([Vocabulary link](#sequencingMethod-vocabularies))| +|35|[verbatimIdentification](https://dwc.tdwg.org/terms/#dwc:verbatimIdentification)|A string representing the taxonomic identification as it appeared in the original record. This term is meant to allow the capture of an unaltered original identification/determination, including identification qualifiers, hybrid formulas, uncertainties, etc. This term is meant to be used in addition to scientificName (and identificationQualifier etc.), not instead of it.|Optional|String|Caladenia ?excelsa| +|36|[dateIdentified](http://rs.tdwg.org/dwc/terms/dateIdentified)|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which the subject was determined as representing the Taxon.|Optional|Timestamp|2019-09-24| +|37|[identifiedBy](http://rs.tdwg.org/dwc/terms/identifiedBy)|Group of names, organisations who assigned the Taxon to the subject. For multiple names, use the pipe separator ( \| ).|Optional|String|J. Doe \| WAM| +|38|identificationMethod|Method used to associate the organism with the scientificName label.|Optional|String|DNA
([Vocabulary link](#identificationMethod-vocabularies))| +|39|[scientificName](http://rs.tdwg.org/dwc/terms/scientificName)|The full scientific name, with authorship and date information if known. When forming part of an Identification, this should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the identificationQualifier column.
NOTE: Phrase names such as Rhagodia sp. Hamersley (M.Trudgen 17794) are permitted in the scientificName field where those are in use.|**Mandatory**|String|Caladenia excelsa| +|40|[identificationQualifier](https://dwc.tdwg.org/terms/#dwc:identificationQualifier)|A brief phrase or a standard term ("cf.", "aff.") to express the determiner's doubts about the Identification.|Optional|String|Species incerta
([Vocabulary link](#identificationQualifier-vocabularies))| +|41|[identificationRemarks](http://rs.tdwg.org/dwc/terms/identificationRemarks)|Comments or notes about the Identification.|Optional|String|DNA evidence may indicate a new species. Further analysis required.| +|42|[acceptedNameUsage](https://dwc.tdwg.org/terms/#dwc:acceptedNameUsage)|The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) taxon.|Optional|String|Occiperipatoides gilesii (Spencer, 1909)| +|43|[kingdom](https://dwc.tdwg.org/terms/#dwc:kingdom)|The full scientific name of the kingdom in which the taxon is classified.|**Mandatory**|String|Plantae
([Vocabulary link](#kingdom-vocabularies))| +|44|[taxonRank](http://rs.tdwg.org/dwc/terms/verbatimTaxonRank)|The taxonomic rank of the most specific name in the scientificName.|Optional|String|Species
([Vocabulary link](#taxonRank-vocabularies))| +|45|threatStatus|The conservation status (or code) assigned to an organism that is recognised in conjunction with a specific jurisdiction.|**Conditionally mandatory with conservationJurisdiction**|String|EN
([Vocabulary link](#threatStatus-vocabularies))| +|46|conservationJurisdiction|The jurisdiction under which an organism is recognised to have a specific conservation status applied.|**Conditionally mandatory with threatStatus**|String|EPBC, WA
([Vocabulary link](#conservationJurisdiction-vocabularies))| +|47|threatStatusCheckProtocol|The method used to determine if the organism is listed under the relevant jurisdictional threatened species list.|Optional|String|Species name check of the Department of Climate Change, Energy, the Environment and Water’s Species Profile and Threat Database http://www.environment.gov.au/cgi-bin/sprat/public/sprat.pl
([Vocabulary link](#threatStatusCheckProtocol-vocabularies))| +|48|threatStatusDateDetermined|The date (with precision of year (YYYY), month year (YYYY-MM) or date in the following formats DD/MM/YYYY or YYYY-MM-DD are accepted) or date-time without timezone (in ISO 8601 format for example 2021-07-11T11:23:00) or date-time with timezone(in ISO 8601 format for example 2022-05-20T06:23:00+08:00) on which this record of this organism was assigned to the nominated threatStatus and conservationJurisdiction|Optional|Timestamp|30/08/2022| +|49|threatStatusDeterminedBy|The person and/organisation responsible for appending the threatStatus and conservationJurisdiction to this organism’s occurrence record.|Optional|String|WA-BIO| +|50|siteID|Corresponds to a unique site identifier, provided within accompanying survey_site_data.csv template.|Optional|String|P1| +|51|surveyID|The identifier of the Survey that the occurrence comes from. This field should be completed if it is ambiguous as to which survey the occurrence belongs to.|Optional|String|AR220-01| + + +## APPENDICES +### APPENDIX-I: VOCABULARY LIST +With the exception of `geodeticDatum`, data validation does not require fields to adhere to the +vocabularies specified for the various vocabularied fields. These vocabularies are merely provided as a +means of assistance in developing a consistent language within the database. New terms may be added +to more appropriately describe your data that goes beyond the current list. Table 2 provides some +suggested values from existing sources such as: [Biodiversity Information Standard (TDWG)](https://dwc.tdwg.org/), +[EPSG.io Coordinate systems worldwide](https://epsg.io/), the [Global Biodiversity Information +System](https://rs.gbif.org/), and [Open Nomenclature in the biodiversity +era](https://doi.org/10.1111/2041-210X.12594). + +Table 2: Suggested values for the controlled vocabulary fields in the template. Each term has +a preferred label with a definition to aid understanding of its meaning. For some terms, alternative +labels with similar semantics are provided. Note: `geodeticDatum` value +**must** come from one of five options in this table. + + + +|Template field name|Preferred label|Definition|Alternate label| +|:---|:---|:---|:---| +|basisOfRecord|FOSSIL SPECIMEN|A preserved specimen that is a fossil.|| +|basisOfRecord|HUMAN OBSERVATION|An output of a human observation.|| +|basisOfRecord|LIVING SPECIMEN|A specimen that is alive.|| +|basisOfRecord|MACHINE OBSERVATION|An output of a machine observation process.|| +|basisOfRecord|MATERIAL SAMPLE|A physical result of a sampling (or subsampling) event. In biological collections, the material sample is typically collected, and either preserved or destructively processed.|| +|basisOfRecord|OCCURRENCE|An existence of an Organism (sensu http://rs.tdwg.org/dwc/terms/Organism) at a particular place at a particular time.|| +|basisOfRecord|PRESERVED SPECIMEN|A specimen that has been preserved.|| +|establishmentMeans|INTRODUCED|Establishment of a taxon by numan agency into an area that is not part of its natural range.|| +|establishmentMeans|INTRODUCED ASSISTED COLONISATION|Establishment of a taxon specifically with the intention of creating a self-sustaining wild population in an area that is not part of the taxon's natural range.|ASSISTED COLONISATION| +|establishmentMeans|NATIVE|A taxon occurring within its natural range.|NATIVE (INDIGENOUS)| +|establishmentMeans|NATIVE REINTRODUCED|A taxon re-established by direct introduction by humans into an area that is not part of its natural range, but from where it had become extinct.|NATIVE: REINTRODUCED| +|establishmentMeans|UNCERTAIN|The origin of the occurrence of the taxon in an area is obscure.|UNKNOWN, CRYPTOGENIC| +|establishmentMeans|VAGRANT|The temporary occurrence of a taxon far outside its natural or migratory range.|CASUAL| +|geodeticDatum|AGD66|Australian Geodetic Datum 1966|EPSG:4202| +|geodeticDatum|AGD84|Australian Geodetic Datum 1984|EPSG:4203| +|geodeticDatum|GDA2020|Geocentric Datum of Australia 2020|EPSG:7844| +|geodeticDatum|GDA94|Geocentric Datum of Australia 1994|EPSG:4283| +|geodeticDatum|WGS84|World Geodetic System 1984, used in GPS|EPSG:4326| +|identificationMethod|TBC|TBC|| +|identificationQualifier|ANIMALIA CETERA|It groups all the unidentified specimens that are not listed as separate taxa. The term cetera (abbreviated c. or cet.) may be applied to a given high-rank taxon, meaning that identification at a lower taxonomic level has not been attempted (see also stetit) but explicitly not including subordinate taxa that may have been identified.|A.C.| +|identificationQualifier|CONFER|"Compare with". Specimens should be compared to reference material, since most of the diagnostic characters correspond to a given species but some are unclear. Also used in the sense of affinis and species incerta (these usages are discouraged).|CF., CFR., CONF., SP. CF.| +|identificationQualifier|EX GREGE|"Of the group including". The specimen has some affinity to a known species or it belongs to a species group or species complex; see also affinis and species proxima.|EX GR., GR.| +|identificationQualifier|FAMILIA GENUS SPECIES|The specimen has not been attributed to any known species nor family; see also species.|FAM. GEN. SP.| +|identificationQualifier|GENUS ET SPECIES NOVA|The specimen is considered to belong to a new species and a new genus; for more details, see species nova.|GEN. ET SP., GEN. NOV., SP. NOV., NOV. GEN. ET SP.| +|identificationQualifier|GENUS NOVUM|The specimen is considered to belong to a new species and a new genus; for more details, see species nova|GEN. NOV., G. NOV., GEN. N., G. N., NOV. GEN| +|identificationQualifier|GENUS SPECIES|The specimen has not been related to any known species nor genus; also species.|GEN. SP., G. SP.| +|identificationQualifier|SPECIES|The specimen has not been identified, nor it has been related to any known species; the uncertainty is potentially provisional: it could be due to the lack of suitable dichotomous keys, or to the occurrence of a species not previously described. Also used in the sense of species indeterminabilis and stetit (these usages are discouraged.|SP| +|identificationQualifier|SPECIES AFFINIS|"Has affinity with". The specimen has some affinity to a known species but it is not identical to it; it generally implies distinction more than a possible identity, in contrast with the qualifier confer; see also species Proxima and ex grege. It is often used in combination with the ON qualifier species nova. Also used in the sense of confer (this usage is discouraged).|AFF., SP. AFF.| +|identificationQualifier|SPECIES INCERTA|The identification is uncertain; it usually indicates a higher reliability with ?, sp. Inc respect to confer. The sign "sp. inc." is also used in the sense of species, species indeterminabilis and species inquirenda (these usages are discouraged).|SP. INC.| +|identificationQualifier|SPECIES INDETERMINABILIS|The specimen is indeterminable beyond a certain taxonomic level due to the deterioration or lack of diagnostic characters. Also used in the sense of species and stetit (these usages are discouraged.|INDET., IND., SP. INDET., SP. IND.| +|identificationQualifier|SPECIES NOVA|The specimen is considered to belong to a new, previously undescribed (1) When describing a new species, the use of the qualifier is required by the ICZN (1999) to explicitly indicate the taxa name as intentionally new. (2) Used as ON qualifier to refer to a new, still unnamed species before the formal publication of the description.|SP. NOV., SPEC. NOV., SP. N., NOV. SP., NOV. SPEC., N. SP.| +|identificationQualifier|SPECIES PROXIMA|The specimen is near to a known species but it is not identical to it; see also affinis and ex grege.|PROX., SP. PROX., NR., SP.NR.| +|identificationQualifier|STETIT|Identification at a lower taxonomic level has not been attempted, even if allowed by the sample conditions. It may also be used when more records with different ON qualifiers need to be merged at a safe taxonomic level.|STET.| +|identificationQualifier|SUBSPECIES|The only infraspecific rank regulated by the ICZN (1999). As ON qualifier, it indicates that the specimen probably belongs to a subspecies but it has not been related to any known one; see also species.|SSP., SUBSP.| +|kingdom|ANIMALIA|Kingdom Animalia|| +|kingdom|FUNGI|Kingdom (taxonRank: Regnum) Fungi|| +|kingdom|PLANTAE|Kingdom (taxonRank: Regnum) Plantae|PLANTAE HAECKEL| +|lifeStage|ADULT|An adult is a plant, animal, or person who has reached full growth or alternatively is capable of reproduction.|IMAGO| +|lifeStage|EMBRYO|An embryo is a multicellular diploid eukaryote in its earliest stage of development, from the time of first cell division until birth, hatching, or germination.|EGG, SEED| +|lifeStage|GAMETE|A gamete is a cell that fuses with another gamete during fertilisation in organisms that reproduce sexually. In species that produce two morphologically distinct types of gametes, and in which each individual produces only one type, a female is any individual that produces the larger type of gamete — called an ovum (or egg) — and a male produces the smaller tadpole-like type — called a sperm. This is an example of anisogamy or heterogamy, the condition wherein females and males produce gametes of different sizes. In contrast, isogamy is the state of gametes from both sexes being the same size and shape, and given arbitrary designators for mating type. Gametes carry half the genetic information of an individual, one chromosome of each type.|OVUM, SPERM, POLLEN| +|lifeStage|GAMETOPHYTE|In plants and algae that undergo alternation of generations, a gametophyte is the multicellular structure, or phase, that is haploid, containing a single set of chromosomes. The gametophyte produces male or female gametes (or both), by a process of cell division called mitosis. In mosses, liverworts and hornworts (bryophytes), the gametophyte is the commonly known phase of the plant. An early developmental stage in the gametophyte of mosses (immediately following germination of the meiospore) is called the protonema. In most other land plants the gametophyte is very small (as in ferns and their relatives) or even reduced as in flowering plants (angiosperms), where the female gametophyte (ovule) is known as a megagametophyte and the male gametophyte (pollen) is called a microgametophyte.|GAMONT, PROTONEMA, POLLEN, OVULE| +|lifeStage|JUVENILE|A juvenile is an individual organism that has not yet reached its adult form, sexual maturity or size. Juveniles sometimes look very different from the adult form, particularly in terms of their colour. In many organisms the juvenile has a different name from the adult.|SEEDLING, EFT, CALF, HATCHLING, INFANT, FOAL, KITTEN, KIT, CHICK, NYMPH, FAWN, WHELP, PUP, ELVER, FRY| +|lifeStage|LARVA|A larva (Latin; plural larvae) is a young (juvenile) form of animal with indirect development, going through or undergoing metamorphosis (for example, insects, amphibians, or cnidarians). The larva can look completely different from the adult form, for example, a caterpillar differs from a butterfly. Larvae often have special (larval) organs which do not occur in the adult form. The larvae of some species can become pubescent and not further develop into the adult form (for example, in some newts). This is a type of neoteny. It is a misunderstanding that the larval form always reflects the group's evolutionary history. It could be the case, but often the larval stage has evolved secondarily, as in insects. In these cases the larval form might differ more from the group's common origin than the adult form. The early life stages of most fish species are considerably different from juveniles and adults of their species and are called larvae.|LARVAE, TADPOLE, POLLIWOG, POLLYWOG, POLLIWIG, POLEWIG, POLWIG, PLANULA, NAUPLIUS, ZOEA, NYMPH, CATERPILLAR| +|lifeStage|PUPA|A pupa is the life stage of some insects undergoing transformation between immature and mature stages. The pupal stage is found only in holometabolous insects, those that undergo a complete metamorphosis, with four life stages: egg (-> embryo), larva, pupa, and imago (-> adult).|PUPPE| +|lifeStage|SPORE|A spore is a reproductive structure that is adapted for dispersal and surviving for extended periods of time in unfavorable conditions. Spores form part of the life cycles of many bacteria, plants, algae, fungi and some protozoans. A chief difference between spores and seeds as dispersal units is that spores have very little stored food resources compared with seeds. Spores are usually haploid and unicellular and are produced by meiosis in the sporangium by the sporophyte. Once conditions are favorable, the spore can develop into a new organism using mitotic division, producing a multicellular gametophyte, which eventually goes on to produce gametes. Many ferns, especially those adapted to dry conditions, produce diploid spores. In this case spores are the units of asexual reproduction, because a single spore develops into a new organism. By contrast, gametes are the units of sexual reproduction, as two gametes need to fuse to create a new organism.|| +|lifeStage|SPOROPHYTE|All land plants, and some algae, have life cycles in which a haploid gametophyte generation alternates with a diploid sporophyte, the generation of a plant or alga that has a double set of chromosomes. A multicellular sporophyte generation or phase is present in the life cycle of all land plants and in some green algae. For common flowering plants (Angiosperms), the sporophyte generation comprises almost their whole life cycle (that is whole green plant, roots etc), except phases of small reproductive structures (pollen and ovule).|AGAMONT| +|lifeStage|ZYGOTE|A zygote (or zygocyte) describes the first stage of a new unique organism blastomere when it consists of just a single cell. The term is also used more loosely to refer to the group of cells formed by the first few cell divisions, although this is properly referred to as a blastomere. A zygote is usually produced by a fertilisation event between two haploid cells - an ovum from a female and a sperm cell from a male - which combine to form the single diploid cell. Thus the zygote contains DNA originating from both mother and father and this provides all the genetic information necessary to form a new individual|BLASTOMERE| +|occurrenceStatus|ABSENT|The occurrence was not present at the location and time of the observation.|| +|occurrenceStatus|PRESENT|The occurrence was present at the location and time of the observation.|| +|organismQuantityType|BIOMASS AFDG|A measurement type where the quantity of a species in a sample is recorded as the ash free dry weight biomass in grams (g).|BIOMASS ASH FREE DRY WEIGHT IN GRAMS, BIOMASS ASH FREE DRY WEIGHT GRAMS| +|organismQuantityType|BIOMASS G|A measurement type where the quantity of a species in a sample is recorded as the biomass in grams (g).|BIOMASS IN GRAMS, BIOMASS GRAMS| +|organismQuantityType|BIOMASS KG|A measurement type where the quantity of a species in a sample is recorded as the biomass in kilograms (kg).|BIOMASS IN KILOGRAMS, BIOMASS KILOGRAMS| +|organismQuantityType|BIOVOLUME CUBIC MICRONS|A measurement type where the quantity of a species in a sample is recorded as the biovolume in cubic microns (µ ^ 3).|BIOVOLUME IN CUBIC MICRONS| +|organismQuantityType|BIOVOLUME ML|A measurement type where the quantity of a species in a sample is recorded as the biovolume in millilitres (ml).|BIOVOLUME IN MILLILITRES, BIOVOLUME MILLILITRES| +|organismQuantityType|BRAUN BLANQUET SCALE|A measurement type where the cover of a species in a sample is recorded using the Braun-Blanquet scale.|| +|organismQuantityType|DOMIN SCALE|A measurement type where the cover of a species in a sample is recorded using the Domin scale.|| +|organismQuantityType|INDIVIDUALS|A measurement type where the quantity of a species in a sample is recorded as the number of individuals (e.g.per litre, per square metre, per cubic metre, per hour, per day).|| +|organismQuantityType|PERCENTAGE COVERAGE|A measurement type where the quantity of a species in a sample is recorded as the percentage coverage of the total area being sampled.|% COVERAGE| +|organismQuantityType|PERCENTAGE OF BIOMASS|A measurement type where the quantity of a species in a sample is recorded as a percentage of the total biomass of all species.|% OF BIOMASS| +|organismQuantityType|PERCENTAGE OF BIOVOLUME|A measurement type where the quantity of a species in a sample is recorded as a percentage of the total biovolume of all species.|% OF BIOVOLUME| +|organismQuantityType|PERCENTAGE OF SPECIES|A measurement type where the quantity of a species in a sample is recorded as a percentage of the total individual count of all species.|% OF SPECIES| +|preparations|ALCOHOL|Alcohol|| +|preparations|DEEP FROZEN|Deep frozen|| +|preparations|DRIED|Dried|| +|preparations|DRIED AND PRESSED|Dried and pressed|| +|preparations|FORMALIN|Formalin|| +|preparations|FREEZE DRIED|Freeze-dried|| +|preparations|GLYCERIN|Glycerin|| +|preparations|GUM ARABIC|Gum arabic|| +|preparations|MICROSCOPIC PREPARATION|Microscopic preparation|| +|preparations|MOUNTED|Mounted|| +|preparations|NO TREATMENT|No treatment|| +|preparations|OTHER|Other|| +|preparations|PINNED|Pinned|| +|preparations|REFRIGERATED|Refrigerated|| +|samplingProtocol|ACOUSTIC RECORDING|An acoustic recorder is a device that emits a soundwave at a range of frequencies, and are used to detect and monitor biodiversity in a given area.|| +|samplingProtocol|ANIMAL CARCASS (WHOLE)|Refers to the fauna observation method, i.e., any observations made on a carcass (whole), i.e., dead and or decaying animal., Refers to the type of voucher specimen sample, i.e., an animal carcass (full/complete).|| +|samplingProtocol|ANIMAL DIGGINGS|The type of evidence of a pest animal presence in the form of 'diggings'.|| +|samplingProtocol|ANIMAL GUT (WITHIN)|Animal gut is the portions of the alimentary canal, particularly the stomach and the intestines.|| +|samplingProtocol|ANIMAL HAIR/FUR|Animal fur are densely packed hairs on the skin of mammals.|| +|samplingProtocol|ANIMAL PELLET|Pellets are fecal droppings of animals such as goat, rats, rabbits, wombats, etc., and are often used as a sign/evidence of the presence of the species in the environment.|| +|samplingProtocol|ANIMAL SKIN|Skin is the outermost protective layer and the largest organ covering the body of vertebrate animal.|| +|samplingProtocol|ANIMAL TRACKING (STATELLITE)|A method of tracking the movements of fauna species facilitated by the assistance from satellite (i.e., imagery for example).|| +|samplingProtocol|ANIMAL TRACKS|Animal tracks are signs in the form of marks or imprints left behind on soil, ground or any related surface indicating the presence of a fauna species., Refers to the fauna observation method, i.e., any signs of a fauna detected from observations of tracks.|| +|samplingProtocol|BONE/TEETH|Bones/teeth are non-perishable remains of mammals that are often divided into skeleton (bones) and dentition (teeth).|| +|samplingProtocol|BURROW|A burrow is a hole or tunnel excavated into the ground by an animal to create a space suitable for habitation, temporary refuge, or as a byproduct of locomotion., Burrow is a small tunnel or a hole made by certain ground-dwelling mammals as a place of refuge., Refers to the microhabitat where the targeted fauna was observed. A burrow is a hole or tunnel excavated into the ground by an animal to create a space suitable for habitation, temporary refuge, or as a byproduct of locomotion.|| +|samplingProtocol|CAGE TRAP|A cage trap is a trap made of metal or galvanised mesh, normally used for trapping mammals., The equipment/method used during a passive, 'targeted fauna survey'. A cage trap is a trap made of metal or galvanised mesh and used in trapping mammals.|| +|samplingProtocol|DNA|DNA, or deoxyribonucleic acid, is the hereditary material in almost all living organisms that carries the genetic instructions used in growth, development, functioning, and reproduction. It consists of two long chains of nucleotides twisted into a double helix, with sequences of four types of nitrogen bases (adenine, thymine, cytosine, and guanine) that encode genetic information.|| +|samplingProtocol|EDNA|Environment DNA (eDNA) are the DNA that contains genetic information of living organisms representing a specific environmental and is usually sourced from soil, water, etc. , Refers to the method of identification of Vertebrate fauna. Taxon is identified using DNA sequencing techniques from environmental samples (eDNA).|| +|samplingProtocol|EGGS/EGGSHELL|An animal egg, or ovum, is the female reproductive cell (gamete) in many animals and vay in shape, size and structure. Egg shells are outer protctive layer that surrounds the egg of many animals. The animal eggs/egg shells here represent particular life stage of animal and often used as a sign/evidence to detect their presence in its habitat.|| +|samplingProtocol|ELLIOTT TRAP|The equipment/method used during a passive, 'fauna survey'. Elliott trapping is a technique used to trap small to medium sized mammals. The are usually hinged design that allows trapping to be conducted by folding into a compact panel and easy transport to field locations and storage., The equipment/method used during a passive, 'targeted fauna survey'. Elliott trapping is a technique used to trap small to medium sized mammals. The are usually hinged design that allows trapping to be conducted by folding into a compact panel and easy transport to field locations and storage.|| +|samplingProtocol|EXOSKELETON|Exoskeleton is the outer rigid covering of an invertebrate fauna with its structural features generally intact.|| +|samplingProtocol|FEATHER|Feathers are light, upright epidermal outgrowths that form the external covering of the body of birds. Feathers include the smaller down feathers and the larger contour and flight feathers., Refers to the type of voucher specimen sample. Feathers are one of the epidermal growths that form the distinctive outer covering, or plumage, on birds.|| +|samplingProtocol|FOSSIL/SUBFOSSIL|Fossils are preserved remains of animal or plant parts, usually of a prehistoric origin. Whereas, a sub-fossil are remains (usually skeletal) of animals that are not ancient enough to qualify as a fossil.|| +|samplingProtocol|FUNNEL TRAP|The equipment/method used in a 'fauna survey'. Funnel trap is a trapping method used in trapping insects/invertebrates. Funnel traps are made of nested black funnels (up to as many as 12). Insects fall through the funnels to a cup that is filled with a preservative., The equipment/method used in a 'targeted fauna survey'. Funnel trap is a trapping method used in trapping insects/invertebrates. Funnel traps are made of nested black funnels (up to as many as 12). Insects fall through the funnels to a cup that is filled with a preservative.|| +|samplingProtocol|GPS TRACKING|Geospatial tracking devices are portable units designed to monitor and track location. They use satellite navigation to determine movement and establish geographic positions.|| +|samplingProtocol|HAIR TUBE|Hair Tubes are short sections of PVC pipe lined with pieces of double-sided sticky-tape and useful to obtain hair/fur samples of animals., Refers to the targeted fauna observation method, i.e., any observations on a fauna made using 'Hair Tubes', which are short sections of PVC pipe lined with pieces of double-sided sticky-tape.|| +|samplingProtocol|HARP TRAP|Refers to the fauna observation method, i.e., any observations made on a fauna captured in a 'Harp trap' (especially designed for bats). They are particularly useful in situations where bats in flight can be channeled through a natural funnel such as above a water course, a cave or mine entrance or a clear area within a forest.|| +|samplingProtocol|HEARD|The method of bird sighting in the form of calls, or acoustic signals., The method of fauna sighting in the form of calls, or acoustic signals.|| +|samplingProtocol|HUMAN OBSERVATION|An observation performed by a human.|| +|samplingProtocol|LIGHT TRAP|Light trapping is designed for collecting flying insects attracted to ultra violet light and is useful for sampling insect populations., The equipment/method used during a passive, 'targeted fauna survey'. Light trapping is designed for collecting flying insects attracted to ultra violet light and is useful for sampling insect populations.|| +|samplingProtocol|MALAISE TRAP|A Malaise trap is a type of insect trap primarily used to capture invertebrates. They are large, tent-like structure effective in capturing flying insects (e.g., members of Hymenoptera and Diptera)., Refers to the targeted fauna observation method, i.e., any observations on a fauna captured using a malaise trap. A Malaise trap is a type of insect trap primarily used to capture invertebrates. They are large, tent-like structure effective in capturing flying insects (e.g., members of Hymenoptera and Diptera).|| +|samplingProtocol|MIST NET|Refers to the fauna observation method, i.e., any observations on a fauna captured using mist nets. The net is made of a very fine diameter cord, which is almost invisible when set up and is often used to capture birds, because they fail to see it, and fly straight into it., Refers to the targeted fauna observation method, i.e., any observations on a fauna captured using mist nets. The net is made of a very fine diameter cord, which is almost invisible when set up and is often used to capture birds, because they fail to see it, and fly straight into it.|| +|samplingProtocol|NEST|A nest is a place of refuge to hold an animal's eggs or provide a place to live or raise offspring.|| +|samplingProtocol|NO STATED METHOD|Refers to NO recognised method of observation stated for a target fauna.|UNSPECIFIED| +|samplingProtocol|NONE|Refers to No observation method of a target fauna., Refers to the targeted fauna observation method, i.e., 'No' standard observation methods were applied.|| +|samplingProtocol|OBSERVATION METHOD - AFTER CALL PLAYBACK|After call playback, is a method used for fauna observations (usually birds) and involves pre-recorded call playback to detect the presence of a target species in the survey area.|| +|samplingProtocol|OBSERVATION METHOD - ANIMAL DEN|A den is a place of refuge for many mammals and are usually either buried deep underground or built by the animal to create a secret shelter., Refers to the microhabitat where the fauna was observed. A den is a place of refuge for many mammals and are usually either buried deep underground or built by the animal to create a secret shelter.|| +|samplingProtocol|OBSERVATION METHOD - ANIMAL ODOUR|Animal odour or pheromones are distinct secretions of animals, often used as a sign/evidence of their presence in its habitat., Refers to the type of fauna observation method, which involves detection of a fauna species via its odour or pheromones.|| +|samplingProtocol|OTHER (SPECIFY)|Other types of liquid preservative used to store invertebrate samples., Refers to the any Other type of substrate/s used for fauna signs-based observation., Represents any 'Other' categorical collection NOT listed in the given collection., Represents any 'other' categorical collection NOT listed.|| +|samplingProtocol|PAN TRAP|A pan trap is a type of insect trap primarily used to capture small invertebrates (e.g., members of Hymenoptera) and often used to sample the abundance and diversity of insects., Refers to the targeted fauna observation method, i.e., any observations made from fauna captures in a pan trap. A pan trap is a type of insect trap primarily used to capture small invertebrates (e.g., members of Hymenoptera) and often used to sample the abundance and diversity of insects., The type/method of invertebrate fauna sampling implemented. Pan trapping consists of small, coloured bowls placed on the ground, either filled with water and a small amount of dishwashing liquid for sampling over one day, or propylene glycol for sampling over a longer duration.|| +|samplingProtocol|PELLET (WITHIN)|Pellets are fecal droppings of animals such as goat, rats, rabbits, wombats, etc., and are often used as a sign/evidence of the presence of the species in the environment. 'Within pellet' here represents an observation method (tier-2) that involves searching for any signs/evidence of a fauna species within a scat.|| +|samplingProtocol|PITFALL TRAP|Refers to the fauna observation method, i.e., any observations made from fauna captures in a pitfall trap. A pitfall trap is a simple device used to catch small animals , particularly insects and other invertebrates , that spend most of their time on the ground., Refers to the targeted fauna observation method, i.e., any observations made from fauna captures in a pitfall trap. A pitfall trap is a simple device used to catch small animals , particularly insects and other invertebrates , that spend most of their time on the ground.|| +|samplingProtocol|RADIO TRACKING|Refers to the fauna observation method, i.e., any signs of a fauna with the assistance of radio tracking device/s.|| +|samplingProtocol|REMOTE CAMERA DEVICE|Remote camera device are special devices that can be programmed to capture media (picture, videos) in places where humans cannot be physically present, and can be controlled remotely over a wireless network.|| +|samplingProtocol|SCATS|Faeces/faecal pellets/dung/droppings of animals. Often individual or scattered pellets (e.g. rabbit), or clumped pellet groups (e.g. deer). Their deposition will be influenced by diet (wet diet often causes clumping of pellets) and their size can reflect age (adult/juvenile). Scat surveys provide an estimate of relative abundances suitable for both herbivores and predators.|| +|samplingProtocol|SCATS (WITHIN)|Scats are fecal droppings of animals and are often represented by most to mark their territory. 'Within scats' here represents an observation method (tier-2) that involves searching for any signs/evidence of a fauna species within a scat.|| +|samplingProtocol|SCENT PAD|Scent pads are specific pads that are used as lures duing fauna observations.|| +|samplingProtocol|SCRATCHINGS (ARBOREAL)|Refers to the fauna observation method, i.e., any signs of a fauna detected from observations of scratchings on a tree.|| +|samplingProtocol|SCRATCHINGS (GROUND)|Scratchings are common traits of certain mammals leaving scars on trees, rocks etc.|| +|samplingProtocol|SHELL|A shell is a hard, rigid outer layer, which has evolved in a very wide variety of different animals, including molluscs, crustaceans, turtles and tortoises.|| +|samplingProtocol|SIGHTING|An observation method made by direct sighting of fauna in its habitat.|| +|samplingProtocol|SPOTLIGHTING|Spotlighting technique is a method used for fauna observations during the night and assists surveyors target nocturnal animals, using off-road vehicles and high-powered lights, spotlights, lamps or flashlights.|| +|samplingProtocol|SWEEP NET|Sweep nets are usually used for capturing insects using a number of sweeps. The net is made of fine diameter mesh fitted to a metal handle to trap invertebrates in air., The equipment/method used during a passive, 'targeted fauna survey'. Sweep nets are usually used for capturing insects using a number of sweeps. The net is made of fine diameter mesh fitted to a metal handle to trap invertebrates in air.|| +|samplingProtocol|TRACKING PAD|A tracking pad is an artificial pad made of loose material (such as sand for example) that are used to study and observe animal tracks. These pads are often designed to be delpoyed in habitats where animal activity/movements are high., Refers to the type of substrate used for fauna signs-based observation. A tracking pad is an artificial pad made of loose material (such as sand for example) that are used to study animal tracks in a fauna survey.|| +|samplingProtocol|ULTRASONIC RECORDING DEVICE|Ultrasound recorders are devices that send high-frequency sound waves in the environment to create images or detect objects and movements within various mediums, such as a mammalian body or other environments. They are popular for wildlife monitoring, biodiversity surveys, habitat assessments and echolocation studies (e.g., bats).|| +|samplingProtocol|UNKNOWN|Refers to the fire history of the plot, unknown., Unknown (unable to be determined)., Unknown capture status., Unknown position., Unknown- unable to be determined., Unknown/unable to be determined.|| +|samplingProtocol|UNKNOWN TRAP TYPE|Refers to the fire history of the plot, unknown., Unknown (unable to be determined)., Unknown capture status., Unknown position., Unknown, unable to be determined., Unknown/unable to be determined.|| +|samplingProtocol|WALLOW|A wallow is a depression containing mud or shallow water, formed by wallowing of large mammals., Wallow is a depression containing mud or shallow water, formed by the wallowing of large mammals such as a buffallo for example.|| +|samplingProtocol|WATER SAMPLE|Water samples are representative samples of a given habitat that serve as a source to study the chemical composition and detect the presence of fauna species (DNA).|| +|samplingProtocol|WET PITFALL TRAP|Refers to the fauna observation method, i.e., any observations made from fauna captures using a wet pitfall trap.|| +|sequencingMethod|TBC|TBC|| +|sex|FEMALE|Female (♀) is the sex of an organism, or a part of an organism, which produces mobile ova (egg cells).|F, ♀| +|sex|HERMAPHRODITE|One organism having both male and female sexual characteristics and organs; at birth an unambiguous assignment of male or female cannot be made|ZWITTER| +|sex|MALE|Male (♂) refers to the sex of an organism, or part of an organism, which produces small mobile gametes, called spermatozoa.|M, ♂| +|sex|UNDETERMINED|If the sex of an organism can't be determined for some reason.|UNDET., UNKNOWN| +|taxonRank|CLASS|Class|| +|taxonRank|CULTIVAR|The epithet is usually output in single quotes and may contain multiple words, see ICBN §28. Examples: Taxus baccata 'Variegata', Juniperus ×pfitzeriana 'Wilhelm Pfitzer'; Magnolia 'Elizabeth' (= a hybrid, no species epithet).|| +|taxonRank|CULTIVAR GROUP|Cultivar group|GREX| +|taxonRank|FAMILY|Family|| +|taxonRank|FORM|Form|FORMA| +|taxonRank|GENUS|Genus|| +|taxonRank|INFORMAL|Informal|| +|taxonRank|INFRAGENERIC NAME|Used for any other unspecific rank below genera and above species.|| +|taxonRank|INFRAORDER|Infraorder|| +|taxonRank|INFRASPECIFIC NAME|Used for any other unspecific rank below genera and above species.|| +|taxonRank|INFRASUBSPECIFIC NAME|Used for any other unspecific rank below subspecies.|| +|taxonRank|KINGDOM|Kingdom|REGNUM| +|taxonRank|ORDER|Order|ALLIANCE| +|taxonRank|PHYLUM|Phylum|DIVISION| +|taxonRank|SECTION|Section within a genus. In Zoology a section sometimes refers to a group above family level, this is NOT meant|| +|taxonRank|SERIES|Series within a genus.|| +|taxonRank|SPECIES|Species|| +|taxonRank|SPECIES AGGREGATE|A loosely defined group of species. Zoology: 'Aggregate - a group of species, other than a subgenus, within a genus. An aggregate may be denoted by a group name interpolated in parentheses.' -- The Berlin/MoreTax model notes:'[these] aren't taxonomic ranks but circumscriptions because on the one hand they are necessary for the concatenation of the fullname and on the other hand they are necessary for distinguishing the aggregate or species group from the microspecies.' Compare subspecific aggregate for a group of subspecies within a species.|AGGREGATE, SPECIES GROUP, SPECIES COMPLEX| +|taxonRank|SUBFAMILY|Subfamily|| +|taxonRank|SUBFORM|Subform|SUBFORMA| +|taxonRank|SUBGENUS|Subgenus|| +|taxonRank|SUBKINGDOM|Subkingdom|| +|taxonRank|SUBORDER|Suborder|| +|taxonRank|SUBSECTION|Subsection within a genus.|| +|taxonRank|SUBSERIES|Subseries within a genus.|| +|taxonRank|SUBSPECIES|Subspecies|| +|taxonRank|SUBSPECIFIC AGGREGATE|A loosely defined group of subspecies. Zoology:'Aggregate - a group of subspecies within a species. An aggregate may be denoted by a group name interpolated in parentheses.'|| +|taxonRank|SUBTRIBE|Subtribe|| +|taxonRank|SUBVARIETY|Subvariety|SUBVARIETAS| +|taxonRank|SUPERFAMILY|Superfamily|| +|taxonRank|SUPRAGENERIC NAME|Used for any other unspecific rank above genera.|| +|taxonRank|TRIBE|Tribe|| +|taxonRank|UNRANKED|Unranked|| +|taxonRank|VARIETY|Variety|VARIETAS| +|threatStatusCheckProtocol|UNSPECIFIED|Unspecified|| + + + +Table 2b: Suggested values for conditionally mandatory values for the `threatStatus` and +`conservationJurisdiction` fields in the template. State and Territory `conservationJurisdictions` +spelt out as words are also valid. For some `threatStatus` terms, alternative labels are provided +that are also valid for that `conservationJurisdiction`. + +|conservationJurisdiction|threatStatus|threatStatus alternative labels| +|:---:|:---|:---| +|ACT|CRITICALLY ENDANGERED|| +|ACT|ENDANGERED|| +|ACT|EXTINCT|| +|ACT|EXTINCT IN THE WILD|| +|ACT|REGIONALLY CONSERVATION DEPENDENT|| +|ACT|VULNERABLE|| +|EPBC|CAMBA|| +|EPBC|CD|CONSERVATION DEPENDENT| +|EPBC|CE|CRITICALLY ENDANGERED, CR| +|EPBC|CITES|| +|EPBC|E|ENDANGERED, EN| +|EPBC|EX|EXTINCT| +|EPBC|JAMBA|| +|EPBC|KAMBA|| +|EPBC|V|VULNERABLE, VU| +|EPBC|XW|EXTINCT IN THE WILD, EW| +|NSW|CE|CRITICALLY ENDANGERED| +|NSW|EN|ENDANGERED| +|NSW|EX|EXTINCT| +|NSW|V|VULNERABLE| +|NT|CE|CRITICALLY ENDANGERED| +|NT|DD|DATA DEFICIENT| +|NT|EN|ENDANGERED| +|NT|EN EXTINCT IN NT|ENDANGERED EXTINCT IN NT| +|NT|EN EXTINCT IN WILD IN NT|ENDANGERED EXTINCT IN WILD IN NT| +|NT|EW|CRITICALLY ENDANGERED POSSIBLY EXTINCT| +|NT|EX|EXTINCT| +|NT|LC|LEAST CONCERN| +|NT|LC EXTINCT IN NT|LEAST CONCERN EXTINCT IN NT| +|NT|NE|NOT EVALUATED| +|NT|NT|NEAR THREATENED| +|NT|VU|VULNERABLE| +|NT|VU EXTINCT IN NT|VULNERABLE EXTINCT IN NT| +|QLD|C|LEAST CONCERN WILDLIFE| +|QLD|CR|CRITICALLY ENDANGERED WILDLIFE| +|QLD|E|ENDANGERED WILDLIFE| +|QLD|EX|EXTINCT WILDLIFE| +|QLD|I|INTERNATIONAL WILDLIFE| +|QLD|NT|NEAR THREATENED WILDLIFE| +|QLD|PE|EXTINCT IN THE WILD WILDLIFE| +|QLD|SL|SPECIAL LEAST CONCERN WILDLIFE| +|QLD|V|VULNERABLE WILDLIFE| +|SA|E|ENDANGERED| +|SA|R|RARE| +|SA|SP|INDICATES THAT A RATING HAS BEEN APPLIED TO THE SPECIES LEVEL THE STATUS HAS NOT BEEN ASSESSED AT THE SUBSPECIES LEVEL| +|SA|SSP|INDICATES THAT AT LEAST ONE SUBSPECIES FOR THIS SPECIES HAS BEEN GIVEN A CONSERVATION RATING| +|SA|V|VULNERABLE| +|TAS|E|ENDANGERED| +|TAS|R|RARE| +|TAS|V|VULNERABLE| +|TAS|X|EXTINCT| +|VIC|CONSERVATION DEPENDENT|| +|VIC|CRITICALLY ENDANGERED|| +|VIC|ENDANGERED|| +|VIC|ENDANGERED EXTINCT IN VICTORIA|| +|VIC|EXTINCT|| +|VIC|EXTINCT IN THE WILD|| +|VIC|RESTRICTED|| +|VIC|VULNERABLE|| +|WA|CD|SPECIES OF SPECIAL CONSERVATION INTEREST CONSERVATION DEPENDENT FAUNA, CONSERVATION DEPENDENT| +|WA|CR|CRITICALLY ENDANGERED, CRITICALLY ENDANGERED SPECIES| +|WA|EN|ENDANGERED SPECIES, ENDANGERED| +|WA|EW|EXTINCT IN THE WILD| +|WA|EX|EXTINCT SPECIES, EXTINCT| +|WA|MI|MIGRATORY SPECIES, MIGRATORY| +|WA|OS|OTHER SPECIFICALLY PROTECTED FAUNA| +|WA|P1|PRIORITY 1 POORLY KNOWN, PRIORITY 1 POORLY KNOWN SPECIES| +|WA|P2|PRIORITY 2 POORLY KNOWN SPECIES, PRIORITY 2 POORLY KNOWN| +|WA|P3|PRIORITY 3 POORLY KNOWN, PRIORITY 3 POORLY KNOWN SPECIES| +|WA|P4|PRIORITY 4 RARE NEAR THREATENED AND OTHER SPECIES IN NEED OF MONITORING| +|WA|SPECIALLY PROTECTED|SPECIALLY PROTECTED SPECIES| +|WA|T|THREATENED, THREATENED SPECIES| +|WA|VU|VULNERABLE SPECIES, VULNERABLE| + + +### APPENDIX-II: Timestamp +Following date and date-time formats are acceptable within the timestamp: + +| TYPE | FORMAT | +| --- |-------------------------------------------------------------------------------------------------------------------------------------| +| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| +| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | +| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | +| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | +| **xsd:gYear** | yyyy | + +Where
+  `yyyy`: four-digit year
+  `mm`: two-digit month (01=January, etc.)
+  `dd`: two-digit day of month (01 through 31)
+  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
+  `mm`: two digits of minute (00 through 59)
+  `ss`: two digits of second (00 through 59)
+ + +### APPENDIX-III: UTF-8 +UTF-8 encoding is considered a best practice for handling character encoding, especially in +the context of web development, data exchange, and modern software systems. UTF-8 +(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of +encoding all possible characters (code points) in Unicode.
+Here are some reasons why UTF-8 is recommended: +- **Universal Character Support:** UTF-8 can represent almost all characters from all writing + systems in use today. This includes characters from various languages, mathematical symbols, + and other special characters. +- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American + Standard Code for Information Interchange). The first 128 characters in UTF-8 are + identical to ASCII, making it easy to work with systems that use ASCII. +- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English + and many other languages). It uses one byte for ASCII characters and up to four + bytes for other characters. This variable-length encoding minimises storage and + bandwidth requirements. +- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is + widely supported by browsers, servers, and web-related technologies. +- **Globalisation:** As software applications become more globalised, supporting a wide + range of languages and scripts becomes crucial. UTF-8 is well-suited for + internationalisation and multilingual support. +- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many + programming languages, databases, and operating systems. Choosing UTF-8 helps + ensure compatibility across different platforms and technologies. + +When working with text data, UTF-8 encoding is recommended to avoid issues related to character +representation and ensure that a diverse set of characters and languages is supported. + +For assistance, please contact: + diff --git a/docs/pages/archived_templates/survey_site_data-v1.0.0.csv.md b/docs/pages/archived_templates/survey_site_data-v1.0.0.csv.md new file mode 100644 index 00000000..305ccf8d --- /dev/null +++ b/docs/pages/archived_templates/survey_site_data-v1.0.0.csv.md @@ -0,0 +1,317 @@ +--- +title: Systematic Survey Site Data Template - v1.0.0 + - Archived + +summary: A template for systematic survey site data +--- + +**survey_site_data** v1.0.0 + + + +!!! failure "Template Archived" + + This Template is archived, and is no longer available for use. + + +# SYSTEMATIC SURVEY SITE DATA TEMPLATE INSTRUCTIONS + +## Intended Usage +This Systematic Survey Site Data template should be used to record data about a +Site area where species occurrences have been sampled during a systematic survey. + +This Systematic Survey Site template **must be used in combination** with the +`Systematic Survey Occurrence` template and the `Systematic Survey Metadata` template. + +Templates have been provided to facilitate integration of data into the Biodiversity Data +Repository (BDR) database. Not all types of data have been catered for in the available +templates at this stage - if you are unable to find a suitable template, please +contact to make us aware of your data needs. + +#### Data Validation Requirements: +For data validation, you will need your data file to: + +- be the correct **file format**, +- have **fields that match the template downloaded** (do not remove, or + change the order of fields), +- have extant values for **mandatory fields** (see Table 1), and +- comply with all **data value constraints**; for example the geographic coordinates are + consistent with a [geodeticDatum](#geodeticDatum-vocabularies) type of the + ***5*** available options. + +Additional fields may be added **after the templated fields** (noting that the data type +is not assumed and values will be encoded as strings). + +### FILE FORMAT +- The systematic survey site data template is a [UTF-8](#appendix-iv-utf-8) encoded csv (not Microsoft + Excel Spreadsheets). Be sure to save this file with your data as a .csv (UTF-8) as follows, + otherwise it will not pass the csv validation step upon upload. +
`[MS Excel: Save As > More options > Tools > Web options > Save this document as > + Unicode (UTF-8)]`
+ otherwise it will not pass the csv validation step upon upload. +- **Do not include empty rows**. + +#### FILE SIZE +MS Excel imposes a limit of 1,048,576 rows on a spreadsheet, limiting a CSV file to the +header row followed by 1,048,575 occurrences. Furthermore, MS Excel has a 32,767 character +limit on individual cells in a spreadsheet. These limits may be overcome by using or +editing CSV files with other software. + +Larger datasets may be more readily ingested using the API interface. Please contact + to make us aware of your data needs. + +## TEMPLATE FIELDS +The template contains the field names in the top row. Table 1 will assist you in transferring +your data to the template indicating: + +- **Field name** in the template (and an external link to the [Darwin Core standard](https://dwc.tdwg.org/terms/) + for that field where relevant); +- **Description** of the field; +- **Required** i.e. whether the field is **mandatory, +conditionally mandatory, or optional**; +- **Format** (datatype) required for the data values for example text (string), number + (integer, float), or date; +- **Example** of an entry or entries for that field; and +- **[Vocabulary links](#appendix-i-vocabulary-list)** within this document (for example pick list values) where + relevant. The fields that have suggested values options for the fields in Table 1 are + listed in Table 2 in alphabetical order of the field name. + +### ADDITIONAL FIELDS +Data that does not match the existing template fields may be added as additional columns in +the CSV files after the templated fields. +For example, `fieldNotes`, `continent`, `country`, `countryCode`, `stateProvince`, `georeferencedDate`, +`landformPattern`, `landformElement`, `aspect`, `slope`, `visitNo`. + +Table 1: Systematic Survey Site data template fields with descriptions, conditions, datatype format, and examples. + +|Field #|Name|Description|Mandatory / Optional|Datatype Format|Examples| +|:---:|:---|:---|:---:|:---:|:---| +|1|siteID|A unique within dataset string identifier for the site. Valid values include strings that are used specifically for this survey or URIs from BDR Sites that have been established in previous surveys.|**Mandatory**|String|P1| +|2|siteIDSource|The organisation that assigned the SiteID to this Site|Optional|String|TERN| +|3|siteType|The type of site that relates to its sampling type and/or dimensions.|Optional|String|Plot
([Vocabulary link](#siteType-vocabularies))| +|4|siteName|A name for the site that may be more descriptive than the siteID.|Optional|String|Plot 1| +|5|siteDescription|The site (plot) description covers important aspects of the site (generally of the land surface). Some overlap in collected information does occur due to the modular nature of the survey processes. The description provides significant background information to gain an appreciation of the plot history, topography, position in the landscape and for understanding the likely relationship between the soils, vegetation and fauna.|Optional|String|Fine woody debris.| +|6|[habitat](https://dwc.tdwg.org/terms/#dwc:habitat)|A collection of habitat types representing the dominant vegetation structural formation class adopted by the National Vegetation Information System (NVIS).|Optional|List|Chenopod Shrubland \| Closed Fernland
([Vocabulary link](#habitat-vocabularies))| +|7|relatedSiteID|Identifier of a related site to the specified site e.g. parent site, same site with different identifier.|**Conditionally mandatory with relationshipToRelatedSite**|String|Same as within dataset or existing URI| +|8|relationshipToRelatedSite|Relationship between the site and the related site. This field can be used to record Site identifiers for the same site from different custodians through the use of URIs.|**Conditionally mandatory with relatedSiteID**|String|Same as within dataset or existing URI
([Vocabulary link](#relationshipToRelatedSite-vocabularies))| +|9|[decimalLatitude](https://dwc.tdwg.org/terms/#dwc:decimalLatitude)|The geographic latitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic origin of a Site. Positive values are north of the Equator, negative values are south of it. Legal values lie between -90 and 0, inclusive for Southern hemisphere.|Optional|Number|-34.036| +|10|[decimalLongitude](https://dwc.tdwg.org/terms/#dwc:decimalLongitude)|The geographic longitude (in decimal degrees, using the spatial reference system given in geodeticDatum) of the geographic origin of a Site. Positive values are east of the Greenwich Meridian, negative values are west of it. Legal values lie between 0 and 180, inclusive for the BDR use case.|Optional|Number|146.363| +|11|[footprintWKT](https://dwc.tdwg.org/terms/#dwc:footprintWKT)|A Well-Known Text (WKT) representation of the shape (footprint, geometry) that defines the Site. A Site may have both a point-radius representation and a footprint representation, and they may differ from each other.|Optional|WKT|LINESTRING (146.363 -34.036, 146.363 -34.037)
([WKT notes](#appendix-ii-well-known-text-wkt))| +|12|[geodeticDatum](https://dwc.tdwg.org/terms/#dwc:geodeticDatum)|The geodetic datum, or spatial reference system (SRS) upon which the geographic coordinates given for the Site are based.|Optional|String|WGS84
([Vocabulary link](#geodeticDatum-vocabularies))| +|13|[coordinateUncertaintyInMeters](https://dwc.tdwg.org/terms/#dwc:coordinateUncertaintyInMeters)|The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude describing the smallest circle containing the whole of the Site. Leave the value empty if the uncertainty is unknown, cannot be estimated, or is not applicable (because there are no coordinates). Zero is not a valid value for this term.|Optional|Integer|50| +|14|dataGeneralizations|Actions taken to make the shared data less specific or complete than in its original form.|Optional|String|Coordinates given in decimalLatitude, decimalLongitude, easting and northing have been rounded to 0.1 DEG. The observer name has been changed to a unique User ID.| +|15|surveyID|The identifier of the Survey that the Site is related to in this dataset.|Optional|String|AR220-01| +|16|siteVisitID|The unique key assigned to a visit. A visit is a time distinct assessment conducted within a survey at a designated site.|Optional|String|CPXEI0000001| +|17|siteVisitStart|The temporal start of when the Site was being used to collect data for the survey. Expected values include date, dateTime, dateTimeStamp.|**Mandatory**|Timestamp|2016-02-28| +|18|siteVisitEnd|The temporal end of when the Site was being used to collect data for the survey. Expected values include date, dateTime, dateTimeStamp.|Optional|Timestamp|2016-02-28| +|19|visitOrgs|The names of the organisations responsible for recording the original Occurrence.|Optional|List|NSW Dept of Planning, Industry and Environment.| +|20|visitObservers|A list (concatenated and separated using \|) of names of people, groups, or organisations responsible for recording the original Occurrence.|Optional|List|Oliver P. Pearson \| Anita K. Pearson| +|21|condition|The state of a patch of vegetation at the time of sampling relative to some specified standard or benchmark (where available).|Optional|String|Burnt| + + +## APPENDICES +### APPENDIX-I: VOCABULARY LIST +With the exception of `geodeticDatum` and `relationshipToRelatedSite`, data validation +does not require adherence to the vocabularies for the various vocabularied fields. +These vocabularies are merely provided as a means of assistance in developing consistent language +within the database. New terms may be added to more appropriately describe your data that goes +beyond the current list. + +Table 2: Suggested values for controlled vocabulary fields in the template. Each term has a preferred label with a definition to aid understanding +of its meaning. For some terms, alternative +labels with similar semantics are provided. +
**Note:** The values for `geodeticDatum` and `relationshipToRelatedSite` must come from one of the Preferred labels or Alternate Labels in this +table. + +|Template field name|Preferred label|Definition|Alternate label| +|:---|:---|:---|:---| +|geodeticDatum|AGD66|Australian Geodetic Datum 1966|EPSG:4202| +|geodeticDatum|AGD84|Australian Geodetic Datum 1984|EPSG:4203| +|geodeticDatum|GDA2020|Geocentric Datum of Australia 2020|EPSG:7844| +|geodeticDatum|GDA94|Geocentric Datum of Australia 1994|EPSG:4283| +|geodeticDatum|WGS84|World Geodetic System 1984, used in GPS|EPSG:4326| +|habitat|BEACH|Type of Landform Element, which is usually short; low; very wide slope; gently or moderately inclined; built up or eroded by waves; forming the shore of a lake or sea.|| +|habitat|BILLABONG OR SWAMP|A swamp is a wetland that features temporary or permanent inundation of large areas of land by shallow bodies of water, generally with a substantial number of hammocks, or dry-land protrusions, and covered by aquatic vegetation, or vegetation that tolerates periodical inundation.|| +|habitat|CAVE|The type of habitat representative of a naturally formed, subterranean open area or chamber.|| +|habitat|CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Chenopodiaceae.|| +|habitat|CLOSED CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Chenopodiaceae.|| +|habitat|CLOSED FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Fern and Fern-allies.|| +|habitat|CLOSED FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|habitat|CLOSED FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Forbs or herbs other than grasses.|| +|habitat|CLOSED HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of heath shrubs (e.g., members of Ericaceae, Myrtaceae).|| +|habitat|CLOSED HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of hummock (e.g., Triodia) grasses.|| +|habitat|CLOSED LICHENLAND|Refers to the type of habitat characterised by lichenised tree trunks and rocks.|| +|habitat|CLOSED LIVERWORTLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|CLOSED MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tree mallee (e.g., some members of Eucalyptus).|| +|habitat|CLOSED MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of mallee shrubs (e.g., some members of Eucalyptus).|| +|habitat|CLOSED MOSSLAND|Refers to the type of habitat characterised by lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|CLOSED RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of Rushes (e.g., Juncaceae).|| +|habitat|CLOSED SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|habitat|CLOSED SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of sedges (e.g., Cyperaceae).|| +|habitat|CLOSED SOD GRASSLAND|Refers to the type of habitat representative of a characteristic sod-like (turf) grass.|| +|habitat|CLOSED TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about >80% members of tussock grasses (e.g., Poa).|| +|habitat|CLOSED VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|habitat|COASTAL WATERS|Refers to the type of habitat representative of an aquatic body typically characterized by a shallow continental shelf, gently sloping seaward to a continental slope, which drops relatively abruptly to the deep ocean.|| +|habitat|CROP LAND|Refers to the type of habitat representative of a cultivated land or land on which agricultural crops are grown or land that is set aside or temporarily not being used for crop production.|| +|habitat|ESTUARY|Type of Landform Element which has a stream channel close to its junction with a sea or lake; where the action of channelled stream flow is modified by tide and waves. The width typically increases downstream.|| +|habitat|FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Fern and Fern-allies.|| +|habitat|FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Forbs or herbaceous plants other than grasses.|| +|habitat|FRESHWATER LAKE|Refers to the type of habitat representative of an enclosed aquatic body having a relatively low mineral content, generally less than 500 mg/l of dissolved solids.|| +|habitat|GRAZING LAND|Refers to the type of habitat representative of a land predominantly used for grazing.|| +|habitat|HEATHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of Heath (e.g., Ericaceae, Myrtaceae).|| +|habitat|HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% members of hummock grasses (e.g., Triodia).|| +|habitat|ISOLATED CHENOPOD SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% members of Chenopodiaceae.|| +|habitat|ISOLATED CLUMP OF CHENOPOD SHRUBS|Refers to the type of habitat characterised by isolated clumps of chenopod shrubs.|| +|habitat|ISOLATED CLUMP OF HEATH SHRUBS|Refers to the type of habitat characterised by isolated clumps of heath or heath-like shrubs.|| +|habitat|ISOLATED CLUMP OF HUMMOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of hummocky grass (e.g., Triodia spp., Spinifex spp.).|| +|habitat|ISOLATED CLUMP OF LIVERWORTS|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|habitat|ISOLATED CLUMP OF MALLEE SHRUBS|Refers to the type of habitat characterised by isolated clumps of mallee shrubs (members of Eucalyptus spp., multistemmed from base).|| +|habitat|ISOLATED CLUMP OF MALLEE TREES|Refers to the type of habitat characterised by isolated clumps of tree mallee (members of Eucalyptus spp., multistemmed from base).|| +|habitat|ISOLATED CLUMP OF MOSSES|Refers to the type of habitat characterised by isolated clumps of bryophytes, moss and liverworts.|| +|habitat|ISOLATED CLUMP OF RUSHES|Refers to the type of habitat characterised by isolated clumps of rushes.|| +|habitat|ISOLATED CLUMP OF SEDGES|Refers to the type of habitat characterised by isolated clumps of sedges.|| +|habitat|ISOLATED CLUMP OF SHRUBS|Refers to the type of habitat characterised by isolated clumps of shrubs.|| +|habitat|ISOLATED CLUMP OF SOD GRASSES|Refers to the type of habitat characterised by isolated clumps of sod grass.|| +|habitat|ISOLATED CLUMP OF TREES|Refers to the type of habitat characterised by isolated clumps of trees.|| +|habitat|ISOLATED CLUMP OF TUSSOCK GRASSES|Refers to the type of habitat characterised by isolated clumps of tussock grasses (e.g., Poa spp).|| +|habitat|ISOLATED CLUMP OF VINES|Refers to the type of habitat characterised by isolated clumps of vines.|| +|habitat|ISOLATED CLUMPS OF FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Fern and Fern-allies.|| +|habitat|ISOLATED CLUMPS OF FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0-5% members of Forbs or herbs other than grasses.|| +|habitat|ISOLATED CLUP OF LICHENS|Refers to the type of habitat characterised by isolated clumps of lichens.|| +|habitat|ISOLATED FERNS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of fern and fern allies.|| +|habitat|ISOLATED FORBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of forbs or herbs other than grasses.|| +|habitat|ISOLATED HEATH SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of heath shrubs (e.g., Ericaceae, Myrtaceae).|| +|habitat|ISOLATED HUMMOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of hummock grasses (e.g., Triodia).|| +|habitat|ISOLATED LICHENS|Refers to the type of habitat characterised by isolated or sparse lichens.|| +|habitat|ISOLATED LIVERWORTS|Refers to the type of habitat characterised by isolated or sparse liverworts.|| +|habitat|ISOLATED MALLEE SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of mallee shrubs (e.g., some multistemmed individuals from base of Eucalyptus).|| +|habitat|ISOLATED MALLEE TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tree mallee (e.g., some multistemmed individuals from base of Eucalyptus).|| +|habitat|ISOLATED MOSSES|Refers to the type of habitat characterised by isolated mosses, including bryophytes and liverworts.|| +|habitat|ISOLATED RUSHES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of rushes (e.g., Juncaceae).|| +|habitat|ISOLATED SEDGES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of sedges (e.g., Cyperaceae).|| +|habitat|ISOLATED SHRUBS|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of shrubs including cycads, grass-tree and tree-fern.|| +|habitat|ISOLATED SOD GRASSES|Refers to the type of habitat characterised by isolated or sparse sod or turf-like grasses.|| +|habitat|ISOLATED TREES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of trees including palms.|| +|habitat|ISOLATED TUSSOCK GRASSES|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about <0.25% of tussock grass (e.g. Poa species).|| +|habitat|ISOLATED VINES|Refers to the type of habitat characterised by isolated or sparse stragglers or climbing woody vines.|| +|habitat|LICHENLAND|Refers to the type of habitat predominated by lichens on rocks, trees or tree stumps, etc.|| +|habitat|LIVERWORTLAND|Refers to the type of habitat predominated by liverworts.|| +|habitat|MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrub mallee (e.g., individuals of some Eucalypts multistemmed from base).|| +|habitat|MALLEE WOODLAND|Refers to the dominant vegetation structural formation, with a percent cover of about 20-50% of Tree Mallee.|| +|habitat|MOSSLAND|Refers to the type of habitat dominated by mosses.|| +|habitat|MUDFLAT|Refers to the type of habitat characterised by a wetland that forms when mud is deposited by the tides, rivers, sea or oceans.|| +|habitat|OPEN CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of members of Chenopodiaceae.|| +|habitat|OPEN FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of ferns and fern allies.|| +|habitat|OPEN FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of forbs or herbs other than grasses.|| +|habitat|OPEN FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of trees including palms.|| +|habitat|OPEN HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of heaths (e.g., Ericaceae, Myrtaceae).|| +|habitat|OPEN HUMMOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of hummock grasses (e.g., Triodia).|| +|habitat|OPEN LICHENLAND|Refers to the type of habitat represented by open or sparse (i.e., 10-30%) hummocky grasses (e.g., Spinifex spp., Triodia spp.).|| +|habitat|OPEN LIVERWORTLAND|Refers to the type of habitat characterised by open or sparse lichenised tree trunks and rocks.|| +|habitat|OPEN MALLEE FOREST|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tree Mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of Mallee shrubs (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MALLEE WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tree mallee (e.g., certain individuals of Eucalypts multistemmed from base).|| +|habitat|OPEN MOSSLAND|Refers to the type of habitat characterised by open or sparse members of lower plant groups such as moss, liverworts and bryophytes.|| +|habitat|OPEN OCEAN|Refers to the type of habitat surrounded by ocean, i.e., a continuous saline-water bodies that surround the continents and fill the Earth's great depressions.|| +|habitat|OPEN RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of rushes (e.g. Juncaceae).|| +|habitat|OPEN SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of sedges (e.g. Cyperaceae).|| +|habitat|OPEN SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of shrubs (e.g. shrubs, cycads, grass-tree, tree-fern).|| +|habitat|OPEN SOD GRASSLAND|Refers to the type of habitat characterised by open or sparse (10-30% ground cover) of a characteristic sod-like (turf) grass.|| +|habitat|OPEN TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 20-50% of tussock grasses (e.g. Poa species).|| +|habitat|OPEN VINELAND|Refers to the type of habitat represented by a closed vegetation dominated by stragglers and woody climbers.|| +|habitat|OPEN WOODLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of trees including palms.|| +|habitat|ROCK OUTCROP|Refers to the type of habitat characterised by rocks, which protrudes through the surface layer.|| +|habitat|RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of rushes (e.g. Juncaceae).|| +|habitat|SALTWATER LAKE|Refers to the type of habitat representative of an aquatic body filled with water (with high salinity) of considerable size contained in a depression on a landmass.|| +|habitat|SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of sedges (e.g., Cyperaceae).|| +|habitat|SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of shrubs (e.g., shrub, cycad, grass-tree, tree-fern).|| +|habitat|SOD GRASSLAND|Refers to the type of habitat characterised by mid-dense (30-70% cover) sod or turf-like grasses.|| +|habitat|SPARSE CHENOPOD SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of Chenopodiaceae.|| +|habitat|SPARSE FERNLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of fern and fern-allies.|| +|habitat|SPARSE FORBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of forbs and herbs other than grasses.|| +|habitat|SPARSE GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of grasses.|| +|habitat|SPARSE HEATH|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of heath (e.g., Ericaceae, Myrtaceae).|| +|habitat|SPARSE LICHENLAND|Refers to the type of habitat characterised by very sparse (<10% cover) lichens.|| +|habitat|SPARSE LIVERWORTLAND|Refers to the type of habitat characterised by very sparse (<10% cover) liverworts.|| +|habitat|SPARSE MALLEE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of members of shrub Mallee.|| +|habitat|SPARSE MOSSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) mosses.|| +|habitat|SPARSE RUSHLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of rushes (e.g., Juncaceae).|| +|habitat|SPARSE SEDGELAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of sedges (e.g., Cyperaceae).|| +|habitat|SPARSE SHRUBLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of shrubs, including cycad, grass-tree, tree-fern.|| +|habitat|SPARSE SOD GRASSLAND|Refers to the type of habitat characterised by very sparse (<10% cover) sod or turf-like grasses.|| +|habitat|SPARSE TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 0.25-20% of tussock grass (e.g., Poa species).|| +|habitat|SPARSE VINELAND|Refers to the type of habitat characterised by well separated or very sparse crown stragglers or woody vines.|| +|habitat|STREAM OR RIVER|Refers to the type of habitat representative of an aquatic body with a watercourse which is linear and flows across the solid portion of a planetary surface.|| +|habitat|TUSSOCK GRASSLAND|Refers to the NVIS dominant vegetation structural formation class, with a percent cover of about 50-80% of tussock grass (e.g., Poa species).|| +|habitat|URBAN|Refers to the type of habitat relating to, located in, or characteristic of a city or densely populated area.|| +|habitat|VINELAND|Refers to the type of habitat characterised by woody climbers/straggling vines.|| +|habitat|WOODLAND|Refers to the type of habitat characterised by a low-density forest forming open habitats with plenty of sunlight and limited shade.|| +|relationshipToRelatedSite|PART OF|When a site is a subset of another site.|| +|relationshipToRelatedSite|SAME AS|When two sites are the same.|| +|siteType|PARENT SITE|Parent site.|| +|siteType|PLOT|Land area selected from within a survey region which abiotic and biotic properties are sampled.|| +|siteType|QUADRAT|A transportable frame (usually a square made out of PVC tube, metal rod or wood) used to isolate a standard unit of area for study of the distribution of item(s) over a large area (e.g. a plot).|| +|siteType|SITE|A place in which study/protocol/sampling activities are conducted.|| +|siteType|TRANSECT|A line along which biotic and abiotic characteristics are sampled|| + + +### APPENDIX-II: Well Known Text (WKT) +For general information on how WKT coordinate reference data is formatted is available [here](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). +The length of a WKT string or of its components is not prescribed; however, MS Excel *does* has a +32,767 (32K) character limit on individual cells in a spreadsheet. + +It is possible to edit CSV files outside of Excel in order to include more than 32K characters. + +![Multipart geometries (2D) WKT](../assets/multipart_geometries_2d_wkt.png) +
*Source: Mwtoews - CC BY-SA 3.0 - Wikipedia *
+ +### APPENDIX-III: Timestamp +Following date and date-time formats are acceptable within the timestamp: + +| TYPE | FORMAT | +| --- |-------------------------------------------------------------------------------------------------------------------------------------| +| **xsd:dateTimeStamp with timezone** | yyyy-mm-ddThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) OR
yyyy-mm-ddThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) OR
yyyy-mm-ddThh:mmTZD (eg 1997-07-16T19:20+01:00)| +| **xsd:dateTime** | yyyy-mm-ddThh:mm:ss.s (eg 1997-07-16T19:20:30.45) OR
yyyy-mm-ddThh:mm:ss (eg 1997-07-16T19:20:30) OR
yyyy-mm-ddThh:mm (eg 1997-07-16T19:20) | +| **xsd:Date** | dd/mm/yyyy OR
d/m/yyyy OR
yyyy-mm-dd OR
yyyy-m-d | +| **xsd:gYearMonth** | mm/yyyy OR
m/yyyy OR
yyyy-mm | +| **xsd:gYear** | yyyy | + +Where:
+  `yyyy`: four-digit year
+  `mm`: two-digit month (01=January, etc.)
+  `dd`: two-digit day of month (01 through 31)
+  `hh`: two digits of hour (00 through 23) (am/pm NOT allowed)
+  `mm`: two digits of minute (00 through 59)
+  `ss`: two digits of second (00 through 59)
+ + +### APPENDIX-IV: UTF-8 +UTF-8 encoding is considered a best practice for handling character encoding, especially in +the context of web development, data exchange, and modern software systems. UTF-8 +(Unicode Transformation Format, 8-bit) is a variable-width character encoding capable of +encoding all possible characters (code points) in Unicode.
+Here are some reasons why UTF-8 is recommended: +- **Universal Character Support:** UTF-8 can represent almost all characters from all writing + systems in use today. This includes characters from various languages, mathematical symbols, + and other special characters. +- **Backward Compatibility:** UTF-8 is backward compatible with ASCII (American + Standard Code for Information Interchange). The first 128 characters in UTF-8 are + identical to ASCII, making it easy to work with systems that use ASCII. +- **Efficiency:** UTF-8 is space-efficient for Latin-script characters (common in English + and many other languages). It uses one byte for ASCII characters and up to four + bytes for other characters. This variable-length encoding minimises storage and + bandwidth requirements. +- **Web Standards:** UTF-8 is the dominant character encoding for web content. It is + widely supported by browsers, servers, and web-related technologies. +- **Globalisation:** As software applications become more globalised, supporting a wide + range of languages and scripts becomes crucial. UTF-8 is well-suited for + internationalisation and multilingual support. +- **Compatibility with Modern Systems:** UTF-8 is the default encoding for many + programming languages, databases, and operating systems. Choosing UTF-8 helps + ensure compatibility across different platforms and technologies. + +When working with text data, UTF-8 encoding is recommended to avoid issues related to character +representation and ensure that a diverse set of characters and languages is supported. + +For assistance, please contact: + diff --git a/docs/tables/threat_status.py b/docs/tables/threat_status.py index 419f0376..47d1d1e7 100644 --- a/docs/tables/threat_status.py +++ b/docs/tables/threat_status.py @@ -127,7 +127,7 @@ def generate_row(self, threat_stat_cons_jur_term: utils.vocabs.Term) -> ThreatSt row = self.row_model( conservation_authority=splt_preferred[0], threat_status=splt_preferred[1], - threat_status_alt_labels=", ".join(threat_stat_alt), + threat_status_alt_labels=", ".join(sorted(threat_stat_alt)), ) # Return diff --git a/scripts/generate_instructions.sh b/scripts/generate_instructions.sh index 896429f0..07c503b8 100755 --- a/scripts/generate_instructions.sh +++ b/scripts/generate_instructions.sh @@ -4,12 +4,6 @@ set -ex # (e) exit on error (x) print commands # incidental python docs/instructions.py -i -o docs/pages/incidental_occurrence_data-v3.0.0.csv.md incidental_occurrence_data-v3.0.0.csv -python docs/instructions.py -o docs/pages/incidental_occurrence_data-v2.0.0.csv.md incidental_occurrence_data-v2.0.0.csv - -# survey v1 -python docs/instructions.py -o docs/pages/survey_occurrence_data-v1.0.0.csv.md survey_occurrence_data-v1.0.0.csv -python docs/instructions.py -o docs/pages/survey_metadata-v1.0.0.csv.md survey_metadata-v1.0.0.csv -python docs/instructions.py -o docs/pages/survey_site_data-v1.0.0.csv.md survey_site_data-v1.0.0.csv # survey v2 python docs/instructions.py -o docs/pages/survey_metadata-v2.0.0.csv.md survey_metadata-v2.0.0.csv diff --git a/tests/docs/tables/test_fields.py b/tests/docs/tables/test_fields.py index 9fb57992..5dc76b27 100644 --- a/tests/docs/tables/test_fields.py +++ b/tests/docs/tables/test_fields.py @@ -212,14 +212,14 @@ def test_header(mocked_mapper: unittest.mock.MagicMock) -> None: def test_determine_checklist() -> None: """Tests the determine_checklist method.""" # Create tabler - tabler = tables.fields.FieldTabler("incidental_occurrence_data-v2.0.0.csv") + tabler = tables.fields.FieldTabler("incidental_occurrence_data-v3.0.0.csv") # Invoke function checklist = tabler.checklist() # Assert assert checklist is not None - assert len(checklist.checks) == 6 + assert len(checklist.checks) == 9 @pytest.mark.parametrize( diff --git a/tests/templates/test_survey_occurrence_data.py b/tests/templates/test_survey_occurrence_data.py deleted file mode 100644 index 3c1a8da7..00000000 --- a/tests/templates/test_survey_occurrence_data.py +++ /dev/null @@ -1,292 +0,0 @@ -"""Tests for specific for the `survey_occurrence_data` template.""" - -# Third-party -import pytest_mock -import attrs -import pytest -import pandas as pd - -# Standard -import io -import csv -import pathlib - -# Local -from abis_mapping import base -from abis_mapping import models -import abis_mapping.templates.survey_occurrence_data.mapping -from tests import conftest - - -class TestDefaultMap: - @attrs.define(kw_only=True) - class Scenario: - """Dataclass to hold the scenario parameters.""" - - name: str - raws: list[list[str]] - expected_error_codes: set[str] = set() - default_map: dict[str, str] - - # List of scenarios for the apply_validation method tests - scenarios: list[Scenario] = [ - Scenario( - name="valid_with_default_map", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site1", "", "", "", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site3", "-38.94", "115.21", "AGD66", "", "", "", ""], - ["site4", "-38.94", "115.21", "EPSG:4202", "", "", "", ""], - ], - default_map={"site1": "something"}, - ), - Scenario( - name="invalid_missing_from_default_map", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site1", "", "", "", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={"site3": "something"}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_incidental_occurrence_requires_latlong", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["", "", "", "", "", "", "VU", "VIC"], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="valid_incidental_occurrence_requires_latlong", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["", "-38.94", "115.21", "WGS84", "", "", "VU", "VIC"], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - # The following show that non-url safe characters get encoded during mapping. - ["site a", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site/b", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site%20c", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={}, - ), - Scenario( - name="invalid_missing_long", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site1", "-38.94", "", "WGS84", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={"site1": "something"}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_missing_lat", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site1", "", "115.21", "WGS84", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={"site1": "something"}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_incidental_occurrence_missing_lat", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["", "", "115.21", "WGS84", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_incidental_occurrence_missing_long", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["", "-38.94", "", "WGS84", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_missing_geodetic_datum", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["site1", "-38.94", "115.21", "", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={"site1": "something"}, - expected_error_codes={"row-constraint"}, - ), - Scenario( - name="invalid_incidental_occurrence_missing_geodetic_datum", - raws=[ - ["site1", "-38.94", "115.21", "WGS84", "", "", "", ""], - ["", "-38.94", "115.21", "", "", "", "", ""], - ["site2", "-38.94", "115.21", "WGS84", "", "", "", ""], - ], - default_map={}, - expected_error_codes={"row-constraint"}, - ), - ] - - @pytest.mark.parametrize( - argnames="scenario", - argvalues=[scenario for scenario in scenarios], - ids=[scenario.name for scenario in scenarios], - ) - def test_apply_validation(self, scenario: Scenario, mocker: pytest_mock.MockerFixture) -> None: - """Tests the `apply_validation` method with a supplied default map. - - Args: - scenario (Scenario): The parameters of the scenario under test. - mocker (pytest_mock.MockerFixture): The mocker fixture. - """ - # Construct fake data - rawh = [ - "siteID", - "decimalLatitude", - "decimalLongitude", - "geodeticDatum", - "organismQuantity", - "organismQuantityType", - "threatStatus", - "conservationJurisdiction", - ] - all_raw = [{hname: val for hname, val in zip(rawh, ln, strict=True)} for ln in scenario.raws] - - # Get mapper - mapper = abis_mapping.templates.survey_occurrence_data.mapping.SurveyOccurrenceMapper - assert mapper is not None - - # Modify schema to only fields required for test - descriptor = {"fields": [field for field in mapper.schema()["fields"] if field["name"] in rawh]} - descriptor["fields"].sort(key=lambda f: rawh.index(f["name"])) - - # Patch the schema for the test - mocker.patch.object(base.mapper.ABISMapper, "schema").return_value = descriptor - - # Create raw data csv string - with io.StringIO() as output: - csv_writer = csv.DictWriter(output, fieldnames=rawh) - csv_writer.writeheader() - - for row in all_raw: - csv_writer.writerow(row) - - csv_data = output.getvalue().encode("utf-8") - - # Apply validation - report = mapper().apply_validation( - data=csv_data, - site_id_geometry_map=scenario.default_map, - ) - - # Assert - assert report.valid == (scenario.expected_error_codes == set()) - if not report.valid: - error_codes = [code for codes in report.flatten(["type"]) for code in codes] - assert set(error_codes) == scenario.expected_error_codes - - def test_apply_mapping(self) -> None: - """Tests apply_mapping method with default geometry map.""" - # Build a dataframe from an existing csv - df = pd.read_csv("abis_mapping/templates/survey_occurrence_data/examples/organism_qty.csv") - - # Modify and preserve first entry - col_names = ["decimalLongitude", "decimalLatitude", "geodeticDatum"] - s_geo_vals = df[[*col_names, "siteID"]].iloc[0] - df.loc[0] = df.loc[0].drop(col_names) - - # Proving the values null for first row - assert df[col_names].loc[0].isna().all() - - # Write out to memory - with io.StringIO() as output: - # Write dataframe to memory as csv - df.to_csv(output, index=False) - - # Assign csv data to variable - csv_data = output.getvalue().encode("utf-8") - - # Get mapper - mapper = abis_mapping.templates.survey_occurrence_data.mapping.SurveyOccurrenceMapper - assert mapper is not None - - expected = pathlib.Path("abis_mapping/templates/survey_occurrence_data/examples/organism_qty.ttl").read_text() - - # Resulting graph doesn't match expected when no lat/long provided - graphs = list(mapper().apply_mapping(csv_data)) - assert len(graphs) == 1 - assert not conftest.compare_graphs(graphs[0], expected) - - # Make site id geo default map using values extracted previously - val = str( - models.spatial.Geometry( - raw=models.spatial.LatLong(s_geo_vals["decimalLatitude"], s_geo_vals["decimalLongitude"]), - datum=s_geo_vals["geodeticDatum"], - ).to_rdf_literal() - ) - default_map = {s_geo_vals["siteID"]: val} - - # Create graph - graphs = list( - mapper().apply_mapping( - data=csv_data, - site_id_geometry_map=default_map, - ) - ) - assert len(graphs) == 1 - - # Now with the provided default map values the graph should match. - assert conftest.compare_graphs(graphs[0], expected) - assert "None" not in graphs[0].serialize(format="ttl") - - -def test_extract_site_id_keys(mocker: pytest_mock.MockerFixture) -> None: - """Test the extract_site_id_keys method. - - Args: - mocker (pytest_mock.MockerFixture): The mocker fixture. - """ - # Construct a raw data set only using fields relevant to method. - rawh = ["siteID"] - raws = [["site1"], [""], ["site2"], ["site3"], ["site3"]] - - # Amalgamate into a list of dicts - all_raw = [{hname: val for hname, val in zip(rawh, ln, strict=True)} for ln in raws] - - # Get the specific mapper - mapper = abis_mapping.templates.survey_occurrence_data.mapping.SurveyOccurrenceMapper() - - # Modify schema to only include the necessary fields - descriptor = {"fields": [{"name": "siteID", "type": "string"}]} - mocker.patch.object(base.mapper.ABISMapper, "schema").return_value = descriptor - - # Create raw data csv string - with io.StringIO() as output: - csv_writer = csv.DictWriter(output, fieldnames=rawh) - csv_writer.writeheader() - - for row in all_raw: - csv_writer.writerow(row) - - csv_data = output.getvalue().encode("utf-8") - - expected = { - "site1": True, - "site2": True, - "site3": True, - } - - # Invoke method - actual = mapper.extract_site_id_keys(csv_data) - - # Validate - assert actual == expected diff --git a/tests/templates/test_survey_occurrence_data_v2.py b/tests/templates/test_survey_occurrence_data_v2.py index 69d638f6..dbb46614 100644 --- a/tests/templates/test_survey_occurrence_data_v2.py +++ b/tests/templates/test_survey_occurrence_data_v2.py @@ -514,3 +514,44 @@ def test_apply_validation(self, scenario: Scenario, mocker: pytest_mock.MockerFi if not report.valid: error_codes = [code for codes in report.flatten(["type"]) for code in codes] assert set(error_codes) == scenario.expected_error_codes + + +def test_extract_site_id_keys( + mocker: pytest_mock.MockerFixture, + mapper: Mapper, +) -> None: + """Test the extract_site_id_keys method. + + Args: + mocker (pytest_mock.MockerFixture): The mocker fixture. + """ + # Construct a raw data set only using fields relevant to method. + rawh = ["siteID"] + raws = [["site1"], [""], ["site2"], ["site3"], ["site3"]] + + # Amalgamate into a list of dicts + all_raw = [{hname: val for hname, val in zip(rawh, ln, strict=True)} for ln in raws] + + # Modify schema to only include the necessary fields + descriptor = {"fields": [{"name": "siteID", "type": "string"}]} + mocker.patch.object(base.mapper.ABISMapper, "schema").return_value = descriptor + + # Create raw data csv string + output = io.StringIO() + csv_writer = csv.DictWriter(output, fieldnames=rawh) + csv_writer.writeheader() + for row in all_raw: + csv_writer.writerow(row) + csv_data = output.getvalue().encode("utf-8") + + expected = { + "site1": True, + "site2": True, + "site3": True, + } + + # Invoke method + actual = mapper.extract_site_id_keys(csv_data) + + # Validate + assert actual == expected diff --git a/tests/templates/test_survey_site_data.py b/tests/templates/test_survey_site_data_v2.py similarity index 95% rename from tests/templates/test_survey_site_data.py rename to tests/templates/test_survey_site_data_v2.py index 1fff4c4c..ec3e5a77 100644 --- a/tests/templates/test_survey_site_data.py +++ b/tests/templates/test_survey_site_data_v2.py @@ -13,7 +13,6 @@ # Local from abis_mapping import base -import abis_mapping.templates.survey_site_data.mapping import abis_mapping.templates.survey_site_data_v2.mapping # Typing @@ -23,10 +22,6 @@ @pytest.mark.parametrize( ("mapper_class",), [ - pytest.param( - abis_mapping.templates.survey_site_data.mapping.SurveySiteMapper, - id="survey_site_mapper_v1", - ), pytest.param( abis_mapping.templates.survey_site_data_v2.mapping.SurveySiteMapper, id="survey_site_mapper_v2", @@ -158,7 +153,7 @@ def test_apply_validation(self, scenario: Scenario, mocker: pytest_mock.MockerFi all_raw = [{hname: val for hname, val in zip(rawh, ln, strict=True)} for ln in scenario.raws] # Get mapper - mapper = abis_mapping.templates.survey_site_data.mapping.SurveySiteMapper() + mapper = abis_mapping.templates.survey_site_data_v2.mapping.SurveySiteMapper() # Modify schema to only fields required for test descriptor = {"fields": [field for field in mapper.schema()["fields"] if field["name"] in rawh]} @@ -218,7 +213,7 @@ def test_add_footprint_geometry_no_geometry(row_dict: dict[str, Any]) -> None: uri = rdflib.URIRef("http://example.com/abis-mapping/test") # Get mapper - mapper = abis_mapping.templates.survey_site_data.mapping.SurveySiteMapper() + mapper = abis_mapping.templates.survey_site_data_v2.mapping.SurveySiteMapper() # Call method mapper.add_footprint_geometry( @@ -263,7 +258,7 @@ def test_add_point_geometry_no_geometry(row_dict: dict[str, Any]) -> None: uri = rdflib.URIRef("http://example.com/abis-mapping/test") # Get mapper - mapper = abis_mapping.templates.survey_site_data.mapping.SurveySiteMapper() + mapper = abis_mapping.templates.survey_site_data_v2.mapping.SurveySiteMapper() # Call method mapper.add_point_geometry(