In [1]:
import json
import pandas as pd

projects = [
    'DigiBatMat',
    'DIGITRUBBER',
    'DiProMag',
    #'DiStAl',
    'GlasDigital',
    #'iBain',
    'KNOW-NOW',
    'KupferDigital',
    'LeBeDigital',
    'ODE_AM',
    'PMDao_MO',
    'PMDao_TTO',
    'SensoTwin',
    'SmaDi',
    'StahlDigital'
]

data = {}

for ont in projects:
    with open(f'{ont}/{ont}.json', 'r', encoding='utf-8') as f:
        data.update({ont: json.load(f)})

Used Top-Level-Ontologies¶

For each of the provided ontologies the use of TLOs was analyzed. This was achieved by counting rdfs:subClassOf and rdfs:subPropertyOf chains, for which the subject belongs to the projects namespace and the object belongs to the TLOs namespace. For example, the SPARQL-Query for the usage of PMD Core Ontology (v2.0.x) in the SensoTwin project reads:

SELECT (COUNT(*) as ?subcount)
WHERE {
    ?ao rdfs:subClassOf+|rdfs:subPropertyOf+ ?tlo .
    FILTER( STRSTARTS( STR(?tlo), "https://w3id.org/pmd/co" ) ) .
    FILTER( STRSTARTS( STR(?ao), "http://w3id.org/sensotwin/applicationontology" ) ) .
}
In [2]:
pd.DataFrame({ont: {tlo: d['subclassesproperties'] for tlo, d in item['tlos']['reasoned'].items()} for ont, item in data.items()}).T
Out[2]:
pmdco-2.0.7 pmdco-v0.1-beta emmo cco bfo ro iao prov-o qudt chebi
DigiBatMat 8 0 0 0 0 0 0 4 1 0
DIGITRUBBER 0 0 0 0 2030 0 328 0 0 232
DiProMag 164 0 0 0 0 0 0 96 83 0
GlasDigital 0 284 0 0 0 0 0 0 0 0
KNOW-NOW 121 0 34 0 0 0 0 81 0 0
KupferDigital 773 0 0 0 0 0 0 293 0 0
LeBeDigital 268 0 0 0 0 0 0 115 0 0
ODE_AM 0 0 0 316 97 0 0 0 0 0
PMDao_MO 337 0 0 0 0 0 0 145 0 0
PMDao_TTO 126 0 0 0 0 0 0 47 0 0
SensoTwin 509 0 0 0 0 0 0 334 0 0
SmaDi 0 0 0 0 0 0 0 0 0 0
StahlDigital 0 52 3 0 0 0 0 0 0 0
SELECT (COUNT(*) as ?count)
WHERE {
    ?ao ?p ?o .
    FILTER( STRSTARTS( STR(?p), "https://w3id.org/pmd/co" ) ) .
    FILTER( STRSTARTS( STR(?ao), "http://w3id.org/sensotwin/applicationontology" ) ) .
}
SELECT (COUNT(*) as ?count)
WHERE {
    ?ao ?p ?o .
    FILTER( STRSTARTS( STR(?o), "https://w3id.org/pmd/co" ) ) .
    FILTER( STRSTARTS( STR(?ao), "http://w3id.org/sensotwin/applicationontology" ) ) .
}
In [3]:
pd.DataFrame({ont: {tlo: d['objects']+d['predicates'] for tlo, d in item['tlos']['reasoned'].items()} for ont, item in data.items()}).T
Out[3]:
pmdco-2.0.7 pmdco-v0.1-beta emmo cco bfo ro iao prov-o qudt chebi
DigiBatMat 1088 0 0 0 0 0 0 479 535 0
DIGITRUBBER 0 0 0 0 375 0 1780 0 0 51
DiProMag 332 0 0 0 0 0 0 17 82 0
GlasDigital 0 118 0 0 0 0 140 0 0 0
KNOW-NOW 1893 0 12 0 0 0 0 97 0 0
KupferDigital 15217 0 0 0 0 0 0 0 0 0
LeBeDigital 4871 0 0 0 0 0 0 436 0 0
ODE_AM 0 0 0 463 3 0 0 0 0 0
PMDao_MO 216 0 0 0 0 0 0 0 0 0
PMDao_TTO 82 0 0 0 0 0 0 0 0 0
SensoTwin 12937 0 0 0 0 0 0 1800 0 0
SmaDi 0 0 0 0 0 0 0 0 0 0
StahlDigital 0 54 1 0 0 0 0 0 2 0

Overall defined concepts¶

The overall number of introduced concepts was analysed. For that, the projects ontology as well as the applicable pmdco were loaded into Protégé and a Reasoner was run. On the resultant graph, the following query was executed (exemplary for owl:Classes in SensoTwin):

SELECT (COUNT(*) as ?classcount)
WHERE {
    ?class a owl:Class .
    FILTER STRSTARTS( ?class, "http://w3id.org/sensotwin/applicationontology" ) .
}

The table below shows the respective numbers of found definitions.

In [4]:
concepts = {ont: {
    'owl:Class': item['definitioncounts']['owl:Class'],
    'owl:ObjectProperty': item['definitioncounts']['owl:ObjectProperty'],
    'owl:DatatypeProperty': item['definitioncounts']['owl:DatatypeProperty'],
    'Total': item['definitioncounts']['owl:Class']+item['definitioncounts']['owl:ObjectProperty']+item['definitioncounts']['owl:DatatypeProperty'],
    'Reasoner': f"{item['reasoner']['reasoner']}-{item['reasoner']['version']}"
} for ont, item in data.items()}
pd.DataFrame(concepts).T
Out[4]:
owl:Class owl:ObjectProperty owl:DatatypeProperty Total Reasoner
DigiBatMat 10 3 0 13 pellet-2.2.0
DIGITRUBBER 636 0 0 636 elk-0.5.0
DiProMag 217 3 2 222 elk-0.5.0
GlasDigital 213 10 33 256 pellet-2.2.0
KNOW-NOW 81 3 0 84 pellet-2.2.0
KupferDigital 293 0 0 293 pellet-2.2.0
LeBeDigital 114 0 0 114 pellet-2.2.0
ODE_AM 256 12 3 271 pellet-2.2.0
PMDao_MO 145 0 0 145 pellet-2.2.0
PMDao_TTO 47 1 0 48 pellet-2.2.0
SensoTwin 193 19 14 226 pellet-2.2.0
SmaDi 105 12 8 125 pellet-2.2.0
StahlDigital 307 295 294 896 pellet-2.2.0

Number of ProcessingNodes, ValueObjects, Processes, Objects (pmdco-2.0.x) and ProcessNodes (pmdco-v0.1-beta)¶

To get an overview over the usage of the PMD Core Ontology the number of subclasses of ProcessingNode, ValueObject, Process and Object was determined. For that, the projects ontology as well as the applicable pmdco were loaded into Protégé and a Reasoner was run. On the resultant graph, the following query was executed (exemplary for sub-classes of ProcessingNode in SensoTwin):

SELECT ?classname
WHERE {
    ?x rdfs:subClassOf+ <https://w3id.org/pmd/co/ProcessingNode> .
    BIND(STR(?x) AS ?classname) .
    FILTER STRSTARTS( ?classname, "http://w3id.org/sensotwin/applicationontology" ) .
}

The table below shows the respective numbers of found definitions.

In [5]:
pmdusage = {ont: {
    'ProcessingNode (2.0.x)': item['processingnodes']['pmdco-2.0.7']['count'],
    'ValueObject (2.0.x)': item['valueobjects']['pmdco-2.0.7']['count'],
    'Process (2.0.x)': item['processes']['pmdco-2.0.7']['count'],
    'Object (2.0.x)': item['objects']['pmdco-2.0.7']['count'],
    'Total (2.0.x)': item['processingnodes']['pmdco-2.0.7']['count']+item['valueobjects']['pmdco-2.0.7']['count']+item['processes']['pmdco-2.0.7']['count']+item['objects']['pmdco-2.0.7']['count'],
    'ProcessNode (v0.1-beta)': item['processingnodes']['pmdco-v0.1-beta']['count'],
    'Total (v0.1-beta)': item['processingnodes']['pmdco-v0.1-beta']['count'],
    'Total (both)': item['processingnodes']['pmdco-2.0.7']['count']+item['valueobjects']['pmdco-2.0.7']['count']+item['processes']['pmdco-2.0.7']['count']+item['objects']['pmdco-2.0.7']['count']+item['processingnodes']['pmdco-v0.1-beta']['count'],
    'Reasoner': f"{item['reasoner']['reasoner']}-{item['reasoner']['version']}"
} for ont, item in data.items()}
pd.DataFrame(pmdusage).T
Out[5]:
ProcessingNode (2.0.x) ValueObject (2.0.x) Process (2.0.x) Object (2.0.x) Total (2.0.x) ProcessNode (v0.1-beta) Total (v0.1-beta) Total (both) Reasoner
DigiBatMat 0 0 4 0 4 0 0 4 pellet-2.2.0
DIGITRUBBER 0 0 0 0 0 0 0 0 elk-0.5.0
DiProMag 21 55 15 4 95 0 0 95 elk-0.5.0
GlasDigital 0 0 0 0 0 3 3 3 pellet-2.2.0
KNOW-NOW 6 51 17 7 81 0 0 81 pellet-2.2.0
KupferDigital 28 196 55 0 279 0 0 279 pellet-2.2.0
LeBeDigital 9 42 13 47 111 0 0 111 pellet-2.2.0
ODE_AM 0 0 0 0 0 0 0 0 pellet-2.2.0
PMDao_MO 37 38 56 11 142 0 0 142 pellet-2.2.0
PMDao_TTO 2 44 1 0 47 0 0 47 pellet-2.2.0
SensoTwin 141 82 52 16 291 0 0 291 pellet-2.2.0
SmaDi 0 0 0 0 0 0 0 0 pellet-2.2.0
StahlDigital 0 0 0 0 0 0 0 0 pellet-2.2.0

Used Licenses¶

The following table summarizes the referenced licenses. The SPARQL used for finding this information reads:

SELECT ?lic
WHERE {
    ?x <http://purl.org/dc/terms/license>|<http://purl.org/dc/elements/1.1/license> ?lic .
}
In [6]:
def license_cleanup(license):
    replacements = [
        ('https://creativecommons.org/licenses/by/4.0', 'CC BY 4.0'),
        ('http://creativecommons.org/licenses/by/4.0', 'CC BY 4.0'),
        ('https://creativecommons.org/licenses/by-sa/4.0/', 'CC BY-SA 4.0'),
        ('https://creativecommons.org/licenses/unspecified', '')
    ]
    license = license.replace('<', '').replace('>', '')
    for old, new in replacements:
        if license.startswith(old):
            return new
    return license

licenses = {ont: {'used_licenses': ', '.join(map(license_cleanup, set(item['license']['items'])))} for ont, item in data.items()}
pd.DataFrame(licenses).T
Out[6]:
used_licenses
DigiBatMat CC BY-SA 4.0
DIGITRUBBER
DiProMag CC BY 4.0
GlasDigital CC BY 4.0
KNOW-NOW
KupferDigital
LeBeDigital CC BY 4.0
ODE_AM CC-BY-4.0
PMDao_MO CC BY 4.0
PMDao_TTO CC BY 4.0
SensoTwin CC BY 4.0
SmaDi CC BY 4.0
StahlDigital

Contributors¶

In [7]:
import re
import rdflib
from IPython.display import display, HTML

def pp(df):
    return display(HTML(df.to_html().replace('\\n', '<br>')))

def orcid_resolve(string):
    m = re.match(r"<?(https://orcid.org/(\d{4}-\d{4}-\d{4}-\d{3}[\dX]))>?", string)
    if m:
        orcid = m.group(1)
        stype = 'uri' if f'<{orcid}>' == string else 'literal'

        g = rdflib.Graph()
        g.parse(orcid)
        names = []
        [names.append(str(row.gname)) for row in g.query(
            f"""
                SELECT ?gname WHERE {{
                    <{orcid}> <http://xmlns.com/foaf/0.1/givenName> ?gname .
                }}
            """
        )]
        [names.append(str(row.fname)) for row in g.query(
            f"""
                SELECT ?fname WHERE {{
                    <{orcid}> <http://xmlns.com/foaf/0.1/familyName> ?fname .
                }}
            """
        )]
        name = ' '.join(names)
        return f'{orcid} ({stype}) -> {name}'
    return string

contributors = {ont: {'creators_contributors': '\n'.join(map(orcid_resolve, set(item['creators_contributors']['items'])))} for ont, item in data.items()}
df = pd.DataFrame(contributors).T
pp(df)
creators_contributors
DigiBatMat Volker Presser
Volker Knoblauch
Jonas Oehm
Arno Kwade
Klaus Dröder
Lisa Beran
Andriy Taranovskyy
https://orcid.org/0000-0002-5918-6407 (literal) -> Marcel Mutz
Laura Gottschalk
Tobias Kraus
Tobias Käfer
Veit Königer
Amir Haghipour
https://orcid.org/0009-0009-2713-802X (literal) -> Vincent Nebel
Yunjie Li
Philip Gümbel
Dirk Werth
Milena Perovic
DIGITRUBBER Sven Schwabe (IFNANO)
https://orcid.org/0000-0002-8688-6599 (literal) -> James Balhoff
Alexander Aschemann
Luis Ramos
ITA
https://orcid.org/0000-0002-6601-2165 (literal) -> Christopher Mungall
DiProMag Moritz Blum
Luana Caron
Sonja Schöning
Lennart Schwan
Inga Ennen
Michael Feige
Günter Reiss
Philipp Cimiano
Christian Schröder
Andreas Hütten
Alisa Chirkova
Simon Bekemeier
Basil Ell
Tapas Samanta
Martin Wortmann
Thomas Hilbig
GlasDigital Simon Stier (https://orcid.org/0000-0003-0410-3616)
Ya-Fan Chen (https://orcid.org/0000-0003-4295-7815)
KNOW-NOW Ben Hassine, Sahar
Guejiep Dowouo, Simplice
Baca Duque, Lui Felipe
KupferDigital Hossein Beygi Nasrabadi (www.orcid.org/0000-0002-3092-0532)
LeBeDigital https://orcid.org/0000-0003-0626-5002 (literal) -> Stephan Pirskawetz
https://orcid.org/0000-0003-2445-6734 (literal) -> Birgit Meng
https://orcid.org/0009-0006-4524-9143 (literal) -> Melissa Telong
https://orcid.org/0009-0004-9700-2439 (literal) -> Aida Zoriyatkha
Mattheo Krüger, Melissa Telong Donfack, Aida Zoriyatkha, Birgit Meng, Stephan Pirskawetz
https://orcid.org/0009-0003-7121-0283 (literal) -> Mattheo Krüger
ODE_AM Mohamed Kamal, Jan Reimann
Mohamed Kamal, Heiko Beinersdorf
Thomas Bjarsch
PMDao_MO https://orcid.org/0000-0002-3717-7104 (literal) -> Bernd Bayerlein
https://orcid.org/0000-0002-7094-5371 (literal) -> Markus Schilling
PMDao_TTO https://orcid.org/0000-0001-7192-7143 (literal) -> Jörg Waitelonis
https://orcid.org/0000-0002-3717-7104 (literal) -> Bernd Bayerlein
https://orcid.org/0000-0003-4971-3645 (literal) -> Philipp von Hartrott
https://orcid.org/0000-0002-7094-5371 (literal) -> Markus Schilling
https://orcid.org/0000-0002-9014-2920 (literal) -> Henk Birkholz
SensoTwin https://orcid.org/0009-0004-1208-3971 (literal) -> Ursula Pähler
SmaDi https://orcid.org/0000-0003-1017-8921 (uri) -> Mena Leemhuis
StahlDigital Clemens Fehrenbach, Alexander Butz, Alexander Wessel, Andreas Trondl, Silke Klitschke, Paul Zierep, Lukas Morand, Dirk Helm

Namespaces¶

To analyze which namespaces were used in the projects T-Boxes, the ontology files were parsed for all occurences of semantically valid uris ('<(https?:\/\/([0-9A-z-_~\.]+[\/|#])+)'). The list of uris was stored (requests_raw.xlsx) and manually curated with applicable namespace identifiers (requests.xlsx). This approach was necessary, as in some of the ontology files wrong or ambiguous identifiers were used (e.g. http://material-digital.de/pmdco/ instead of https://material-digital.de/pmdco/). For all uris it was tested, if they are dereferecenceable. If so, it was checked if they allow for content negotiation and deliver some owl serialization.

In [8]:
import requests
from ipywidgets import IntProgress
from IPython.display import display

mime_types = ['text/turtle','application/rdf+xml','application/ld+json','application/n-triples']
res = {
    'accept': {},
    'noaccept': {},
    'error': {}
}

all_namespaces = list(set(x for ds in data.values() for x in ds['namespaces']['items']))

f = IntProgress(min=0, max=len(all_namespaces))
display(f)

for x in all_namespaces:
    f.value += 1
    try:
        req = requests.head(x, headers={'Accept': ','.join(mime_types)}, allow_redirects=True)
        if req.headers['content-type'] in mime_types: 
            res['accept'].update({x: {'status_code': req.status_code, 'content_type': req.headers['content-type']}})
        else:
            res['noaccept'].update({x: {'status_code': req.status_code, 'content_type': req.headers['content-type']}})
    except Exception as e:
        res['error'].update({x: {'error': e}})
responses = pd.concat((
    pd.DataFrame(res['accept']).T, 
    pd.DataFrame(res['noaccept']).T, 
    #pd.DataFrame(res['error']).T
))

import json
with open('requests.json', 'r', encoding='utf8') as jf:
    requests_data = json.load(jf)

for a, x in responses.iterrows():
    if a not in requests_data:
        requests_data.update({a: {
            'status_code': x['status_code'],
            'content_type': x['content_type'],
            'countas_tlo': None,
            'countas_ao': None}})
        print(f'added {a} to requests_data (with empty information)')
    if a in requests_data:
        if not x['status_code'] == requests_data[a]['status_code']:
            requests_data[a].update({'status_code': x['status_code']})
            print(f'updated status code for {a}')
        if not x['content_type'] == requests_data[a]['content_type']:
            requests_data[a].update({'content_type': x['content_type']})
            print(f'updated content type for {a}')

with open('requests.json', 'w', encoding='utf8') as jf:
    json.dump(requests_data, jf, indent=4)

Namespace identifiers¶

The following uri(-stubs) were collected into the respective namespace identifiers.

In [9]:
with open('requests.json', 'r', encoding='utf8') as jf:
    requests_data = json.load(jf)

tlodict = dict()
for tkey, tval in requests_data.items():
    if not tval['countas_tlo']:
        continue
    if tval['countas_tlo'] not in tlodict:
        tlodict[tval['countas_tlo']] = {'uris': [tkey]}
    else:
        tlodict[tval['countas_tlo']]['uris'].append(tkey)
tlodict = {k: {'uris': ', '.join(v['uris'])} for k, v in tlodict.items()}
pd.set_option('display.max_colwidth', None)
pd.DataFrame(tlodict).T
Out[9]:
uris
edamontology http://edamontology.org/
tekom_iirds http://iirds.tekom.de/iirds#
pmdco01 https://material-digital.de/pmdco/, http://material-digital.de/pmdco/
nmrCV http://nmrML.org/nmrCV#
allotrope http://purl.allotrope.org/, http://purl.allotrope.org/ontologies/
dataone http://purl.dataone.org/odo/
bfo http://purl.obolibrary.org/obo/bfo.owl#, http://purl.obolibrary.org/obo/bfo/axiom/
ro http://purl.obolibrary.org/obo/ro/docs/direct-and-indirect-relations/, http://purl.obolibrary.org/obo/ro/docs/, http://purl.obolibrary.org/obo/ro.owl#, http://purl.obolibrary.org/obo/ro/docs/reflexivity/, http://purl.obolibrary.org/obo/ro/subsets#, http://purl.obolibrary.org/obo/ro/docs/temporal-semantics/
chebi http://purl.obolibrary.org/obo/chebi#, http://purl.obolibrary.org/obo/chebi/
dcelements http://purl.org/dc/elements/1.1/
pav http://purl.org/pav/
dcterms http://purl.org/dc/terms/
qudt http://qudt.org/schema/qudt/, https://qudt.org/2.1/schema/qudt/, http://qudt.org/vocab/, http://qudt.org/schema/, http://qudt.org/vocab/quantitykind/, http://qudt.org/vocab/unit/
cco https://raw.githubusercontent.com/CommonCoreOntology/CommonCoreOntologies/v2021-03-01/, http://www.ontologyrepository.com/CommonCoreOntologies/
swrl http://swrl.stanford.edu/ontologies/3.3/swrla.owl#, http://www.w3.org/2003/11/swrl#
prov https://w3.org/ns/prov#
csvw https://w3.org/ns/csvw#
pmdco20 https://w3id.org/pmd/co/, https://w3id.org/pmd/co/2.0.7/
okn https://w3id.org/okn/o/
nfdi4ing http://w3id.org/nfdi4ing/metadata4ing#
geneontology http://wiki.geneontology.org/index.php/, http://www.geneontology.org/formats/oboInOwl#
wikibase http://wikiba.se/ontology/, http://wikiba.se/ontology#
aidimme http://www.aidimme.es/
efo http://www.ebi.ac.uk/efo/
ontology-of-units-of-measure http://www.ontology-of-units-of-measure.org/resource/om-2/, http://www.ontology-of-units-of-measure.org/resource/
geosparql http://www.opengis.net/ont/geosparql#
shacl http://www.w3.org/ns/shacl#
proc http://www.w3.org/ns/prov#
sosa http://www.w3.org/ns/sosa/
ssn http://www.w3.org/ns/ssn/systems/
rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#
dcat http://www.w3.org/ns/dcat#
owl http://www.w3.org/2002/07/owl#
rdfs http://www.w3.org/2000/01/rdf-schema#
skos http://www.w3.org/2004/02/skos/core#
xml http://www.w3.org/2001/XMLSchema#
foaf http://xmlns.com/foaf/0.1/
PMDao_TTO https://w3id.org/pmd/tto/
oa http://www.w3.org/ns/oa#
PMDao_MO https://w3id.org/pmd/mo/
emmo http://emmo.info/emmo/top/annotations#, http://emmo.info/emmo/middle/math#, http://emmo.info/emmo/middle/models#, http://emmo.info/emmo/middle/metrology#, http://emmo.info/emmo#
emterms https://www.jeol.co.jp/en/words/emterms/
emglossary https://codebase.helmholtz.cloud/em_glossary/em_glossary/-/blob/main/terms/
In [10]:
aodict = dict()
for tkey, tval in requests_data.items():
    if not tval['countas_ao']:
        continue
    if tval['countas_ao'] not in aodict:
        aodict[tval['countas_ao']] = {'uris': [tkey]}
    else:
        aodict[tval['countas_ao']]['uris'].append(tkey)
aodict = {k: {'uris': ', '.join(v['uris'])} for k, v in aodict.items()}
pd.set_option('display.max_colwidth', None)
pd.DataFrame(aodict).T
Out[10]:
uris
KupferDigital https://gitlab.com/kupferdigital/process-graphs/lcf-test/, https://gitlab.com/kupferdigital/process-graphs/tensile-test/, https://gitlab.com/kupferdigital/ontologies/mechanical-testing-ontology/, https://gitlab.com/kupferdigital/process-graphs/relaxation-test/
GlasDigital https://glasdigi.cms.uni-jena.de/, https://glasdigi.cms.uni-jena.de/glass/, https://w3id.org/pmd/glass-ontology/
DIGITRUBBER http://purl.obolibrary.org/obo/digitrubber/releases/2023-06-01/, http://purl.obolibrary.org/obo/digitrubber/, https://www.tib.eu/digitrubber#
LeBeDigital https://w3id.org/cpto/GGBS/, https://w3id.org/cpto/
SensoTwin http://w3id.org/sensotwin/applicationontology#, http://w3id.org/sensotwin/, http://w3id.org/sensotwin/applicationontology/
ODE_AM https://w3id.org/ODE_AM/, https://w3id.org/ODE_AM/AMAO#, https://w3id.org/ODE_AM/AMAO/, https://w3id.org/ODE_AM/CEMAO/, https://w3id.org/ODE_AM/MAO/, https://w3id.org/ODE_AM/PBFAO/, https://w3id.org/ODE_AM/WAAMAO/
DiProMag https://www.dipromag.de/dipromag_onto/0.1/, https://www.dipromag.de/ottr-templates/
PMDao_TTO https://w3id.org/pmd/tto/
PMDao_MO https://w3id.org/pmd/mo/
KNOW-NOW http://www.semanticweb.org/ontologies/KnowNow#
DigiBatMat https://purl.org/bpco/, https://purl.org/bpco#
StahlDigital https://w3id.org/steel/, https://w3id.org/steel/ProcessOntology/

TLO usage¶

The used TLOs are listed in the table below. Also trivial cases like owl and rdfs were included. The column Sum denoted the number of evaluated A-Boxes, that used concepts belonging to the respective namespace.

In [11]:
pd.reset_option('display.max_colwidth')
tlodict = dict()
for tkey, tval in requests_data.items():
    if not tval['countas_tlo']:
        continue
    if tval['countas_tlo'] not in tlodict:
        tlodict[tval['countas_tlo']] = {'uris': [tkey]}
    else:
        tlodict[tval['countas_tlo']]['uris'].append(tkey)

dftlo = pd.DataFrame({proj: {key: max([int(x in data[proj]['namespaces']['items']) for x in tlodict[key]['uris']]) for key in tlodict.keys()} for proj in data.keys()})
dftlo.insert(loc=len(dftlo.columns), column='Sum', value=dftlo.sum(axis=1))
dftlo['name'] = dftlo.index
dftlo.sort_values(by=['Sum', 'name'], ascending=[False, True], inplace=True)
dftlo
Out[11]:
DigiBatMat DIGITRUBBER DiProMag GlasDigital KNOW-NOW KupferDigital LeBeDigital ODE_AM PMDao_MO PMDao_TTO SensoTwin SmaDi StahlDigital Sum name
owl 1 1 1 1 1 1 1 1 1 1 1 1 1 13 owl
rdfs 1 1 1 1 1 1 1 1 1 1 1 1 1 13 rdfs
dcterms 1 1 1 1 1 1 1 0 1 1 1 1 1 12 dcterms
rdf 1 1 1 1 1 0 0 1 0 1 1 1 1 10 rdf
xml 1 1 1 1 1 1 0 1 0 1 1 0 1 10 xml
dcelements 1 1 0 0 1 0 0 1 1 1 1 0 1 8 dcelements
pmdco20 1 0 1 0 1 1 1 0 1 1 1 0 0 8 pmdco20
skos 0 1 0 1 1 1 0 1 1 1 0 0 1 8 skos
proc 0 0 0 0 1 1 1 0 0 1 1 0 0 5 proc
qudt 1 0 1 0 1 1 0 0 0 0 0 0 1 5 qudt
bfo 0 1 0 0 0 0 0 1 0 0 0 0 0 2 bfo
emmo 0 0 0 0 1 0 0 0 0 0 0 0 1 2 emmo
pmdco01 0 0 0 1 0 0 0 0 0 0 0 0 1 2 pmdco01
swrl 0 1 0 0 0 0 0 1 0 0 0 0 0 2 swrl
PMDao_MO 0 0 0 0 0 0 0 0 1 0 0 0 0 1 PMDao_MO
PMDao_TTO 0 0 0 0 0 0 0 0 0 1 0 0 0 1 PMDao_TTO
aidimme 0 1 0 0 0 0 0 0 0 0 0 0 0 1 aidimme
allotrope 0 1 0 0 0 0 0 0 0 0 0 0 0 1 allotrope
cco 0 0 0 0 0 0 0 1 0 0 0 0 0 1 cco
chebi 0 1 0 0 0 0 0 0 0 0 0 0 0 1 chebi
csvw 0 0 0 0 0 1 0 0 0 0 0 0 0 1 csvw
dataone 0 1 0 0 0 0 0 0 0 0 0 0 0 1 dataone
dcat 0 0 1 0 0 0 0 0 0 0 0 0 0 1 dcat
edamontology 0 1 0 0 0 0 0 0 0 0 0 0 0 1 edamontology
efo 0 1 0 0 0 0 0 0 0 0 0 0 0 1 efo
emglossary 0 0 0 0 0 0 0 0 1 0 0 0 0 1 emglossary
emterms 0 0 0 0 0 0 0 0 1 0 0 0 0 1 emterms
foaf 0 1 0 0 0 0 0 0 0 0 0 0 0 1 foaf
geneontology 0 1 0 0 0 0 0 0 0 0 0 0 0 1 geneontology
geosparql 0 1 0 0 0 0 0 0 0 0 0 0 0 1 geosparql
nfdi4ing 0 1 0 0 0 0 0 0 0 0 0 0 0 1 nfdi4ing
nmrCV 0 1 0 0 0 0 0 0 0 0 0 0 0 1 nmrCV
oa 0 0 0 0 1 0 0 0 0 0 0 0 0 1 oa
okn 0 1 0 0 0 0 0 0 0 0 0 0 0 1 okn
ontology-of-units-of-measure 0 1 0 0 0 0 0 0 0 0 0 0 0 1 ontology-of-units-of-measure
pav 0 1 0 0 0 0 0 0 0 0 0 0 0 1 pav
prov 0 0 0 0 0 1 0 0 0 0 0 0 0 1 prov
ro 0 1 0 0 0 0 0 0 0 0 0 0 0 1 ro
shacl 0 1 0 0 0 0 0 0 0 0 0 0 0 1 shacl
sosa 0 1 0 0 0 0 0 0 0 0 0 0 0 1 sosa
ssn 0 1 0 0 0 0 0 0 0 0 0 0 0 1 ssn
tekom_iirds 0 1 0 0 0 0 0 0 0 0 0 0 0 1 tekom_iirds
wikibase 0 0 0 1 0 0 0 0 0 0 0 0 0 1 wikibase

Inter-AO usage¶

The table below denotes the usage of concepts from other projects namespaces. It can easily be seen, that there is no concept usage between the projects visible in the current state.

In [12]:
aodict = dict()
for tkey, tval in requests_data.items():
    if not tval['countas_ao']:
        continue
    if tval['countas_tlo'] not in aodict:
        aodict[tval['countas_ao']] = {'uris': [tkey]}
    else:
        aodict[tval['countas_ao']]['uris'].append(tkey)

dfao = pd.DataFrame({proj: {key: max([int(x in data[proj]['namespaces']['items']) for x in aodict[key]['uris']]) for key in aodict.keys()} for proj in data.keys()})
dfao.insert(loc=len(dfao.columns), column='Sum', value=dfao.sum(axis=1))
dfao['name'] = dfao.index
dfao.sort_values(by=['Sum', 'name'], ascending=[False, True], inplace=True)
dfao[list(dfao.index) + ['Sum']]
Out[12]:
DIGITRUBBER DiProMag DigiBatMat GlasDigital KNOW-NOW KupferDigital LeBeDigital ODE_AM PMDao_MO PMDao_TTO SensoTwin StahlDigital Sum
DIGITRUBBER 1 0 0 0 0 0 0 0 0 0 0 0 1
DiProMag 0 1 0 0 0 0 0 0 0 0 0 0 1
DigiBatMat 0 0 1 0 0 0 0 0 0 0 0 0 1
GlasDigital 0 0 0 1 0 0 0 0 0 0 0 0 1
KNOW-NOW 0 0 0 0 1 0 0 0 0 0 0 0 1
KupferDigital 0 0 0 0 0 1 0 0 0 0 0 0 1
LeBeDigital 0 0 0 0 0 0 1 0 0 0 0 0 1
ODE_AM 0 0 0 0 0 0 0 1 0 0 0 0 1
PMDao_MO 0 0 0 0 0 0 0 0 1 0 0 0 1
PMDao_TTO 0 0 0 0 0 0 0 0 0 1 0 0 1
SensoTwin 0 0 0 0 0 0 0 0 0 0 1 0 1
StahlDigital 0 0 0 0 0 0 0 0 0 0 0 1 1
In [ ]: