def export_csv(dir, overwrite_existing, template):
    dir = Path(dir)
    export = DocumentExport(UserTemplate.load(template) if template else DWC)
    for p in dir.glob('*' + InselectDocument.EXTENSION):
        try:
            debug_print('Loading [{0}]'.format(p))
            doc = InselectDocument.load(p)
            validation = export.validation_problems(doc)
            csv_path = export.csv_path(doc)
            if validation.any_problems:
                print(
                    'Not exporting metadata for [{0}] because there are '
                    'validation problems'.format(p)
                )
                for msg in format_validation_problems(validation):
                    print(msg)
            elif not overwrite_existing and csv_path.is_file():
                print('CSV file [{0}] exists - skipping'.format(csv_path))
            else:
                print('Writing CSV for [{0}]'.format(p))
                export.export_csv(doc)
        except KeyboardInterrupt:
            raise
        except Exception:
            print('Error saving CSV from [{0}]'.format(p))
            traceback.print_exc()
Exemple #2
0
def save_crops(dir, overwrite_existing, template):
    dir = Path(dir)
    export = DocumentExport(UserTemplate.load(template) if template else DWC)
    for p in dir.glob('*' + InselectDocument.EXTENSION):
        try:
            debug_print('Loading [{0}]'.format(p))
            doc = InselectDocument.load(p)
            validation = export.validation_problems(doc)
            if validation.any_problems:
                print(
                    u'Not saving crops for [{0}] because there are validation '
                    u'problems'.format(p)
                )
                for msg in format_validation_problems(validation):
                    print(msg)
            elif not overwrite_existing and doc.crops_dir.is_dir():
                print(u'Crops dir [{0}] exists - skipping'.format(doc.crops_dir))
            else:
                print(u'Will save crops for [{0}] to [{1}]'.format(p, doc.crops_dir))

                debug_print(u'Loading full-resolution scanned image')
                doc.scanned.array

                debug_print(u'Saving crops')
                export.save_crops(doc)
        except Exception:
            print(u'Error saving crops from [{0}]'.format(p))
            traceback.print_exc()
Exemple #3
0
    def test_export_csv_invalid_document(self, mock_question, mock_setdetailed,
                                         mock_settext):
        """The user wants to export to CSV for a document with a single
        validation failure
        """
        w = self.window

        w.open_document(path=TESTDATA / 'shapes.inselect')

        template = UserTemplate({
            'Name': 'T1',
            'Fields': [{'Name': 'F1'}],
            'Cropped file suffix': '.jpg',
            'Thumbnail width pixels': 5000,
            'Object label': '{catalogNumber}',
        })

        # Set the catalogNumber for each box to the same value, creating a
        # single validation problem
        for index in (w.model.index(row, 0) for row in range(5)):
            w.model.setData(index, {'catalogNumber': '1234'}, MetadataRole)

        w.export_csv(user_template=template)

        # Close the document
        with patch.object(QMessageBox, 'question', return_value=QMessageBox.No):
            self.assertTrue(self.window.close_document())

        # Should have been called
        self.assertEqual(1, mock_settext.call_count)
        self.assertIn('The document contains 1 validation problems',
                      mock_settext.call_args[0][0])

        # Detailed text should not have been given
        self.assertEqual(0, mock_setdetailed.call_count)
def save_crops(dir, overwrite_existing, template):
    dir = Path(dir)
    export = DocumentExport(UserTemplate.load(template) if template else DWC)
    for p in dir.glob('*' + InselectDocument.EXTENSION):
        try:
            debug_print('Loading [{0}]'.format(p))
            doc = InselectDocument.load(p)
            validation = export.validation_problems(doc)
            if validation.any_problems:
                print(
                    'Not saving crops for [{0}] because there are validation '
                    'problems'.format(p)
                )
                for msg in format_validation_problems(validation):
                    print(msg)
            elif not overwrite_existing and doc.crops_dir.is_dir():
                print('Crops dir [{0}] exists - skipping'.format(doc.crops_dir))
            else:
                print('Will save crops for [{0}] to [{1}]'.format(p, doc.crops_dir))

                debug_print('Loading full-resolution scanned image')
                doc.scanned.array

                debug_print('Saving crops')
                export.save_crops(doc)
        except KeyboardInterrupt:
            raise
        except Exception:
            print('Error saving crops from [{0}]'.format(p))
            traceback.print_exc()
class TestCropFnameCollision(unittest.TestCase):
    TEMPLATE = UserTemplate({
        'Name': 'Test',
        'Cropped file suffix': '.png',
        'Thumbnail width pixels': 4096,
        'Object label': '{scientificName}',
        'Fields': [{
            'Name': 'scientificName'
        }]
    })

    def test_fname_collison(self):
        "Duplicated crop fnames have numerical suffixes to avoid collisions"

        class FakeDocument(object):
            pass

        document = FakeDocument()
        document.items = [{
            "fields": {
                "scientificName": "A"
            },
        }, {
            "fields": {
                "scientificName": "A"
            },
        }, {
            "fields": {
                "scientificName": "A"
            },
        }, {
            "fields": {
                "scientificName": "D"
            },
        }, {
            "fields": {
                "scientificName": "B"
            },
        }, {
            "fields": {
                "scientificName": "D"
            },
        }, {
            "fields": {
                "scientificName": "A"
            },
        }]

        fnames = list(DocumentExport(self.TEMPLATE).crop_fnames(document))
        self.assertEqual([
            'A.png', 'A-1.png', 'A-2.png', 'D.png', 'B.png', 'D-1.png',
            'A-3.png'
        ], fnames)
 def test_from_file(self):
     "Load from a YAML file"
     doc = UserTemplate.load(TESTDATA / 'test.inselect_template')
     self.assertEqual(doc.name, "Test user template")
     self.assertEqual(doc.cropped_file_suffix, '.jpg')
     self.assertEqual(doc.thumbnail_width_pixels, 4096)
     self.assertEqual(4, len(doc.fields))
     self.assertEqual('Department', doc.fields[0].name)
     self.assertEqual('Palaeontology', doc.fields[0].fixed_value)
     self.assertEqual('catalogNumber', doc.fields[1].name)
     self.assertEqual('Catalog number', doc.fields[1].label)
     self.assertEqual('http://rs.tdwg.org/dwc/terms/catalogNumber',
                      doc.fields[1].uri)
     self.assertTrue(doc.fields[1].mandatory)
     self.assertEqual('Catalog number', doc.fields[1].label)
     self.assertEqual('Location', doc.fields[2].name)
     self.assertTrue(doc.fields[2].mandatory)
     self.assertEqual('Taxonomy', doc.fields[3].name)
     self.assertTrue(doc.fields[3].mandatory)
Exemple #7
0
    def test_save_crops_invalid_document(self, mock_question, mock_setdetailed,
                                         mock_settext):
        """The user wants to export crops for a document with many validation
        failures
        """
        w = self.window

        # This document has 15 validation problems with this template
        w.open_document(path=TESTDATA / 'shapes.inselect')
        template = UserTemplate.load(TESTDATA / 'test.inselect_template')

        w.save_crops(user_template=template)

        # Close the document
        self.assertTrue(w.close_document())

        # Should have been called
        self.assertEqual(1, mock_settext.call_count)
        self.assertIn('The document contains 15 validation problems',
                      mock_settext.call_args[0][0])

        # Detailed text should not have been given
        self.assertEqual(1, mock_setdetailed.call_count)
class TestUserTemplate(unittest.TestCase):
    TEMPLATE = UserTemplate({
        'Name':
        'T1',
        'Fields': [{
            'Name': 'F1'
        }],
        'Cropped file suffix':
        '.tiff',
        'Thumbnail width pixels':
        5000,
        'Object label':
        '{ItemNumber:03}-{First}-{Second}-{Second-value}-{Last}',
        'Fields': [
            {
                'Name': 'First',
                'Mandatory': True,
                'Choices': ['A', 'B']
            },
            {
                'Name': 'Second',
                'Choices with data': OrderedDict([
                    ('ABC', 0),
                    ('DEF', 1),
                ]),
            },
            {
                'Name': 'Third',
                'Parser': 'int'
            },
            {
                'Name': 'Last',
                'Regex parser': '^[0-9]{9}$'
            },
        ],
    })

    def test_str_repr(self):
        t = self.TEMPLATE
        self.assertEqual('UserTemplate [T1] with 4 fields', str(t))
        self.assertEqual('<UserTemplate [T1] with 4 fields>', repr(t))

    def test_properties(self):
        t = self.TEMPLATE
        self.assertEqual('T1', t.name)
        self.assertEqual('.tiff', t.cropped_file_suffix)
        self.assertEqual(5000, t.thumbnail_width_pixels)
        self.assertEqual(4, len(t.fields))

        self.assertEqual('First', t.fields[0].name)
        self.assertTrue(t.fields[0].mandatory)
        self.assertEqual(['A', 'B'], t.fields[0].choices)
        self.assertIsNone(t.fields[0].choices_with_data)
        self.assertIsNone(t.fields[0].parse_fn)

        self.assertEqual('Second', t.fields[1].name)
        self.assertFalse(t.fields[1].mandatory)
        self.assertIsNone(t.fields[1].choices)
        self.assertEqual(OrderedDict([('ABC', 0), ('DEF', 1)]),
                         t.fields[1].choices_with_data)
        self.assertIsNone(t.fields[1].parse_fn)

        self.assertEqual('Third', t.fields[2].name)
        self.assertTrue(t.fields[2].parse_fn)

        self.assertEqual('Last', t.fields[3].name)
        self.assertTrue(t.fields[3].parse_fn)

    def test_field_names(self):
        t = self.TEMPLATE
        self.assertEqual(
            RESERVED_FIELD_NAMES +
            ('First', 'Second', 'Second-value', 'Third', 'Last'),
            tuple(t.field_names()))

    def test_format_label(self):
        t = self.TEMPLATE
        metadata = {'Second': 'DEF', 'Last': '22'}
        self.assertEqual('010--DEF-1-22', t.format_label(10, metadata))

    def test_validate_field_mandatory(self):
        t = self.TEMPLATE
        self.assertTrue(t.validate_field('Second', 'ABC'))
        self.assertTrue(t.validate_field('Not a field', '123'))
        self.assertFalse(t.validate_field('First', ''))
        self.assertTrue(t.validate_field('First', 'A'))

    def test_validate_field_parser(self):
        t = self.TEMPLATE
        self.assertTrue(t.validate_field('Third', ''))
        self.assertFalse(t.validate_field('Third', 'x'))
        self.assertTrue(t.validate_field('Third', '123'))

    def test_validate_field_parser_regex(self):
        t = self.TEMPLATE
        self.assertTrue(t.validate_field('Last', ''))
        self.assertFalse(t.validate_field('Last', '12345678'))
        self.assertTrue(t.validate_field('Last', '123456789'))

    def test_validate_metadata_fail_parse(self):
        t = self.TEMPLATE
        self.assertTrue(t.validate_metadata({'First': 'A', 'Third': ''}))
        self.assertFalse(t.validate_metadata({'First': 'A', 'Third': 'xyz'}))
        self.assertTrue(t.validate_metadata({'First': 'A', 'Third': '0'}))
        self.assertTrue(t.validate_metadata({'First': 'A', 'Third': '1'}))

    def test_validate_metadata_missing_mandatory(self):
        t = self.TEMPLATE
        self.assertFalse(t.validate_metadata({'First': ''}))
        self.assertTrue(t.validate_metadata({'First': 'A'}))

    def test_validate_not_in_choices(self):
        t = self.TEMPLATE
        self.assertFalse(t.validate_metadata({'First': 'xyz'}))
        self.assertFalse(t.validate_metadata({'Second': 'xyz'}))

    def test_from_file(self):
        "Load from a YAML file"
        doc = UserTemplate.load(TESTDATA / 'test.inselect_template')
        self.assertEqual(doc.name, "Test user template")
        self.assertEqual(doc.cropped_file_suffix, '.jpg')
        self.assertEqual(doc.thumbnail_width_pixels, 4096)
        self.assertEqual(4, len(doc.fields))
        self.assertEqual('Department', doc.fields[0].name)
        self.assertEqual('Palaeontology', doc.fields[0].fixed_value)
        self.assertEqual('catalogNumber', doc.fields[1].name)
        self.assertEqual('Catalog number', doc.fields[1].label)
        self.assertEqual('http://rs.tdwg.org/dwc/terms/catalogNumber',
                         doc.fields[1].uri)
        self.assertTrue(doc.fields[1].mandatory)
        self.assertEqual('Catalog number', doc.fields[1].label)
        self.assertEqual('Location', doc.fields[2].name)
        self.assertTrue(doc.fields[2].mandatory)
        self.assertEqual('Taxonomy', doc.fields[3].name)
        self.assertTrue(doc.fields[3].mandatory)
 def _load(self, path):
     "Loads the UserTemplate in path"
     debug_print('UserTemplateChoice._load [{0}]'.format(path))
     return UserTemplate.load(path)
 def _load(self, path):
     "Loads the UserTemplate in path"
     debug_print('UserTemplateChoice._load [{0}]'.format(path))
     return UserTemplate.load(path)
class TestDocumentExportWithTemplate(unittest.TestCase):
    TEMPLATE = UserTemplate({
        'Name':
        'Test',
        'Cropped file suffix':
        '.png',
        'Thumbnail width pixels':
        4096,
        'Object label':
        '{ItemNumber:02}_{scientificName-value}',
        'Fields': [
            {
                'Name': 'catalogNumber',
            },
            {
                'Name': 'Department',
                'Fixed value': 'Entomology',
            },
            {
                'Name':
                'scientificName',
                'Choices with data': [
                    ('A', 1),
                    ('B', 2),
                    ('Elsinoë', 3),
                    ('D', 4),
                    ('インセクト', 10),
                ],
            },
        ]
    })

    def test_save_crops(self):
        "Cropped object images are written correctly"
        with temp_directory_with_files(TESTDATA / 'shapes.inselect',
                                       TESTDATA / 'shapes.png') as tempdir:
            doc = InselectDocument.load(tempdir / 'shapes.inselect')

            crops_dir = DocumentExport(self.TEMPLATE).save_crops(doc)

            self.assertTrue(crops_dir.is_dir())
            self.assertEqual(crops_dir, doc.crops_dir)

            cropped_fnames = sorted(crops_dir.glob('*.png'))
            self.assertEqual(
                ['01_1.png', '02_2.png', '03_10.png', '04_3.png', '05_4.png'],
                [f.name for f in cropped_fnames])

            # Check the contents of each file
            boxes = doc.scanned.from_normalised(i['rect'] for i in doc.items)
            for box, path in zip(boxes, sorted(crops_dir.glob('*.png'))):
                x0, y0, x1, y1 = box.coordinates
                self.assertTrue(
                    np.all(doc.scanned.array[y0:y1,
                                             x0:x1] == cv2.imread(str(path))))

    def test_cancel_save_crops(self):
        "User cancels save crops"
        with temp_directory_with_files(TESTDATA / 'shapes.inselect',
                                       TESTDATA / 'shapes.png') as tempdir:
            doc = InselectDocument.load(tempdir / 'shapes.inselect')

            # Create crops dir with some data
            doc.crops_dir.mkdir()
            with doc.crops_dir.joinpath('a_file').open('w') as outfile:
                outfile.write('Some data\n')

            class CancelExport(Exception):
                pass

            def progress(msg):
                "A progress function that cancels the export"
                raise CancelExport()

            self.assertRaises(CancelExport,
                              DocumentExport(self.TEMPLATE).save_crops,
                              doc,
                              progress=progress)

            # Nothing should have changed within tempdir
            self.assertEqual(
                ['shapes.inselect', 'shapes.png', doc.crops_dir.name],
                sorted(p.name for p in tempdir.iterdir()))
            self.assertEqual(['a_file'],
                             [p.name for p in doc.crops_dir.iterdir()])

    def test_csv_export(self):
        "CSV data are exported as expected"
        with temp_directory_with_files(TESTDATA / 'shapes.inselect',
                                       TESTDATA / 'shapes.png') as tempdir:
            doc = InselectDocument.load(tempdir / 'shapes.inselect')

            csv_path = DocumentExport(self.TEMPLATE).export_csv(doc)
            self.assertEqual(csv_path, tempdir / 'shapes.csv')

            # Check CSV contents

            with csv_path.open('rb') as f:
                reader = unicodecsv.reader(f, encoding='utf8')
                headers = [
                    'Cropped_image_name', 'ItemNumber', 'NormalisedLeft',
                    'NormalisedTop', 'NormalisedRight', 'NormalisedBottom',
                    'ThumbnailLeft', 'ThumbnailTop', 'ThumbnailRight',
                    'ThumbnailBottom', 'OriginalLeft', 'OriginalTop',
                    'OriginalRight', 'OriginalBottom', 'catalogNumber',
                    'Department', 'scientificName', 'scientificName-value'
                ]
                self.assertEqual(headers, next(reader))

                # Check only the metadata columns and 'original' coordinates
                # columns, ignoring thumbnail (which doesn't exist)
                # and normalised (which are floating point) coordinates
                metadata_cols = itemgetter(0, 1, 10, 11, 12, 13, 14, 15, 16,
                                           17)
                self.assertEqual(('01_1.png', '1', '0', '0', '189', '189', '1',
                                  'Entomology', 'A', '1'),
                                 metadata_cols(next(reader)))
                self.assertEqual(('02_2.png', '2', '271', '0', '459', '189',
                                  '2', 'Entomology', 'B', '2'),
                                 metadata_cols(next(reader)))
                self.assertEqual(('03_10.png', '3', '194', '196', '257', '232',
                                  '3', 'Entomology', 'インセクト', '10'),
                                 metadata_cols(next(reader)))
                self.assertEqual(('04_3.png', '4', '0', '248', '189', '437',
                                  '4', 'Entomology', 'Elsinoë', '3'),
                                 metadata_cols(next(reader)))
                self.assertEqual(('05_4.png', '5', '271', '248', '459', '437',
                                  '5', 'Entomology', 'D', '4'),
                                 metadata_cols(next(reader)))
                self.assertIsNone(next(reader, None))
Exemple #12
0
DWC = UserTemplate.from_specification({
    'Name': 'Simple Darwin Core terms',
    'Fields': [
        {
            "Group": "Identifier",
            "Name": "occurrenceID",
            "Label": "Occurrence ID",
            "URI": "http://rs.tdwg.org/dwc/terms/occurrenceID",
        },
        {
            "Group": "Identifier",
            "Name": "organismID",
            "Label": "Organism ID",
            "URI": "http://rs.tdwg.org/dwc/terms/organismID",
        },
        {
            "Group": "Identifier",
            "Name": "materialSampleID",
            "Label": "Material sample ID",
            "URI": "http://rs.tdwg.org/dwc/terms/materialSampleID",
        },
        {
            "Group": "Identifier",
            "Name": "eventID",
            "Label": "Event ID",
            "URI": "http://rs.tdwg.org/dwc/terms/eventID",
        },
        {
            "Group": "Identifier",
            "Name": "locationID",
            "Label": "Location ID",
            "URI": "http://rs.tdwg.org/dwc/terms/locationID",
        },
        {
            "Group": "Identifier",
            "Name": "geologicalContextID",
            "Label": "Geological context ID",
            "URI": "http://rs.tdwg.org/dwc/terms/geologicalContextID",
        },
        {
            "Group": "Identifier",
            "Name": "identificationID",
            "Label": "Identification ID",
            "URI": "http://rs.tdwg.org/dwc/terms/identificationID",
        },
        {
            "Group": "Identifier",
            "Name": "taxonID",
            "Label": "Taxon ID",
            "URI": "http://rs.tdwg.org/dwc/terms/taxonID",
        },
        {
            "Group": "Record level",
            "Name": "type",
            "Label": "Type",
            "URI": "http://purl.org/dc/terms/type",
        },
        {
            "Group": "Record level",
            "Name": "modified",
            "Label": "Modified",
            "URI": "http://purl.org/dc/terms/modified"
        },
        {
            "Group": "Record level",
            "Name": "language",
            "Label": "Language",
            "URI": "http://purl.org/dc/terms/language"
        },
        {
            "Group": "Record level",
            "Name": "license",
            "Label": "License",
            "URI": "http://purl.org/dc/terms/license"
        },
        {
            "Group": "Record level",
            "Name": "rightsHolder",
            "Label": "Rights holder",
            "URI": "http://purl.org/dc/terms/rightsHolder"
        },
        {
            "Group": "Record level",
            "Name": "accessRights",
            "Label": "Access rights",
            "URI": "http://purl.org/dc/terms/accessRights"
        },
        {
            "Group": "Record level",
            "Name": "bibliographicCitation",
            "Label": "Bibliographic citation",
            "URI": "http://purl.org/dc/terms/bibliographicCitation"
        },
        {
            "Group": "Record level",
            "Name": "references",
            "Label": "References",
            "URI": "http://purl.org/dc/terms/references"
        },
        {
            "Group": "Record level",
            "Name": "institutionID",
            "Label": "Institution ID",
            "URI": "http://rs.tdwg.org/dwc/terms/institutionID",
        },
        {
            "Group": "Record level",
            "Name": "collectionID",
            "Label": "Collection ID",
            "URI": "http://rs.tdwg.org/dwc/terms/collectionID",
        },
        {
            "Group": "Record level",
            "Name": "datasetID",
            "Label": "Dataset ID",
            "URI": "http://rs.tdwg.org/dwc/terms/datasetID",
        },
        {
            "Group": "Record level",
            "Name": "institutionCode",
            "Label": "Institution code",
            "URI": "http://rs.tdwg.org/dwc/terms/institutionCode",
        },
        {
            "Group": "Record level",
            "Name": "collectionCode",
            "Label": "Collection code",
            "URI": "http://rs.tdwg.org/dwc/terms/collectionCode",
        },
        {
            "Group": "Record level",
            "Name": "datasetName",
            "Label": "Dataset name",
            "URI": "http://rs.tdwg.org/dwc/terms/datasetName",
        },
        {
            "Group": "Record level",
            "Name": "ownerInstitutionCode",
            "Label": "Owner institution code",
            "URI": "http://rs.tdwg.org/dwc/terms/ownerInstitutionCode",
        },
        {
            "Group": "Record level",
            "Name": "basisOfRecord",
            "Label": "Basis of record",
            "URI": "http://rs.tdwg.org/dwc/terms/basisOfRecord",
        },
        {
            "Group": "Record level",
            "Name": "informationWithheld",
            "Label": "Information withheld",
            "URI": "http://rs.tdwg.org/dwc/terms/informationWithheld",
        },
        {
            "Group": "Record level",
            "Name": "dataGeneralizations",
            "Label": "Data generalizations",
            "URI": "http://rs.tdwg.org/dwc/terms/dataGeneralizations",
        },
        {
            "Group": "Record level",
            "Name": "dynamicProperties",
            "Label": "Dynamic properties",
            "URI": "http://rs.tdwg.org/dwc/terms/dynamicProperties",
        },
        {
            "Group": "Occurrence",
            "Name": "catalogNumber",
            "Label": "Catalog number",
            "URI": "http://rs.tdwg.org/dwc/terms/catalogNumber",
        },
        {
            "Group": "Occurrence",
            "Name": "recordNumber",
            "Label": "Record number",
            "URI": "http://rs.tdwg.org/dwc/terms/recordNumber",
        },
        {
            "Group": "Occurrence",
            "Name": "recordedBy",
            "Label": "Recorded by",
            "URI": "http://rs.tdwg.org/dwc/terms/recordedBy",
        },
        {
            "Group": "Occurrence",
            "Name": "individualCount",
            "Label": "Individual count",
            "URI": "http://rs.tdwg.org/dwc/terms/individualCount",
            "Parser": "int_gt0",
        },
        {
            "Group": "Occurrence",
            "Name": "sex",
            "Label": "Sex",
            "URI": "http://rs.tdwg.org/dwc/terms/sex",
        },
        {
            "Group": "Occurrence",
            "Name": "lifeStage",
            "Label": "Life stage",
            "URI": "http://rs.tdwg.org/dwc/terms/lifeStage",
        },
        {
            "Group": "Occurrence",
            "Name": "reproductiveCondition",
            "Label": "Reproductive condition",
            "URI": "http://rs.tdwg.org/dwc/terms/reproductiveCondition",
        },
        {
            "Group": "Occurrence",
            "Name": "behavior",
            "Label": "Behavior",
            "URI": "http://rs.tdwg.org/dwc/terms/behavior",
        },
        {
            "Group": "Occurrence",
            "Name": "establishmentMeans",
            "Label": "Establishment means",
            "URI": "http://rs.tdwg.org/dwc/terms/establishmentMeans",
        },
        {
            "Group": "Occurrence",
            "Name": "occurrenceStatus",
            "Label": "Occurrence status",
            "URI": "http://rs.tdwg.org/dwc/terms/occurrenceStatus",
        },
        {
            "Group": "Occurrence",
            "Name": "preparations",
            "Label": "Preparations",
            "URI": "http://rs.tdwg.org/dwc/terms/preparations",
        },
        {
            "Group": "Occurrence",
            "Name": "disposition",
            "Label": "Disposition",
            "URI": "http://rs.tdwg.org/dwc/terms/disposition",
        },
        {
            "Group": "Occurrence",
            "Name": "associatedMedia",
            "Label": "Associated media",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedMedia",
        },
        {
            "Group": "Occurrence",
            "Name": "associatedReferences",
            "Label": "Associated references",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedReferences",
        },
        {
            "Group": "Occurrence",
            "Name": "associatedSequences",
            "Label": "Associated sequences",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedSequences",
        },
        {
            "Group": "Occurrence",
            "Name": "associatedTaxa",
            "Label": "Associated taxa",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedTaxa",
        },
        {
            "Group": "Occurrence",
            "Name": "otherCatalogNumbers",
            "Label": "Other catalog numbers",
            "URI": "http://rs.tdwg.org/dwc/terms/otherCatalogNumbers",
        },
        {
            "Group": "Occurrence",
            "Name": "occurrenceRemarks",
            "Label": "Occurrence remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/occurrenceRemarks",
        },
        {
            "Group": "Organism",
            "Name": "organismName",
            "Label": "Organism name",
            "URI": "http://rs.tdwg.org/dwc/terms/organismName",
        },
        {
            "Group": "Organism",
            "Name": "organismScope",
            "Label": "Organism scope",
            "URI": "http://rs.tdwg.org/dwc/terms/organismScope",
        },
        {
            "Group": "Organism",
            "Name": "associatedOccurrences",
            "Label": "Associated occurrences",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedOccurrences",
        },
        {
            "Group": "Organism",
            "Name": "associatedOrganisms",
            "Label": "Associated organisms",
            "URI": "http://rs.tdwg.org/dwc/terms/associatedOrganisms",
        },
        {
            "Group": "Organism",
            "Name": "previousIdentifications",
            "Label": "Previous identifications",
            "URI": "http://rs.tdwg.org/dwc/terms/previousIdentifications",
        },
        {
            "Group": "Organism",
            "Name": "organismRemarks",
            "Label": "Organism remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/organismRemarks",
        },
        {
            "Group": "Event",
            "Name": "eventDate",
            "Label": "Event date",
            "URI": "http://rs.tdwg.org/dwc/terms/eventDate",
            "Parser": "date",
        },
        {
            "Group": "Event",
            "Name": "eventTime",
            "Label": "Event time",
            "URI": "http://rs.tdwg.org/dwc/terms/eventTime",
            # TODO Parser
        },
        {
            "Group": "Event",
            "Name": "startDayOfYear",
            "Label": "Start day of year",
            "URI": "http://rs.tdwg.org/dwc/terms/startDayOfYear",
        },
        {
            "Group": "Event",
            "Name": "endDayOfYear",
            "Label": "End day of year",
            "URI": "http://rs.tdwg.org/dwc/terms/endDayOfYear",
        },
        {
            "Group": "Event",
            "Name": "year",
            "Label": "Year",
            "URI": "http://rs.tdwg.org/dwc/terms/year",
            "Parser": "four_digit_int",
        },
        {
            "Group": "Event",
            "Name": "month",
            "Label": "Month",
            "URI": "http://rs.tdwg.org/dwc/terms/month",
            "Parser": "one_or_two_digit_int",
        },
        {
            "Group": "Event",
            "Name": "day",
            "Label": "Day",
            "URI": "http://rs.tdwg.org/dwc/terms/day",
            "Parser": "one_or_two_digit_int",
        },
        {
            "Group": "Event",
            "Name": "verbatimEventDate",
            "Label": "Verbatim event date",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimEventDate",
        },
        {
            "Group": "Event",
            "Name": "habitat",
            "Label": "Habitat",
            "URI": "http://rs.tdwg.org/dwc/terms/habitat",
        },
        {
            "Group": "Event",
            "Name": "fieldNumber",
            "Label": "Field number",
            "URI": "http://rs.tdwg.org/dwc/terms/fieldNumber",
        },
        {
            "Group": "Event",
            "Name": "samplingProtocol",
            "Label": "Sampling protocol",
            "URI": "http://rs.tdwg.org/dwc/terms/samplingProtocol",
        },
        {
            "Group": "Event",
            "Name": "samplingEffort",
            "Label": "Sampling effort",
            "URI": "http://rs.tdwg.org/dwc/terms/samplingEffort",
        },
        {
            "Group": "Event",
            "Name": "fieldNotes",
            "Label": "Field notes",
            "URI": "http://rs.tdwg.org/dwc/terms/fieldNotes",
        },
        {
            "Group": "Event",
            "Name": "eventRemarks",
            "Label": "Event remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/eventRemarks",
        },
        {
            "Group": "Location",
            "Name": "higherGeographyID",
            "Label": "Higher geography ID",
            "URI": "http://rs.tdwg.org/dwc/terms/higherGeographyID",
        },
        {
            "Group": "Location",
            "Name": "higherGeography",
            "Label": "Higher geography",
            "URI": "http://rs.tdwg.org/dwc/terms/higherGeography",
        },
        {
            "Group": "Location",
            "Name": "continent",
            "Label": "Continent",
            "URI": "http://rs.tdwg.org/dwc/terms/continent",
        },
        {
            "Group": "Location",
            "Name": "waterbody",
            "Label": "Waterbody",
            "URI": "http://rs.tdwg.org/dwc/terms/waterbody",
        },
        {
            "Group": "Location",
            "Name": "islandGroup",
            "Label": "Island group",
            "URI": "http://rs.tdwg.org/dwc/terms/islandGroup",
        },
        {
            "Group": "Location",
            "Name": "island",
            "Label": "Island",
            "URI": "http://rs.tdwg.org/dwc/terms/island",
        },
        {
            "Group": "Location",
            "Name": "country",
            "Label": "Country",
            "URI": "http://rs.tdwg.org/dwc/terms/country",
        },
        {
            "Group": "Location",
            "Name": "countryCode",
            "Label": "Country code",
            "URI": "http://rs.tdwg.org/dwc/terms/countryCode",
        },
        {
            "Group": "Location",
            "Name": "stateProvince",
            "Label": "State province",
            "URI": "http://rs.tdwg.org/dwc/terms/stateProvince",
        },
        {
            "Group": "Location",
            "Name": "county",
            "Label": "County",
            "URI": "http://rs.tdwg.org/dwc/terms/county",
        },
        {
            "Group": "Location",
            "Name": "municipality",
            "Label": "Municipality",
            "URI": "http://rs.tdwg.org/dwc/terms/municipality",
        },
        {
            "Group": "Location",
            "Name": "locality",
            "Label": "Locality",
            "URI": "http://rs.tdwg.org/dwc/terms/locality",
        },
        {
            "Group": "Location",
            "Name": "verbatimLocality",
            "Label": "Verbatim locality",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimLocality",
        },
        {
            "Group": "Location",
            "Name": "minimumElevationInMeters",
            "Label": "Minimum elevation in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/minimumElevationInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "maximumElevationInMeters",
            "Label": "Maximum elevation in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/maximumElevationInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "verbatimElevation",
            "Label": "Verbatim elevation",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimElevation",
        },
        {
            "Group": "Location",
            "Name": "minimumDepthInMeters",
            "Label": "Minimum depth in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/minimumDepthInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "maximumDepthInMeters",
            "Label": "Maximum depth in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/maximumDepthInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "verbatimDepth",
            "Label": "Verbatim depth",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimDepth",
        },
        {
            "Group": "Location",
            "Name": "minimumDistanceAboveSurfaceInMeters",
            "Label": "Minimum distance above surface in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/minimumDistanceAboveSurfaceInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "maximumDistanceAboveSurfaceInMeters",
            "Label": "Maximum distance above surface in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/maximumDistanceAboveSurfaceInMeters",
            "Parser": "float_ge0",
        },
        {
            "Group": "Location",
            "Name": "locationRemarks",
            "Label": "Location remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/locationRemarks",
        },
        {
            "Group": "Location",
            "Name": "decimalLatitude",
            "Label": "Decimal latitude",
            "URI": "http://rs.tdwg.org/dwc/terms/decimalLatitude",
            "Parser": "latitude",
        },
        {
            "Group": "Location",
            "Name": "decimalLongitude",
            "Label": "Decimal longitude",
            "URI": "http://rs.tdwg.org/dwc/terms/decimalLongitude",
            "Parser": "longitude",
        },
        {
            "Group": "Location",
            "Name": "geodeticDatum",
            "Label": "Geodetic datum",
            "URI": "http://rs.tdwg.org/dwc/terms/geodeticDatum",
        },
        {
            "Group": "Location",
            "Name": "coordinateUncertaintyInMeters",
            "Label": "Coordinate uncertainty in meters",
            "URI": "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters",
            "Parser": "float_gt0",
        },
        {
            "Group": "Location",
            "Name": "coordinatePrecision",
            "Label": "Coordinate precision",
            "URI": "http://rs.tdwg.org/dwc/terms/coordinatePrecision",
            "Parser": "float_gt0",
        },
        {
            "Group": "Location",
            "Name": "pointRadiusSpatialFit",
            "Label": "Point radius spatial fit",
            "URI": "http://rs.tdwg.org/dwc/terms/pointRadiusSpatialFit",
        },
        {
            "Group": "Location",
            "Name": "verbatimCoordinates",
            "Label": "Verbatim coordinates",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimCoordinates",
        },
        {
            "Group": "Location",
            "Name": "verbatimLatitude",
            "Label": "Verbatim latitude",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimLatitude",
        },
        {
            "Group": "Location",
            "Name": "verbatimLongitude",
            "Label": "Verbatim longitude",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimLongitude",
        },
        {
            "Group": "Location",
            "Name": "verbatimCoordinateSystem",
            "Label": "Verbatim coordinate system",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimCoordinateSystem",
        },
        {
            "Group": "Location",
            "Name": "verbatimSRS",
            "Label": "Verbatim srs",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimSRS",
        },
        {
            "Group": "Location",
            "Name": "footprintWKT",
            "Label": "Footprint wkt",
            "URI": "http://rs.tdwg.org/dwc/terms/footprintWKT",
        },
        {
            "Group": "Location",
            "Name": "footprintSRS",
            "Label": "Footprint srs",
            "URI": "http://rs.tdwg.org/dwc/terms/footprintSRS",
        },
        {
            "Group": "Location",
            "Name": "footprintSpatialFit",
            "Label": "Footprint spatial fit",
            "URI": "http://rs.tdwg.org/dwc/terms/footprintSpatialFit",
        },
        {
            "Group": "Location",
            "Name": "georeferencedBy",
            "Label": "Georeferenced by",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferencedBy",
        },
        {
            "Group": "Location",
            "Name": "georeferencedDate",
            "Label": "Georeferenced date",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferencedDate",
            "Parser": "date",
        },
        {
            "Group": "Location",
            "Name": "georeferenceProtocol",
            "Label": "Georeference protocol",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferenceProtocol",
        },
        {
            "Group": "Location",
            "Name": "georeferenceSources",
            "Label": "Georeference sources",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferenceSources",
        },
        {
            "Group": "Location",
            "Name": "georeferenceVerificationStatus",
            "Label": "Georeference verification status",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferenceVerificationStatus",
        },
        {
            "Group": "Location",
            "Name": "georeferenceRemarks",
            "Label": "Georeference remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/georeferenceRemarks",
        },
        {
            "Group": "Geological context",
            "Name": "earliestEonOrLowestEonothem",
            "Label": "Earliest eon or lowest eonothem",
            "URI": "http://rs.tdwg.org/dwc/terms/earliestEonOrLowestEonothem",
        },
        {
            "Group": "Geological context",
            "Name": "latestEonOrHighestEonothem",
            "Label": "Latest eon or highest eonothem",
            "URI": "http://rs.tdwg.org/dwc/terms/latestEonOrHighestEonothem",
        },
        {
            "Group": "Geological context",
            "Name": "earliestEraOrLowestErathem",
            "Label": "Earliest era or lowest erathem",
            "URI": "http://rs.tdwg.org/dwc/terms/earliestEraOrLowestErathem",
        },
        {
            "Group": "Geological context",
            "Name": "latestEraOrHighestErathem",
            "Label": "Latest era or highest erathem",
            "URI": "http://rs.tdwg.org/dwc/terms/latestEraOrHighestErathem",
        },
        {
            "Group": "Geological context",
            "Name": "earliestPeriodOrLowestSystem",
            "Label": "Earliest period or lowest system",
            "URI": "http://rs.tdwg.org/dwc/terms/earliestPeriodOrLowestSystem",
        },
        {
            "Group": "Geological context",
            "Name": "latestPeriodOrHighestSystem",
            "Label": "Latest period or highest system",
            "URI": "http://rs.tdwg.org/dwc/terms/latestPeriodOrHighestSystem",
        },
        {
            "Group": "Geological context",
            "Name": "earliestEpochOrLowestSeries",
            "Label": "Earliest epoch or lowest series",
            "URI": "http://rs.tdwg.org/dwc/terms/earliestEpochOrLowestSeries",
        },
        {
            "Group": "Geological context",
            "Name": "latestEpochOrHighestSeries",
            "Label": "Latest epoch or highest series",
            "URI": "http://rs.tdwg.org/dwc/terms/latestEpochOrHighestSeries",
        },
        {
            "Group": "Geological context",
            "Name": "earliestAgeOrLowestStage",
            "Label": "Earliest age or lowest stage",
            "URI": "http://rs.tdwg.org/dwc/terms/earliestAgeOrLowestStage",
        },
        {
            "Group": "Geological context",
            "Name": "latestAgeOrHighestStage",
            "Label": "Latest age or highest stage",
            "URI": "http://rs.tdwg.org/dwc/terms/latestAgeOrHighestStage",
        },
        {
            "Group": "Geological context",
            "Name": "lowestBiostratigraphicZone",
            "Label": "Lowest biostratigraphic zone",
            "URI": "http://rs.tdwg.org/dwc/terms/lowestBiostratigraphicZone",
        },
        {
            "Group": "Geological context",
            "Name": "highestBiostratigraphicZone",
            "Label": "Highest biostratigraphic zone",
            "URI": "http://rs.tdwg.org/dwc/terms/highestBiostratigraphicZone",
        },
        {
            "Group": "Geological context",
            "Name": "lithostratigraphicTerms",
            "Label": "Lithostratigraphic terms",
            "URI": "http://rs.tdwg.org/dwc/terms/lithostratigraphicTerms",
        },
        {
            "Group": "Geological context",
            "Name": "group",
            "Label": "Group",
            "URI": "http://rs.tdwg.org/dwc/terms/group",
        },
        {
            "Group": "Geological context",
            "Name": "formation",
            "Label": "Formation",
            "URI": "http://rs.tdwg.org/dwc/terms/formation",
        },
        {
            "Group": "Geological context",
            "Name": "member",
            "Label": "Member",
            "URI": "http://rs.tdwg.org/dwc/terms/member",
        },
        {
            "Group": "Geological context",
            "Name": "bed",
            "Label": "Bed",
            "URI": "http://rs.tdwg.org/dwc/terms/bed",
        },
        {
            "Group": "Identification",
            "Name": "identificationQualifier",
            "Label": "Identification qualifier",
            "URI": "http://rs.tdwg.org/dwc/terms/identificationQualifier",
        },
        {
            "Group": "Identification",
            "Name": "typeStatus",
            "Label": "Type status",
            "URI": "http://rs.tdwg.org/dwc/terms/typeStatus",
        },
        {
            "Group": "Identification",
            "Name": "identifiedBy",
            "Label": "Identified by",
            "URI": "http://rs.tdwg.org/dwc/terms/identifiedBy",
        },
        {
            "Group": "Identification",
            "Name": "dateIdentified",
            "Label": "Date identified",
            "URI": "http://rs.tdwg.org/dwc/terms/dateIdentified",
            "Parser": "date",
        },
        {
            "Group": "Identification",
            "Name": "identificationReferences",
            "Label": "Identification references",
            "URI": "http://rs.tdwg.org/dwc/terms/identificationReferences",
        },
        {
            "Group": "Identification",
            "Name": "identificationVerificationStatus",
            "Label": "Identification verification status",
            "URI": "http://rs.tdwg.org/dwc/terms/identificationVerificationStatus",
        },
        {
            "Group": "Identification",
            "Name": "identificationRemarks",
            "Label": "Identification remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/identificationRemarks",
        },
        {
            "Group": "Taxon",
            "Name": "scientificNameID",
            "Label": "Scientific name ID",
            "URI": "http://rs.tdwg.org/dwc/terms/scientificNameID",
        },
        {
            "Group": "Taxon",
            "Name": "acceptedNameUsageID",
            "Label": "Accepted name usage ID",
            "URI": "http://rs.tdwg.org/dwc/terms/acceptedNameUsageID",
        },
        {
            "Group": "Taxon",
            "Name": "parentNameUsageID",
            "Label": "Parent name usage ID",
            "URI": "http://rs.tdwg.org/dwc/terms/parentNameUsageID",
        },
        {
            "Group": "Taxon",
            "Name": "originalNameUsageID",
            "Label": "Original name usage ID",
            "URI": "http://rs.tdwg.org/dwc/terms/originalNameUsageID",
        },
        {
            "Group": "Taxon",
            "Name": "nameAccordingToID",
            "Label": "Name according to ID",
            "URI": "http://rs.tdwg.org/dwc/terms/nameAccordingToID",
        },
        {
            "Group": "Taxon",
            "Name": "namePublishedInID",
            "Label": "Name published in ID",
            "URI": "http://rs.tdwg.org/dwc/terms/namePublishedInID",
        },
        {
            "Group": "Taxon",
            "Name": "taxonConceptID",
            "Label": "Taxon concept ID",
            "URI": "http://rs.tdwg.org/dwc/terms/taxonConceptID",
        },
        {
            "Group": "Taxon",
            "Name": "scientificName",
            "Label": "Scientific name",
            "URI": "http://rs.tdwg.org/dwc/terms/scientificName",
        },
        {
            "Group": "Taxon",
            "Name": "acceptedNameUsage",
            "Label": "Accepted name usage",
            "URI": "http://rs.tdwg.org/dwc/terms/acceptedNameUsage",
        },
        {
            "Group": "Taxon",
            "Name": "parentNameUsage",
            "Label": "Parent name usage",
            "URI": "http://rs.tdwg.org/dwc/terms/parentNameUsage",
        },
        {
            "Group": "Taxon",
            "Name": "originalNameUsage",
            "Label": "Original name usage",
            "URI": "http://rs.tdwg.org/dwc/terms/originalNameUsage",
        },
        {
            "Group": "Taxon",
            "Name": "nameAccordingTo",
            "Label": "Name according to",
            "URI": "http://rs.tdwg.org/dwc/terms/nameAccordingTo",
        },
        {
            "Group": "Taxon",
            "Name": "namePublishedIn",
            "Label": "Name published in",
            "URI": "http://rs.tdwg.org/dwc/terms/namePublishedIn",
        },
        {
            "Group": "Taxon",
            "Name": "namePublishedInYear",
            "Label": "Name published in year",
            "URI": "http://rs.tdwg.org/dwc/terms/namePublishedInYear",
            "Parser": "four_digit_int",
        },
        {
            "Group": "Taxon",
            "Name": "higherClassification",
            "Label": "Higher classification",
            "URI": "http://rs.tdwg.org/dwc/terms/higherClassification",
        },
        {
            "Group": "Taxon",
            "Name": "kingdom",
            "Label": "Kingdom",
            "URI": "http://rs.tdwg.org/dwc/terms/kingdom",
        },
        {
            "Group": "Taxon",
            "Name": "phylum",
            "Label": "Phylum",
            "URI": "http://rs.tdwg.org/dwc/terms/phylum",
        },
        {
            "Group": "Taxon",
            "Name": "class",
            "Label": "Class",
            "URI": "http://rs.tdwg.org/dwc/terms/class",
        },
        {
            "Group": "Taxon",
            "Name": "order",
            "Label": "Order",
            "URI": "http://rs.tdwg.org/dwc/terms/order",
        },
        {
            "Group": "Taxon",
            "Name": "family",
            "Label": "Family",
            "URI": "http://rs.tdwg.org/dwc/terms/family",
        },
        {
            "Group": "Taxon",
            "Name": "genus",
            "Label": "Genus",
            "URI": "http://rs.tdwg.org/dwc/terms/genus",
        },
        {
            "Group": "Taxon",
            "Name": "subgenus",
            "Label": "Subgenus",
            "URI": "http://rs.tdwg.org/dwc/terms/subgenus",
        },
        {
            "Group": "Taxon",
            "Name": "specificEpithet",
            "Label": "Specific epithet",
            "URI": "http://rs.tdwg.org/dwc/terms/specificEpithet",
        },
        {
            "Group": "Taxon",
            "Name": "infraspecificEpithet",
            "Label": "Infraspecific epithet",
            "URI": "http://rs.tdwg.org/dwc/terms/infraspecificEpithet",
        },
        {
            "Group": "Taxon",
            "Name": "taxonRank",
            "Label": "Taxon rank",
            "URI": "http://rs.tdwg.org/dwc/terms/taxonRank",
        },
        {
            "Group": "Taxon",
            "Name": "verbatimTaxonRank",
            "Label": "Verbatim taxon rank",
            "URI": "http://rs.tdwg.org/dwc/terms/verbatimTaxonRank",
        },
        {
            "Group": "Taxon",
            "Name": "scientificNameAuthorship",
            "Label": "Scientific name authorship",
            "URI": "http://rs.tdwg.org/dwc/terms/scientificNameAuthorship",
        },
        {
            "Group": "Taxon",
            "Name": "vernacularName",
            "Label": "Vernacular name",
            "URI": "http://rs.tdwg.org/dwc/terms/vernacularName",
        },
        {
            "Group": "Taxon",
            "Name": "nomenclaturalCode",
            "Label": "Nomenclatural code",
            "URI": "http://rs.tdwg.org/dwc/terms/nomenclaturalCode",
        },
        {
            "Group": "Taxon",
            "Name": "taxonomicStatus",
            "Label": "Taxonomic status",
            "URI": "http://rs.tdwg.org/dwc/terms/taxonomicStatus",
        },
        {
            "Group": "Taxon",
            "Name": "nomenclaturalStatus",
            "Label": "Nomenclatural status",
            "URI": "http://rs.tdwg.org/dwc/terms/nomenclaturalStatus",
        },
        {
            "Group": "Taxon",
            "Name": "taxonRemarks",
            "Label": "Taxon remarks",
            "URI": "http://rs.tdwg.org/dwc/terms/taxonRemarks",
        },
    ]
})