Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions bids2openminds/converter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import warnings
import os
import yaml
import pandas as pd
from ancpbids import BIDSLayout
from ancpbids.query import Artifact
Expand All @@ -18,6 +19,7 @@
("participants.tsv", "participants", ".tsv"),
("participants.json", "participants", ".json"),
("CHANGES", None, None),
("CITATION.cff", "CITATION", None),
("README", None, None),
("README.md", None, None),
]
Expand Down Expand Up @@ -77,10 +79,14 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal

subjects_id = bids_layout.get_subjects()

# imprting the dataset description file containing some of the
# importing the dataset description file containing some of the metadata
dataset_description_path = utility.table_filter(layout_df, "description")

dataset_description = utility.read_json(dataset_description_path.iat[0, 0])
citation_path = utility.table_filter(layout_df, "CITATION")
Comment thread
lzehl marked this conversation as resolved.
Resolved
citation = None
if not citation_path.empty:
with open(citation_path.iat[0, 0], encoding="utf-8") as fp:
citation = yaml.safe_load(fp)

[subjects_dict, subject_state_dict, subjects_list] = main.create_subjects(
subjects_id, layout_df, bids_layout, collection)
Expand All @@ -92,7 +98,7 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal
layout_df, input_path, collection)

dataset_version = main.create_dataset_version(
bids_layout, dataset_description, layout_df, subjects_list, file_repository, behavioral_protocols, collection)
bids_layout, citation, dataset_description, layout_df, subjects_list, file_repository, behavioral_protocols, collection)

dataset = main.create_dataset(
dataset_description, dataset_version, collection)
Expand Down
82 changes: 64 additions & 18 deletions bids2openminds/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,35 @@ def create_openminds_person(full_name):


def create_persons(dataset_description, collection):
# citation.cff case
if "authors" in dataset_description:
person_list = dataset_description["authors"]
openminds_list=[]
for person in person_list:
person_orcid = None
person_affiliation = None
person_contact_information = None
if 'orcid' in person:
person_orcid = [omcore.ORCID(identifier=person['orcid'])]
if 'email' in person:
person_contact_information = omcore.ContactInformation(email=person['email'])
if 'affiliation' in person:
# Handle multiple affiliations separated by semicolon
affiliation_list = [item.strip() for item in person['affiliation'].split(';')]
person_affiliation = []
for affiliation in affiliation_list:
person_affiliation.append(omcore.Affiliation(
member_of=omcore.Organization(full_name=affiliation)))

openminds_person = omcore.Person(
affiliations=person_affiliation, digital_identifiers=person_orcid, given_name=person['given-names'],
family_name=person['family-names'], contact_information=person_contact_information)
openminds_list.append(openminds_person)
collection.add(openminds_person)
return openminds_list

if "Authors" in dataset_description:
# dataset_description.json case
elif "Authors" in dataset_description:
person_list = dataset_description["Authors"]
else:
return None
Expand Down Expand Up @@ -185,21 +212,39 @@ def create_openminds_age(data_subject):
return None


def create_dataset_version(bids_layout, dataset_description, layout_df, studied_specimens, file_repository, behavioral_protocols, collection):
def create_dataset_version(bids_layout, citation, dataset_description, layout_df, studied_specimens, file_repository, behavioral_protocols, collection):

# Fetch the dataset type from dataset description file

# dataset_type=bids2openminds_instance(dataset_description.get("DatasetType",None))

# Fetch the digitalIdentifier from dataset description file

if "DatasetDOI" in dataset_description:
digital_identifier = omcore.DOI(
identifier=dataset_description["DatasetDOI"])
license = None
digital_identifier = None
name = None
version_identifier = None
# General rules on the usage of CITATION.cff and dataset_description.json
# https://bids-specification.readthedocs.io/en/stable/modality-agnostic-files/dataset-description.html#citationcff
if citation:
if 'doi' in citation:
digital_identifier = omcore.DOI(identifier=citation['doi'])
if 'license' in citation:
license = omcore.License.by_name(citation['license'])
Comment thread
Raphael-Gazzotti marked this conversation as resolved.
Resolved
if license is None:
warn(f"Could not resolve license '{citation['license']}' "
"to an openMINDS License."
)
if 'title' in citation:
Comment thread
Raphael-Gazzotti marked this conversation as resolved.
Resolved
name = citation['title']
if 'version' in citation:
version_identifier = citation['version']
authors = create_persons(citation, collection)
else:
digital_identifier = None
# if CITATION.cff is present, the "Authors" field of dataset_description.json MUST be omitted
authors = create_persons(dataset_description, collection)

authors = create_persons(dataset_description, collection)
name = dataset_description["Name"] if name is None else name
# Fetch the digitalIdentifier from dataset description file
if digital_identifier is None and "DatasetDOI" in dataset_description:
digital_identifier = omcore.DOI(identifier=dataset_description["DatasetDOI"])

if "Acknowledgements" in dataset_description:
other_contribution = dataset_description["Acknowledgements"]
Expand Down Expand Up @@ -235,19 +280,20 @@ def create_dataset_version(bids_layout, dataset_description, layout_df, studied_
experimental_approaches = create_approaches(layout_df)

dataset_version = omcore.DatasetVersion(
authors=authors,
behavioral_protocols=behavioral_protocols,
data_types=dataset_type,
digital_identifier=digital_identifier,
experimental_approaches=experimental_approaches,
short_name=dataset_description["Name"],
full_name=dataset_description["Name"],
studied_specimens=studied_specimens,
authors=authors,
techniques=techniques,
full_name=name,
how_to_cite=how_to_cite,
license=license,
repository=file_repository,
behavioral_protocols=behavioral_protocols,
data_types=dataset_type
short_name=name,
studied_specimens=studied_specimens,
techniques=techniques,
version_identifier=version_identifier,
# other_contributions=other_contribution # needs to be a Contribution object
# version_identifier
)

collection.add(dataset_version)
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ dependencies = [
"openminds >= 0.2.3",
"click>=8.1",
"pandas",
"nameparser >= 1.1.3"
"nameparser >= 1.1.3",
"PyYAML >= 6.0"
]
requires-python = ">=3.9"
authors = [
Expand Down
63 changes: 63 additions & 0 deletions test/test_dataset_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import pytest

import pandas as pd
from openminds import Collection
import openminds.v4.core as omcore

from bids2openminds.main import create_dataset_version

# Mock BIDS layout DataFrame
layout_df = pd.DataFrame({
"suffix": ["T1w", "T2w", "bold"],
"path": ["sub-01/anat/sub-01_T1w.nii.gz", "sub-01/anat/sub-01_T2w.nii.gz", "sub-01/func/sub-01_task-rest_bold.nii.gz"],
"datatype": ["anat", "anat", "func"]
})


def test_create_dataset_version_citation():
Comment thread
Raphael-Gazzotti marked this conversation as resolved.
Resolved
# Mock loaded CITATION.cff
citation = {
Comment thread
Raphael-Gazzotti marked this conversation as resolved.
Resolved
"title": "My Dataset",
"version": "1.05.9",
"doi": "10.5281/zenodo.123456",
"license": "Apache-2.0"
}

citation_dataset_version = create_dataset_version(
"", citation, {}, layout_df, [], [], [], Collection()
)

expected = omcore.DatasetVersion(
digital_identifier=omcore.DOI(identifier="10.5281/zenodo.123456"),
full_name="My Dataset",
short_name="My Dataset",
license=omcore.License.apache_2_0,
version_identifier="1.05.9"
)

for field in ["full_name", "short_name", "version_identifier", "license"]:
assert getattr(citation_dataset_version, field) == getattr(expected, field)
assert citation_dataset_version.digital_identifier.identifier == expected.digital_identifier.identifier


def test_create_dataset_version_without_citation():
# Mock missing CITATION.cff
citation = None
dataset_description = {
"Name": "My Dataset",
"DatasetDOI": "10.5281/zenodo.123456"
}

dataset_version = create_dataset_version(
"", citation, dataset_description, layout_df, [], [], [], Collection()
)

expected = omcore.DatasetVersion(
digital_identifier=omcore.DOI(identifier="10.5281/zenodo.123456"),
full_name="My Dataset",
short_name="My Dataset"
)

for field in ["full_name", "short_name"]:
assert getattr(dataset_version, field) == getattr(expected, field)
assert dataset_version.digital_identifier.identifier == expected.digital_identifier.identifier
59 changes: 58 additions & 1 deletion test/test_person.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# test for create_openminds_person function in the main
import pytest
from bids2openminds.main import create_openminds_person

from openminds import Collection
import openminds.v4.core as omcore

from bids2openminds.main import create_openminds_person, create_persons

# Test data: (full_name, given_name, family_name)
example_names = [("John Ronald Reuel Tolkien", "John Ronald Reuel", "Tolkien"),
("Bilbo Baggins", "Bilbo", "Baggins"),
Expand All @@ -28,6 +31,60 @@ def test_create_openminds_person(full_name, given_name, family_name):
# assert openminds_person_object == bids2openminds_person_object


def test_create_openminds_person_citation_explicit():
citation = {
"authors": [
{
"family-names": "Awart",
"given-names": "Peter",
"affiliation": "Place1",
"orcid": "https://orcid.org/1234-5678-9123-4567"
},
{
"family-names": "Detienne",
"given-names": "Franck",
"affiliation": "Place1; Place2"
}
]
}

persons = create_persons(citation, Collection())
author1 = persons[0]
author2 = persons[1]

# Expected objects
expected_author1 = omcore.Person(
given_name="Peter",
family_name="Awart",
affiliations=[
omcore.Affiliation(member_of=omcore.Organization(full_name="Place1"))
],
digital_identifiers=[omcore.ORCID(identifier="https://orcid.org/1234-5678-9123-4567")]
)

expected_author2 = omcore.Person(
given_name="Franck",
family_name="Detienne",
affiliations=[
omcore.Affiliation(member_of=omcore.Organization(full_name="Place1")),
omcore.Affiliation(member_of=omcore.Organization(full_name="Place2"))
]
)

assert author1.given_name == expected_author1.given_name
assert author1.family_name == expected_author1.family_name
assert author1.digital_identifiers[0].identifier == expected_author1.digital_identifiers[0].identifier
assert author2.given_name == expected_author2.given_name
assert author2.family_name == expected_author2.family_name

# Single affiliation
assert author1.affiliations[0].member_of.full_name == expected_author1.affiliations[0].member_of.full_name

# Multiple affiliations
assert author2.affiliations[0].member_of.full_name == expected_author2.affiliations[0].member_of.full_name
assert author2.affiliations[1].member_of.full_name == expected_author2.affiliations[1].member_of.full_name


@pytest.mark.parametrize("full_not_name", example_not_names)
def test_create_openminds_person_not_names(full_not_name):
bids2openminds_person_object = create_openminds_person(full_not_name)
Expand Down
Loading