Sign in

iiinova is part of the Atmosphere — an open, public network where you own your identity.

Charles Tapley Hoyt

@cthoyt.scholar.social.ap.brid.gy
19 followers 2 following 145 posts

Bio/cheminformatician, software developer, open scientist. 🇺🇸 living in Bonn 🇩🇪🇪🇺 (he/him) Current projects: @NFDI4Chem and @dalia 🌉 bridged from ⁂ scholar.social/@cthoyt, follow @ap.brid.gy to interact

PostsRepliesMedia
Reposted by Charles Tapley Hoyt
ploum @ploum.mamot.fr.ap.brid.gy · 14/10/2026
I’ve read today a contributor to an open source project says, in substance: "If generated code is accepted in the project, I will stop contributing because I don’t want to spend time trying to understand the code in order to contribute just to see it changed at the commit of generated code" […]
mamot.fr
Original post on mamot.fr
020 2
Reposted by Charles Tapley Hoyt
Dustin L. Howett @dhowett.mas.to.ap.brid.gy · 13/10/2026
When I talk about the impact of language-model-based and "agentic" coding on open-source communities, and on human to human interaction, I am more often than not talking about: - How I cannot trust there is a human on the other end who wants to learn or be part of my community - How it is an […]
mas.to
Original post on mas.to
102 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 09/10/2026
one minor way I try and promote early career researchers in academia is to always remove titles (e.g., Dr. and Prof.) from senior researchers in written text
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 05/10/2026
just submitted an abstract to present @bioregistry at the @linkml@fosstodon.org 2026 Virtual LinkML Community Symposium the proposed talk is about the `bioregistry validate linkml` command, which can help LinkML modelers to choose standard prefixes for their CURIEs and URIs it'll expand on […]
scholar.social
Original post on scholar.social
102 2
Reposted by Charles Tapley Hoyt
Erik Uden 🚩 @erikuden.mastodon.de.ap.brid.gy · 19/08/2025
Slurs for people who use artificial intelligence: * slopholm syndrome * clanksmen * sloppers * aidiots * clanker crankers * second hand thinkers * grokkers * bot licker * fartist (fake artist) Feel free to use ❤️
526 6
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 22/09/2026
there's an unfortunate conflict between open science (I can participate in discussion and contribute to code on a centralized platform like GitHub) and sovereign science (I can't easily contribute or meet people on internal platforms like institutional GitLab instances) my EBI GitLab […]
scholar.social
Original post on scholar.social
000 0
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 20/09/2026
[Fires of December spoilers] do you think that the sixth word is related to the dawnshard(s?) that Hoid held? #cosmere #sanderson
100 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 04/09/2026
blogged today about ChEBI, data properties in OWL ontologies, computational chemistry, atomic numbers, and basis sets cthoyt.com/2026/09/04/chebi-atomic-… all part of @NFDI4Chem #obo #owl #chebi #obofoundry #nfdi #nfdi4chem
A diagram showing how ontology inference could be used to connect molecules and applicable basis sets for computational chemistry experiments
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 04/09/2026
a semantic web-heavy paper that declares a prefix map in its appendix! very cool! www.sciencedirect.com/science/artic…
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 04/09/2026
i'm signing off pull requests with this from now on: 🫀 No generative artificial intelligence was used to produce the code and text for this contribution; only human intelligence anyone have ideas on how to make this text better?
121 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 31/08/2026
i submitted a beautiful, hand-crafted PR with good variable names, which got merged, then the maintainers updated it in a follow-up to change the variable names to be cryptic. crazy times we live in
101 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 28/08/2026
RE: mastodon.social/@andrewnez/11717270… lincoln, nebraska got me xkcd.com/2347
021 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 21/08/2026
Today was the first time ever that a situation where having a copy of my email address as part of my email signature would have been helpful It was also caused by interacting with an email list, which I avoid like the plague, so I don't think I'm going to change my signature
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 18/08/2026
tfw a repository that is now vibe coding closes your well-thought out issue from pre-vibe coding era for not having enough active discussion
012 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 18/08/2026
new two-part blog post on automating the evaluation of predicted semantic mappings in SSSOM: Part 1: opportunities for competitions like the Ontology Alignment Evaluation Initiative (OAEI) cthoyt.com/2026/08/17/mapping-evalu… Part 2: implementation of a new […]
scholar.social
Original post on scholar.social
022 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 17/08/2026
that feeling when a service takes down its API which does exactly what you want, and replaces it with MCP :/
201 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 10/08/2026
I put my experience and wisdom into organizing Python code into a cookiecutter package (with lots of documentation and learning materials) keeping this up to date is easier than updating my old blog posts (e.g., I use ruff instead of flake8, so […]
scholar.social
Original post on scholar.social
002 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 07/08/2026
i've implemented a transformation from SSSOM to OWL to support ontology curators in externalizing their mappings and making them higher quality this was primarily motivated by work in @NFDI4Chem to revitalize CHMO, RXNO, and MOP here's how it works […]
scholar.social
Original post on scholar.social
002 2
Reposted by Charles Tapley Hoyt
Slowbiex (Andreas S.) @slowbiex.beige.party.ap.brid.gy · 29/07/2026
Schienen im Donau- und Rhein-Flussbett verlegen!
003 3
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 30/07/2026
@criticalmass findet Critical Mass morgen statt?
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 29/07/2026
my team at RWTH Aachen is bringing informatics approaches tried and true in medicinal chemistry to bioinorganic catalysis ➡️ here's a ontology-augmented reaction network for polylactic acid (PLA) which is linked to literature-derived catalytic experimental […] [Original post on scholar.social]
a reaction network for polylactic acid (PLA)A depiction of the molecule [FeCl2 (TMG5NMe2 asme)], published by Lisa Burkart et al. (2023; https://pubmed.ncbi.nlm.nih.gov/36577118/)
113 3
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 27/07/2026
I have an opening in my group at RWTH Aachen University for a research internship for a bachelor or master's student in chemistry or computer science who would like to learn about cheminformatics methods in catalyst design for plastics recycling more info: zenodo.org/records/20758266 […]
scholar.social
Original post on scholar.social
0011 11
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 19/06/2026
a blog post on comparing overlapping SSSOM curations from two different curators cthoyt.com/2026/06/19/comparing-sss… #sssom #semanticweb #owl #ontologies
cthoyt.com
Comparing manually curated semantic mappings in SSSOM
I am currently supporting Philip Strömert and Noura Rayya in the efforts to modernize and revitalize the Chemical Methods Ontology (CHMO) to support annotation of instrumentation used to produce experimental data captured in the Chemotion electronic laboratory notebook as part of NFDIChem. This post is about the adoption of Simple Standard for Sharing Ontological Mappings (SSSOM) to support interoperability between CHMO and other resources, and the workflow I developed to compare overlapping manual curations from different researchers. Philip and Noura have already completed the important initial steps of assuming maintainership from the Royal Society of Chemistry, porting the ontology to use a standardized Ontology Development Kit (ODK) layout, and revising the definitions of many classes based on the IUPAC GoldBook. ## Landscape of Resources There are several other NFDI consortia including NFDI4Cat (catalysis), DAPHNE4NFDI (photon and neutron physics), and FAIRmat (materials science) that have similar goals to annotate instrumentation. While each reuse CHMO to some extent for this purpose, DAPHNE4NFDI additionally develops the Photon and Neutron Experimental Techniques (PANET) Ontology and FAIRmat develops the NeXus format and associated NeXus Ontology as part of the NOMAD materials science data management platform. Further, there are several other resources with similar goals including the Allotrope Foundation Ontology (AFO), the deprecated Physico-chemical Methods and Properties (FIX) ontology, the deprecated Physico-chemical process (REX) ontology, IUPAC GoldBook, and Wikidata. # Establishing Interoperability In order to establish interoperability between these many resources, we are using the Simple Standard for Sharing Ontological Mappings (SSSOM) to curate exact matches, narrow matches, and broad matches between CHMO terms and external ones in PANET, NeXuS (sort of), AFO, FIX, REX, IUPAC GoldBook, and Wikidata. First, Philip had Ambika, a student research assistant (_Hiwi_ , abbreviated in German), work for several months to manually curate mappings from CHMO to REX, FIX, AFO, and Wikidata (see this PR). In parallel, I took the opportunity to spin up a new instance of a SSSOM Curator repository within the NFDI Section Metadata Working Group for Ontology Harmonization and Mappings GitHub repository, run lexical prediction to generate candidate mappings from CHMO, and efficiently manually curate the results in this PR. and this PR over the course of about an hour. ## Need for Comparison The next challenge was to efficiently triage the similarities and differences between my curations and Ambika’s. Therefore, I implemented a workflow for comparing the manually curated mappings in two SSSOM documents in cthoyt/sssom-pydantic#141. This workflow creates a Markdown file describing similarities and differences. I chained together the following two CLI commands with `sssom_pydantic` to get the separate mapping files from Ambika’s branch in the NFDI4Chem fork of CHMO, merge them, then run the comparison against my own curations. Note that these won’t be reproducible after the branch is merged and deleted, and the actual results will change as more curation is done. $ sssom_pydantic merge \ --input https://github.com/NFDI4Chem/rsc-cmo/raw/refs/heads/Add-tsv-files/src/mappings/fix-mappings.sssom.tsv \ --input https://github.com/NFDI4Chem/rsc-cmo/raw/refs/heads/Add-tsv-files/src/mappings/afo-mappings.sssom.tsv \ --input https://github.com/NFDI4Chem/rsc-cmo/raw/refs/heads/Add-tsv-files/src/mappings/rex-mappings.sssom.tsv \ --input https://github.com/NFDI4Chem/rsc-cmo/raw/refs/heads/Add-tsv-files/src/mappings/wikidata-mappings.sssom.tsv \ --standardize \ --output ambika.sssom.tsv $ sssom_pydantic compare \ ambika.sssom.tsv \ https://github.com/nfdi-de/section-metadata-wg-onto/raw/refs/heads/main/sssom/data/positive.sssom.tsv \ --standardize \ --standardize-flip \ --left-label Ambika \ --right-label Charlie Since the comparison workflow outputs Markdown, its results can easily be embedded in GitHub issues or my blog, which is itself written in Markdown. ## Results I am happy with the first version of the comparison workflow. Luckily, there were only a small number of discrepancies which have obvious solutions. There were also a few interesting discrepancies which were novel to either my or Ambika’s curations, which can be reviewed by a third curator (sorry Philip, more work for you). ## Next Steps I think that it can be extended to identify and report on one-to-many, many-to-one, and many-to-many mappings which arise when jointly examining two mapping sets. After Philip and others interact with the results, I’m sure we will be able to extend it with other analyses. More generally, the implementation of the comparison workflow is part of a larger suite of workflows that I would like to describe in future posts including: 1. merging manually curated mappings 2. generating OWL ontology bridges 3. incorporating SSSOM into ODK builds, which I will support Damien Goutte-Gattat to document in the ODK repository and the OBOOK. 4. unify this analysis with my other idea for doing automated evaluation of predicted mappings, which I hope can be used to run future mapping challenges Without further ado, here’s the comparison, copied verbatim from the output of the previous command: # Comparison between Ambika and Charlie 1. CHMO to FIX 2. CHMO to REX ## CHMO to FIX ### Subject Comparison * 288 entities appear as subjects only in Ambika * 19 entities appear as subjects only in Charlie only * 138 entities appear as subjects in both The following 6 subjects (4.3%) appearing in both have conflicting objects: subject_id | subject_label | Ambika | both | Charlie ---|---|---|---|--- CHMO:0000141 | diffraction method | FIX:0000004 (crystallography) | FIX:0000217 (diffraction method) | CHMO:0000164 | electron scattering | FIX:0000666 (electron scattering spectroscopy) | FIX:0000401 (electron scattering) | CHMO:0000255 | flame atomic emission spectroscopy | FIX:0000935 (spark method) | FIX:0000928 (flame atomic emission spectroscopy) | CHMO:0000307 | X-ray emission spectroscopy | FIX:0000673 (X-ray fluorescence spectroscopy) | FIX:0000100 (X-ray emission spectroscopy) | CHMO:0000366 | electron energy loss spectroscopy | FIX:0000664 (electron impact spectroscopy) | FIX:0000663 (electron energy loss spectroscopy) | CHMO:0000570 | proton transfer reaction ion trap mass spectrometry | FIX:0000919 (proton transfer reaction ion trap mass spectrometry) | | FIX:0000918 (proton transfer reaction mass spectrometry) ### Object Comparison * 296 entities appear as objects only in Ambika * 19 entities appear as objects only in Charlie * 138 entities appear as objects in both The following 2 objects (1.4%) appearing in both have conflicting subjects: object_id | object_label | Ambika | both | Charlie ---|---|---|---|--- FIX:0000629 | pulsed field gel electrophoresis | CHMO:0002315 (pulsed-field electrophoresis) | | CHMO:0002316 (pulsed-field gel electrophoresis) FIX:0000816 | square-wave polarography | CHMO:0000040 (square-wave voltammetry) | CHMO:0000035 (square-wave polarography) | ### Subject-Object Pair Comparison * 301 subject-object pairs only appear in Ambika * 20 subject-object pairs only appear in Charlie * 137 subject-object pairs appear in both The following 1 subject-object pairs (0.7%) appearing in have conflicting predicates or predicate modifiers: subject_id | subject_label | object_id | object_label | warning | Ambika | Charlie ---|---|---|---|---|---|--- CHMO:0000164 | electron scattering | FIX:0000401 | electron scattering | different predicate | skos:narrowMatch | skos:exactMatch ## CHMO to REX ### Subject Comparison * 1 entities appear as subjects only in Ambika * 18 entities appear as subjects only in Charlie only * 0 entities appear as subjects in both ### Object Comparison * 1 entities appear as objects only in Ambika * 18 entities appear as objects only in Charlie * 0 entities appear as objects in both ### Subject-Object Pair Comparison * 1 subject-object pairs only appear in Ambika * 18 subject-object pairs only appear in Charlie * 0 subject-object pairs appear in both
002 2
Reposted by Charles Tapley Hoyt
Radentscheid Bonn @radentscheid-bonn.bonn.social.ap.brid.gy · 16/06/2026
Jetzt unsere Petition unterzeichnen und teilen! Die #Oxfordstraße ist alternativlos und lebensgefährlich ohne Radspur #teilderlösung #rausausdemstau #zusammen #criticalmass #visionzero […]
bonn.social
Original post on bonn.social
2811 11
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 15/06/2026
RE: mastodon.social/@egonw/116753932826… my biocurator blood makes me a sucker for doing more curation to make metadata completeness numbers go up @rogue_scholar is there documentation somewhere on how to encode metadata in my posts to get my ORCiD, ROR, and other metadata […]
scholar.social
Original post on scholar.social
201 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 03/06/2026
new blog post: A practical approach to translate OWL to SKOS 👀 cthoyt.com/2026/06/03/owl-to-skos.h… #owl #skos #ontology #hierarchy #taxononomy
cthoyt.com
A practical approach to translate OWL to SKOS
The data model in PyOBO closely resembles the Web Ontology Language (OWL) and macros in the OBO Flat File format. However, some communities prefer the simplified nature of the SKOS data model compared to the highly precise (and sometimes burdensome) nature of OWL semantics. This post describes the workflow I implemented to downscale OWL to SKOS. Before diving into this, I searched for previous work in mapping OWL to SKOS and was surprised to find only a few things (and they’re all old): * Exploring the Relationships between OWL and SKOS by Nor Azlinayati Abdul Manaf (2009) * Using OWL and SKOS by Sean Bechhofer and Alstair Miles (2008) * SKOS2OWL by Hepp _et al._ (2007) ## Predicate Mappings However, I didn’t find these resources very helpful, so I just jumped right into an implementation. First, I mapped several predicates used in OWL to predicates used in SKOS: * `rdfs:label` maps to `skos:prefLabel` * synonym predicates from OBO-flavored OWL (`oboInOwl:hasExactSynonym`, `oboInOwl:hasNarrowSynonym`, `oboInOwl:hasBroadSynonym`) are squashed to `skos:altLabel`, and synonym type information is thrown away * `dcterms:description` maps to `skos:scopeNote` * `rdf:subClassOf` and `rdf:type` are squashed to `skos:broadMatch` * similarly, individuals (`owl:NamedIndividual`) and classes (`owl:Class`) are both squashed to `skos:Concept` * predicates and relationships are omitted * root terms annotated on the ontology with `IAO:0000700` (ontology has root term) get annotated on the SKOS concept scheme with `skos:hasTopConcept` ## Hierarchical Reasoning I introduced `OMO:0003014` (has ontology hierarchical property) in information-artifact-ontology/ontology-metadata#193 to enable ontologies to explicitly annotate which predicates should be used during hierarchical browsing (in addition to `rdf:subClassOf`). For example, the Uber Anatomy Ontology (UBERON) contains a partonomy of anatomical features, and should therefore be browsable based on the `BFO:0000050` (part of) relationship. This annotation was originally inspired by the custom configuration for adding new ontologies to the EBI’s Ontology Lookup Service (OLS) - now, the configuration for the OLS can be upstreamed into the ontologies themselves and be made more reusable. Accordingly, I used hierarchical properties annotated on to the ontology with `OMO:0003014` to translate object property constraints into broad matches. Inside PyOBO, I updated the source for the Research Organization Registry (ROR) to explicitly annotate `org:subOrganizationOf` as a hierarchical property. Below, the entry for the French Techniques of Informatics and Microelectronics for Integrated Systems Architecture shows the translation into broad matches for both the subclass relation to the _ad hoc_ term for a facility and the sub-organization relations to its four parent organizations: ror:000063q30 a skos:Concept ; skos:altLabel "TIMA", "TIMA Laboratory", "Techniques de l'Informatique et de la Microélectronique pour l'Architecture des Systèmes Intégrés"@fr ; skos:broadMatch <http://purl.obolibrary.org/obo/ror#facility>, ror:02feahw73, ror:02rx3b187, ror:04z22qz54, ror:05sbt2524 ; skos:prefLabel "Techniques of Informatics and Microelectronics for Integrated Systems Architecture" ; skos:scopeNote "a facility in Grenoble established in 2003" . ## Inverse Hierarchical Reasoning I extended this notion further to leverage inverse predicate information for the hierarchical property annotations. If the inverse of a hierarchical property is used in an object property constraint (or annotation property), then it is translated into a narrow match. For example, in FamPlex, complexes are annotated with the `RO:0002351` (has member) relationship to genes. This algorithm looks up the inverse relationship `RO:0002350` (is member of) and annotates that as a complex has narrow match to gene triple, and simultaneously, gene has broad match to complex triple. fplx:Sarcoglycan_complex a skos:Concept ; skos:broadMatch fplx:DGC ; skos:inScheme <https://w3id.org/biopragmatics/resources/fplx/fplx.ttl> ; skos:narrowMatch hgnc:10805, hgnc:10806, hgnc:10807, hgnc:10808, hgnc:14075 ; skos:prefLabel "Sarcoglycan_complex" ; skos:scopeNote "A family of transmembrane dystrophin-associated proteins that play a role in the membrane association of the DYSTROPHIN-ASSOCIATED PROTEIN COMPLEX." . ## More or Less, Semantics We have the goal in NFDI4Chem to map from ontology terms in the Chemical Methods Ontology (CHMO) to the IUPAC GoldBook, a compendium of chemical terminology which also covers instrumentation and experimental techniques. While GoldBook’s data is now available in both JSON and XML, neither ascribe semantics to their fields, i.e., the XML doesn’t use namespaces and the JSON doesn’t have a _linked data_ component. This meant that as I implemented a PyOBO source for GoldBook in biopragmatics/pyobo#436, I had to interpret what each field means, and ascribe semantics to them by assigning existing, well-known predicates to each. However, based on discussions in preparation for the 6th Ontologies4Chem workshop later this year, it appears IUPAC does not want to make ontological commitments for its entities, and would instead prefer to produce a SKOS vocabulary. My work on ontologizing GoldBook was done without discussion with IUPAC, similar to most PyOBO sources. Personally, I think it’s much more valuable to ascribe precise semantics. I am less dogmatic about ontological commitments and have usually focused on what makes a data resource useful for me. In this case, it was being able to access GoldBook through an ontology-like interface such that it could be loaded in SSSOM Curator to lexically predict then manually curate CHMO-GoldBook mappings. However, now with the SKOS exporter described earlier in this post, I can have it both ways: first starting with a more precise OWL artifact, then downscaling to a simpler SKOS artifact with entries that look like: goldbook:08003 a skos:Concept ; skos:inScheme <https://w3id.org/biopragmatics/resources/goldbook/goldbook.ttl> ; skos:prefLabel "analytical chemistry" ; skos:scopeNote "Scientific discipline that develops and applies strategies, instruments, and procedures to obtain information on the composition and nature of matter in space and time." . * * * There are still a few parts of SKOS that I’m not familiar with, so I expect that this translation will evolve over time. For example, because SKOS is so tightly tied to RDF as a serialization, it has better support for language tags. OWL can be serialized in RDF, but the OBO Flat File Format is inherently limited in its ability to express language. I’m interested to overcome these limits in the PyOBO implementation.
011 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 03/06/2026
RE: mastodon.social/@egonw/116680238193… woohoo! i still like to blog
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 29/05/2026
new blog post: transparent provenance for derived semantic mappings in SSSOM cthoyt.com/2026/05/29/sssom-derived… #sssom #semanticweb #fairdata #dataintegration
cthoyt.com
Transparent provenance for derived semantic mappings in SSSOM
The Simple Standard for Sharing Ontological Mappings (SSSOM) requires semantic mappings to annotate a _justification_ from the Semantic Mapping Vocabulary (SEMAPV) such as `semapv:ManualMappingCuration`, `semapv:MappingInversion`, and `semapv:MappingChaining`. However, SSSOM did not have a mechanism for tracking which mappings were used during inference workflows like inversion or chaining. This post is about my recent SSSOM enhancement proposal to add a new field `derived_from` to support this. ## Background Before we get started, it’s worth defining a few terms about mappings to make sure that we stay precise. ### Mapping Triple A _mapping triple_ is a subject, predicate, and object such as `mesh:C000089`, `skos:exactMatch`, `CHEBI:28646`. By semantic web conventions based on the open world assumption (OWA), triples are assumed to be true unless stated otherwise. flowchart LR mesh:C000089[ammeline mesh:C000089] CHEBI:28646[ammeline CHEBI:28646] mesh:C000089-->|skos:exactMatch|CHEBI:28646 ### Mapping Quadruple A _mapping quadruple_ is a subject, predicate, object, and truthiness (a boolean). SSSOM represents the truthiness using the `predicate_modifier` field, where an empty value means that the mapping is true, and a value of `Not` means that it is false. For example, (`mesh:C000089`, `skos:exactMatch`, `CHEBI:28646`, `True`) makes the example _mapping triple_ from above into a mapping quadruple that explicitly states its truthiness. flowchart LR mesh:C000089[ammeline mesh:C000089] CHEBI:28646[ammeline CHEBI:28646] mesh:C000089-->|"skos:exactMatch\n(true)"|CHEBI:28646 Conversely, (`CHEBI:10057`, `skos:exactMatch`, `mesh:C002563`, `False`) is false because `CHEBI:10057` refers to 9H-xanthene, a small molecule, and `mesh:C002563` refers to xanthan gum, a polysaccharide. flowchart LR mesh:C002563[xanthan gum mesh:C000089] CHEBI:10057[9H-xanthene CHEBI:10057] mesh:C002563-->|"not skos:exactMatch"|CHEBI:10057 By convention, mapping triples are implicitly considered to refer to the corresponding _true_ mapping quadruple. ### Mapping Record A _mapping record_ is a subject, predicate, object, truthiness, and other metadata about the mapping that appears in the SSSOM Mapping data model. A mapping record best be visualized by reifying the triple (i.e., make into a node) to show how additional metadata is connected. flowchart LR mesh:C000089[ammeline mesh:C000089] CHEBI:28646[ammeline CHEBI:28646] 1181E81AD58C1B94("mesh:C000089 skos:exactMatch CHEBI:28646 manual curation") style 1181E81AD58C1B94 fill:#bbf orcid:0000-0003-4423-4370[Charles Tapley Hoyt orcid:0000-0003-4423-4370] style orcid:0000-0003-4423-4370 fill: #bef wikidata:Q111239110[Biomappings wikidata:Q111239110] style wikidata:Q111239110 fill: #feb 1181E81AD58C1B94 -->|has author|orcid:0000-0003-4423-4370 1181E81AD58C1B94-->|source|wikidata:Q111239110 mesh:C000089 -->|subject of|1181E81AD58C1B94 CHEBI:28646 -->|object of|1181E81AD58C1B94 Note that I’m playing a bit fast and loose with the semantics of the predicates relating the mapping record to other components. This is explicitly specified as part of SSSOM, but I don’t think super instructive here, so I’ve used more human-readable labels. ## Motivation I’ve been thinking about the large-scale aggregation and inference over semantic mappings for several years now. My initial work resulted in the implementation of the Semantic Mapping Reasoner and Assembler (SeMRA) and the publication of its companion article Assembly and reasoning over semantic mappings at scale for biomedical data integration. Initially, SeMRA implemented a custom data model that was similar to SSSOM, but had a more explicit provenance model for which mapping records (e.g., from SSSOM) were used to infer/derive new mapping quadruples. As SeMRA and its applications have matured, I have been able to backport many of its good ideas to SSSOM. This post is specifically about how I’ve proposed a simple, optional, explicit provenance model that allows mapping records in SSSOM derived through inference to reference the set of mapping quadruples that were used during inference, in a new `derived_from` slot. ### Reference the Triple, Quadruple, or Record? This slot is deliberately under-specified, but there’s a key nuance that the values in this field should point to identifiers for mapping quadruples, not mapping triples nor mapping records for the following reasons: 1. Mapping triples are insufficient: without the judgment of whether a mapping is true or false, then an algorithm could accidentally conclude from `A skos:exactMatch B` and `B (not) skos:exactMatch C` that `A skos:exactMatch C`. This is why mapping triples are insufficient 2. Inference happens on the mapping quadruple level, so it matches nicely 3. Full mapping records are inflexible: the SSSOM data should be flexible so if additional evidence (i.e., records) for a given mapping quadruple are found, then the confidence in the inferred/derived mapping (e.g., chained or inverted) can be adjusted accordingly. This is possible because most chaining and inversion algorithms logically operate on mapping quadruples, and not on records. This is why in the following diagrams, there are mapping quads represented in pink boxes and mapping records represented by purple boxes. Note: the local unique identifiers used for mappings in this example are related to the proposal in https://github.com/ts4nfdi/mapping-sameness-identifier (which currently is under review). For now, the SSSOM specification isn’t prescribing how to assign identifiers to mapping quadruples. ## Contribution See the original issue mapping-commons/sssom#537 and pull request mapping-commons/sssom#548. This post is an extension of the documentation I wrote in that PR (https://mapping-commons.github.io/sssom/dev/inference). I implemented the `derived_from` field in SSSOM Pydantic in cthoyt/sssom-pydantic#108. Subsequently, while preparing this post, I implemented a mechanism for generating the pretty Mermaid diagrams I’ve used throughout this post in cthoyt/sssom-pydantic#129. Here’s how this looks in Python: from curies import Converter, NamableReference, NamedReference from curies.vocabulary import charlie, manual_mapping_curation, mapping_chaining, exact_match from sssom_pydantic import SemanticMapping, hash_triple_to_reference CONVERTER = Converter.from_prefix_map({ "BTO": "http://purl.obolibrary.org/obo/CHEBI_", "CL": "http://purl.obolibrary.org/obo/CL_", "mesh": "http://id.nlm.nih.gov/mesh/", "wikidata": "http://www.wikidata.org/entity/", "orcid": "https://orcid.org/", "semapv": "https://w3id.org/semapv/vocab/", "skos": "http://www.w3.org/2004/02/skos/core#", }) E1 = NamedReference.from_curie("BTO:0006078", name="pluripotent stem cell") E2 = NamedReference.from_curie("CL:0002248", name="pluripotent stem cell") E3 = NamedReference.from_curie("mesh:D039904", name="Pluripotent Stem Cells") SOURCE = NamableReference.from_curie("wikidata:Q111239110", name="Biomappings") m1 = SemanticMapping( subject=E1, predicate=exact_match, object=E2, justification=manual_mapping_curation, authors=[charlie], source=SOURCE, ) m2 = SemanticMapping( subject=E2, predicate=exact_match, object=E3, justification=manual_mapping_curation, authors=[charlie], source=SOURCE, ) m3 = SemanticMapping( subject=E1, predicate=exact_match, object=E3, justification=mapping_chaining, # This is the new part! derived_from=[ hash_triple_to_reference(m1, CONVERTER), hash_triple_to_reference(m2, CONVERTER), ], ) Damien Goutte-Gattat also implemented the `derived_from` in SSSOM Java in gouttegd/sssom-java#19. ## Examples To finish off this post, I’ve included five real-world examples combining manually curated mappings from Biomappings and the ChEBI ontology that show off three types of inference: inversion, chaining, and background knowledge-based mapping. ### Inversion A mapping inversion workflow inverts the mapping predicate then swaps subject and object components. For example, the mapping predicate `skos:narrowMatch` and`skos:broadMatch` are inverses and `skos:exactMatch` is its own inverse. More information about mapping predicates can be found in the SSSOM documentation. The introduction of the `derived_from` field allows an inverted mapping record to refer back to the mapping it was derived from. In the example below, a manually curated mapping between MeSH and ChEBI’s terms for ammeline is inverted. flowchart LR mesh:C000089[ammeline mesh:C000089] CHEBI:28646[ammeline CHEBI:28646] 1181E81AD58C1B94("mesh:C000089 skos:exactMatch CHEBI:28646 manual curation") style 1181E81AD58C1B94 fill:#bbf orcid:0000-0003-4423-4370[Charles Tapley Hoyt orcid:0000-0003-4423-4370] style orcid:0000-0003-4423-4370 fill: #bef wikidata:Q111239110[Biomappings wikidata:Q111239110] style wikidata:Q111239110 fill: #feb 36a1f9244ea7641a90987c82f33c25c0c13712ee8f48207b2a0825f8a4e4e26a[["mesh:C000089 skos:exactMatch CHEBI:28646"]] style 36a1f9244ea7641a90987c82f33c25c0c13712ee8f48207b2a0825f8a4e4e26a fill: #f9f 54D1553627DC5514("CHEBI:28646 skos:exactMatch mesh:C000089 inversion") style 54D1553627DC5514 fill: #bbf faeefc6d1dd08238a9732de5a3c9dcf99388e62fa8b1caaf9ba28c7eaf6d483a[["CHEBI:28646 skos:exactMatch mesh:C000089"]] style faeefc6d1dd08238a9732de5a3c9dcf99388e62fa8b1caaf9ba28c7eaf6d483a fill: #f9f 1181E81AD58C1B94 -->|has author|orcid:0000-0003-4423-4370 1181E81AD58C1B94-->|source|wikidata:Q111239110 mesh:C000089 -->|subject of|1181E81AD58C1B94 CHEBI:28646 -->|object of|1181E81AD58C1B94 36a1f9244ea7641a90987c82f33c25c0c13712ee8f48207b2a0825f8a4e4e26a -->|has evidence|1181E81AD58C1B94 CHEBI:28646 -->|subject of|54D1553627DC5514 mesh:C000089 -->|object of|54D1553627DC5514 faeefc6d1dd08238a9732de5a3c9dcf99388e62fa8b1caaf9ba28c7eaf6d483a -->|has evidence|54D1553627DC5514 54D1553627DC5514 -->|derived from|36a1f9244ea7641a90987c82f33c25c0c13712ee8f48207b2a0825f8a4e4e26a Source SSSOM TSV | subject_id | subject_label | predicate_id | object_id | object_label | mapping_justification | author_id | mapping_source | derived_from | | :----------- | :------------ | :-------------- | :----------- | :----------- | :--------------------------- | :------------------------ | :------------------ | :----------------------------------------------------------------------- | | mesh:C000089 | ammeline | skos:exactMatch | CHEBI:28646 | ammeline | semapv:ManualMappingCuration | orcid:0000-0003-4423-4370 | wikidata:Q111239110 | | | CHEBI:28646 | ammeline | skos:exactMatch | mesh:C000089 | ammeline | semapv:MappingInversion | | | mapping:36a1f9244ea7641a90987c82f33c25c0c13712ee8f48207b2a0825f8a4e4e26a | ## Chaining A mapping chaining workflow applies SSSOM chaining rules to combine one or more mappings who share subjects/objects. The resulting mappings should be tagged with `semapv:MappingChaining` as a justification. Depending on the implementation, directionality is important, so inferring inverted mappings before chaining is important. flowchart LR BTO:0006078[pluripotent stem cell BTO:0006078] CL:0002248[pluripotent stem cell CL:0002248] EEB83E3B60649C0E("BTO:0006078 skos:exactMatch CL:0002248 manual curation") style EEB83E3B60649C0E fill: #bbf orcid:0000-0003-4423-4370[Charles Tapley Hoyt orcid:0000-0003-4423-4370] style orcid:0000-0003-4423-4370 fill: #bef wikidata:Q111239110[Biomappings wikidata:Q111239110] style wikidata:Q111239110 fill:#feb 8a12a396b85642cccfc799fb24320c51a4aabf3294780cb31116d45f773a2572[["BTO:0006078 skos:exactMatch CL:0002248"]] style 8a12a396b85642cccfc799fb24320c51a4aabf3294780cb31116d45f773a2572 fill: #f9f mesh:D039904[pluripotent stem cells mesh:D039904] CD2204936C2DDC93("CL:0002248 skos:exactMatch mesh:D039904 manual curation") style CD2204936C2DDC93 fill: #bbf 988ce14e26fdbf24aeb27b4d8b5ad4bcc25b5cdb46be4e674bfa88a2abe12264[["CL:0002248 skos:exactMatch mesh:D039904"]] style 988ce14e26fdbf24aeb27b4d8b5ad4bcc25b5cdb46be4e674bfa88a2abe12264 fill: #f9f AC5F57BF466F5641("BTO:0006078 skos:exactMatch mesh:D039904 chaining") style AC5F57BF466F5641 fill: #bbf 0d2804dff03667d435d38f61e97cd8435382ad45104c6be460f9aa318e0a4622[["BTO:0006078 skos:exactMatch mesh:D039904"]] style 0d2804dff03667d435d38f61e97cd8435382ad45104c6be460f9aa318e0a4622 fill: #f9f EEB83E3B60649C0E -->|has author|orcid:0000-0003-4423-4370 EEB83E3B60649C0E-->|source|wikidata:Q111239110 BTO:0006078 -->|subject of|EEB83E3B60649C0E CL:0002248 -->|object of|EEB83E3B60649C0E 8a12a396b85642cccfc799fb24320c51a4aabf3294780cb31116d45f773a2572 -->|has evidence|EEB83E3B60649C0E CD2204936C2DDC93 -->|has author|orcid:0000-0003-4423-4370 CD2204936C2DDC93 -->|source|wikidata:Q111239110 CL:0002248 -->|subject of|CD2204936C2DDC93 mesh:D039904 -->|object of|CD2204936C2DDC93 988ce14e26fdbf24aeb27b4d8b5ad4bcc25b5cdb46be4e674bfa88a2abe12264 -->|has evidence|CD2204936C2DDC93 BTO:0006078 -->|subject of|AC5F57BF466F5641 mesh:D039904 -->|object of|AC5F57BF466F5641 0d2804dff03667d435d38f61e97cd8435382ad45104c6be460f9aa318e0a4622-->|has evidence|AC5F57BF466F5641 AC5F57BF466F5641 -->|derived from|8a12a396b85642cccfc799fb24320c51a4aabf3294780cb31116d45f773a2572 AC5F57BF466F5641 -->|derived from|988ce14e26fdbf24aeb27b4d8b5ad4bcc25b5cdb46be4e674bfa88a2abe12264 Source SSSOM TSV | subject_id | subject_label | predicate_id | object_id | object_label | mapping_justification | author_id | mapping_source | derived_from | | :---------- | :-------------------- | :-------------- | :----------- | :--------------------- | :--------------------------- | :------------------------ | :------------------ | :----------------------------------------------------------------------- | ------------------------------------------------------------------------ | | BTO:0006078 | pluripotent stem cell | skos:exactMatch | CL:0002248 | pluripotent stem cell | semapv:ManualMappingCuration | orcid:0000-0003-4423-4370 | wikidata:Q111239110 | | | CL:0002248 | pluripotent stem cell | skos:exactMatch | mesh:D039904 | pluripotent stem cells | semapv:ManualMappingCuration | orcid:0000-0003-4423-4370 | wikidata:Q111239110 | | | BTO:0006078 | pluripotent stem cell | skos:exactMatch | mesh:D039904 | pluripotent stem cells | semapv:MappingChaining | | | mapping:8a12a396b85642cccfc799fb24320c51a4aabf3294780cb31116d45f773a2572 | mapping:988ce14e26fdbf24aeb27b4d8b5ad4bcc25b5cdb46be4e674bfa88a2abe12264 | ## Chaining with Negatives When I wrote the initial SSSOM chaining rules, I did not include any examples on how negative modifiers interact with the rules. This example is a prospective look on how negative mappings and positive mappings could interact. I will be making some improvements to the SSSOM docs with additional concrete rules soon. flowchart LR CHEBI:10057[9H-xanthene CHEBI:10057] mesh:C002563[xanthan gum mesh:C002563] 462D9D4128330C63("CHEBI:10057 not skos:exactMatch mesh:C002563 manual curation") style 462D9D4128330C63 fill: #bbf orcid:0000-0003-4423-4370[Charles Tapley Hoyt orcid:0000-0003-4423-4370] style orcid:0000-0003-4423-4370 fill: #bef wikidata:Q111239110[Biomappings wikidata:Q111239110] style wikidata:Q111239110 fill:#feb 58f24ccfaf71431276da873c9e7b77ea61a2425e4e8b283b943542290deb292bN[["CHEBI:10057 not skos:exactMatch mesh:C002563"]] style 58f24ccfaf71431276da873c9e7b77ea61a2425e4e8b283b943542290deb292bN fill: #f9f cas:92-83-1[Xanthene cas:92-83-1] 190EA9377428B4CB("cas:92-83-1 skos:exactMatch CHEBI:10057 manual curation") style 190EA9377428B4CB fill: #bbf bb1162fb2afb1c519c0aa8be98c352061720af220e2d052c571a1fecabff9800[["cas:92-83-1 skos:exactMatch CHEBI:10057"]] style bb1162fb2afb1c519c0aa8be98c352061720af220e2d052c571a1fecabff9800 fill: #f9f 25AC613A93F7EF14("cas:92-83-1 not skos:exactMatch mesh:C002563 chaining") style 25AC613A93F7EF14 fill: #bbf 84238c3cc875f0939ee4a8cf76bf33f216784434756833e3ba8d1b1183c372f5N[["cas:92-83-1 not skos:exactMatch mesh:C002563"]] style 84238c3cc875f0939ee4a8cf76bf33f216784434756833e3ba8d1b1183c372f5N fill: #f9f 462D9D4128330C63 -->|has author|orcid:0000-0003-4423-4370 462D9D4128330C63 -->|source|wikidata:Q111239110 CHEBI:10057 -->|subject of|462D9D4128330C63 mesh:C002563 -->|object of|462D9D4128330C63 58f24ccfaf71431276da873c9e7b77ea61a2425e4e8b283b943542290deb292bN -->|has evidence|462D9D4128330C63 190EA9377428B4CB -->|has author|orcid:0000-0003-4423-4370 190EA9377428B4CB -->|source|wikidata:Q111239110 cas:92-83-1 -->|subject of|190EA9377428B4CB CHEBI:10057 -->|object of|190EA9377428B4CB bb1162fb2afb1c519c0aa8be98c352061720af220e2d052c571a1fecabff9800 -->|has evidence|190EA9377428B4CB cas:92-83-1 -->|subject of|25AC613A93F7EF14 mesh:C002563 -->|object of|25AC613A93F7EF14 84238c3cc875f0939ee4a8cf76bf33f216784434756833e3ba8d1b1183c372f5N -->|has evidence|25AC613A93F7EF14 25AC613A93F7EF14 -->|derived from|58f24ccfaf71431276da873c9e7b77ea61a2425e4e8b283b943542290deb292bN 25AC613A93F7EF14 -->|derived from|bb1162fb2afb1c519c0aa8be98c352061720af220e2d052c571a1fecabff9800 Source SSSOM TSV | subject_id | subject_label | predicate_id | predicate_modifier | object_id | object_label | mapping_justification | author_id | mapping_source | derived_from | | :---------- | :------------ | :-------------- | :----------------- | :----------- | :----------- | :--------------------------- | :------------------------ | :------------------ | :------------------------------------------------------------------------ | ------------------------------------------------------------------------ | | CHEBI:10057 | 9H-xanthene | skos:exactMatch | Not | mesh:C002563 | xanthan gum | semapv:ManualMappingCuration | orcid:0000-0003-4423-4370 | wikidata:Q111239110 | | | cas:92-83-1 | Xanthene | skos:exactMatch | | CHEBI:10057 | 9H-xanthene | semapv:ManualMappingCuration | orcid:0000-0003-4423-4370 | wikidata:Q111239110 | | | cas:92-83-1 | Xanthene | skos:exactMatch | Not | mesh:C002563 | xanthan gum | semapv:MappingChaining | | | mapping:58f24ccfaf71431276da873c9e7b77ea61a2425e4e8b283b943542290deb292b~ | mapping:bb1162fb2afb1c519c0aa8be98c352061720af220e2d052c571a1fecabff9800 | ## Background Knowledge Inference based on background knowledge was one of the key contributions of SeMRA. For example, it’s known that mappings in ChEBI to CAS are exact matches, but by curation convention, they’re annotated with the less precise `oboInOwl:hasDbXref`. Workflows that incorporate this knowledge should be tagged with `semapv:BackgroundKnowledgeBasedMatching` as a mapping justification. In this example, I show how a poorly specified mapping from ChEBI is upgraded to an exact match. flowchart LR CHEBI:10057[9H-xanthene CHEBI:10057] cas:92-83-1[Xanthene cas:92-83-1] 964DD2FDA95501A2("CHEBI:10057 oboInOwl:hasDbXref cas:92-83-1 unspecified") style 964DD2FDA95501A2 fill: #bbf obo:chebi[ChEBI Ontology obo:chebi] style obo:chebi fill: #feb 887c2cc0c006b49df5fa0bc281e23bd3722880d5096e27218082bd6edf96f59e[["CHEBI:10057 oboInOwl:hasDbXref cas:92-83-1"]] style 887c2cc0c006b49df5fa0bc281e23bd3722880d5096e27218082bd6edf96f59e fill: #f9f B5CF0F3AB755AC6D("CHEBI:10057 skos:exactMatch cas:92-83-1 background know.") style B5CF0F3AB755AC6D fill: #bbf e61f33dbb925f2282823afdad56c24feee9875953ea2de9124a50e47bd63418a[["CHEBI:10057 skos:exactMatch cas:92-83-1"]] style e61f33dbb925f2282823afdad56c24feee9875953ea2de9124a50e47bd63418a fill: #f9f 964DD2FDA95501A2 -->|source|obo:chebi CHEBI:10057 -->|subject of|964DD2FDA95501A2 cas:92-83-1 -->|object of|964DD2FDA95501A2 887c2cc0c006b49df5fa0bc281e23bd3722880d5096e27218082bd6edf96f59e -->|has evidence|964DD2FDA95501A2 CHEBI:10057 -->|subject of|B5CF0F3AB755AC6D cas:92-83-1 -->|object of|B5CF0F3AB755AC6D e61f33dbb925f2282823afdad56c24feee9875953ea2de9124a50e47bd63418a -->|has evidence|B5CF0F3AB755AC6D B5CF0F3AB755AC6D -->|derived from|887c2cc0c006b49df5fa0bc281e23bd3722880d5096e27218082bd6edf96f59e Source SSSOM TSV | subject_id | subject_label | predicate_id | predicate_label | object_id | object_label | mapping_justification | mapping_source | derived_from | | :---------- | :------------ | :----------------- | :--------------------------- | :---------- | :----------- | :-------------------------------------- | :------------- | :----------------------------------------------------------------------- | | CHEBI:10057 | 9H-xanthene | oboInOwl:hasDbXref | has database cross-reference | cas:92-83-1 | Xanthene | semapv:UnspecifiedMatching | obo:chebi | | | CHEBI:10057 | 9H-xanthene | skos:exactMatch | | cas:92-83-1 | Xanthene | semapv:BackgroundKnowledgeBasedMatching | | mapping:887c2cc0c006b49df5fa0bc281e23bd3722880d5096e27218082bd6edf96f59e | ## End-to-End Inference This end-to-end example demonstrates the cumulation of inversion, chaining, and background-based workflows. While it only starts with two mappings, it shows how the successive application of these workflows can give full transparency and auditability in the process of inference. In real-world scenarios, I would want to use the mesh-cas exact match to automatically integrate data, such as in the construction of a knowledge graph. In case this mapping is adjacent to a node important for a prediction, I would want to be able to fully audit how that node was constructed via this mapping diagram. flowchart LR CHEBI:133530[tyramine sulfate CHEBI:133530] cas:30223-92-8[Tyramine sulfate cas:30223-92-8] 983062C7B8D6517E("CHEBI:133530 oboInOwl:hasDbXref cas:30223-92-8 unspecified") style 983062C7B8D6517E fill: #bbf obo:chebi[ChEBI Ontology obo:chebi] style obo:chebi fill:#feb 0b8eb968c306d65e1715a7b0961f6a4d99b5b19081edb67cee701fd887af1290[["CHEBI:133530 oboInOwl:hasDbXref cas:30223-92-8"]] style 0b8eb968c306d65e1715a7b0961f6a4d99b5b19081edb67cee701fd887af1290 fill: #f9f 21056C0956788E11("CHEBI:133530 skos:exactMatch cas:30223-92-8 background know.") style 21056C0956788E11 fill: #bbf a0022401f47964288ecc1ab706d79b4d4abc10edf33d0a71953834a0b0b3c24c[["CHEBI:133530 skos:exactMatch cas:30223-92-8"]] style a0022401f47964288ecc1ab706d79b4d4abc10edf33d0a71953834a0b0b3c24c fill: #f9f mesh:C027957[tyramine O-sulfate mesh:C027957] 244808D78AFCBDC1("CHEBI:133530 skos:exactMatch mesh:C027957 manual curation") style 244808D78AFCBDC1 fill: #bbf orcid:0000-0003-4423-4370[Charles Tapley Hoyt orcid:0000-0003-4423-4370] style orcid:0000-0003-4423-4370 fill: #bef wikidata:Q111239110[Biomappings wikidata:Q111239110] style wikidata:Q111239110 fill: #feb b8d737b89a421bd6ca058314564c9ed507cbfe3ec4a2e82979fefdfe708019ea[["CHEBI:133530 skos:exactMatch mesh:C027957"]] style b8d737b89a421bd6ca058314564c9ed507cbfe3ec4a2e82979fefdfe708019ea fill: #f9f 474146D6A6AFF3C7("mesh:C027957 skos:exactMatch CHEBI:133530 inversion") style 474146D6A6AFF3C7 fill: #bbf 1036c55358639c5db78ada181ac38d8eda337e83efe1db901716d101777f8474[["mesh:C027957 skos:exactMatch CHEBI:133530"]] style 1036c55358639c5db78ada181ac38d8eda337e83efe1db901716d101777f8474 fill: #f9f AED810A43159DA66("mesh:C027957 skos:exactMatch cas:30223-92-8 chaining") style AED810A43159DA66 fill: #bbf b5cd9f2dfa98540a3485a473bed0870720d7de23b87847ba508b8c85961e3b7d[["mesh:C027957 skos:exactMatch cas:30223-92-8"]] style b5cd9f2dfa98540a3485a473bed0870720d7de23b87847ba508b8c85961e3b7d fill: #f9f 983062C7B8D6517E -->|source|obo:chebi CHEBI:133530 -->|subject of|983062C7B8D6517E cas:30223-92-8 -->|object of|983062C7B8D6517E 0b8eb968c306d65e1715a7b0961f6a4d99b5b19081edb67cee701fd887af1290 -->|has evidence|983062C7B8D6517E CHEBI:133530 -->|subject of|21056C0956788E11 cas:30223-92-8 -->|object of|21056C0956788E11 a0022401f47964288ecc1ab706d79b4d4abc10edf33d0a71953834a0b0b3c24c -->|has evidence|21056C0956788E11 244808D78AFCBDC1 -->|has author|orcid:0000-0003-4423-4370 244808D78AFCBDC1 -->|source|wikidata:Q111239110 CHEBI:133530 -->|subject of|244808D78AFCBDC1 mesh:C027957 -->|object of|244808D78AFCBDC1 b8d737b89a421bd6ca058314564c9ed507cbfe3ec4a2e82979fefdfe708019ea -->|has evidence|244808D78AFCBDC1 mesh:C027957 -->|subject of|474146D6A6AFF3C7 CHEBI:133530 -->|object of|474146D6A6AFF3C7 1036c55358639c5db78ada181ac38d8eda337e83efe1db901716d101777f8474-->|has evidence|474146D6A6AFF3C7 mesh:C027957-->|subject of|AED810A43159DA66 cas:30223-92-8 -->|object of|AED810A43159DA66 b5cd9f2dfa98540a3485a473bed0870720d7de23b87847ba508b8c85961e3b7d -->|has evidence|AED810A43159DA66 21056C0956788E11-->|derived from|0b8eb968c306d65e1715a7b0961f6a4d99b5b19081edb67cee701fd887af1290 474146D6A6AFF3C7 -->|derived from|b8d737b89a421bd6ca058314564c9ed507cbfe3ec4a2e82979fefdfe708019ea AED810A43159DA66 -->|derived from|a0022401f47964288ecc1ab706d79b4d4abc10edf33d0a71953834a0b0b3c24c AED810A43159DA66 -->|derived from|1036c55358639c5db78ada181ac38d8eda337e83efe1db901716d101777f8474 Source SSSOM TSV | subject_id | subject_label | predicate_id | predicate_label | object_id | object_label | mapping_justification | mapping_source | derived_from | author_id | | :----------- | :----------------- | :----------------- | :--------------------------- | :------------- | :----------------- | :-------------------------------------- | :------------------ | :----------------------------------------------------------------------- | :----------------------------------------------------------------------- | --- | | CHEBI:133530 | tyramine sulfate | oboInOwl:hasDbXref | has database cross-reference | cas:30223-92-8 | Tyramine sulfate | semapv:UnspecifiedMatching | obo:chebi | | | | CHEBI:133530 | tyramine sulfate | skos:exactMatch | | cas:30223-92-8 | Tyramine sulfate | semapv:BackgroundKnowledgeBasedMatching | | mapping:0b8eb968c306d65e1715a7b0961f6a4d99b5b19081edb67cee701fd887af1290 | | | CHEBI:133530 | tyramine sulfate | skos:exactMatch | | mesh:C027957 | tyramine O-sulfate | semapv:ManualMappingCuration | wikidata:Q111239110 | | orcid:0000-0003-4423-4370 | | mesh:C027957 | tyramine O-sulfate | skos:exactMatch | | CHEBI:133530 | tyramine sulfate | semapv:MappingInversion | | mapping:b8d737b89a421bd6ca058314564c9ed507cbfe3ec4a2e82979fefdfe708019ea | | | mesh:C027957 | tyramine O-sulfate | skos:exactMatch | | cas:30223-92-8 | Tyramine sulfate | semapv:MappingChaining | | mapping:a0022401f47964288ecc1ab706d79b4d4abc10edf33d0a71953834a0b0b3c24c | mapping:1036c55358639c5db78ada181ac38d8eda337e83efe1db901716d101777f8474 | |
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 22/05/2026
my software package `drugbank-downloader` which automated downloading and parsing DrugBank XML doesn't work anymore because DrugBank has (temporarily) discontinued allowing academics to download it I guess this gets categorized as "API rug-pull" under @andrewnez's taxonomy of software death in […]
scholar.social
Original post on scholar.social
202 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 22/05/2026
when I get cold emails asking about my open source code, I give the option to publicly continue discussion on the corresponding GitHub repository or offer paid private consulting
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 19/05/2026
RE: nfdi.social/@NFDI4Chem/116561900886… summary of interesting discussions I had last week at the NFDI4Chem Consortium Meeting 7.0: cthoyt.com/2026/05/18/nfdi4chem-7th…
nfdi.social
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 19/05/2026
RE: nfdi.social/@dalia/1166001954354649… i helped
nfdi.social
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 19/05/2026
RE: mastodon.social/@glynmoody/11660033… at my sister's graduation from physician's assistant school last week, AI was only mentioned once in passing to remind the graduates not to lose sight that the personal aspect of care is the most important
mastodon.social
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 17/05/2026
A Field Manual for Three Years on Deutsche Bahn | Larvitz Blog blog.hofstede.it/a-field-manual-for…
002 2
Reposted by Charles Tapley Hoyt
theHigherGeometer @highergeometer.mathstodon.xyz.ap.brid.gy · 15/05/2026
"We have recently clarified our penalties for this. If a submission contains incontrovertible evidence that the authors did not check the results of LLM generation, this means we can't trust anything in the paper. 3/ The penalty is a 1-year ban from arXiv followed by the requirement that […]
mathstodon.xyz
Original post on mathstodon.xyz
1112 12
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 10/05/2026
@osma you might appreciate this article: til.andrew-quinn.me/posts/replacing…
til.andrew-quinn.me
Replacing a 3 GB SQLite database with a 10 MB FST (finite state transducer) binary
Note for numberphiles: all numbers have been rounded to their first significant digit, because I’m a fan of Rob Eastaway’s “zequals” method of getting to the point when it comes to estimation. It’s much more valuable to walk away with the heuristic “some dude got a 300x memory reduction by swapping out a database he hacked together for a tiny, static, specialized data structure that does exactly what he needs it to and no more.”
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 22/04/2026
do i just dislike the font that AI-generated (scientific) images use? Is it that I can see the kerning is bad? Or do I just have disdain that they are AI-generated?
101 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 14/04/2026
SSSOM now specifies an algorithm for hashing _records_ (i.e., rows in a SSSOM TSV file) to support interoperability across implementations and make semantic mappings more FAIR 📖 mapping-commons.github.io/sssom/spe… Implementations are already available in SSSOM-Java and […]
scholar.social
Original post on scholar.social
001 1
Reposted by Charles Tapley Hoyt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 04/04/2026
What does Open Source mean? nesbitt.io/2026/04/04/what-does-ope…
nesbitt.io
What does Open Source mean?
Every few months someone declares that “X will kill open source” or that “open source is not sustainable” or that “open source won”, and every time the responses split into factions that seem to be having completely different conversations. People have been pointing this out for at least a decade. Replacement terms like “post-open source” never stuck, because the problem isn’t the label. The phrase “open source” carries so many meanings that people routinely talk past each other while using the exact same words, each person confident the other is being obtuse when really they’re just working from a different definition. **A licensing regime.** Software distributed under a license meeting the Open Source Definition: free redistribution, source availability, derived works permitted. The OSI maintains this formal definition, and for a certain kind of conversation it’s the only one that counts. **A development methodology.** The Cathedral and the Bazaar thesis, “given enough eyeballs, all bugs are shallow”, the idea that developing in the open with public revision history and review produces better software. You can have this without the licensing (source-available projects with public repos) and the licensing without this (code-dump releases with no public development process at all). The two definitions are doing different work. **A business model.** Open core, dual licensing, managed hosting, support contracts, consulting, and the dozen other ways companies try to capture value from code they give away. At the strategic end, this includes open sourcing something specifically to commoditise a competitor’s differentiator, the way Android commoditised mobile operating systems and Kubernetes commoditised container orchestration. These models sit in permanent tension with most other definitions on this list. Open source business arguments tend to go in circles because everyone is talking about different things. **A supply chain.** The set of packages in your dependency tree, the SBOM, the compliance checklist, a procurement category where the vendor has unusual contractual terms (namely, none). Governments have started treating it the same way, funding programs like Alpha-Omega and the Sovereign Tech Fund because software supply chain security is now a national security concern. The people producing the software are, as they will remind you, not your supplier. **A commons.** What Nadia Eghbal called “roads and bridges.” Shared infrastructure that everyone depends on but nobody owns. Making the commons visible enough that people might actually help maintain it remains the unsolved problem. **A political movement.** Free Software’s sibling, or depending on who you ask, its corporate-friendly dilution. User freedom, transparency, power dynamics, who controls computing. People who hold this definition get frustrated with everyone else on this list for treating those concerns as secondary. **A marketing label.** “We open sourced it” plays well in a press release. Source-available projects call themselves open source for the brand halo, and companies open source a project, collect the community goodwill, then quietly change the license two years later. **A social identity.** “I’m an open source developer” describes belonging to a scene with its own conferences, norms, status hierarchies, and cultural touchstones. It exists independently of any particular codebase. The career-oriented version treats GitHub profiles as resumes and open source contributions as proof of competence, which quietly advantages people with free time and disadvantages everyone else. **A governance model.** Who has commit access and how did they earn it? BDFLs, steering committees, foundations, do-ocracy, rough consensus. When a maintainer disappears or a foundation makes an unpopular decision, this is the definition people are arguing about even if they frame it in licensing or business terms. **A coordination layer.** Neutral ground where companies that compete in the market collaborate on shared infrastructure none of them can justify building alone. The Linux kernel, Kubernetes, and OpenTelemetry all work this way. The foundation politics that surround them make more sense as multi-party coordination problems than as altruistic code sharing. **A forkability guarantee.** The credible threat of a fork shapes behaviour even when no fork happens, and it disciplines maintainers, companies, and foundations alike. This is why license changes provoke such intense reactions: OpenTofu exists because HashiCorp broke the forkability guarantee, and MariaDB exists because Oracle made people nervous about it. Forkability is one of the few accountability mechanisms open source actually has. **An innovation diffusion mechanism.** HTTP servers, container runtimes, programming languages: open source is the way standards actually propagate, how technology becomes infrastructure. Nobody coordinates it because open source code can be adopted without negotiation. **A moral obligation.** “You should open source that” carries real social pressure, sometimes justified and sometimes not, rooted in the idea that if you built on open source you owe something back. This reciprocity norm causes particular friction when it collides with the business model definition, where the whole point is capturing value. **A research output.** In academia, open source is the reproducibility layer, software as a scholarly artefact with the FAIR principles applied to code. This definition barely overlaps with the business or supply chain readings, which is part of why academic open source and industry open source often feel like they’re happening on different planets. **A free help desk.** People file GitHub issues that are support tickets or feature demands, expecting maintainers to triage, respond, and deliver, and vendor packages into their products expecting indefinite updates without any relationship or contribution flowing back. The issue tracker becomes a customer service portal where the customer paid nothing, and the lockfile becomes an eternal service contract nobody signed. The people holding this definition rarely state it explicitly because they don’t think of it as a definition, they just think that’s how open source works. **Free infrastructure.** Package registries, CDNs, CI runners, and mirror networks get treated like tap water. npm, PyPI, RubyGems.org, and crates.io all absorb enormous operational costs and traffic while people build entire businesses on top of them without considering who pays for any of it. **Vibes.** The code is on GitHub. That’s about as far as the thinking goes. Probably the most common usage of the term by volume. The help desk and free infrastructure framings are entitlement definitions, “open source” meaning “someone else bears the costs so I don’t have to.” One is about labour, the other about operational infrastructure, and they compound on each other: the person filing a feature request on a registry’s GitHub repo is simultaneously demanding free labour and taking the free infrastructure for granted. These cause the most material harm to the people actually doing the work, and the people holding them don’t recognise them as definitions at all. How can the commons also be a supply chain? How can a moral obligation also be a business model? “Open source” is a stack of incompatible expectations. Next time someone says something will kill it, ask them which one. They’re probably right about at least one of them.
002 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 01/04/2026
RE: sigmoid.social/@osma/11632836492293… cool stuff from the SKOS and SKOSMOS crew :)
002 2
Reposted by Charles Tapley Hoyt
𝓒𝓱𝓻𝓲𝓼𝓽𝓸𝓯 𝓓𝓸𝓷𝓪𝓽 @cdonat.hostsharing.coop.ap.brid.gy · 26/03/2026
I have started a new project: ProFed. I’m trying to understand how far #professionalNetworking can go in the #Fediverse. joinprofed.social codeberg.org/GrayDurian/ProFed I’m interested in how you see this.
ProFed - federated professional networking
101 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 23/03/2026
that feeling when someone sends a pull request that includes modifications to turn off linter checks they didn't pass
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 19/03/2026
Astral (makers of uv and ruff) will be acquired by OpenAI (openai.com/index/openai-to-acquire-…) 😐
001 1
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 15/03/2026
RE: mastodon.social/@sethmlarson/116229… I just added a human.json to my blog too! I like writing and creating and won't start offloading that to AI anytime soon. commit: github.com/cthoyt/cthoyt.github.io/…
mastodon.social
001 1
Reposted by Charles Tapley Hoyt
Matt Campbell @matt.toot.cafe.ap.brid.gy · 07/03/2026
This blog post recently crossed my timeline. blogs.gentoo.org/mgorny/2026/03/07/… It talks about burnout among FOSS maintainers, which is an important subject. It saddens me, though, that the author called out Rust alongside generative AI as […]
toot.cafe
Original post on toot.cafe
202 2
Reposted by Charles Tapley Hoyt
Robert Kingett @weirdwriter.caneandable.social.ap.brid.gy · 08/03/2026
You all should read this fantastic post by @onepict about how, largely, AI people just can't leave us the fuck alone. But I'm noticing more and more and more that they get super mad when they wanna shove their #AI creation at you and you simply say, no thanks. That's it. No extra bashing, just […]
caneandable.social
Original post on caneandable.social
0218 18
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 04/03/2026
RE: genomic.social/@biocurator/11616594… lots of work went into planning the virtual conference series this year. please join, especially if you're not in the bio- part of the curation and FAIR data world to have cross-disciplinary exchange!
genomic.social
001 1
Reposted by Charles Tapley Hoyt
Ax=b @melissawm.pynews.com.br.ap.brid.gy · 19/02/2026
Hi folks, I'm trying to put together a list of AI generated contribution policies for different open source projects. Do you have any you can link to me here? You can also directly submit a PR to github.com/melissawm/open-source-ai…
github.com
GitHub - melissawm/open-source-ai-contribution-policies: A list of policies by different open source projects about how to engage with AI-generated contributions.
A list of policies by different open source projects about how to engage with AI-generated contributions. - melissawm/open-source-ai-contribution-policies
095 9
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 10/02/2026
I blogged about software I wrote for efficiently downloading and querying @opencitations in bulk 📖 blog: cthoyt.com/2026/02/10/opencitations… 💽 code: github.com/cthoyt/opencitations-cli… #opencitations #bibliometrics #opensource
cthoyt.com
Efficient Bulk Access to Citations in OpenCitations
OpenCitations aggregates and deduplicates bibliographic information from CrossRef, Europe PubMed Central, and other sources to construct a comprehensive, open index of citations between scientific works. This post describes the `opencitations-client` package which wraps the OpenCitations API and implements an automated pipeline for locally downloading, caching, and accessing OpenCitations in bulk. ## Background OpenCitations both provides access via an API and bulk data downloads distributed across FigShare and Zenodo. Importantly, it publishes its data under the CC0 public domain license to democratize access to citations - previously, this data was only available through paid access to commercial databases owned by publishers. While API access can be convenient for _ad-hoc_ usage, it’s generally slow, rate-limited, susceptible to DDoS (e.g., from crawlers), and therefore difficult (if not impossible) to use in bulk. My solution is to write software that automates downloading, processing, and caching databases in bulk and provides fast, highly available, local access. I’ve previously written about developing standalone software packages for several large databases including DrugBank, ChEMBL, UMLS, ORCiD, and ClinicalTrials.gov. Similarly, I maintain several similar workflows in the PyOBO software package for converting resources into ontology-like data structures. I previously wrote about how this looks for HGNC. ## Building on an Existing Ecosystem I’ve been developing a software ecosystem over the last decade to support common workflows in research data management and data integration. When I start a new project, I try and reuse or improve existing components from that ecosystem wherever possible. Importantly, I try and find meaningful ways of organizing code across my ecosystem to reduce duplication, separate concerns, reduce the burden of testing, and ease maintenance. OpenCitations publishes its bulk data dumps across several records in Figshare and Zenodo. I’ve previously written `zenodo-client` to interact with Zenodo’s API and orchestrates downloading and caching. `zenodo-client` heavily builds on `pystow`, which implements I/O and filesystem operations to enable reproducible, automated downloading, caching, and opening of data. I had not previously written software to interact with Figshare, so I followed the form of `zenodo-client` and created a new package, `figshare-client`. I’m able to quickly create new high-quality packages because I’ve encoded all the wisdom and experience I’ve gained over the years in a Cookiecutter template, cookiecutter-snekpack, which I can use to set up a new project in mere minutes. Along the way, I realized that the archives in Zenodo and Figshare were a combination of TAR and ZIP archives, each with many CSV files inside. In Python, TAR and ZIP archives have lots of weird quirks, even though they mostly do the same thing. However, rather than addressing those issues in `opencitations-client`, it made more sense to add utility functions in PyStow in cthoyt/pystow#125 (tar and zip archive iteration), which I was much better able to test in the PyStow archive. A key functionality of OpenCitations is to implement graph-like queries to find incoming and outgoing citations. I considered several solutions for efficiently caching and querying graph-like data including pickles and SQLite, but these were respectively slow and disk inefficient. I found better solutions based on NumPy’s memory maps and was surprised that I couldn’t find an implementation in a popular package (e.g., SciPy). So, I had to decide where to put an implementation of disk-based cached graph. I didn’t want to put it in OpenCitations nor make a tiny package for just this one operation, so I decided to expand the scope of PyStow and add it there in cthoyt/pystow#121. Finally, OpenCitations deals with a variety of identifier spaces including first-party OpenCitations Metadata IDs (OMIDs) and OpenCitations Citation IDs (OCIs) as well as third-party identifiers from Wikidata, OpenAlex, PubMed, DOI, and others. I’ve written the `curies` to handle identifiers in an explicit and transparent way. In the end, the `opencitations-client` relies on several components from my ecosystem, and of course, several more generic and popular packages. Here’s how the dependencies look: flowchart LR opencitations-client -- depends on --> figshare-client opencitations-client -- depends on --> zenodo-client opencitations-client -- depends on --> curies figshare-client -- depends on --> pystow zenodo-client -- depends on --> pystow ## Demo It’s important for software packages to implement simple, top-level APIs that cover 99% of use cases with reasonable defaults. Most use cases for OpenCitations are to get incoming/outgoing citations for a DOI, PubMed identifiers, or OpenCitations identifiers. Here’s how this looks: from curies import Reference from opencitations_client import get_incoming_citations, get_outgoing_citations # a CURIE for the DOI for the Bioregistry paper bioregistry_curie = "doi:10.1038/s41597-022-01807-3" # who did the Bioregistry paper cite? outgoing: list[Reference] = get_outgoing_citations(bioregistry_curie) # who cited the Bioregistry paper? incoming: list[Reference] = get_incoming_citations(bioregistry_curie) Importantly, each of these functions has a `backend` argument that defaults to `api` and can be swapped to `local`. Because everything is built on software that is smart about caching, loading, and data workflows, on the first time `backend='local'` is used, all processing happens automatically (warning, takes a few hours on a single core). This function also has a `return_value` argument that can be used to swap between principled `curies.Reference` data structures that explicitly encode identifiers, simple string local unique identifiers that match the input prefix, or full citation objects (only available through OpenCitations API). See the `opencitations-client` code on GitHub (https://github.com/cthoyt/opencitations-client) and documentation on ReadTheDocs (https://opencitations-client.readthedocs.io). * * * While I’ve been thinking about adding citations to the bibliographic components of knowledge graph construction workflows for several years, I was finally pushed to implement `opencitations-client` for the Catalaix project, where we’re developing new methods for recycling and reuse of (bio)plastics. I wanted to get all seventeen laboratories’ publications, who they cited, and who cited them as a seed for information extraction and curation. Here’s a small example of a citation network from those queries: flowchart TD 26802344["Mechanism-specific and whole-organism ecotoxicity of mono-rhamnolipids. Blank (2016)"] 34492827["The Green toxicology approach: Insight towards the eco-toxicologically safe development of benign catalysts. Herres-Pawlis (2021)"] 28779508["Highly Active N,O Zinc Guanidine Catalysts for the Ring-Opening Polymerization of Lactide. Herres-Pawlis (2017)"] 33195133["Genetic Cell-Surface Modification for Optimized Foam Fractionation. Blank (2020)"] 32974309["Integration of Genetic and Process Engineering for Optimized Rhamnolipid Production Using Jupke, Blank (2020)"] 30811863["New Kids in Lactide Polymerization: Highly Active and Robust Iron Guanidine Complexes as Superior Catalysts. Pich, Herres-Pawlis (2019)"] 30758389["Tuning a robust system: N,O zinc guanidine catalysts for the ROP of lactide. Pich, Herres-Pawlis (2019)"] 28524364["Biofunctional Microgel-Based Fertilizers for Controlled Foliar Delivery of Nutrients to Plants. Pich, Schwaneberg (2017)"] 34865895["A plea for the integration of Green Toxicology in sustainable bioeconomy strategies - Biosurfactants and microgel-based pesticide release systems as examples. Pich, Blank, Schwaneberg (2022)"] 32449840["Robust Guanidine Metal Catalysts for the Ring-Opening Polymerization of Lactide under Industrially Relevant Conditions. Herres-Pawlis (2020)"] 34492827 --> 30811863 34492827 --> 30758389 34492827 --> 28779508 34492827 --> 32449840 32974309 --> 33195133 34865895 --> 26802344 34865895 --> 32974309 34865895 --> 28524364 34865895 --> 34492827
022 2
Charles Tapley Hoyt @cthoyt.scholar.social.ap.brid.gy · 05/02/2026
RE: genomic.social/@biocurator/11601888… I always wanted to see a podcast where people get into the specifics of how they do (bio)curation and FAIR data... so we made that podcast
genomic.social
102 2