MAJ terminée. Nous sommes passés en version 14.6.2 . Pour consulter les "releases notes" associées c'est ici :

Commit 8dfa286e authored by Ludovic Courtès's avatar Ludovic Courtès
Browse files

Add toolchain to build the ReScience article.

* article: New directory.
parent 717304a1
# ReScience yaml parser
# Released under the BSD two-clauses licence
import yaml
class Contributor:
def __init__(self, role, name, orcid="", email="", affiliations=[]):
self.role = role = name
self.fullname = name
self.lastname = self.get_lastname(name)
self.abbrvname = self.get_abbrvname(name)
self.orcid = orcid = email
self.affiliations = affiliations
def get_abbrvname(self, name):
if not name: return ""
if ',' in name:
lastname = name.split(",")[0]
firstnames = name.split(",")[1].strip().split(" ")
lastname = name.split(" ")[-1]
firstnames = name.split(" ")[:-1]
abbrvname = ""
for firstname in firstnames:
if "-" in firstname:
for name in firstname.split("-"):
abbrvname += name[0].strip().upper() + '.-'
abbrvname = abbrvname[:-1]
abbrvname += firstname[0].strip().upper() + '.'
return abbrvname + " " + lastname
def get_lastname(self, name):
if not name: return ""
# Rougier, Nicolas P.
if ',' in name:
lastname = name.split(",")[0].strip()
firstname = name.split(",")[1].strip()
# Nicolas P. Rougier
lastname = name.split(" ")[-1]
firstname = name.split(" ")[:-1]
return lastname
class Affiliation:
def __init__(self, code, name, address=""):
self.code = code = name
self.address = address
class Repository:
def __init__(self, name, url, doi, swh=""): = name
self.url = url
self.doi = doi
self.swh = swh
class Replication:
def __init__(self, cite, bib, url, doi):
self.cite = cite
self.bib = bib
self.url = url
self.doi = doi
class Review:
def __init__(self, url, doi):
self.url = url
self.doi = doi
class Date:
def __init__(self, date):
import dateutil.parser
date = dateutil.parser.parse(date) = date
self.year = date.year
self.month = date.month =
self.textual ="%d %B %Y")
import datetime
now = = now
self.year = now.year
self.month = now.month =
self.textual = ""
def __str__(self):
return self.textual
#return"%d %B %Y")
def __repr__(self):
return self.textual
# return"%d %B %Y")
class Article:
def __init__(self, data):
self.title = ""
self.absract = ""
self.type = ""
self.domain = ""
self.language = ""
self.bibliography = ""
self.keywords = []
self.authors = []
self.editors = []
self.reviewers = []
self.affiliations = []
self.code = "" = "" = "" = ""
self.replication = ""
self.date_received = ""
self.date_accepted = ""
self.date_published = ""
self.journal_name = ""
self.journal_issn = ""
self.journal_volume = ""
self.journal_issue = ""
self.article_number = ""
self.article_doi = ""
self.article_url = ""
# Build authors list
self.authors_short = "" # Family names only
self.authors_abbrv = "" # Abbreviated firsnames + Family names
self.authors_full = "" # Full names
n = len(self.authors)
if n > 3:
self.authors_short = self.authors[0].lastname + " et al."
self.authors_abbrv = self.authors[0].abbrvname + " et al."
self.authors_full = self.authors[0].fullname + " et al."
elif n==1:
self.authors_short += self.authors[0].lastname
self.authors_abbrv += self.authors[0].abbrvname
self.authors_full += self.authors[0].fullname
for i in range(n-2):
self.authors_short += self.authors[i].lastname + ", "
self.authors_abbrv += self.authors[i].abbrvname + ", "
self.authors_full += self.authors[i].fullname + ", "
if n >= 2:
self.authors_short += self.authors[n-2].lastname + " and "
self.authors_short += self.authors[n-1].lastname
self.authors_abbrv += self.authors[n-2].abbrvname + " and "
self.authors_abbrv += self.authors[n-1].abbrvname
self.authors_full += self.authors[n-2].fullname + " and "
self.authors_full += self.authors[n-1].fullname
def parse(self, data):
document = yaml.load(data)
self.title = document.get("title", "")
self.abstract = document.get("abstract","") or ""
self.keywords = document["keywords"] or ""
self.type = document["type"] or ""
self.domain = document["domain"] or ""
self.language = document["language"] or ""
self.bibliography = document["bibliography"] or ""
# Miscellaneous dates
dates = {key:value for data in document["dates"]
for key, value in data.items()}
self.date_received = Date(dates["received"] or "")
self.date_accepted = Date(dates["accepted"] or "")
self.date_published = Date(dates["published"] or "")
# Add authors
for item in document["authors"]:
role = "author"
name = item["name"] or ""
orcid = item.get("orcid","") or ""
email = item.get("email","") or ""
if item["affiliations"] is not None:
if len(str(item["affiliations"])) > 1:
affiliations = item["affiliations"].split(",")
if "*" in affiliations:
author = Contributor(role, name, orcid, email, affiliations)
self.add_contributor(author) = author
author = Contributor(role, name, orcid, email, affiliations)
affiliations = list(str(item["affiliations"]))
author = Contributor(role, name, orcid, email, affiliations)
# Add author affiliations
for item in document["affiliations"]:
item.get("address", "")))
# Add editor & reviewers
for item in document["contributors"]:
role = item["role"]
name = item["name"] or ""
orcid = item.get("orcid","") or ""
contributor = Contributor(role, name, orcid)
# Code repository (mandatory)
if "code" in document.keys():
code = {key:value for data in document["code"]
for key, value in data.items()}
self.code = Repository("code",
code.get("url","") or "",
code.get("doi","") or "",
code.get("swh","") or "")
raise IndexError("Code repository not found")
# Data repository (optional)
if "data" in document.keys():
data = {key:value for data in document["data"]
for key, value in data.items()} = Repository("data",
data.get("url","") or "",
data.get("doi","") or "")
else: = Repository("data", "", "")
# Review
review = {key:value for review in document["review"]
for key, value in review.items()} = Review(review.get("url","") or "",
review.get("doi","") or "")
# Replication
replication = {key:value for replication in document["replication"]
for key, value in replication.items()}
self.replication = Replication(replication["cite"] or "",
replication["bib"] or "",
replication["url"] or "",
replication["doi"] or "")
# Article number & DOI
article = {key:value for article in document["article"]
for key, value in article.items()}
self.article_number = article["number"] or ""
self.article_doi = article["doi"] or ""
self.article_url = article["url"] or ""
# Journal volume and issue
journal = {key:value for journal in document["journal"]
for key, value in journal.items()}
self.journal_name = str(journal.get("name",""))
self.journal_issn = str(journal.get("issn", ""))
self.journal_volume = journal["volume"] or ""
self.journal_issue = journal["issue"] or ""
def add_contributor(self, contributor):
if contributor.role == "author":
elif contributor.role == "editor":
elif contributor.role == "reviewer":
# -----------------------------------------------------------------------------
if __name__ == '__main__':
with open("metadata.yaml") as file:
article = Article(
\renewcommand\emph[1]{{\bfseries #1}}
\ No newline at end of file
doi = {10.1038/d41586-018-04628-w},
year = {2018},
month = apr,
publisher = {Springer Nature},
volume = {556},
number = {7701},
pages = {309--309},
author = {Rougier, Nicolas P. and Hinsen, Konrad},
title = {Code reviewing puts extra demands on referees },
journal = {Nature},
doi = {10.1126/science.359.6377.725},
author = {Hutson, Matthew},
url = {},
year = {2018},
month = feb,
volume = {359},
number = {6377},
title = {Artificial intelligence faces a replication crisis},
journal = {Science},
author = {Christian Robertson},
title = {The Roboto family of fonts (Google)},
url = {},
year = 2011,
note = {Apache License, verison 2.0},
author = {Frank Grießhammer},
title = {Source Serif Pro (Adobe Systems)},
url = {},
year = 2014,
note = {SIL Open Font License, version 1.1},
author = {Paul D. Hunt},
title = {Source Code Pro (Adobe Systems)},
url = {},
year = 2012,
note = {SIL Open Font License, version 1.1},
author = {Topalidou, Meropi and Rougier, Nicolas P.},
title = {{[Re] Interaction between cognitive and motor cortico-basal
ganglia loops during decision making: a computational study}},
journal = {ReScience},
year = 2015,
volume = 1,
number = 1,
doi = {10.5281/zenodo.27944},
doi = {10.7717/peerj-cs.142},
author = {Nicolas P. Rougier and Konrad Hinsen and Frédéric Alexandre
and Thomas Arildsen and Lorena Barba and Fabien
C. Y. Benureau and C. Titus Brown and Pierre de Buyl and Ozan
Caglayan and Andrew P. Davison and Marc André Delsuc and
Georgios Detorakis and Alexandra K. Diem and Damien Drix and
Pierre Enel and Benoît Girard and Olivia Guest and Matt
G. Hall and Rafael Neto Henriques and Xavier Hinaut and Kamil
S Jaron and Mehdi Khamassi and Almar Klein and Tiina Manninen
and Pietro Marchesi and Dan McGlinn and Christoph Metzner and
Owen L. Petchey and Hans Ekkehard Plesser and Timothée Poisot
and Karthik Ram and Yoav Ram and Etienne Roesch and Cyrille
Rossant and Vahid Rostami and Aaron Shifman and Joseph
Stachelek and Marcel Stimberg and Frank Stollmeier and
Federico Vaggi and Guillaume Viejo and Julien Vitay and Anya
Vostinar and Roman Yurchak and Tiziano Zito},
title = {{Sustainable computational science: the ReScience
journal = {{PeerJ} Computer Science},
month = 12,
volume = 3,
pages = {e142},
year = 2017,
github = {},
keywords = {journal},
tags = {OS},
Three years, we launched ReScience, a new scientific journal aimed at publishing the
replication of existing computational research. Since ReScience published its first
article\supercite{Topalidou:2015}, things have been
going steadily. We are still alive, independent and without a budget. In the
meantime, we have published around 24 articles (mostly in computational
neuroscience \& computational ecology) and the initial
\href{}{editorial board} has grown from
around 10 to roughly 100 members (editors and reviewers), we have advertised
ReScience at several conferences worldwide, gave some
interviews\supercite{Science:2018}, and published an article introducing
ReScience in PeerJ~CS\supercite{Rougier:2017}. Based on our
experience\supercite{Rougier:2018} at managing the journal during these three
years, we think that time is ripe for some changes.
\subsubsection{ReScience C \& ReScience X}
The biggest and most visible change we would like to propose is to change the
name of the journal ``ReScience'' in favor of ``ReScience C'' where the C
stands for (c)omputational. This change would be necessary to have consistent
naming with the upcoming creation of the ``ReScience X'' journal that will be
dedicated to e(x)perimental replications and co-directed by E.Roesch
(University of Reading) and N.Rougier (University of Bordeaux). The name
``ReScience'' would then be used for the name of a non-profit organization
(that is yet to be created) for the two journals as well as future journals
(such as the utopian CoScience\supercite{Rougier:2017} or a future and
tentative ``ReScience T'' for theoretical science).
\subsubsection{A new submission process}
The current submission process requires authors to fork, clone and branch the
submission repository in order to write their article and to place code and
data at the relevant places in the forked repository. Once done, authors have
to push their changes and to make a pull request that is considered as a
submission. This process is cumbersome for authors and has induced many
troubles for editors as well once the article is accepted and ready to be
published, mostly because of the complexity of the editing procedure. In order
to make life easier for everyone, we greatly simplified the submission process
for ReScience C and X. Authors are now responsible for getting a DOI for their
code \& data and only have to submit a PDF and a metadata file in a GitHub
We also provide Python programs that largely automate the subsequent editing
process. We will still archive the submission on Zenodo but this archive will
be made for the final PDF only. However, both the PDF and the Zenodo entry will
contain all associated DOIs (data and code).
\subsubsection{A simplified publishing process}
In ReScience, we have have been using a combination of
\href{}{markdown} and
\href{}{pandoc} for producing both the draft and the final
version of all the published articles. This had worked reasonably well until it
started to cause all kind of problems for both authors and editors, especially
with the reference and citation plugins. Consequently, articles will be now
submitted directly in PDF with accompanying metadata in a separate file using
the \href{}{YAML} format (they were
previously embedded in the markdown file). Once an article has been accepted,
authors will be responsible for updating the metadata and for rebuilding the PDF if
necessary. We could also consider using the
\href{}{Whedon} API that helps with automating
most of the editorial tasks for \href{}{JOSS} and
\href{}{JOSE}. This will most probably require some
tweaking because our publishing pipeline is a bit different.
\subsubsection{A new design}
The combination of markdown and pandoc has also severely limited the layout and
style possibilities for the article template and since we are switching to
\LaTeX, this is the opportunity to propose a new design based on a more elegant
style, using a new font stack\supercite{SourceSerifPro:2014, Roboto:2011,
SourceCodePro:2012} (you are currently reading it). The goal is to have a
subtle but strong identity with enhanced readability. Considering that articles
will be mostly read on screen (as opposed to printed), we can benefit from a
more ethereal style. Once this design will have stabilized, an
\href{}{overleaf} template will be made available for
those without a \TeX~installation. If a \TeX~expert is ready to help review
the template (and possibly rewrite it as a class), their help would be much
welcome and appreciated. The same holds for LibreOffice, Word or Pages, any
template is welcome, just contact us beforehand such that we can coordinate
\subsubsection{Editorials, letters and special issues}
ReScience C remains dedicated to the publication of computational replications
but we (i.e., the editorial team) would like to have the opportunity to
publish \emph{editorials} when deemed necessary and to give anyone the
opportunity to write \emph{letters} to the community on a specific topic
related to reproducibility. Both editorials and letters are expected to be 1 or
2 pages long (but no hard limit will be enforced), will be (quickly) peer reviewed,
and will be assigned a DOI. Furthermore, with the advent of reproducibility
hackatons worldwide, we will host {\em special issues} with guest editors (such
as, for example, the organizers of a hackaton) in order to publish the results
and to enhance their discoverability. Each entry will have to go through the
regular open peer-reviewed pipeline.\\
We hope that most readers will agree on the proposed changes such that we can
commit to them in the next few weeks. The review for this editorial is open (as
usual) and anyone can comment on and/or oppose any of the proposed changes. New
ideas are also welcome.
;;; Copyright © 2020 Ludovic Courtès <>
;;; This program is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;; This program is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <>.
;; This file contains code to build the ReScience C article. Run with:
;; guix build -f guix.scm
(use-modules (guix) (gnu)
(guix git-download))
(define locales
(specification->package "glibc-utf8-locales"))
(define python
(specification->package "python"))
(define python-pyyaml
(specification->package "python-pyyaml"))
(define biber
(specification->package "biber"))
(define texlive
(specification->package "texlive"))
(define texlive
;; FIXME: Use the modular texlive along these lines:
;; (texlive-union (map specification->package
;; '("texlive-base" "texlive-beamer"
;; "texlive-fonts-ec" "texlive-etoolbox"
;; "texlive-generic-ulem" "texlive-cm-super" "texlive-latex-capt-of"
;; "texlive-latex-wrapfig" "texlive-latex-geometry"
;; "texlive-latex-ms" "texlive-amsfonts" "texlive-latex-graphics"
;; "texlive-latex-pgf"
;; "texlive-marginnote" "texlive-csquotes")))
(specification->package "texlive"))
(define rescience-template
(method git-fetch)
(uri (git-reference (url "")
(commit "93ead8f348925aa2c649e2a55c6e16e8f3ab64a5")))
(base32 "10xrflbkrv6bq92nd169y5jpsv36dk4i6h765026wln7kpyfwk8j"))))
(define metadata.tex
(computed-file "metadata.tex"
(setenv "GUIX_LOCPATH"
#$(file-append locales "/lib/locale"))
(setenv "LC_ALL" "en_US.utf8")
(copy-file #$(local-file "") "")
(setenv "PYTHONPATH"
(getcwd) ":"
#$(file-append python-pyyaml "/lib/python"
(package-version python))
(zero? (system* #$(file-append python "/bin/python3")
#$(local-file "")
"-i" #$(local-file "metadata.yaml")
"-o" #$output)))))
(define source
(local-file "." "rescience-c-article-source"
#:recursive? #t
#:select? (lambda (file stat)
(or (string-suffix? ".tex" file)
(string-suffix? ".bib" file)
(string-suffix? ".cls" file)))))
(define article.pdf
;; Building the PDF. Adapted from the ReScience template makefile.
(let ()
(define build
(with-imported-modules '((guix build utils))
(use-modules (guix build utils))
(copy-recursively #$source ".")
(copy-file #$metadata.tex "metadata.tex")
(for-each (lambda (font)
(symlink (string-append #$rescience-template "/"
'("roboto" "source-code-pro"
"source-sans-pro" "source-serif-pro"))
(setenv "PATH"
(string-join '(#$texlive #$biber)
"/bin:" 'suffix))
(invoke "latexmk" "-pdf"
"-pdflatex=xelatex -interaction=nonstopmode"
"-use-make" "article.tex")
(copy-file "article.pdf" #$output))))