Skip to content

Commit

Permalink
Added affiliations for zenodo framework
Browse files Browse the repository at this point in the history
  • Loading branch information
jose-luis-rs committed Dec 7, 2024
1 parent 4a7126d commit fc69756
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 126 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/check_metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH, Darmstadt, Germany
#
# SPDX-License-Identifier: CC0-1.0
# SPDX-License-Identifier: LGPL-3.0-or-later

name: Check AUTHORS and CONTRIBUTORS in metadata

Expand All @@ -9,13 +9,11 @@ on:
paths:
- AUTHORS
- CONTRIBUTORS
- codemeta.json
- .zenodo.json
pull_request:
paths:
- AUTHORS
- CONTRIBUTORS
- codemeta.json
- .zenodo.json

jobs:
Expand Down
108 changes: 71 additions & 37 deletions .zenodo.json
Original file line number Diff line number Diff line change
@@ -1,65 +1,99 @@
{
"description": "The SOFIA module within the R3BRoot framework encapsulates the configuration and functionality of the SOFIA detectors, specifically designed for fission experiments conducted with the GLAD spectrometer. R3BRoot, built on the FairRoot framework, serves as a software environment for performing detailed Monte Carlo simulations and processing experimental data from R3B (Reactions with Relativistic Radioactive Beams) experiments. These capabilities include precise modeling of detector geometry, particle tracking, event reconstruction, and physics analysis, supporting the investigation of fission dynamics and nuclear structure in high-energy heavy-ion collision scenarios at the GSI-FAIR facility.",
"related_identifiers": [
{
"identifier": "https://github.com/R3BRootGroup/sofia/",
"relation": "isSupplementTo",
"resource_type": "software",
"scheme": "url"
}
],
"maintainers": [
{
"name": "Rodriguez-Sánchez, Jose Luis",
"orcid": "0000-0002-4702-5294",
"email": "[email protected]",
"affiliation": "CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain"
}
],
"title": "SOFIA Software",
"upload_type": "software",
"softwareRequirements": [
"FairSoft, FairRoot, R3BRoot"
],
"programmingLanguage": [
"C",
"C++"
],
"runtimePlatform": [
"ROOT"
],
"operatingSystem": [
"Linux",
"macOS"
],
"keywords": [
"Geant4",
"c-plus-plus",
"cmake",
"vmc",
"modular",
"Track reconstruction",
"Simulation",
"Data analysis",
"Structure and dynamics of nuclei",
"Nuclear reactions",
"Nuclear fission",
"SOFIA/R3B experiments",
"GSI/FAIR facility"
],
"creators": [
{
"name": "Alvarez Pol, Hector",
"orcid": "0000-0001-9643-6252"
"name": "Rodríguez-Sánchez, Jose Luis",
"orcid": "0000-0002-4702-5294",
"email": "[email protected]",
"affiliation": "CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain"
},
{
"name": "Chatillon, Audrey"
"name": "Alvarez Pol, Hector",
"orcid": "0000-0001-9643-6252",
"affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain"
},
{
"name": "Garcia Jimenez, Gabriel"
"name": "Chatillon, Audrey",
"affiliation": "CEA, DAM, DIF, 91297 Arpajon, France"
},
{
"name": "Gra\u00f1a Gonzalez, Antia",
"orcid": "0000-0002-0842-4110"
"name": "García-Jiménez, Gabriel",
"affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain"
},
{
"name": "Morfouace, Pierre",
"orcid": "0000-0002-2131-2199"
"name": "Graña-González, Antia",
"orcid": "0000-0002-0842-4110",
"affiliation": "CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain"
},
{
"name": "Rodriguez Sanchez, Jose Luis",
"orcid": "0000-0002-4702-5294"
"name": "Morfouace, Pierre",
"orcid": "0000-0002-2131-2199",
"affiliation": "CEA, DAM, DIF, 91297 Arpajon, France"
},
{
"name": "Taniuchi, Ryo",
"orcid": "0000-0002-8057-7074"
"orcid": "0000-0002-8057-7074",
"affiliation": "School of Physics, Engineering and Technology, University of York, YO10 5DD York, UK"
}
],
"contributors": [
{
"type": "Other",
"name": "Mayer, Jan"
"name": "Mayer, Jan",
"affiliation": "Technical University of Berlin, 10587 Berlin, Germany"
},
{
"type": "Other",
"name": "Wang, Yanzhao",
"orcid": "0000-0002-7006-7986"
}
],
"description": "The SOFIA module within the R3BRoot framework encapsulates the configuration and functionality of the SOFIA detectors, specifically designed for fission experiments conducted with the GLAD spectrometer. R3BRoot, built on the FairRoot framework, serves as a software environment for performing detailed Monte Carlo simulations and processing experimental data from R3B (Reactions with Relativistic Radioactive Beams) experiments. These capabilities include precise modeling of detector geometry, particle tracking, event reconstruction, and physics analysis, supporting the investigation of fission dynamics and nuclear structure in high-energy heavy-ion collision scenarios at the GSI-FAIR facility.",
"related_identifiers": [
{
"identifier": "https://github.com/R3BRootGroup/sofia/",
"relation": "isSupplementTo",
"resource_type": "software",
"scheme": "url"
"orcid": "0000-0002-7006-7986",
"affiliation": "Universität zu Köln, 50923 Köln, Germany"
}
],
"title": "SOFIA software",
"upload_type": "software",
"keywords": [
"Geant4",
"c-plus-plus",
"cmake",
"vmc",
"modular",
"Event reconstruction",
"Simulation",
"Data analysis",
"Structure and dynamics of nuclei",
"Nuclear reactions",
"Nuclear fission"
]
}
14 changes: 7 additions & 7 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Alvarez Pol, Hector [https://orcid.org/0000-0001-9643-6252]
Chatillon, Audrey
Garcia Jimenez, Gabriel
Graña Gonzalez, Antia [https://orcid.org/0000-0002-0842-4110]
Morfouace, Pierre [https://orcid.org/0000-0002-2131-2199]
Rodriguez Sanchez, Jose Luis [https://orcid.org/0000-0002-4702-5294]
Taniuchi, Ryo [https://orcid.org/0000-0002-8057-7074]
Rodríguez-Sánchez, Jose Luis [[email protected]] [https://orcid.org/0000-0002-4702-5294] [CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain]
Alvarez Pol, Hector [https://orcid.org/0000-0001-9643-6252] [IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain]
Chatillon, Audrey [CEA, DAM, DIF, 91297 Arpajon, France]
García-Jiménez, Gabriel [IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain]
Graña-González, Antia [https://orcid.org/0000-0002-0842-4110] [CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain]
Morfouace, Pierre [https://orcid.org/0000-0002-2131-2199] [CEA, DAM, DIF, 91297 Arpajon, France]
Taniuchi, Ryo [https://orcid.org/0000-0002-8057-7074] [School of Physics, Engineering and Technology, University of York, YO10 5DD York, UK]
4 changes: 2 additions & 2 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Mayer, Jan
Wang, Yanzhao [https://orcid.org/0000-0002-7006-7986]
Mayer, Jan [Technical University of Berlin, 10587 Berlin, Germany]
Wang, Yanzhao [https://orcid.org/0000-0002-7006-7986] [Universität zu Köln, 50923 Köln, Germany]
9 changes: 9 additions & 0 deletions COPYRIGHT
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: sofia
Upstream-Contact: Jose Luis Rodríguez-Sánchez <[email protected]>
Source: https://github.com/R3BRootGroup/sofia

Files: *
Copyright: 2017-2024, GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright: 2017-2024, [see AUTHORS file]
Copyright: 2017-2024, [see CONTRIBUTORS file]
133 changes: 56 additions & 77 deletions meta_update.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#! /usr/bin/env python3
# Copyright (C) 2019-2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# SPDX-License-Identifier: LGPL-3.0-or-later

from argparse import ArgumentParser
import json
import re
import json
from collections import OrderedDict

from argparse import ArgumentParser
import os

class Manipulator(object):
def __str__(self):
Expand All @@ -13,95 +16,72 @@ def __str__(self):
def load(self, filename=None):
if filename is None:
filename = self.default_filename
with open(filename, 'rb') as fp:
self.data = json.load(fp, object_pairs_hook=OrderedDict)
try:
with open(filename, 'r', encoding='utf8') as fp:
self.data = json.load(fp, object_pairs_hook=OrderedDict)
except FileNotFoundError as e:
print(f'Error: The file {filename} was not found. {e}')
except json.JSONDecodeError as e:
print(f'Error in JSON file: {e}')
raise # Raise the error and stop execution

def save(self, filename=None, indent=2):
if filename is None:
filename = self.default_filename
with open(filename, 'w', encoding='utf8') as fp:
json.dump(self.data, fp, indent=indent)
fp.write('\n')
try:
with open(filename, 'w', encoding='utf8') as fp:
json.dump(self.data, fp, indent=indent, ensure_ascii=False)
fp.write('\n')
except IOError as e:
print(f'Error saving the file {filename}: {e}')

@staticmethod
def _dict_entry_cmp(dict1, dict2, field1, field2=None):
if field2 is None:
field2 = field1
if (field1 in dict1) and (field2 in dict2):
return dict1[field1] == dict2[field2]
else:
return False
return False

def _handle_person_list_file(self, filename, field_name, **kwargs):
fp = open(filename, 'r', encoding='utf8')
person_list = self.data.setdefault(field_name, [])
for i, line in enumerate(fp, start=0):
line = line.strip()
m = self.findregex.match(line)
if m is None:
raise RuntimeError("Could not analyze line %r" % line)
found_entry = self._find_person_entry(person_list, m.groupdict())
entry = self.update_person_entry(found_entry, m.groupdict(),
**kwargs)
if found_entry is None:
person_list.insert(i, entry)


class CodeMetaManipulator(Manipulator):
default_filename = 'codemeta.json'
findregex = re.compile(r'^(?P<familyName>[-\w\s]*[-\w]),\s*'
r'(?P<givenName>[-\w\s]*[-\w])\s*'
r'(?:<(?P<email>\S+@\S+)>)?\s*'
r'(\[(?P<orcid>\S+)\])?$')

@classmethod
def _find_person_entry(cls, person_list, matchdict):
# orcid is unique
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, '@id', 'orcid'):
return entry
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'email'):
return entry
if cls._dict_entry_cmp(entry, matchdict, 'familyName') \
and cls._dict_entry_cmp(entry, matchdict, 'givenName'):
return entry
return None

@staticmethod
def update_person_entry(entry, matchdict):
if entry is None:
entry = OrderedDict()
entry['@type'] = 'Person'
for field in ('orcid', 'givenName', 'familyName', 'email'):
val = matchdict.get(field, None)
if val is not None:
if field == 'orcid':
entry['@id'] = val
else:
entry[field] = val
return entry

def update_authors(self):
self._handle_person_list_file('AUTHORS', 'author')
self._handle_person_list_file('CONTRIBUTORS', 'contributor')

def version(self, new_version):
self.data['softwareVersion'] = new_version
# Check if the file exists before trying to open it
if not os.path.exists(filename):
print(f'File {filename} not found, skipping.')
return

try:
with open(filename, 'r', encoding='utf8') as fp:
person_list = self.data.setdefault(field_name, [])
for i, line in enumerate(fp, start=0):
line = line.strip()
m = self.findregex.match(line)
if m is None:
print(f"Could not analyze line: {line}")
continue # Skip malformed lines
found_entry = self._find_person_entry(person_list, m.groupdict())
entry = self.update_person_entry(found_entry, m.groupdict(), **kwargs)
if found_entry is None:
person_list.insert(i, entry)
except FileNotFoundError as e:
print(f'Error: The file {filename} was not found. {e}')
except RuntimeError as e:
print(e)

class ZenodoManipulator(Manipulator):
default_filename = '.zenodo.json'
findregex = re.compile(r'^(?P<name>[-\w\s,]*[-\w])\s*'
r'(?:<(?P<email>\S+@\S+)>)?\s*'
r'(\[https://orcid\.org/(?P<orcid>\S+)\])?$')
# Improved regular expression to handle different author formats
findregex = re.compile(r'^(?P<name>[-\w\s,]*[-\w])\s*' # Name
r'(?:\[(?P<email>\S+@\S+)\])?\s*' # Optional email
r'(\[https://orcid\.org/(?P<orcid>\S+)\])?\s*' # Optional ORCID
r'(\[(?P<affiliation>[^\]]+)\])?$') # Optional affiliation

@classmethod
def _find_person_entry(cls, person_list, matchdict):
# Match on orcid first
# First attempt to match using ORCID
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'orcid'):
return entry
# If not, attempt to match by name
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'name'):
return entry
Expand All @@ -113,16 +93,16 @@ def update_person_entry(entry, matchdict, contributor_type=None):
entry = OrderedDict()
if contributor_type:
entry['type'] = contributor_type
for field in ('name', 'orcid'):
for field in ('name', 'orcid', 'email', 'affiliation'):
val = matchdict.get(field, None)
if val is not None:
entry[field] = val
return entry

def update_authors(self):
# Update the authors and contributors if the files exist
self._handle_person_list_file('AUTHORS', 'creators')
self._handle_person_list_file('CONTRIBUTORS', 'contributors',
contributor_type='Other')
self._handle_person_list_file('CONTRIBUTORS', 'contributors', contributor_type='Other')

def save(self, filename=None):
super().save(filename, 4)
Expand All @@ -132,16 +112,15 @@ def version(self, new_version):


def main():
parser = ArgumentParser(description='Update codemeta.json and '
'.zenodo.json')
parser = ArgumentParser(description='Update .zenodo.json')
parser.add_argument('--set-version', dest='newversion')
args = parser.parse_args()

for manipulator in (CodeMetaManipulator(), ZenodoManipulator()):
for manipulator in (ZenodoManipulator(),):
try:
manipulator.load()
except FileNotFoundError as e:
print('*** Skipping {}: {}'.format(manipulator, e))
except Exception as e:
print(f'*** Error loading {manipulator}: {e}')
continue
if args.newversion is not None:
manipulator.version(args.newversion)
Expand Down

0 comments on commit fc69756

Please sign in to comment.