Posted:October 13, 2020

A Design for a Working Ecosystem of Existing Applications

In our last installment of the Cooking with Python and KBpedia series, I discussed the rationale for using distributed Web widgets as one means to bring the use and management of a knowledge graph into closer alignment with existing content tasks. The idea is to embed small Web controls as either plug-ins, enhancements to existing application Web interfaces, or as simply accompanying Web pages. Under this design, ease-of-use and immediacy are paramount in order to facilitate the capture of new knowledge if and where it arises.

More complicated knowledge graph tasks like initial builds, bulk changes, logic testing and the like are therefore kept as separate tasks. For our immediate knowledge purposes, knowledge workers should be able to issue suggestions for new concepts or modifications or deletions when they are discovered. These suggested modifications may be made to a working version of the knowledge graph that operates in parallel to a public (or staff-wide) release version.

The basic concept behind this and the previous installment is that we would like to have the ability to use simple widgets — embedded on any Web page for the applications we use — as a means of capturing and communicating immediate new information of relevance to our knowledge graphs. In a distributed manner, while working with production versions, we may want to communicate these updates to an interim version in the queue for review and promotion via a governance pipeline that might lead to a new production version.

On some periodic basis, this modified working version could be inspected and tested by assigned managers with the responsibility to vet new, public versions. There is much governance and policy that may guide these workflows, which may also be captured by their own ontologies, that is a topic separate from the widget infrastructure to make this vision operational.

While there are widgets available for analysis and visualization purposes, which we will touch upon in later installments, the ones we will emphasize in today’s CWPK installment are focused on CRUD (create – read – update – delete) activities. CRUD is the means by which we manage our knowledge graphs in the immediate sense. We will be looking to develop these widgets in a manner directly useful to distributed applications.

Getting Started

Remember from our last installment that we are basing our approach to code examples on the Jupyter Notebook ipywidgets package. That package does not come pre-installed, so we need to install it in our system using conda:

  conda install -c conda-forge ipywidgets

Once done, we fire up our Notebook and begin with our standard start-up, only now including a new autoFill module, which I explain next. This module is an example of an ipywidgets extension. Place this new autoFill.py page as a new module page within your Spyder cowpoke project. Make sure and copy that file into the project before beginning the startup:

from cowpoke.__main__ import *
from cowpoke.config import *
from cowpoke.autoFill import *
from owlready2 import *

Some Basic Controls (Widgets)

As noted, our basic controls for this installment revolve around CRUD, though we will not address them in that order. But before we can start manipulating individual objects, we need ways to discover what is already in the KBpedia (or your own) knowledge graph. Search and auto-completion are two essential tools for this job, particularly given the fact that KBpedia has more than 58,000 concepts and 5,000 different properties.

Basic Search

Recall in CWPK #23 that we covered owlready2’s basic search function and parameters. You may use the interactive commands shown in that documentation to search by type, subclasses, IRI, etc.

Auto-complete Helper

We list the auto-completion helper next because it is leveraged by virtually every widget. Auto-completion is used in a text entry box where as characters are typed, a dropdown list provides matching items that satisfy the search string as entered so far. It is a useful tool to discover what exists in a system as well as to provide the exact spelling and capitalization, which may be necessary for the match. As suggested items appear in the dropdown, if the right one appears you click it to make your current selection.

The added utility we found for this is the ipywidget-autocomplete module, which we have added as our own module to cowpoke. The module provides the underlying ‘autofill’ code that we import in the actual routine that we use within the Notebook. Here is an example of that Notebook code, with some explanations that follow below:

import cowpoke.autoFill as af
from ipywidgets import *                                  # Note 1

def open(value):
    show.value=value.new

strlist = []                                              # Note 2
listing = list(kb.classes())                              # Note 3
for item in listing:                                      # Note 4
    item = str(item)
    item = item.replace('rc.', '')
    strlist.append(item)

autofill = af.autoFill(strlist,callback=open)

show = HTML("Begin typing substring characters to see 'auto-complete'!")

display(HBox([autofill,show]))

Besides the ‘autofill’ component, we also are importing some of the basic ipywidgets code (1). In this instance, we want to auto-complete on the 58 K concepts in KBpedia (3), which we have to convert from a listing of classes to a listing of strings (1) and (4). We can just as easily do an auto-complete on properties by changing one line (3):

  listing = list(kb.classes())

or, of course, other specifications may be entered for the boundaries of our auto-complete.

To convert the owlready2 listing of classes to strings occurs by looping over all items in the list, converting each item to a string, replacing the ‘rc.’ prefix, and then appending the new string item to a new strlist (4). The ‘callback’ option relates the characters typed into the text box with this string listing. This particular expression will find string matches at any position (not just the beginning) and is case insensitive.

When the item appears in the dropdown list that matches your interest, pick it. This value can then be retrieved with the following statement:

show.value
'Mammal'

Read Item

Let’s use a basic record format to show how individual property values may be obtained for a given reference concept (RC), as we just picked with the auto-complete helper. We could obviously expand this example to include any of the possible RC property values, but we will use the most prominent ones here:

r_val = show.value 
r_val = getattr(rc, r_val)                               # Note 1                                   
a_val = str(r_val.prefLabel)                             # Note 2
b_val = r_val.altLabel
b_items = ''
for index, item in enumerate(b_val):                     # Note 3 
    item = str(item)
    if index == [0]:        
        b_items = item
    else: 
        b_items = b_items + '||' + item
b_val = b_items
c_val = str(r_val.definition)
d_val = r_val.subclasses()
d_items = ''
for index, item in enumerate(d_val):                     # Note 3
    item = str(item)
    if index == [0]:        
        d_items = item
    else: 
        d_items = d_items + '||' + item
d_val = d_items
e_val = str(r_val.wikidata_q_id)
f_val = str(r_val.wikipedia_id)
g_val = str(r_val.schema_org_id)
                                                         # Note 4 
a = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='Preferred Label:', value = a_val)
b = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='AltLabel(s):', value = b_val)
c = widgets.Textarea(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='Definition:', value = c_val)
d = widgets.Textarea(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='subClasses:', value = d_val)
e = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='Q ID:', value = e_val)
f = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='Wikipedia ID:', value = f_val)
g = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), 
                 description='schema.org ID:', value = g_val)

def f_out(a, b, c, d, e, f, g):
    print(''.format(a, b, c, d, e, f, g))

out = widgets.interactive_output(f_out, {'a': a, 'b': b, 'c': c, 'd': d, 'e': e, 'f': f, 'g': g})

widgets.HBox([widgets.VBox([a, b, c, d, e, f, g]), out]) # Note 5 

We begin by grabbing the show.value value (1) that came from our picking an item from the auto-complete list. We then start retrieving individual attribute values (2) for that resource, some of which we need to iterate over (3) because they return multiple items in a list. For display purposes, we need to convert all retrieved property values to strings.

We can style our widgets (4). ‘Layout’ applies to the entire widget, and ‘style’ applies to selected elements. Other values are possible, depending on the widget, which we can inspect with this statement (vary by widget type):

text = Text(description='text box')
print(text.style.keys)

Then, after defining a simple call procedure, we invoke the control on the Notebook page (5).

We could do more to clean up interim output values (such as removing brackets and quotes as we have done elsewhere), and can get fancier with grid layouts and such. In these regards, the Notebook widgets tend to work like and have parameter settings similar to other HTML widgets, though the amount of examples and degree of control is not as extensive as other widget libraries.

Again, though, since so much of this in an actual deployment would need to be tailored for other Web frameworks and environments, we can simply state for now that quite a bit of control is available, depending on language, for bringing your knowledge graph information local to your current applications.

Modify (Update) Item

Though strings in Python are what is known as ‘immutable’ (unchanging), it is possible through the string.replace('old', 'new') option to update or modify strings. For entire strings, ‘old’ may be brought into a text box via a variable name as shown above, altered, and then captured as show.value on a click event. The basic format of this approach can be patterned as follows (changing properties as appropriate):

from ipywidgets import widgets                      # Run the code cell to start

old_text = widgets.Text(style={'description_width': '100px'}, layout=Layout(width='760px'), description = 'Value to modify:', value = 'This is the old input.')
new_text = widgets.Text(description = 'New value:', value = 'This is the NEW value.')

def bind_old_to_new(sender):
    old_text.value = new_text.value
    old_text.description = new_text.description
old_text.on_submit(bind_old_to_new)

old_text                                 # Click on the text box to invoke

It is better to make modifications to an existing property or an existing class using something like Protégé, which is able to better account for internal cross-references. But, changes to attribute values may be pursued through the above approach.

New class names or properties, or modifications to existing class names or properties, should never be allowed to production systems. These CRUD actions, like create, are best slipstreamed into a reserved cache or made against a review copy of the knowledge base that is segregated away from the production system. This separation allows review steps and the enforcement of governance standards before changes are made to an operating version of the knowledge graph.

Create Item

Newly created items include new concepts and their attributes or subsumption relations, which deserve scrutiny before committing to a production version. Other items that perhaps deserve a lower degree of governance before adding include additional altLabels or mapping properties.

In the case of new concepts, the form of addition (see also CWPK #39, Note #6) has a number of forms, but one has worked best for KBpedia.

On the other hand, the general form for adding a new attribute has the form:

  CurResource.append(new_item)

As with modifications, creating items should be limited to working, and not production copies.

Delete Item

The form to delete an item is very simple, and takes the form:

  destroy_entity(xxxName)

Clearly, this is a function that should not be made available to casual users, and needs to be subject to governance policies and review. Again, working copies are the best versions to be the target of any such actions, and the acceptance of deletions should be an active subject of review. Forms to enable this are simple to build.

Not Part of the Package

For the reasons of diversity of use and applications, none of these routines has been formally added to the cowpoke package. We see examples of how such can be implemented, and I have argued for the use of distributed Web widgets under governance and using working copies as the best means for utilizing these functions. But, given this diversity, it does not make sense to add widgets to the cowpoke package at this time.

That being said, we also hope some of this discussion and related code commentary have encouraged you to think of how to apply workflows and life-cycle management to your own knowledge graphs. Embedding widgets into existing distributed applications is one means to bring the benefits and updates of knowledge graphs into immediate relevance.

Additional Documentation

Here is additional documentation of working with the ipywidgest package:

In addition, there are other interactive uses of Notebooks:

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site. The cowpoke Python code listing covering the series is also available from GitHub.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Posted by AI3's author, Mike Bergman Posted on October 13, 2020 at 9:07 am in CWPK, KBpedia, Semantic Web Tools | Comments (0)
The URI link reference to this post is: https://www.mkbergman.com/2398/cwpk-52-distributed-interactions-via-web-widgets-ii/
The URI to trackback this post is: https://www.mkbergman.com/2398/cwpk-52-distributed-interactions-via-web-widgets-ii/trackback/
Posted:October 12, 2020

Bringing Knowledge Graphs into the Content Workflow

The rationale for starting this Cooking with Python and KBpedia series is to better match knowledge graph creation and use with practical requirements and workflows. The notion of ‘roundtripping‘ has one major use when bulk changes are needed, such as making modifications to the domain or scope of the knowledge graph. But roundtripping also supports the idea of a knowledge graph as a computable object, not simply an editable one.

Think for a moment about this: your organization has a vetted knowledge graph at the center of many analytic and knowledge management functions. How does one grow and extend such a resource, while also being able to make bulk changes or have it operate as a constantly available schema? On the one hand, such a vision requires a dynamic, always-on resource that is subject to constant querying and modification. On the other hand, this vision also means staff extending and maintaining the knowledge graph according to organizational standards and governance. The versions of the artifact may differ at various stages when these two hands work together. The capabilities needed to support a roundtripping capability are also some of the same ones needed to support these twin dynamic and standard roles. At some points we work directly with the artifact as a standalone thing, extending it and testing it for consistency and logic. At some points, the current production version of the knowledge graph is being actively exercised for knowledge management, data analysis, data integration, machine learning, or natural language processing tasks.

Now that we have put in place a framework for bulk changes and roundtripping, we next need to turn our attention to how we can access and use that knowledge artifact in a dynamic way. Such serious deployments of knowledge graphs imply many other things in version control, version deployments, and release governance. Those are topics outside of our series on the cowpoke Python package. But dynamic access and use of the knowledge graph is not outside of that scope.

How we may approach this issue in relation to workflows and HTML widgets that we may deploy directly to knowledge workers in a distributed manner is the topic of today’s CWPK installment. Our next installment with then showcase a few code examples of these widgets. Note we will also return to this topic in CWPK #58 onward when we also discuss how to publish results from our knowledge graphs to the Web.

Let’s First Consider Workflows

If your interests at this point are simply in learning a bit more about knowledge graphs (KGs), and perhaps how to design and build them, you may want to set today’s and tomorrow’s installments aside until another day. But, assuming that your interest in knowledge graphs is for eventual productive use within your organization, you will need to grapple at some point with how to integrate KGs into your staff’s current activities and how KGs may contribute to new capabilities.

There are clearly many ways to look at content workflows, but here is our longstanding view of knowledge graphs (ontologies) and content management for what might occur in a ‘typical’ larger organization:

Content Workflow with a Knowledge Graph

Figure 1: Content Workflow with a Knowledge Graph

Starting at the center, we can understand the Manage/Store bubble to represent what we have in owlready2 (or any similarly hosted knowledge graph). That central hub (which might be a different deployment version) can be the target for gathering activities, creating, tagging, analyzing, managing knowledge, publishing or planning. A separate Ontologies bubble may be the source for bulk updates or changes or for reviewing submissions prior to committing to the central, deployed hub. Older hubs or retired versions may be shifted to an archive status.

There could be different stages and names for these basic activities, and one might also use an ontology to actually govern and provide the ‘tags’ for tracking where content stands. (Including such things as sign-offs.) But, this circle, in general, represents a common set of uses to which any organization would likely aspire. These steps can be expanded or collapsed as local circumstances dictate.

What is important to note, however, is that most activities around the circumference of the workflow occur in context with other existing activities. For example, when reviewing Internet search results or creating documents, both tagging of new content or updating the existing knowledge base would be made easier by having small plug-ins or widgets for the existing applications. Machine learning and statistical tests, or natural language applications, may all surface possible inconsistencies in an existing knowledge graph, which is best captured immediately in conjunction with the tests.

What emerges when inspecting opportunity or choke points for using knowledge graphs is that in nearly all cases new knowledge discoveries occur in conjunction with existing work activities, and if not captured immediately and easily, are all too often not recorded. This inability to capture knowledge in real time undercuts the usefulness of knowledge management and causes existing knowledge to go stale.

For these reasons, it makes sense to assemble a suite of widgets that may conduct simple activities against the knowledge graph, and can be embedded in HTML pages for interacting with current applications. Of course, the nature of the widget and what it does is dependent on the specific current activity at-hand. But these simple activities all tend to be one of the CRUD activities (create – read – update – delete) and are quite patterned.

Python Web Frameworks and Related

The reasons for me to choose Python as the basis for this CWPK series was based on data science applications with a broad user base and an abundance of useful packages and libraries. The usefulness of Python to Web page or site development was not an initial consideration.

Our own experience with Web site development, which as been extensive over the years, began with PHP and eventually migrated into the more modern JavaScript approaches like Bootstrap, our current preferred basis. Sometimes we have created intimate relationships with CMS systems, most prominently Drupal, though we have moved away from such monolithic frameworks to the more fluid ones like Bootstrap.

However, I have been quite impressed working with Jupyter Notebook and have also been following certain Web framework Python packages. Prominent ones that have impressed me (though for very different reasons) include Flask, Tornado, Flexx, Pyramid, Bottle and CherryPy. Useful supporting packages and libraries include Requests and WSGI.

My first thought about this part of the CWPK series was to pick one of these frameworks, learn some rudimentary things with it sufficient to support our widget orientation, and then use it consistently for all HTML aspects. Were I to make that decision, Flask would be my choice based on what I have studied. But I am not now choosing to move in that direction, for a number of reasons.

First, it is difficult to demo Web interactions when it it unlikely that some in the audience may not be readily able to set up their own Web sites. Second, a distributed work environment relies on many existing applications. Even if all of these use HTML interfaces in some manner, it is likely that an effective deployment would still require perhaps multiple frameworks and integrations. Third, though I could set up a dedicated demo site, that would still require adopting a full Web framework with socket, authentication, and content negotiation support. In an ultimate deployment, that is a likely step that must be taken, but our job right now is not to prototype a production system. And, fourth, the easiest way to showcase dynamic demos is to piggyback on what we already have installed and are using: Jupyter Notebook.

Fortunately, there is a nice library of widgets useful in Jupyter Notebook, the ipywidget package, and additional third-party extensions. Widgets are objects that have familiar user interfaces that may be embedded in an HTML page. Example widgets include textboxes, radiobuttons, regular buttons, dropdown lists, tabular displays, graph plots or charts, slider controls, or other forms for interacting with a Web page and its data. Dashboards, for example, are often a built-up combination of multiple widgets. Widgets are common to all modern languages used on the Web, though how they are set up and controlled varies widely.

Because we could relatively demo these widget capabilities directly through Notebook without much further complexity, and have that work in other user settings, we decided to go with the ipywidget option. We will install and demo some Flask uses in about ten installments from now. But, for our current interests in tieing our knowledge graphs to existing work activities, we introduce code for some exemplar widgets in our next CWPK installment.

Additional Documentation

Here are some background materials on the Web frameworks in Python that may be of some use to you:

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site. The cowpoke Python code listing covering the series is also available from GitHub.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Posted by AI3's author, Mike Bergman Posted on October 12, 2020 at 11:06 am in CWPK, KBpedia, Semantic Web Tools | Comments (0)
The URI link reference to this post is: https://www.mkbergman.com/2397/cwpk-51-distributed-interactions-via-web-widgets-i/
The URI to trackback this post is: https://www.mkbergman.com/2397/cwpk-51-distributed-interactions-via-web-widgets-i/trackback/
Posted:October 8, 2020

The Nearly Infinite Usefulness of SPARQL

We are now two-thirds of the way through our CWPK series. One reason we have emphasized ‘roundtripping‘ in Cooking with Python and KBpedia is to accommodate the incorporation of information from external sources into KBpedia. From hierarchical relationships to annotations like definitions or labels, external sources can be essential. Of course, one can find flat files or spreadsheets or CSV files directly, but often times we need specific information that can only come from querying the external source directly. Two of the ones we heavily rely on in particular — Wikidata and DBpedia — provide this access through SPARQL queries. We first introduced SPARQL in CWPK #25.

External SPARQL queries are the basis of getting instance data, values for instance attributes, missing fields like altLabels and skos.definition, existing crosswalks or mappings, longer descriptions, subsumption relations, related links, and interesting joins and intersections across external knowledge base content. Often, one is able to specify the format (serialization) of the desired results.

The outputs from these external queries can be manipulated as strings, and then written to flat files useful for ingest into the various build routines. Of course, it is important that the format and CSV-nature of the results be maintained in a form that the build routines expect. One may alter the build formats or the extract formats, but to work they need to match on both ends.

So, what we provide in today’s installment are some guidelines and recipes for using SPARQL to obtain information you need and to write them to flat files. Because of their importance, we emphasize Wikidata and DBpedia (also a stand-in for Wikipedia) in our examples. Once populated, you may need to do some intermediate wrangling of these files to get them into shape for direct import. We covered that topic in brief in CWPK #36, but really do not address file wrangling further here. There are way too many varieties to cover the topic in a meaningful way, though we certainly have examples in today’s installment and across the entire CWPK series that should provide a useful foundation to your own efforts.

Choosing Access Method

There are not that many public SPARQL endpoints available, and some are not always up and available. But the endpoints that do exist, with their identification in the Query Sources section at the conclusion of today’s installment, are often comprehensive and with high value. The two we will be emphasizing today, Wikidata and DBpedia (and, by extension, the linked open data (LOD) cloud beyond that), are among the most valuable. (Of course, many endpoints, like ones specific to a particular organization, are private, and can be parts of valuable, distributed information ecosystems.) Another notable endpoint worthy of your attention is the LOD endpoint maintained by OpenLink Software.

It is possible to query many of these sources directly online with an HTML interface, often also providing a choice of the output format desired. In some of the examples below, I provide a Try it! link that takes you directly to the source site and uses their native SPARQL interface. (Also, inspect the URI links for these Try it! options, since it shows how SPARQL gets communicated over the Web.) You may often find this is the fastest and cleanest way to get useful results, and sometimes better formatted than what our home-brewed options below produce. Your mileage may vary. In any case, it is useful to learn how to conduct direct SPARQL capabilities from within cowpoke. For that reason, I emphasize our home-brewed examples below.

Setting Up This Installment

Like we have been emphasing of late, we begin today’s installment with our standard start-up instructions:

from cowpoke.__main__ import *
from cowpoke.config import *
from owlready2 import *
from SPARQLWrapper import SPARQLWrapper, JSON
from rdflib import Graph

#sparql = SPARQLWrapper('http://dbpedia.org/sparql')
sparql = SPARQLWrapper('https://query.wikidata.org/sparql')
graph = world.as_rdflib_graph()

Of course, we actually have a very capable query method to our own internal stores:

form_1 = list(graph.query_owlready("""
  PREFIX rc: <http://kbpedia.org/kko/rc/>
  PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
  SELECT DISTINCT ?x ?label
  WHERE
  {
    ?x rdfs:subClassOf rc:Eutheria.
    ?x skos:prefLabel  ?label. 
  }
"""))

print(form_1)

Wikidata Queries

For the following Wikidata queries, Run these assignments first:

from SPARQLWrapper import SPARQLWrapper, JSON
from rdflib import Graph

sparql = SPARQLWrapper('https://query.wikidata.org/sparql', agent='cowpoke 0.1 (github.com/Cognonto/cowpoke)')

We need to assign an ‘agent=’ because of limits Wikidata occasionally puts on queries. If you do many requests, you may want to consider adding your own agent defintion.

One of the techniques I use most heavily is the VALUES statement. This construct allows a listing of IDs to be passed to the query source. Depending on various endpoint limits, you may be able to list 1000 or more IDs in such a listing; experience with a given endpoint will dictate. If you use the VALUES construct, just make sure you are using the proper format and prefix (wd: in this instance for a Q item within Wikidata) in front of each value.

Parent Class from Q IDs

The first query is to obtain the parent class from submitted listing of Q items. You may also Try it! directly from Wikidata:

sparql.setQuery("""
PREFIX schema: <http://schema.org/>
SELECT ?item ?itemLabel ?wikilink ?itemDescription ?subClass ?subClassLabel WHERE {
  VALUES ?item { wd:Q25297630
  wd:Q537127
  wd:Q16831714
  wd:Q24398318
  wd:Q11755880
  wd:Q681337
}
 ?item wdt:P910 ?subClass.
 SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

#for result in results["results"]["bindings"]:
#    print(result["item"]["value"])

print(results)

Notice that once we set our SPARQL endpoint and user agent, we are able to cut-and-paste different SPARQL queries between the opening and ending triple quotes (“””). The bracketing statements around that can be used repeatedly for different queries.

Go ahead and toggle between the print statements above to see how we can start varying outputs. Chances are you will need to do some string manipulation before your flat files are ready for ingest, but we can vary these specifications to get the initial output closer to our requirements.

subClass and Instance listings for Q ID

Try it! as well.

sparql.setQuery("""
SELECT ?subclass ?subclassLabel ?instance ?instanceLabel
WHERE
{
 ?subclass wdt:P279 wd:Q183366.
 ?instance wdt:P31 wd:Q183366.
 SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY xsd:integer(SUBSTR(STR(?subclass),STRLEN("http://www.wikidata.org/entity/Q")+1))
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

#for result in results["results"]["bindings"]:
#    print(result["item"]["value"])

print(results)

Useful Q Item Attributes

Try it!

sparql.setQuery("""
PREFIX schema: <http://schema.org/>

SELECT ?item ?itemLabel ?class ?classLabel ?description ?article ?itemAltLabel WHERE {
  VALUES ?item { wd:Q1 wd:Q2 wd:Q3 wd:Q4 wd:Q5 }
  ?item wdt:P31 ?class;
        wdt:P5008 ?project.
#  ?article rdfs:comment ?description.
  
   OPTIONAL {
    ?article schema:about ?item.
    ?article schema:isPartOf <https://en.wikipedia.org/>.
  }
  
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

Get English Wikipedia Article Names from Q ID

Try it!

sparql.setQuery("""
SELECT DISTINCT ?lang ?item ?name WHERE {
 VALUES ?item { wd:Q1
wd:Q2
wd:Q3
wd:Q4
wd:Q5 
}
 ?article schema:about ?item; schema:inLanguage ?lang; schema:name ?name .
 FILTER(?lang in ('en')) .
 FILTER (!CONTAINS(?name, ':')) .
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

Listing of Q IDs from Property

Try it!

sparql.setQuery("""
 SELECT
 ?item ?itemLabel
 ?value ?valueLabel
 # valueLabel is only useful for properties with item-datatype
 WHERE 
 {
 ?item wdt:P2167 ?value
 # change P2167 to desired property        
 SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
 }
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

subClass and Instance Listings for Q ID

Try it!

sparql.setQuery("""
SELECT ?subclass ?subclassLabel ?instance ?instanceLabel
WHERE
{
 ?subclass wdt:P279 wd:Q183366.
 ?instance wdt:P31 wd:Q183366.
 SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY xsd:integer(SUBSTR(STR(?subclass),STRLEN("http://www.wikidata.org/entity/Q")+1))
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

Missing Q Data from Wikidata

Try it!

sparql.setQuery("""
PREFIX schema: <http://schema.org/>
PREFIX w: <https://en.wikipedia.org/wiki/>
SELECT ?wikipedia ?item WHERE {
VALUES ?wikipedia { w:Tom_Hanks }
?wikipedia schema:about ?item .
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

Q ID from Wikipedia ID

Try it!

sparql.setQuery("""
PREFIX schema: <http://schema.org/>
PREFIX w: <https://en.wikipedia.org/wiki/>
SELECT ?wikipedia ?item WHERE {
VALUES ?wikipedia { w:Euthanasia
w:Commercial_art_gallery
}
 ?wikipedia schema:about ?item .
 SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

schema.org ← → Wikidata Mapping

Try it!

sparql.setQuery("""
SELECT ?wd ?wdLabel ?type ?uri ?prefix ?localName WHERE {
 {
   { ?wd wdt:P1628 ?uri . BIND("equivalent property" AS ?type) } UNION
   { ?wd wdt:P1709 ?uri . BIND("equivalent class" AS ?type) } UNION
   { ?wd wdt:P2888 ?uri . BIND("exact match" AS ?type) } UNION
   { ?wd wdt:P2235 ?uri . BIND("superproperty" AS ?type) } UNION
   { ?wd wdt:P2236 ?uri . BIND("subproperty" AS ?type) } 
 }
 BIND( REPLACE(STR(?uri),'[^#/]+$',) AS ?prefix)
 BIND( REPLACE(STR(?uri),'^.*[#/]',) AS ?localName)
 # filter by ontology (otherwise timeout expected)
 FILTER(?prefix = "http://schema.org/")
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ?prefix ?localName
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

Main Topic of Q ID

Try it!

sparql.setQuery("""
PREFIX schema: <http://schema.org/>
 SELECT ?item ?itemLabel ?mainTopic ?mainTopicLabel WHERE {
   VALUES ?item { wd:Q13307732
 wd:Q8953981
 wd:Q1458376
 wd:Q8953071
 }
  ?mainTopic wdt:P910 ?item.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
 }
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()

print(results)

DBpedia Queries

DBpedia is a bit more tricky to deal with.

Again, we set up our major call, to be followed by a series of SPARQL queries to DBpedia:

from SPARQLWrapper import SPARQLWrapper, RDFXML
from rdflib import Graph

sparql = SPARQLWrapper("http://dbpedia.org/sparql")

Languages in DBpedia with schema.org Language Code

In this query, we are looking for items that have been already mapped or characterized in a second ontology (schema.org).

Try it!

sparql.setQuery("""
    PREFIX dbo: <http://dbpedia.org/ontology/>
    PREFIX schema: <http://schema.org/>

    CONSTRUCT {
      ?lang a schema:Language ;
      schema:alternateName ?iso6391Code .
    }
    WHERE {
      ?lang a dbo:Language ;
      dbo:iso6391Code ?iso6391Code .
      FILTER (STRLEN(?iso6391Code)=2) # to filter out non-valid values
    }
""")

sparql.setReturnFormat(RDFXML)
results = sparql.query().convert()
print(results.serialize(format='xml'))

Missing Definitions

Try it!

sparql.setQuery("""
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://dbpedia.org/resource/>
SELECT ?item, ?description WHERE {
  VALUES ?item { :Child_prostitution
  :Ice_Hockey_World_Championships
  :Major_League_Soccer
  :Tamil_language
  :Acne }
  ?item rdfs:comment ?description .

  FILTER ( LANG(?description) = "en" ) 
} 
""")

sparql.setReturnFormat(RDFXML)
results = sparql.query().convert()
print(results.serialize(format='xml'))

Get URIs from Aliases

Try it!

sparql.setQuery("""
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?x ?redirectsTo WHERE {
 VALUES ?wikipedia { "Abies"@en 
 "Abolitionists"@en}
 ?x rdfs:label ?wikipedia .
 ?x dbo:wikiPageRedirects ?redirectsTo
}
""")

sparql.setReturnFormat(XML)
results = sparql.query().convert()
print(results.serialize(format='xml'))

Of course, SPARQL is a language unto itself, and it takes time to become fluent. The examples above are closer to baby-talk than Shakespearean speech. Nonetheless, one begins to gain a feel for the power of the language.

As we move forward, we will try to leverage SPARQL as the query language to our knowledge graph, since it provides the most powerful and flexible language for doing so. There will obviously be times when direct Python calls are more direct and shorter to implement. But the most flexible filters and intersections will come from our use of SPARQL.

Query Resources

A partial, but useful, list of public SPARQL endpoints is provided by:

An assessment of their current availability is provided by:

Here are the top 100 named graphs available with their triple counts:

Wikidata provides its own listing of 100 SPARQL endpoints:

There is an excellent (and growing) compilation of useful SPARQL queries to Wikidata available from:

Two smaller, but similarly useful resource for DBpedia queries, are available from:

The latter also provides some SPARQL construction tips.

Example OpenStreetMap SPARQL examples are available from:

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site. The cowpoke Python code listing covering the series is also available from GitHub.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Posted by AI3's author, Mike Bergman Posted on October 8, 2020 at 10:00 am in CWPK, KBpedia, Semantic Web Tools | Comments (0)
The URI link reference to this post is: https://www.mkbergman.com/2396/cwpk-50-querying-external-sources/
The URI to trackback this post is: https://www.mkbergman.com/2396/cwpk-50-querying-external-sources/trackback/
Posted:October 7, 2020

Sometimes KR is Kind of Tricky

I think I pretty much lied to you about ‘roundtripping‘ and the importance of the last major section that we just completed in this Cooking with Python and KBpedia series. We had indeed accomplished the extraction-and-build cycle for classes, properties, and their annotations. These are the same roundtrip objectives we had been pursuing and doing with our Clojure procedures for years. But we were incomplete.

There is another purpose to KBpedia as a ‘scaffolding’ to external sources that is not captured in this initial ’roundtripping’ sense. If you download KBpedia, right now as version 2.50, and load it up into an editor like Protégé, you will see the KBpedia structure and its properties and annotations, but you will not see the links to the external resources that KBpedia integrates. These mappings (correspondences) are provided in separate mapping files, and have been since KBpedia was first released. This has struck me for some time as an unneeded indirection. I think the better approach is to embed these links directly into KBpedia (or whatever your master knowledge graph may be).

OK, so if we do that, does that not become part of the baseline that needs to be roundtripped? And, if to be used, what is the best practice for representing these external relationships?

Like much that has an open world approach, these kinds of questions and open-ended project requirements can stretch into the unachievable future. I don’t want to keep moving the goalposts. But I do think the role of top-level knowledge graphs is integration and coverage. The addition of key mappings to our basic expectation for our central knowledge graph seems appropriate and reasonable. Thus, for a ‘truer’ conceptualization of ’roundtripping’, I now include mappings with our basic remit.

This correction (which, of course, is an addition), and some other utilities and tools explorations, are the focus of this next major Part V in our CWPK series. Think of this next major part as wrapping our basic knowledge graph into the tools of the trade.

Representing External Resources

The standard way to handle links with an external source in most ontologies is to ‘import’ the external source. In OWL terms, this means to actually import an ontology and to incorporate the import’s full aspects. This is a bit of a more blunderbuss approach when using semantic technologies like OWL. At least in Python, as we have learned, we can actually limit our imports to specific methods or procedures.

With the standard OWL import command one brings the entire knowledge graph into the active space. Perhaps this is OK, though it does seem excessive if one only wants a small portion of the external resource, perhaps only for a specific class or predicate or three. But we have a more fundamental problem in that some of our external resources are not defined in a formal ontology subject to an import, but are just persistent URIs. Actually, with external knowledge bases like Wikipedia or Wikidata, this design is more common than one where a single ontology call can bring in all of the external structure. Moreover, even if the external source has a complete OWL-based specification, there is no guarantee that this external source embodies the same assertions and world view of our main knowledge resource, KBpedia.

If we are not bringing in a full ontology import — or may not even be able to do so because the external resources are only accessible via a URI scheme and not a logical ontology — then we will need to formulate a different linkage protocol. The one we have chosen to follow is: Give each external source its own mapping predicate, and then annotate any KBpedia resource with a mapping to show the link to the external source and its specific mapping predicate. This design decision means we can not apply a reasoner to the external sources, but that we may identify and collect them using SPARQL queries. This demarks an important realization point where we see that we can now supplement our information access and aggregation for our knowledge graph not only using logical inferencing and subsumption chains, but through directed queries that make all aspects of our information characterization, including annotations, available for selection and retrieval.

External Mapping Approach

OK, given this design, we proceed to code up our build (load) routines to bring the external mappings into KBpedia. We begin with our standard start-up instructions:

from cowpoke.__main__ import *
from cowpoke.config import *
from owlready2 import *

And then proceed to develop up our routine in the standard manner, including a header showing key configuration inputs. I explain some of the important implementation notes below the routine:

### KEY CONFIG SETTINGS (see build_deck in config.py) ###             
# 'kb_src'        : 'standard'                                        # Set in master_deck
# 'loop_list'     : mapping_dict.values(),                             
# 'base'          : 'C:/1-PythonProjects/kbpedia/v300/build_ins/mappings/',              
# 'ext'           : '.csv',                                         
# 'out_file'      : 'C:/1-PythonProjects/kbpedia/v300/targets/ontologies/kbpedia_reference_concepts.csv',


def mapping_builder(**build_deck):
    print('Beginning KBpedia mappings build . . .')
    loop_list = build_deck.get('loop_list')
    base = build_deck.get('base')
    ext = build_deck.get('ext')
    out_file = build_deck.get('out_file')
    for loopval in loop_list:                                               # Note 1
        print('   . . . processing', loopval)                             
        in_file = (base + loopval + ext)
        print(in_file)
        with open(in_file, 'r', encoding='utf8') as input:
            is_first_row = True
            reader = csv.DictReader(input, delimiter=',', fieldnames=['s', 'p', 'o'])
            for row in reader:                                              # Note 2
                if is_first_row:
                    is_first_row = False                
                    continue
                r_s = row['s']                                              # Note 3
                if 'kko/rc' in r_s:                                         # Note 4
                    r_s = r_s.replace('http://kbpedia.org/kko/rc/', '')
                    r_s = getattr(rc, r_s)
                else:
                    r_s = r_s.replace('http://kbpedia.org/ontologies/kko#', '')
                    r_s = getattr(kko, r_s)                                 # Note 5        
                r_p = row['p']                                              # Note 6
                r_o = row['o']
                if loopval == 'dbpedia':                                    # Note 7                    
                    kb_frag = 'dbpedia_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.dbpedia_id.append(r_o)                              # Note 8
                elif loopval == 'dbpedia-ontology':
                    kb_frag = 'dbpedia_ontology_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.dbpedia_ontology_id.append(r_o)
                elif loopval == 'geonames':
                    kb_frag = 'geo_names_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.geo_names_id.append(r_o)
                elif loopval == 'schema.org':
                    kb_frag = 'schema_org_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.schema_org_id.append(r_o)
                elif loopval == 'wikidata':
                    kb_frag = 'wikidata_q_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.wikidata_q_id.append(r_o)
                elif loopval == 'wikipedia':
                    kb_frag = 'wikipedia_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.wikipedia_id.append(r_o)
                elif loopval == 'wikipedia-categories':
                    kb_frag = 'wikipedia_category_id'
                    kb_prop = getattr(rc, kb_frag)
                    r_s.wikipedia_category_id.append(r_o)
                else:
                    print(loopval, 'is not on list.')
                kko.mappingAsObject[r_s, kb_prop, r_o] = [r_p]              # Note 9         
                print(r_s)
    print('External mapping uploads are complete.')                

We set up our standard looping routine (1), progressing through a new ‘loop_list’ that is contained in a new dictionary (mapping_dict) in our config.py file. Like our other build methods, we use the csv module and progress through the input files row-by-row (2). We pick up our column values (3) and (6) for each row, and assign them to a local variable, corresponding to the s-p-o ‘triples‘ for each row. We need to account for the fact that our KBpedia resources are under either the ‘rc’ or ‘kko’ namespaces (4), and pare them down to their fragments (since the resources are stored on file using their complete IRIs). Because these are string values we are extracting from the input files, we need to look them up and convert them to their internal attribute form (5), which are KBpedia classes in these instances.

We have a long list of switch statements (7) that detect the input file type and then pick the proper mapping predicate (there is one for each external mapping source). This long list of else-if statements would seem to lend themselves to a helper function of some sort, but I decide just to repeat the code blocks because they are simple and straightforward. (Rather than a ‘dict’ format I want something more akin to a ‘record’ where a single key may point to many different values, but that is an expansion of the ‘dict’ approach that actually seems a little complicated in Python). All of material up to this point is really set-up and processing for the two key owlready2 algorithms that we need to use.

The first algorithm (8) we have seen before and associates the external mapped IRI to the current KBpedia class in the loop routine, and has the form of:

  subject.predicate.append(object)

The only tricky part here is making sure that namespace prefixes are used as indicated and that we have converted the external mapping predicate to its internal form (kb_prop). This code is now associating the external IRI to the subject KBpedia class. However, we are still lacking the nature of the mapping predicate.

For this purpose, we need to “annotate the annotation”, or basically reify the annotation with its specific mapping predicate. There is a format in owlready2 where we basically treat the entire tuple of the s-p-o object as the target for the added annotation, shown in the form as (9). The predicate for this purpose is the kko.mappingAsObject. The basic format is:

  kko.mappingAsObject[s, p, o] = 'specific mapping predicate'

The ‘specific mapping predicate’ is either owl:equivalentClass, rdfs:subClassOf, kko:superClassOf, kko:isAbout, or kko:isRelatedTo. The kko:mappingAsObject is named as it is because this specifically assigned mapping predicate applies to the external IRI when it appears in the object slot of the s-p-o triple. In other words, the triple so formed has the s-p-o construction of:

   Kbpedia class - 'specific mapping predicate' - external IRI

Just as it appears in our external mapping files. It is important to keep this ordering straight, since reversing the order of the subject and object causes the inverse properties to be required (rdfs:subClassOf is the inverse of kko:superClassOf, kko:isAbout is the inverse of kko:isRelatedTo).

So, with this code block now set, we can run our routine:

mapping_builder(**build_deck)

Once processed, here is the form the mapping takes within the Protégé editor:

Mapping Annotations
Figure 1: Mapping Annotations

The first callout (1) indicates we successfully changed our hyphens to underscores, as discussed in the last major part. The second callout (2) shows how our mapping annotations now appear, with the annotation itself being annotated with the specific mapping predicate used.

Since we like how these mappings turned out, we decide to save the file:

kb.save('C:/1-PythonProjects/kbpedia/v300/targets/ontologies/kbpedia_reference_concepts_test.owl', format="rdfxml") 

Since these mappings add considerably to the file size, I actually save both mapped and unmapped versions for later use, depending.

Completing the Roundtrip

Now that our builds contain external mappings, it is appropriate we also create extraction routines to get these assignments back out. First, we can list all of the KBpedia RCs that have a specific external mapping (rc.dbpedia_ontology_id in this case), which also returns a string value for the external IRI:

list(rc.dbpedia_ontology_id.get_relations())
[(rc.Person, 'http://dbpedia.org/ontology/Person'),
(rc.SoccerPlayer, 'http://dbpedia.org/ontology/SoccerPlayer'),
(rc.ConceptualWork, 'http://dbpedia.org/ontology/Work'),
(rc.Bird, 'http://dbpedia.org/ontology/Bird'),
(rc.TextualPCW, 'http://dbpedia.org/ontology/WrittenWork'),
(rc.Scientist, 'http://dbpedia.org/ontology/Scientist'),
(rc.BasketballPlayer, 'http://dbpedia.org/ontology/BasketballPlayer'),
(rc.Artist, 'http://dbpedia.org/ontology/Artist'),
(rc.GeopoliticalEntity,
'http://dbpedia.org/ontology/GeopoliticalOrganisation'),
(rc.GeopoliticalEntity, 'http://dbpedia.org/ontology/Region'),
(rc.Lighthouse, 'http://dbpedia.org/ontology/Lighthouse'),
(rc.FootballPlayer_American,
'http://dbpedia.org/ontology/GridironFootballPlayer'),
(rc.FootballPlayer_American,
'http://dbpedia.org/ontology/AmericanFootballPlayer'),
(rc.Organization, 'http://dbpedia.org/ontology/Organisation'),
(rc.Organization, 'http://dbpedia.org/ontology/EmployersOrganisation'),
(rc.Organization, 'http://dbpedia.org/ontology/OrganisationMember'),
(rc.Athlete, 'http://dbpedia.org/ontology/Athlete'),
(rc.Athlete, 'http://dbpedia.org/ontology/AthleticsPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/ArcherPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/Biathlete'),
(rc.Athlete, 'http://dbpedia.org/ontology/BobsleighAthlete'),
(rc.Athlete, 'http://dbpedia.org/ontology/Canoeist'),
(rc.Athlete, 'http://dbpedia.org/ontology/Curler'),
(rc.Athlete, 'http://dbpedia.org/ontology/DartsPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/GaelicGamesPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/HorseRider'),
(rc.Athlete,
'http://dbpedia.org/ontology/NationalCollegiateAthleticAssociationAthlete'),
(rc.Athlete, 'http://dbpedia.org/ontology/NetballPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/Rower'),
(rc.Athlete, 'http://dbpedia.org/ontology/Skater'),
(rc.Athlete, 'http://dbpedia.org/ontology/Ski-jumper'),
(rc.Athlete, 'http://dbpedia.org/ontology/SnookerChamp'),
(rc.Athlete, 'http://dbpedia.org/ontology/SnookerPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/SpeedSkater'),
(rc.Athlete, 'http://dbpedia.org/ontology/SportsTeamMember'),
(rc.Athlete, 'http://dbpedia.org/ontology/TableTennisPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/TeamMember'),
(rc.Athlete, 'http://dbpedia.org/ontology/WaterPoloPlayer'),
(rc.Athlete, 'http://dbpedia.org/ontology/WinterSportPlayer'),
(rc.Building, 'http://dbpedia.org/ontology/Building'),
(rc.Philosopher, 'http://dbpedia.org/ontology/Philosopher'),
(rc.MusicalComposition, 'http://dbpedia.org/ontology/MusicalWork'),
(rc.Horse, 'http://dbpedia.org/ontology/Horse'),
(rc.MartialArtist, 'http://dbpedia.org/ontology/MartialArtist'),
(rc.Golfer, 'http://dbpedia.org/ontology/GolfPlayer'),
(rc.Amphibian, 'http://dbpedia.org/ontology/Amphibian'),
(rc.RailroadStation, 'http://dbpedia.org/ontology/RailwayStation'),
(rc.RailroadStation, 'http://dbpedia.org/ontology/TramStation'),
(rc.Anime, 'http://dbpedia.org/ontology/Anime'),
(rc.Monument, 'http://dbpedia.org/ontology/Monument'),
(rc.Arachnid, 'http://dbpedia.org/ontology/Arachnid'),
(rc.Architect, 'http://dbpedia.org/ontology/Architect'),
(rc.Legislator, 'http://dbpedia.org/ontology/Senator'),
(rc.Article_PCW, 'http://dbpedia.org/ontology/Article'),
(rc.Cave, 'http://dbpedia.org/ontology/Cave'),
(rc.ChemicalSubstanceType, 'http://dbpedia.org/ontology/ChemicalCompound'),
(rc.ChemicalSubstanceType, 'http://dbpedia.org/ontology/ChemicalSubstance'),
(rc.TennisPlayer, 'http://dbpedia.org/ontology/TennisPlayer'),
(rc.TennisTournament, 'http://dbpedia.org/ontology/TennisTournament'),
(rc.AdministrativeDistrict,
'http://dbpedia.org/ontology/GovernmentalAdministrativeRegion'),
(rc.AdministrativeDistrict,
'http://dbpedia.org/ontology/ClericalAdministrativeRegion'),
(rc.AdministrativeDistrict, 'http://dbpedia.org/ontology/MicroRegion'),
(rc.Food, 'http://dbpedia.org/ontology/Food'),
(rc.BaseballPlayer, 'http://dbpedia.org/ontology/BaseballPlayer'),
(rc.FootballPlayer_Australian,
'http://dbpedia.org/ontology/AustralianRulesFootballPlayer'),
(rc.Municipality, 'http://dbpedia.org/ontology/Municipality'),
(rc.Municipality, 'http://dbpedia.org/ontology/FormerMunicipality'),
(rc.ElectedOfficial, 'http://dbpedia.org/ontology/OfficeHolder'),
(rc.BadmintonPlayer, 'http://dbpedia.org/ontology/BadmintonPlayer'),
(rc.PopulatedPlace, 'http://dbpedia.org/ontology/PopulatedPlace'),
(rc.RugbyPlayer, 'http://dbpedia.org/ontology/RugbyPlayer'),
(rc.School_AcademicOrganization, 'http://dbpedia.org/ontology/School'),
(rc.BodyOfWater, 'http://dbpedia.org/ontology/BodyOfWater'),
(rc.Temple, 'http://dbpedia.org/ontology/Temple'),
(rc.VolleyballPlayer, 'http://dbpedia.org/ontology/VolleyballPlayer'),
(rc.VolleyballPlayer, 'http://dbpedia.org/ontology/BeachVolleyballPlayer'),
(rc.Brewery, 'http://dbpedia.org/ontology/Brewery'),
(rc.Judge, 'http://dbpedia.org/ontology/Judge'),
(rc.Mountain, 'http://dbpedia.org/ontology/Mountain'),
(rc.Pass_Geographical, 'http://dbpedia.org/ontology/MountainPass'),
(rc.Game, 'http://dbpedia.org/ontology/Game'),
(rc.Ship, 'http://dbpedia.org/ontology/Ship'),
(rc.HotelBuilding, 'http://dbpedia.org/ontology/Hotel'),
(rc.Boxer, 'http://dbpedia.org/ontology/Boxer'),
(rc.Boxer, 'http://dbpedia.org/ontology/AmateurBoxer'),
(rc.Brain, 'http://dbpedia.org/ontology/Brain'),
(rc.Bridge, 'http://dbpedia.org/ontology/Bridge'),
(rc.Periodical, 'http://dbpedia.org/ontology/PeriodicalLiterature'),
(rc.Wrestler, 'http://dbpedia.org/ontology/Wrestler'),
(rc.VisualImage, 'http://dbpedia.org/ontology/Image'),
(rc.Professor, 'http://dbpedia.org/ontology/Professor'),
(rc.ReligiousOrganization, 'http://dbpedia.org/ontology/ClericalOrder'),
(rc.ReligiousOrganization,
'http://dbpedia.org/ontology/ReligiousOrganisation'),
(rc.Archive, 'http://dbpedia.org/ontology/Archive'),
(rc.Treaty, 'http://dbpedia.org/ontology/Treaty'),
(rc.FictionalCharacter, 'http://dbpedia.org/ontology/FictionalCharacter'),
(rc.FictionalCharacter, 'http://dbpedia.org/ontology/MythologicalFigure'),
(rc.SoftwareObject_Individual, 'http://dbpedia.org/ontology/Software'),
(rc.Parish_EcclesiasticalDistrict, 'http://dbpedia.org/ontology/Deanery'),
(rc.Actor, 'http://dbpedia.org/ontology/Actor'),
(rc.Actor, 'http://dbpedia.org/ontology/AdultActor'),
(rc.ReligiousBuilding, 'http://dbpedia.org/ontology/ReligiousBuilding'),
(rc.Concept, 'http://dbpedia.org/ontology/ScientificConcept'),
(rc.Reserve_OutdoorRegion, 'http://dbpedia.org/ontology/ProtectedArea'),
(rc.ResearchProject, 'http://dbpedia.org/ontology/ResearchProject'),
(rc.Country, 'http://dbpedia.org/ontology/Country'),
(rc.Cyclist_Athlete, 'http://dbpedia.org/ontology/Cyclist'),
(rc.Cricketer, 'http://dbpedia.org/ontology/Cricketer'),
(rc.ConstructionArtifact,
'http://dbpedia.org/ontology/ArchitecturalStructure'),
(rc.Currency, 'http://dbpedia.org/ontology/Currency'),
(rc.Graveyard, 'http://dbpedia.org/ontology/Cemetery'),
(rc.CyclingSportsEvent, 'http://dbpedia.org/ontology/CyclingCompetition'),
(rc.CyclingSportsEvent, 'http://dbpedia.org/ontology/CyclingRace'),
(rc.Racehorse, 'http://dbpedia.org/ontology/RaceHorse'),
(rc.Neighborhood, 'http://dbpedia.org/ontology/CityDistrict'),
(rc.Asteroid, 'http://dbpedia.org/ontology/Asteroid'),
(rc.City, 'http://dbpedia.org/ontology/City'),
(rc.Library_Organization, 'http://dbpedia.org/ontology/Library'),
(rc.Actor_Voice, 'http://dbpedia.org/ontology/VoiceActor'),
(rc.HumanGivenName, 'http://dbpedia.org/ontology/GivenName'),
(rc.Painter_FineArtist, 'http://dbpedia.org/ontology/Painter'),
(rc.AilmentCondition, 'http://dbpedia.org/ontology/Disease'),
(rc.Park, 'http://dbpedia.org/ontology/Park'),
(rc.EducationalOrganization,
'http://dbpedia.org/ontology/EducationalInstitution'),
(rc.EducationalOrganization, 'http://dbpedia.org/ontology/SambaSchool'),
(rc.IceHockeyPlayer, 'http://dbpedia.org/ontology/IceHockeyPlayer'),
(rc.Surfer, 'http://dbpedia.org/ontology/Surfer'),
(rc.ProteinMolecule, 'http://dbpedia.org/ontology/Protein'),
(rc.Magazine, 'http://dbpedia.org/ontology/Magazine'),
(rc.Gene_HereditaryUnit, 'http://dbpedia.org/ontology/Gene'),
(rc.Action, 'http://dbpedia.org/ontology/Activity'),
(rc.District_State_Geopolitical, 'http://dbpedia.org/ontology/District'),
(rc.Law, 'http://dbpedia.org/ontology/Law'),
(rc.FashionDesigner, 'http://dbpedia.org/ontology/FashionDesigner'),
(rc.Theater_PhysicalStructure, 'http://dbpedia.org/ontology/Theatre'),
(rc.Airport_Physical, 'http://dbpedia.org/ontology/Airport'),
(rc.PersonTypeByOccupation, 'http://dbpedia.org/ontology/CareerStation'),
(rc.PersonTypeByOccupation, 'http://dbpedia.org/ontology/Profession'),
(rc.Swimmer, 'http://dbpedia.org/ontology/Swimmer'),
(rc.Gymnast, 'http://dbpedia.org/ontology/Gymnast'),
(rc.Restaurant, 'http://dbpedia.org/ontology/Restaurant'),
(rc.Lake, 'http://dbpedia.org/ontology/Lake'),
(rc.SnowSkier, 'http://dbpedia.org/ontology/Skier'),
(rc.SnowSkier, 'http://dbpedia.org/ontology/CrossCountrySkier'),
(rc.Flag, 'http://dbpedia.org/ontology/Flag'),
(rc.Genome_GIS, 'http://dbpedia.org/ontology/GeneLocation'),
(rc.Genome_GIS, 'http://dbpedia.org/ontology/HumanGeneLocation'),
(rc.Genome_GIS, 'http://dbpedia.org/ontology/MouseGeneLocation'),
(rc.CommercialOrganization, 'http://dbpedia.org/ontology/Company'),
(rc.Photographer, 'http://dbpedia.org/ontology/Photographer'),
(rc.HistoricPeriod, 'http://dbpedia.org/ontology/HistoricalPeriod'),
(rc.HistoricPeriod, 'http://dbpedia.org/ontology/PeriodOfArtisticStyle'),
(rc.HistoricPeriod, 'http://dbpedia.org/ontology/ProtohistoricalPeriod'),
(rc.Cleric, 'http://dbpedia.org/ontology/Cleric'),
(rc.Cleric, 'http://dbpedia.org/ontology/Priest'),
(rc.Cleric, 'http://dbpedia.org/ontology/Vicar'),
(rc.MedicalFieldOfStudy, 'http://dbpedia.org/ontology/Medicine'),
(rc.PokerPlayer, 'http://dbpedia.org/ontology/PokerPlayer'),
(rc.LandTopographicalFeature, 'http://dbpedia.org/ontology/NaturalPlace'),
(rc.Glacier, 'http://dbpedia.org/ontology/Glacier'),
(rc.NonProfitOrganization,
'http://dbpedia.org/ontology/Non-ProfitOrganisation'),
(rc.NonProfitOrganization, 'http://dbpedia.org/ontology/RecordOffice'),
(rc.Mineral, 'http://dbpedia.org/ontology/Mineral'),
(rc.Diver, 'http://dbpedia.org/ontology/HighDiver'),
(rc.Fungus, 'http://dbpedia.org/ontology/Fungus'),
(rc.PersonTypeByEthnicity, 'http://dbpedia.org/ontology/EthnicGroup'),
(rc.Island, 'http://dbpedia.org/ontology/Island'),
(rc.Specification, 'http://dbpedia.org/ontology/Standard'),
(rc.FigureSkater, 'http://dbpedia.org/ontology/FigureSkater'),
(rc.Town, 'http://dbpedia.org/ontology/Town'),
(rc.FootballPlayer_Canadian,
'http://dbpedia.org/ontology/CanadianFootballPlayer'),
(rc.JournalSeries, 'http://dbpedia.org/ontology/AcademicJournal'),
(rc.JournalSeries, 'http://dbpedia.org/ontology/UndergroundJournal'),
(rc.Singer, 'http://dbpedia.org/ontology/Singer'),
(rc.Director_Movie, 'http://dbpedia.org/ontology/MovieDirector'),
(rc.ComputerGameProgram, 'http://dbpedia.org/ontology/VideoGame'),
(rc.TransportationPathSystemType,
'http://dbpedia.org/ontology/On-SiteTransportation'),
(rc.MusicalComposition_Song, 'http://dbpedia.org/ontology/Song'),
(rc.MusicalComposition_Song,
'http://dbpedia.org/ontology/EurovisionSongContestEntry'),
(rc.EukaryoticGene, 'http://dbpedia.org/ontology/HumanGene'),
(rc.EukaryoticGene, 'http://dbpedia.org/ontology/MouseGene'),
(rc.MilitaryVehicle, 'http://dbpedia.org/ontology/MilitaryVehicle'),
(rc.MusicalInstrument, 'http://dbpedia.org/ontology/Instrument'),
(rc.LacrossePlayer, 'http://dbpedia.org/ontology/LacrossePlayer'),
(rc.FashionModel, 'http://dbpedia.org/ontology/Model'),
(rc.Sculpture, 'http://dbpedia.org/ontology/Sculpture'),
(rc.MusicalComposer, 'http://dbpedia.org/ontology/MusicComposer'),
(rc.Manga, 'http://dbpedia.org/ontology/Manga'),
(rc.Astronaut, 'http://dbpedia.org/ontology/Astronaut'),
(rc.MilitaryPerson, 'http://dbpedia.org/ontology/MilitaryPerson'),
(rc.Village, 'http://dbpedia.org/ontology/Settlement'),
(rc.Village, 'http://dbpedia.org/ontology/Village'),
(rc.Village, 'http://dbpedia.org/ontology/IranSettlement'),
(rc.PublicPlace, 'http://dbpedia.org/ontology/Venue'),
(rc.Street_Generic, 'http://dbpedia.org/ontology/Street'),
(rc.PhysicalDevice, 'http://dbpedia.org/ontology/Device'),
(rc.Insect, 'http://dbpedia.org/ontology/Insect'),
(rc.SquashPlayer, 'http://dbpedia.org/ontology/SquashPlayer'),
(rc.River, 'http://dbpedia.org/ontology/River'),
(rc.Roadway, 'http://dbpedia.org/ontology/Road'),
(rc.RollerCoaster, 'http://dbpedia.org/ontology/RollerCoaster'),
(rc.TransportFacility, 'http://dbpedia.org/ontology/LaunchPad'),
(rc.TransportFacility, 'http://dbpedia.org/ontology/RouteStop'),
(rc.Volcano, 'http://dbpedia.org/ontology/Volcano'),
(rc.Dam, 'http://dbpedia.org/ontology/Dam'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/SportsTeam'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/CyclingTeam'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/FormulaOneTeam'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/HandballTeam'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/NationalSoccerClub'),
(rc.SportsTeam, 'http://dbpedia.org/ontology/SpeedwayTeam'),
(rc.Election, 'http://dbpedia.org/ontology/Election'),
(rc.Monarch_HeadOfState, 'http://dbpedia.org/ontology/Monarch'),
(rc.AnimalBodyPart, 'http://dbpedia.org/ontology/AnatomicalStructure'),
(rc.BloodVessel, 'http://dbpedia.org/ontology/BloodVessel'),
(rc.PoliticalParty, 'http://dbpedia.org/ontology/PoliticalParty'),
(rc.Terminal_TransferPoint, 'http://dbpedia.org/ontology/Station'),
(rc.MilitaryAircraft, 'http://dbpedia.org/ontology/MilitaryAircraft'),
(rc.Name, 'http://dbpedia.org/ontology/Name'),
(rc.Earthquake, 'http://dbpedia.org/ontology/Earthquake'),
(rc.Automobile, 'http://dbpedia.org/ontology/Automobile'),
(rc.Animal, 'http://dbpedia.org/ontology/Animal'),
(rc.SportsEvent, 'http://dbpedia.org/ontology/SportsEvent'),
(rc.SportsEvent, 'http://dbpedia.org/ontology/FootballMatch'),
(rc.SportsEvent,
'http://dbpedia.org/ontology/InternationalFootballLeagueEvent'),
(rc.MusicSingle, 'http://dbpedia.org/ontology/Single'),
(rc.Spacecraft, 'http://dbpedia.org/ontology/Spacecraft'),
(rc.AirlineCompany, 'http://dbpedia.org/ontology/Airline'),
(rc.Bishop_Clerical, 'http://dbpedia.org/ontology/ChristianBishop'),
(rc.Engine, 'http://dbpedia.org/ontology/Engine'),
(rc.CourtCase, 'http://dbpedia.org/ontology/Case'),
(rc.CourtCase, 'http://dbpedia.org/ontology/LegalCase'),
(rc.Holiday, 'http://dbpedia.org/ontology/Holiday'),
(rc.Event, 'http://dbpedia.org/ontology/Event'),
(rc.SportsCompetition, 'http://dbpedia.org/ontology/SportCompetitionResult'),
(rc.AwardPractice, 'http://dbpedia.org/ontology/Award'),
(rc.RacingSportsEvent, 'http://dbpedia.org/ontology/Race'),
(rc.RacingSportsEvent, 'http://dbpedia.org/ontology/GrandPrix'),
(rc.Province, 'http://dbpedia.org/ontology/Province'),
(rc.Nerve, 'http://dbpedia.org/ontology/Nerve'),
(rc.Conference, 'http://dbpedia.org/ontology/AcademicConference'),
(rc.Rating, 'http://dbpedia.org/ontology/SnookerWorldRanking'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/SportsLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/AmericanFootballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/AutoRacingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/BasketballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/BowlingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/BoxingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/CanadianFootballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/CricketLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/CurlingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/CyclingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/FieldHockeyLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/FormulaOneRacing'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/GolfLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/HandballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/IceHockeyLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/InlineHockeyLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/LacrosseLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/MixedMartialArtsLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/MotorcycleRacingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/PaintballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/PoloLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/RadioControlledRacingLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/RugbyLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/SoccerLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/SoftballLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/SpeedwayLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/TennisLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/VideogamesLeague'),
(rc.SportsLeague, 'http://dbpedia.org/ontology/VolleyballLeague'),
(rc.Competition, 'http://dbpedia.org/ontology/Competition'),
(rc.Abbey, 'http://dbpedia.org/ontology/Abbey'),
(rc.Muscle, 'http://dbpedia.org/ontology/Muscle'),
(rc.LegislativeOrganization, 'http://dbpedia.org/ontology/Legislature'),
(rc.Wine, 'http://dbpedia.org/ontology/Wine'),
(rc.SportSeason, 'http://dbpedia.org/ontology/SportsSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/SportsTeamSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/MotorsportSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/NationalFootballLeagueSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/NCAATeamSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/SoccerClubSeason'),
(rc.SportSeason, 'http://dbpedia.org/ontology/SoccerLeagueSeason'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricPlace'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricalCountry'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricalDistrict'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricalProvince'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricalRegion'),
(rc.HistoricalSite, 'http://dbpedia.org/ontology/HistoricalSettlement'),
(rc.FieldOfStudy, 'http://dbpedia.org/ontology/AcademicSubject'),
(rc.PharmacyProductType, 'http://dbpedia.org/ontology/Drug'),
(rc.GeologicalTimePeriod, 'http://dbpedia.org/ontology/GeologicalPeriod'),
(rc.PersonWithOccupation, 'http://dbpedia.org/ontology/Deputy'),
(rc.BankOrganization, 'http://dbpedia.org/ontology/Bank'),
(rc.AutoEngine, 'http://dbpedia.org/ontology/AutomobileEngine'),
(rc.Galaxy, 'http://dbpedia.org/ontology/Galaxy'),
(rc.PowerGenerationComplex, 'http://dbpedia.org/ontology/PowerStation'),
(rc.TravelRoute, 'http://dbpedia.org/ontology/RouteOfTransportation'),
(rc.Stream, 'http://dbpedia.org/ontology/Stream'),
(rc.SportsClub, 'http://dbpedia.org/ontology/SportsClub'),
(rc.SportsClub, 'http://dbpedia.org/ontology/RugbyClub'),
(rc.SportsClub, 'http://dbpedia.org/ontology/SoccerClub'),
(rc.Sport, 'http://dbpedia.org/ontology/Sport'),
(rc.StructuredSportsEvent, 'http://dbpedia.org/ontology/PenaltyShootOut'),
(rc.SerialKiller, 'http://dbpedia.org/ontology/SerialKiller'),
(rc.GolfCourse, 'http://dbpedia.org/ontology/GolfCourse'),
(rc.Doctor_Medical, 'http://dbpedia.org/ontology/Medician'),
(rc.Canton_Swiss, 'http://dbpedia.org/ontology/Canton'),
(rc.Monarchy, 'http://dbpedia.org/ontology/Fiefdom'),
(rc.Monarchy, 'http://dbpedia.org/ontology/HistoricalAreaOfAuthority'),
(rc.Monarchy, 'http://dbpedia.org/ontology/Regency'),
(rc.Artery, 'http://dbpedia.org/ontology/Artery'),
(rc.PoliticalBeliefSystem, 'http://dbpedia.org/ontology/Ideology'),
(rc.PoliticalBeliefSystem, 'http://dbpedia.org/ontology/PoliticalConcept'),
(rc.Mammal, 'http://dbpedia.org/ontology/Mammal'),
(rc.Lawyer, 'http://dbpedia.org/ontology/Lawyer'),
(rc.Patriarch, 'http://dbpedia.org/ontology/ChristianPatriarch'),
(rc.Vodka, 'http://dbpedia.org/ontology/Vodka'),
(rc.Document, 'http://dbpedia.org/ontology/Document'),
(rc.Document, 'http://dbpedia.org/ontology/DocumentType'),
(rc.PhilosophyBeliefs, 'http://dbpedia.org/ontology/PhilosophicalConcept'),
(rc.AbstractProgrammingLanguage,
'http://dbpedia.org/ontology/ProgrammingLanguage'),
(rc.CapitalCityOfRegion, 'http://dbpedia.org/ontology/CapitalOfRegion'),
(rc.CapitalCityOfRegion, 'http://dbpedia.org/ontology/Capital'),
(rc.DomesticCat, 'http://dbpedia.org/ontology/Cat'),
(rc.Movie, 'http://dbpedia.org/ontology/Film'),
(rc.MusicalInstrumentPlayer, 'http://dbpedia.org/ontology/Instrumentalist'),
(rc.BusinessPerson, 'http://dbpedia.org/ontology/BusinessPerson'),
(rc.Enzyme, 'http://dbpedia.org/ontology/Enzyme'),
(rc.ArchitecturalTypeByStyle,
'http://dbpedia.org/ontology/ArchitecturalStructure'),
(rc.Color, 'http://dbpedia.org/ontology/Colour'),
(rc.Bacterium, 'http://dbpedia.org/ontology/Bacteria'),
(rc.Weapon, 'http://dbpedia.org/ontology/Weapon'),
(rc.Artist_Performer, 'http://dbpedia.org/ontology/BeautyQueen'),
(rc.Painting_ArtForm, 'http://dbpedia.org/ontology/Painting'),
(rc.SocialOccurrence, 'http://dbpedia.org/ontology/SocietalEvent'),
(rc.Family_Human, 'http://dbpedia.org/ontology/Family'),
(rc.FilmGenre, 'http://dbpedia.org/ontology/MovieGenre'),
(rc.Dancer_Performer, 'http://dbpedia.org/ontology/Dancer'),
(rc.Economist, 'http://dbpedia.org/ontology/Economist'),
(rc.MountainRange, 'http://dbpedia.org/ontology/MountainRange'),
(rc.Department, 'http://dbpedia.org/ontology/Department'),
(rc.Archipelago, 'http://dbpedia.org/ontology/Archipelago'),
(rc.Sea, 'http://dbpedia.org/ontology/Sea'),
(rc.WebSite, 'http://dbpedia.org/ontology/Website'),
(rc.AdultFemaleHuman, 'http://dbpedia.org/ontology/BeautyQueen'),
(rc.AthleticActivity, 'http://dbpedia.org/ontology/Athletics'),
(rc.Project, 'http://dbpedia.org/ontology/Project'),
(rc.PersonTypeByActivity, 'http://dbpedia.org/ontology/ChessPlayer'),
(rc.SociabilityBasedAction, 'http://dbpedia.org/ontology/PublicService'),
(rc.Biologist, 'http://dbpedia.org/ontology/Biologist'),
(rc.Engineer, 'http://dbpedia.org/ontology/Engineer'),
(rc.Dog, 'http://dbpedia.org/ontology/Dog'),
(rc.HumanSurname, 'http://dbpedia.org/ontology/Surname'),
(rc.Dying, 'http://dbpedia.org/ontology/Death'),
(rc.Journalist, 'http://dbpedia.org/ontology/Journalist'),
(rc.Agent_Generic, 'http://dbpedia.org/ontology/Agent'),
(rc.SocialQuantity, 'http://dbpedia.org/ontology/HumanDevelopmentIndex'),
(rc.Facility_Construct, 'http://dbpedia.org/ontology/Infrastructure'),
(rc.Crustacean, 'http://dbpedia.org/ontology/Crustacean'),
(rc.Conveying_Generic, 'http://dbpedia.org/ontology/ConveyorSystem'),
(rc.AirTransportationVehicle, 'http://dbpedia.org/ontology/Aircraft'),
(rc.TransportationDevice_Vehicle,
'http://dbpedia.org/ontology/MeanOfTransportation'),
(rc.PartOfBuilding, 'http://dbpedia.org/ontology/NoteworthyPartOfBuilding'),
(rc.PortFacility, 'http://dbpedia.org/ontology/Port'),
(rc.Driver_TransportationProfessional,
'http://dbpedia.org/ontology/MotorsportRacer'),
(rc.Driver_TransportationProfessional,
'http://dbpedia.org/ontology/RacingDriver'),
(rc.Driver_TransportationProfessional,
'http://dbpedia.org/ontology/RallyDriver'),
(rc.Fish, 'http://dbpedia.org/ontology/Fish'),
(rc.Sound, 'http://dbpedia.org/ontology/Sound'),
(rc.Album, 'http://dbpedia.org/ontology/Album'),
(rc.Drink, 'http://dbpedia.org/ontology/Beverage'),
(rc.Star, 'http://dbpedia.org/ontology/Star'),
(rc.Beer, 'http://dbpedia.org/ontology/Beer'),
(rc.Writer, 'http://dbpedia.org/ontology/Writer'),
(rc.Plant, 'http://dbpedia.org/ontology/Plant'),
(rc.God, 'http://dbpedia.org/ontology/Deity'),
(rc.ReferenceWork, 'http://dbpedia.org/ontology/Reference'),
(rc.Letter_Alphabetic, 'http://dbpedia.org/ontology/Letter'),
(rc.List_Information, 'http://dbpedia.org/ontology/List'),
(rc.MusicTypeByGenre, 'http://dbpedia.org/ontology/MusicGenre'),
(rc.RecordCompany, 'http://dbpedia.org/ontology/RecordLabel'),
(rc.Altitude, 'http://dbpedia.org/ontology/Altitude'),
(rc.Desert, 'http://dbpedia.org/ontology/Desert'),
(rc.HumanActivity, 'http://dbpedia.org/ontology/PersonFunction'),
(rc.Territory, 'http://dbpedia.org/ontology/Territory'),
(rc.Territory, 'http://dbpedia.org/ontology/OldTerritory'),
(rc.Ambassador, 'http://dbpedia.org/ontology/Ambassador'),
(rc.Moss, 'http://dbpedia.org/ontology/Moss'),
(rc.FootballTeam, 'http://dbpedia.org/ontology/AmericanFootballTeam'),
(rc.FootballTeam, 'http://dbpedia.org/ontology/AustralianFootballTeam'),
(rc.FootballTeam, 'http://dbpedia.org/ontology/CanadianFootballTeam'),
(rc.BaseballSeason, 'http://dbpedia.org/ontology/BaseballSeason'),
(rc.AmusementParkRide, 'http://dbpedia.org/ontology/AmusementParkAttraction'),
(rc.AmusementParkRide, 'http://dbpedia.org/ontology/WaterRide'),
(rc.Reptile, 'http://dbpedia.org/ontology/Reptile'),
(rc.GeopoliticalEntityBySystemOfGovernment,
'http://dbpedia.org/ontology/GovernmentType'),
(rc.VisualWork, 'http://dbpedia.org/ontology/Artwork'),
(rc.HorseRacingEvent, 'http://dbpedia.org/ontology/HorseRace'),
(rc.Forest, 'http://dbpedia.org/ontology/Forest'),
(rc.OlympicGames, 'http://dbpedia.org/ontology/Olympics'),
(rc.TownSquare, 'http://dbpedia.org/ontology/Square'),
(rc.Constellation, 'http://dbpedia.org/ontology/Constellation'),
(rc.Chancellor_HeadOfGovernment, 'http://dbpedia.org/ontology/Chancellor'),
(rc.BiologicalSpecies, 'http://dbpedia.org/ontology/Species'),
(rc.Diocese, 'http://dbpedia.org/ontology/Diocese'),
(rc.AnimalTrainer, 'http://dbpedia.org/ontology/HorseTrainer'),
(rc.TVShow, 'http://dbpedia.org/ontology/TelevisionShow'),
(rc.Club_Organization, 'http://dbpedia.org/ontology/HockeyClub'),
(rc.Valuable_PersonalPossession,
'http://dbpedia.org/ontology/CollectionOfValuables'),
(rc.Cheese, 'http://dbpedia.org/ontology/Cheese'),
(rc.Cultivar, 'http://dbpedia.org/ontology/CultivatedVariety'),
(rc.OfficialDocument, 'http://dbpedia.org/ontology/StatedResolution'),
(rc.FloralPlant, 'http://dbpedia.org/ontology/FloweringPlant'),
(rc.Conifer, 'http://dbpedia.org/ontology/Conifer'),
(rc.Archaea, 'http://dbpedia.org/ontology/Archaea'),
(rc.Archaeologist, 'http://dbpedia.org/ontology/Archeologist'),
(rc.Ocean, 'http://dbpedia.org/ontology/Ocean'),
(rc.Area, 'http://dbpedia.org/ontology/Area'),
(rc.Stadium, 'http://dbpedia.org/ontology/Arena'),
(rc.Stadium, 'http://dbpedia.org/ontology/Stadium'),
(rc.FootballSeason, 'http://dbpedia.org/ontology/FootballLeagueSeason'),
(rc.RocketPropelledTransportationDevice,
'http://dbpedia.org/ontology/Rocket'),
(rc.Aristocrat, 'http://dbpedia.org/ontology/Aristocrat'),
(rc.Aristocrat, 'http://dbpedia.org/ontology/Royalty'),
(rc.Aristocrat, 'http://dbpedia.org/ontology/BritishRoyalty'),
(rc.AristocratTypeByTitle, 'http://dbpedia.org/ontology/Noble'),
(rc.AristocraticFamilyLine, 'http://dbpedia.org/ontology/NobleFamily'),
(rc.Bone_BodyPart, 'http://dbpedia.org/ontology/Bone'),
(rc.AttackOnObject, 'http://dbpedia.org/ontology/Attack'),
(rc.MilitaryFacility, 'http://dbpedia.org/ontology/MilitaryStructure'),
(rc.Book, 'http://dbpedia.org/ontology/Book'),
(rc.Arrondissement, 'http://dbpedia.org/ontology/Arrondissement'),
(rc.MilitaryOrganization, 'http://dbpedia.org/ontology/MilitaryUnit'),
(rc.Criminal, 'http://dbpedia.org/ontology/Criminal'),
(rc.Decoration, 'http://dbpedia.org/ontology/Decoration'),
(rc.Museum_Organization, 'http://dbpedia.org/ontology/Museum'),
(rc.Language, 'http://dbpedia.org/ontology/Language'),
(rc.Community, 'http://dbpedia.org/ontology/Community'),
(rc.ArtistTypeByArtForm, 'http://dbpedia.org/ontology/ArtisticGenre'),
(rc.Band_MusicGroup, 'http://dbpedia.org/ontology/Band'),
(rc.Murderer, 'http://dbpedia.org/ontology/Murderer'),
(rc.Soccer, 'http://dbpedia.org/ontology/Soccer'),
(rc.CelestialObject, 'http://dbpedia.org/ontology/Globularswarm'),
(rc.CelestialObject, 'http://dbpedia.org/ontology/Openswarm'),
(rc.CelestialObject, 'http://dbpedia.org/ontology/Swarm'),
(rc.SpaceMission, 'http://dbpedia.org/ontology/SpaceMission'),
(rc.ClothingTypeByStyle, 'http://dbpedia.org/ontology/LineOfFashion'),
(rc.SportsPlayingArea, 'http://dbpedia.org/ontology/SportFacility'),
(rc.Atoll, 'http://dbpedia.org/ontology/Atoll'),
(rc.SalesActivity, 'http://dbpedia.org/ontology/Sales'),
(rc.ReligiousBeliefs, 'http://dbpedia.org/ontology/TheologicalConcept'),
(rc.BasketballTeam, 'http://dbpedia.org/ontology/BasketballTeam'),
(rc.AustralianFootballLeague,
'http://dbpedia.org/ontology/AustralianFootballLeague'),
(rc.CarRacing, 'http://dbpedia.org/ontology/DTMRacer'),
(rc.State_Geopolitical, 'http://dbpedia.org/ontology/State'),
(rc.Motorcycle, 'http://dbpedia.org/ontology/Motorcycle'),
(rc.TrainEngine, 'http://dbpedia.org/ontology/Locomotive'),
(rc.Gate, 'http://dbpedia.org/ontology/Gate'),
(rc.BoardGame, 'http://dbpedia.org/ontology/BoardGame'),
(rc.Tournament, 'http://dbpedia.org/ontology/Tournament'),
(rc.Bay, 'http://dbpedia.org/ontology/Bay'),
(rc.Poem, 'http://dbpedia.org/ontology/Poem'),
(rc.Baronet, 'http://dbpedia.org/ontology/Baronet'),
(rc.BaseballTeam, 'http://dbpedia.org/ontology/BaseballTeam'),
(rc.SportsCoach, 'http://dbpedia.org/ontology/Coach'),
(rc.SportsCoach, 'http://dbpedia.org/ontology/AmericanFootballCoach'),
(rc.SportsCoach, 'http://dbpedia.org/ontology/VolleyballCoach'),
(rc.BasketballLeague, 'http://dbpedia.org/ontology/BaseballLeague'),
(rc.TeamSport, 'http://dbpedia.org/ontology/TeamSport'),
(rc.Parliament, 'http://dbpedia.org/ontology/Parliament'),
(rc.HockeyTeam, 'http://dbpedia.org/ontology/HockeyTeam'),
(rc.Collection, 'http://dbpedia.org/ontology/Type'),
(rc.Beach, 'http://dbpedia.org/ontology/Beach'),
(rc.IrregularMilitaryForce,
'http://dbpedia.org/ontology/MemberResistanceMovement'),
(rc.Tower, 'http://dbpedia.org/ontology/Tower'),
(rc.Database_AbstractContent, 'http://dbpedia.org/ontology/Database'),
(rc.LegalCode, 'http://dbpedia.org/ontology/SystemOfLaw'),
(rc.Lipid, 'http://dbpedia.org/ontology/Lipid'),
(rc.BiologicalTaxon, 'http://dbpedia.org/ontology/Taxon'),
(rc.BiopolymerMolecule, 'http://dbpedia.org/ontology/Biomolecule'),
(rc.BirthEvent, 'http://dbpedia.org/ontology/Birth'),
(rc.CardGame, 'http://dbpedia.org/ontology/CardGame'),
(rc.Meeting_SocialGathering, 'http://dbpedia.org/ontology/Meeting'),
(rc.BloodType, 'http://dbpedia.org/ontology/BloodType'),
(rc.Walkway, 'http://dbpedia.org/ontology/MovingWalkway'),
(rc.Poet, 'http://dbpedia.org/ontology/Poet'),
(rc.Bodybuilder, 'http://dbpedia.org/ontology/Bodybuilder'),
(rc.Psychologist, 'http://dbpedia.org/ontology/Psychologist'),
(rc.Garden, 'http://dbpedia.org/ontology/Garden'),
(rc.NaturalRegion, 'http://dbpedia.org/ontology/NaturalRegion'),
(rc.BoxingSport, 'http://dbpedia.org/ontology/Boxing'),
(rc.BoxingSport, 'http://dbpedia.org/ontology/BoxingCategory'),
(rc.BoxingSport, 'http://dbpedia.org/ontology/BoxingStyle'),
(rc.Prison, 'http://dbpedia.org/ontology/Prison'),
(rc.GovernmentAgency, 'http://dbpedia.org/ontology/GovernmentAgency'),
(rc.BroadcastMediaShow, 'http://dbpedia.org/ontology/Broadcast'),
(rc.NuclearPowerStation, 'http://dbpedia.org/ontology/NuclearPowerStation'),
(rc.ReligiousPerson, 'http://dbpedia.org/ontology/Religious'),
(rc.ComputerFile, 'http://dbpedia.org/ontology/File'),
(rc.BusLine, 'http://dbpedia.org/ontology/BusCompany'),
(rc.MassTransitSystem, 'http://dbpedia.org/ontology/PublicTransitSystem'),
(rc.Tax_COC, 'http://dbpedia.org/ontology/Tax'),
(rc.PopulatedLocality, 'http://dbpedia.org/ontology/Locality'),
(rc.PopulatedLocality, 'http://dbpedia.org/ontology/FrenchLocality'),
(rc.ProfessionalSportsEvent,
'http://dbpedia.org/ontology/NationalFootballLeagueEvent'),
(rc.ConceptualWorkSeries_Periodic,
'http://dbpedia.org/ontology/MultiVolumePublication'),
(rc.CabinetOffice, 'http://dbpedia.org/ontology/GovernmentCabinet'),
(rc.MemorialMarker, 'http://dbpedia.org/ontology/Memorial'),
(rc.CalendarYear, 'http://dbpedia.org/ontology/Year'),
(rc.Camera, 'http://dbpedia.org/ontology/Camera'),
(rc.MobilePhone, 'http://dbpedia.org/ontology/MobilePhone'),
(rc.HumanResidenceArea, 'http://dbpedia.org/ontology/Agglomeration'),
(rc.Canal, 'http://dbpedia.org/ontology/Canal'),
(rc.PlayboyModel, 'http://dbpedia.org/ontology/PlayboyPlaymate'),
(rc.FactoryBuilding, 'http://dbpedia.org/ontology/Factory'),
(rc.Valley, 'http://dbpedia.org/ontology/Valley'),
(rc.Cape_Topographical, 'http://dbpedia.org/ontology/Cape'),
(rc.CarRaceTrack, 'http://dbpedia.org/ontology/Racecourse'),
(rc.RaceTrack, 'http://dbpedia.org/ontology/RaceTrack'),
(rc.RomanCatholicCardinal, 'http://dbpedia.org/ontology/Cardinal'),
(rc.Cartoon, 'http://dbpedia.org/ontology/Cartoon'),
(rc.Cartoon, 'http://dbpedia.org/ontology/HollywoodCartoon'),
(rc.CartoonCharacter, 'http://dbpedia.org/ontology/ComicsCharacter'),
(rc.CartoonCharacter, 'http://dbpedia.org/ontology/AnimangaCharacter'),
(rc.CartoonCharacter, 'http://dbpedia.org/ontology/DisneyCharacter'),
(rc.CartoonCharacter, 'http://dbpedia.org/ontology/NarutoCharacter'),
(rc.Cartoonist, 'http://dbpedia.org/ontology/ComicsCreator'),
(rc.Casino, 'http://dbpedia.org/ontology/Casino'),
(rc.Castle, 'http://dbpedia.org/ontology/Castle'),
(rc.Catalog, 'http://dbpedia.org/ontology/ArtistDiscography'),
(rc.Caterer_Person, 'http://dbpedia.org/ontology/Caterer'),
(rc.Church_Building, 'http://dbpedia.org/ontology/Church'),
(rc.HorsebackRiding, 'http://dbpedia.org/ontology/HorseRiding'),
(rc.Celebrity, 'http://dbpedia.org/ontology/Celebrity'),
(rc.Celebrity_Political, 'http://dbpedia.org/ontology/PoliticianSpouse'),
(rc.CelestialBody, 'http://dbpedia.org/ontology/CelestialBody'),
(rc.Polysaccharide, 'http://dbpedia.org/ontology/Polysaccharide'),
(rc.Mollusk, 'http://dbpedia.org/ontology/Mollusca'),
(rc.Cycad, 'http://dbpedia.org/ontology/Cycad'),
(rc.MusicalComposition_Classical,
'http://dbpedia.org/ontology/ClassicalMusicComposition'),
(rc.Politician, 'http://dbpedia.org/ontology/Politician'),
(rc.Tunnel, 'http://dbpedia.org/ontology/Tunnel'),
(rc.Tunnel, 'http://dbpedia.org/ontology/RailwayTunnel'),
(rc.Tunnel, 'http://dbpedia.org/ontology/RoadTunnel'),
(rc.Tunnel, 'http://dbpedia.org/ontology/WaterwayTunnel'),
(rc.HolyRomanEmperor, 'http://dbpedia.org/ontology/RomanEmperor'),
(rc.Chart, 'http://dbpedia.org/ontology/ChartsPlacements'),
(rc.Infographic, 'http://dbpedia.org/ontology/ElectionDiagram'),
(rc.Chef, 'http://dbpedia.org/ontology/Chef'),
(rc.UNESCOWorldHertitageSite,
'http://dbpedia.org/ontology/SiteOfSpecialScientificInterest'),
(rc.UNESCOWorldHertitageSite,
'http://dbpedia.org/ontology/WorldHeritageSite'),
(rc.Minister_Governmental, 'http://dbpedia.org/ontology/VicePrimeMinister'),
(rc.Marriage_Agreement, 'http://dbpedia.org/ontology/Marriage'),
(rc.Divorce, 'http://dbpedia.org/ontology/Divorce'),
(rc.Christianity, 'http://dbpedia.org/ontology/ChristianDoctrine'),
(rc.Historian, 'http://dbpedia.org/ontology/Historian'),
(rc.Historian, 'http://dbpedia.org/ontology/Egyptologist'),
(rc.LocalReligiousCongregation, 'http://dbpedia.org/ontology/Parish'),
(rc.MovingImage, 'http://dbpedia.org/ontology/MovingImage'),
(rc.Mayor, 'http://dbpedia.org/ontology/Mayor'),
(rc.TradeUnion, 'http://dbpedia.org/ontology/TradeUnion'),
(rc.Satellite, 'http://dbpedia.org/ontology/ArtificialSatellite'),
(rc.Comedian, 'http://dbpedia.org/ontology/Comedian'),
(rc.Comedian, 'http://dbpedia.org/ontology/Humorist'),
(rc.CoalField_Developed, 'http://dbpedia.org/ontology/CoalPit'),
(rc.College, 'http://dbpedia.org/ontology/College'),
(rc.CollegeCoach, 'http://dbpedia.org/ontology/CollegeCoach'),
(rc.PropositionalConceptualWork_DramaGenre,
'http://dbpedia.org/ontology/Drama'),
(rc.ComicalMode, 'http://dbpedia.org/ontology/Comic'),
(rc.ComedyTeam, 'http://dbpedia.org/ontology/ComedyGroup'),
(rc.ComicBookSeries, 'http://dbpedia.org/ontology/Comics'),
(rc.ComicBookSeries, 'http://dbpedia.org/ontology/Manhua'),
(rc.ComicBookSeries, 'http://dbpedia.org/ontology/Manhwa'),
(rc.ComicStrip, 'http://dbpedia.org/ontology/ComicStrip'),
(rc.InternationalOrganization,
'http://dbpedia.org/ontology/InternationalOrganisation'),
(rc.ConflictEvent, 'http://dbpedia.org/ontology/MilitaryConflict'),
(rc.ComplexQuantityPredicate,
'http://dbpedia.org/ontology/GrossDomesticProduct'),
(rc.ComplexQuantityPredicate,
'http://dbpedia.org/ontology/GrossDomesticProductPerCapita'),
(rc.Executive_PublicOfficial, 'http://dbpedia.org/ontology/Lieutenant'),
(rc.Linguist, 'http://dbpedia.org/ontology/Linguist'),
(rc.ConcentrationCamp, 'http://dbpedia.org/ontology/ConcentrationCamp'),
(rc.Convention_Meeting, 'http://dbpedia.org/ontology/Convention'),
(rc.Contest, 'http://dbpedia.org/ontology/Contest'),
(rc.Continent, 'http://dbpedia.org/ontology/Continent'),
(rc.TimeInterval, 'http://dbpedia.org/ontology/TimePeriod'),
(rc.TimeInterval, 'http://dbpedia.org/ontology/YearInSpaceflight'),
(rc.Insurgency, 'http://dbpedia.org/ontology/Rebellion'),
(rc.CountySeat, 'http://dbpedia.org/ontology/CountrySeat'),
(rc.CourtCase_Appellate,
'http://dbpedia.org/ontology/SupremeCourtOfTheUnitedStatesCase'),
(rc.Statistics, 'http://dbpedia.org/ontology/Statistic'),
(rc.MusicalPerformer, 'http://dbpedia.org/ontology/ClassicalMusicArtist'),
(rc.MusicalPerformer, 'http://dbpedia.org/ontology/MusicalArtist'),
(rc.Crater, 'http://dbpedia.org/ontology/Crater'),
(rc.Crater, 'http://dbpedia.org/ontology/LunarCrater'),
(rc.Creek, 'http://dbpedia.org/ontology/Creek'),
(rc.CricketField, 'http://dbpedia.org/ontology/CricketGround'),
(rc.CricketTeam, 'http://dbpedia.org/ontology/CricketTeam'),
(rc.SystemOfWrittenMaterials, 'http://dbpedia.org/ontology/LiteraryGenre'),
(rc.Fern, 'http://dbpedia.org/ontology/Fern'),
(rc.PoliticalAction, 'http://dbpedia.org/ontology/PoliticalFunction'),
(rc.Demographics, 'http://dbpedia.org/ontology/Demographics'),
(rc.DepthPerception, 'http://dbpedia.org/ontology/Depth'),
(rc.Mine_ExcavationFacility, 'http://dbpedia.org/ontology/Mine'),
(rc.DigitalCamera, 'http://dbpedia.org/ontology/DigitalCamera'),
(rc.Dike, 'http://dbpedia.org/ontology/Dike'),
(rc.Diploma, 'http://dbpedia.org/ontology/Diploma'),
(rc.Prefecture, 'http://dbpedia.org/ontology/Prefecture'),
(rc.Ginkgo, 'http://dbpedia.org/ontology/Ginkgo'),
(rc.Vein, 'http://dbpedia.org/ontology/Vein'),
(rc.DwarfStar, 'http://dbpedia.org/ontology/BrownDwarf'),
(rc.King_HeadOfState, 'http://dbpedia.org/ontology/PolishKing'),
(rc.PyramidMonument, 'http://dbpedia.org/ontology/Pyramid'),
(rc.ElementStuff, 'http://dbpedia.org/ontology/ChemicalElement'),
(rc.Embryology, 'http://dbpedia.org/ontology/Embryology'),
(rc.Skyscraper, 'http://dbpedia.org/ontology/Skyscraper'),
(rc.Employer, 'http://dbpedia.org/ontology/Employer'),
(rc.Zoologist, 'http://dbpedia.org/ontology/Entomologist'),
(rc.PopulationOfType_Organism_Whole,
'http://dbpedia.org/ontology/Population'),
(rc.Escalator, 'http://dbpedia.org/ontology/Escalator'),
(rc.Train, 'http://dbpedia.org/ontology/Train'),
(rc.Planet, 'http://dbpedia.org/ontology/Planet'),
(rc.ExurbanNeighborhood, 'http://dbpedia.org/ontology/Intercommunality'),
(rc.SoccerCompetition, 'http://dbpedia.org/ontology/SoccerTournament'),
(rc.WrestlingSportsEvent, 'http://dbpedia.org/ontology/WrestlingEvent'),
(rc.GenreTypes, 'http://dbpedia.org/ontology/Genre'),
(rc.Farmer, 'http://dbpedia.org/ontology/Farmer'),
(rc.Guitar, 'http://dbpedia.org/ontology/Guitar'),
(rc.FilmFestival, 'http://dbpedia.org/ontology/FilmFestival'),
(rc.Flooding, 'http://dbpedia.org/ontology/StormSurge'),
(rc.ForeignOffice, 'http://dbpedia.org/ontology/OverseasDepartment'),
(rc.FormulaOneRacer, 'http://dbpedia.org/ontology/FormulaOneRacer'),
(rc.FortTheShelterRegion, 'http://dbpedia.org/ontology/Fort'),
(rc.WineTypeByRegion,
'http://dbpedia.org/ontology/ControlledDesignationOfOriginWine'),
(rc.TVShowHost, 'http://dbpedia.org/ontology/TelevisionHost'),
(rc.GatedCommunity, 'http://dbpedia.org/ontology/GatedCommunity'),
(rc.SocialGroup, 'http://dbpedia.org/ontology/Group'),
(rc.GeneralManager_SportsTeam, 'http://dbpedia.org/ontology/SportsManager'),
(rc.GeneralManager_SportsTeam, 'http://dbpedia.org/ontology/SoccerManager'),
(rc.GeographicalDirection_General,
'http://dbpedia.org/ontology/CardinalDirection'),
(rc.Prehistoric, 'http://dbpedia.org/ontology/PrehistoricalPeriod'),
(rc.HotSpring, 'http://dbpedia.org/ontology/HotSpring'),
(rc.GnetopsidaClass, 'http://dbpedia.org/ontology/Gnetophytes'),
(rc.Musical, 'http://dbpedia.org/ontology/Musical'),
(rc.GolfTournament, 'http://dbpedia.org/ontology/GolfTournament'),
(rc.StateGovernor, 'http://dbpedia.org/ontology/Governor'),
(rc.Grape, 'http://dbpedia.org/ontology/Grape'),
(rc.GraveMarker, 'http://dbpedia.org/ontology/GraveMonument'),
(rc.GreenAlgae, 'http://dbpedia.org/ontology/GreenAlga'),
(rc.Mill_ManufacturingFacility, 'http://dbpedia.org/ontology/Mill'),
(rc.Guitarist, 'http://dbpedia.org/ontology/Guitarist'),
(rc.Play, 'http://dbpedia.org/ontology/Play'),
(rc.Organ_MusicalInstrument, 'http://dbpedia.org/ontology/Organ'),
(rc.HeraldicDevice, 'http://dbpedia.org/ontology/Blazon'),
(rc.HistoricBuilding, 'http://dbpedia.org/ontology/HistoricBuilding'),
(rc.RailwayTramwayCar, 'http://dbpedia.org/ontology/TrainCarriage'),
(rc.HospitalBuilding, 'http://dbpedia.org/ontology/Hospital'),
(rc.HumanTypeByLifeStageType, 'http://dbpedia.org/ontology/PersonalEvent'),
(rc.ShoppingMallBuilding, 'http://dbpedia.org/ontology/ShoppingMall'),
(rc.InformationManagementUse,
'http://dbpedia.org/ontology/InformationAppliance'),
(rc.MassCommunicating, 'http://dbpedia.org/ontology/Media'),
(rc.InternetMovieDatabase, 'http://dbpedia.org/ontology/Imdb'),
(rc.RoadwayJunction, 'http://dbpedia.org/ontology/RoadJunction'),
(rc.TelevisionStation, 'http://dbpedia.org/ontology/TelevisionStation'),
(rc.Jockey, 'http://dbpedia.org/ontology/Jockey'),
(rc.Polyhedron, 'http://dbpedia.org/ontology/Polyhedron'),
(rc.MartialArtsSportsEvent,
'http://dbpedia.org/ontology/MixedMartialArtsEvent'),
(rc.StillImage, 'http://dbpedia.org/ontology/StillImage'),
(rc.LawFirm, 'http://dbpedia.org/ontology/LawFirm'),
(rc.Ligament, 'http://dbpedia.org/ontology/Ligament'),
(rc.LycophytinaSubdivision, 'http://dbpedia.org/ontology/ClubMoss'),
(rc.LymphFluid, 'http://dbpedia.org/ontology/Lymph'),
(rc.Matador, 'http://dbpedia.org/ontology/BullFighter'),
(rc.MathematicalThing, 'http://dbpedia.org/ontology/MathematicalConcept'),
(rc.PornStar, 'http://dbpedia.org/ontology/Pornstar'),
(rc.MediaOrganization, 'http://dbpedia.org/ontology/Broadcaster'),
(rc.MediaOrganization, 'http://dbpedia.org/ontology/BroadcastNetwork'),
(rc.MedicalDatabase, 'http://dbpedia.org/ontology/BiologicalDatabase'),
(rc.ParliamentMember, 'http://dbpedia.org/ontology/MemberOfParliament'),
(rc.Monastery_Residence, 'http://dbpedia.org/ontology/Monastery'),
(rc.Sculptor, 'http://dbpedia.org/ontology/Sculptor'),
(rc.Novel, 'http://dbpedia.org/ontology/Novel'),
(rc.Satellite_HeavenlyBody, 'http://dbpedia.org/ontology/Satellite'),
(rc.Mosque, 'http://dbpedia.org/ontology/Mosque'),
(rc.MotorRacing, 'http://dbpedia.org/ontology/MotorRace'),
(rc.Motorcyclist_Professional, 'http://dbpedia.org/ontology/MotocycleRacer'),
(rc.Motorcyclist_Professional, 'http://dbpedia.org/ontology/MotorcycleRider'),
(rc.Motorcyclist_Professional, 'http://dbpedia.org/ontology/SpeedwayRider'),
(rc.MusicDirector, 'http://dbpedia.org/ontology/MusicDirector'),
(rc.MusicFestival, 'http://dbpedia.org/ontology/MusicFestival'),
(rc.NASCARDriver, 'http://dbpedia.org/ontology/NascarDriver'),
(rc.OlympicCompetition, 'http://dbpedia.org/ontology/OlympicEvent'),
(rc.OlympicCompetition, 'http://dbpedia.org/ontology/OlympicResult'),
(rc.NationalAnthem, 'http://dbpedia.org/ontology/NationalAnthem'),
(rc.NewspaperSeries, 'http://dbpedia.org/ontology/Newspaper'),
(rc.NobelPrize, 'http://dbpedia.org/ontology/NobelPrize'),
(rc.NordicCombinedSportsEvent, 'http://dbpedia.org/ontology/NordicCombined'),
(rc.Note_Document, 'http://dbpedia.org/ontology/Annotation'),
(rc.Novella, 'http://dbpedia.org/ontology/LightNovel'),
(rc.ObjectTypeByStyle, 'http://dbpedia.org/ontology/Fashion'),
(rc.Opera, 'http://dbpedia.org/ontology/Opera'),
(rc.Orphan, 'http://dbpedia.org/ontology/Orphan'),
(rc.Playwright, 'http://dbpedia.org/ontology/PlayWright'),
(rc.Pope, 'http://dbpedia.org/ontology/Pope'),
(rc.PopulatedPlacePart, 'http://dbpedia.org/ontology/SubMunicipality'),
(rc.Windmill, 'http://dbpedia.org/ontology/Windmill'),
(rc.PresidentOfOrganization, 'http://dbpedia.org/ontology/President'),
(rc.PrimeMinister_HeadOfGovernment,
'http://dbpedia.org/ontology/PrimeMinister'),
(rc.ProWrestler, 'http://dbpedia.org/ontology/SumoWrestler'),
(rc.Producer, 'http://dbpedia.org/ontology/Producer'),
(rc.University, 'http://dbpedia.org/ontology/University'),
(rc.PublicWaterSystem, 'http://dbpedia.org/ontology/DistrictWaterBoard'),
(rc.Publisher, 'http://dbpedia.org/ontology/Publisher'),
(rc.Songwriter, 'http://dbpedia.org/ontology/SongWriter'),
(rc.RadioShow, 'http://dbpedia.org/ontology/RadioProgram'),
(rc.RadioStation_Organization, 'http://dbpedia.org/ontology/RadioStation'),
(rc.RadioTalkShowHost, 'http://dbpedia.org/ontology/RadioHost'),
(rc.TalkShowHost, 'http://dbpedia.org/ontology/Host'),
(rc.TalkShowHost, 'http://dbpedia.org/ontology/Presenter'),
(rc.Railway, 'http://dbpedia.org/ontology/RailwayLine'),
(rc.Referee, 'http://dbpedia.org/ontology/Referee'),
(rc.RestArea, 'http://dbpedia.org/ontology/RestArea'),
(rc.Resume, 'http://dbpedia.org/ontology/Resume'),
(rc.RocketEngine, 'http://dbpedia.org/ontology/RocketEngine'),
(rc.Streetcar, 'http://dbpedia.org/ontology/Tram'),
(rc.SabreFencer, 'http://dbpedia.org/ontology/Fencer'),
(rc.Saint, 'http://dbpedia.org/ontology/Saint'),
(rc.Screenwriter, 'http://dbpedia.org/ontology/ScreenWriter'),
(rc.ServiceStation, 'http://dbpedia.org/ontology/FillingStation'),
(rc.Shrine_Religious, 'http://dbpedia.org/ontology/Shrine'),
(rc.SkiArea, 'http://dbpedia.org/ontology/SkiArea'),
(rc.SkiResort_Attraction, 'http://dbpedia.org/ontology/SkiResort'),
(rc.SolarEclipse, 'http://dbpedia.org/ontology/SolarEclipse'),
(rc.SpaceShuttle, 'http://dbpedia.org/ontology/SpaceShuttle'),
(rc.SpaceStation, 'http://dbpedia.org/ontology/SpaceStation'),
(rc.SubwayStation, 'http://dbpedia.org/ontology/MetroStation'),
(rc.Synagogue, 'http://dbpedia.org/ontology/Synagogue'),
(rc.TVCharacter, 'http://dbpedia.org/ontology/SoapCharacter'),
(rc.TVSeason, 'http://dbpedia.org/ontology/TelevisionSeason'),
(rc.TVShow_Single, 'http://dbpedia.org/ontology/TelevisionEpisode'),
(rc.TeamHandballPlayer, 'http://dbpedia.org/ontology/HandballPlayer'),
(rc.TelevisionDirector, 'http://dbpedia.org/ontology/TelevisionDirector'),
(rc.TelevisionStar, 'http://dbpedia.org/ontology/TelevisionPersonality'),
(rc.TheHumanLifeCycle, 'http://dbpedia.org/ontology/LifeCycleEvent'),
(rc.TheatreDirector, 'http://dbpedia.org/ontology/TheatreDirector'),
(rc.TimeInPosition_Served, 'http://dbpedia.org/ontology/TermOfOffice'),
(rc.ToDoList, 'http://dbpedia.org/ontology/TrackList'),
(rc.TransformerSubstation,
'http://dbpedia.org/ontology/ElectricalSubstation'),
(rc.Treadmill, 'http://dbpedia.org/ontology/Treadmill'),
(rc.USRepresentative, 'http://dbpedia.org/ontology/Congressman'),
(rc.VicePresidentOfOrganization, 'http://dbpedia.org/ontology/VicePresident'),
(rc.ViticulturalDomain, 'http://dbpedia.org/ontology/WineRegion'),
(rc.WaterPoweredMill, 'http://dbpedia.org/ontology/Watermill'),
(rc.WaterTower, 'http://dbpedia.org/ontology/WaterTower'),
(rc.WaterwayLock, 'http://dbpedia.org/ontology/Lock'),
(rc.WindPoweredTurbine, 'http://dbpedia.org/ontology/WindMotor'),
(rc.Winery, 'http://dbpedia.org/ontology/Winery'),
(rc.WomensTennisAssociationTournament,
'http://dbpedia.org/ontology/WomensTennisAssociationTournament'),
(rc.WorkQuantity, 'http://dbpedia.org/ontology/UnitOfWork'),
(rc.ZooOrganization, 'http://dbpedia.org/ontology/Zoo'),
(kko.TopicsCategories, 'http://dbpedia.org/ontology/TopicalConcept'),
(kko.Eukaryotes, 'http://dbpedia.org/ontology/Eukaryote'),
(kko.Geopolitical, 'http://dbpedia.org/ontology/AdministrativeRegion')]

Then, we can decompose those results to construct up our format for annotating a s-p-o tuple to get the exact mapping predicate used:

list(kko.mappingAsObject[rc.Currency, rc.dbpedia_ontology_id, 'http://dbpedia.org/ontology/Currency']) 
['owl:equivalentClass']

With some string replacements and shifting the orders, we then can see how we can get a reconstruction of the input rows we used to load the external mappings in the first place, with our example becoming:

  rc.Currency, owl:equivalentClass, http://dbpedia.org/ontology/Currency

(Using ‘rc.’ rather than base IRI in this example.) For the moment, we will defer writing the full routine, but will eventually add it to our extract.py module. We will also embed this code block into a loop that writes our individual mapping files to disk, thereby completing the external mapping portion of our roundtrip.

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site. The cowpoke Python code listing covering the series is also available from GitHub.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Posted by AI3's author, Mike Bergman Posted on October 7, 2020 at 10:02 am in CWPK, KBpedia, Semantic Web Tools | Comments (0)
The URI link reference to this post is: https://www.mkbergman.com/2395/cwpk-49-mapping-external-sources/
The URI to trackback this post is: https://www.mkbergman.com/2395/cwpk-49-mapping-external-sources/trackback/
Posted:October 6, 2020

Bringing Home the Lessons to Date with KBpedia v 3.00

Today’s installment in our Cooking with Python and KBpedia series is a doozy. Not only are we wrapping up perhaps the most important part of our series — building KBpedia from scratch — but we are also applying the full roundtrip software in our cowpoke Python package to a major re-factoring of KBpedia itself. This re-factoring will lead to the next release of KBpedia v. 3.00.

This re-factoring and new release was NOT part of the original plan for this CWPK series. Today’s current efforts were the result of issues we have discovered in the current version 2.50 of KBpedia, the version with which we began this series. The very process we have gone through in developing the cowpoke software to date has surfaced these problems. The problems have been there and perhaps part of KBpedia for some time, but our prior build routines were such that these issues were not apparent. By virtue of different steps and different purposes, we have now seen these things, and now have the extract and build procedures to address them.

It turns out the seven or so problems so identified provide a ‘perfect‘ (in the sense of ‘storm‘) case study for why a roundtrip capability makes sense and how it may be applied. Without further ado, let’s begin.

Summary of the Problem Issues

The cowpoke Python package as we have used to date has surfaced seven types of issues with KBpedia, v. 250, the basis with which we started this CWPK series. Our starting build files for this series are ones extracted from the current public v 250 version. About half of the issues are in the KBpedia knowledge graph, but had remained hidden given the nuances of our prior Clojure build routines. The other half of the issues relate to our new use of Python and owlready2.

These seven issues, with some background explanation, are:

  1. Remove hyphens – in our prior build routines with Clojure, that language has a style that favors dashes (or hyphens) when conjoining words in a label identifier. Python is not hyphen-friendly. While we have not seen issues when working directly with the owlready2 package, there are some Python functions that burp with hyphenated KBpedia identifiers:
print(rc.Chemistry-Topic)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-5566a42d12b4> in <module>
----> 1 print(rc.Chemistry-Topic)

NameError: name 'rc' is not defined
Across class and property identifiers, there are thousands of such hyphenated IDs in KBpedia. We could retain and trap for these instances, but with provisions for current users of KBpedia, we have decided to conform more to the Python underscore style. That would shield other amateurs (such as me) from having to trap for it in any new Python code written to support cowpoke or its knowledge graphs.
  1. Ensure the kko.superClassOf property is moved to an AnnotationProperty. When we want to use the concept of superclass as an object property, we can now use the built-in owlready2 superclass.

  2. Remove OpenCyc href’s – part of KBpedia’s heritage comes from the open-source version of the Cyc ontology, including many initial concept definitions. OCyc distribution and support was ceased in 2017, though the ontology is still referenceable online. Given the receding usefulness of OCyc, we want to remove all of the internal URI references in definitions within KBpedia.

  3. Remove duplicates – one nice aspect of the owlready2 engine is its identification of circular references, but gracefully proceeding with only a warning. Our new build routines have surfaced about ten of these circularities in KBpedia v 250. Two of these, Person ←→ HomoSapiens, and a second, God ←→ Diety, are intended design decisions by us as editors of KBpedia. The other instances, however, are unintended, and ones we want to resolve. We need to remove these.

  4. Remove the SuperType concept and move it to an annotation property – besides being one of the duplicates (see (4) above), our adoption of Charles Sanders Peirce‘s universal categories in the KBpedia Knowledge Ontology (KKO) has supplanted the ‘SuperType’ nomenclature with Generals.

  5. Correct domain and range assignments – our internal specifications had nearly complete domain and range assignments for version 2.50, but apparently during processing were not properly loaded. The fact they were not completely assigned in the public release was missed, and needs to be corrected.

  6. Remove trailing spaces in the prefLabels for properties – the preferred labels for virtually all of the properties in version 250 had trailing spaces, which never were apparent in listings or user interfaces, but did become evident once the labels were parsed for roundtripping.

The latter four problems ((4), (5), (6), (7) ) were prior to cowpoke, having been issues in KBpedia v 250 at time of release. Processing steps and other different aspects of how the builds are handled in Python made these issues much more evident.

The Plan of Attack

Some of these issues make sense to address prior to others. In looking across these needed changes, here is what emerged as the logical plan of attack:

A. Make KKO changes first ((2), (4), and (5))

Since the build process always involves a pre-built KKO knowledge graph, it is the logical first focus if any changes involve it. Three of the seven issues do so, and efforts can not proceed until these are changed. With respect to (5), we will retain the idea of ‘SuperType’ as the root node of an typology, and designate the 80 or such KKO concepts that operate as such with an annotation property. To prevent confusion with Generals, we will also remove the SuperType concept.

B. Make bulk, flat-file changes ((1), (3), (6), (7))

This step in the plan confirms why it is important to have a design with roundtripping and the ability to make bulk changes to input files via spreadsheets. Mass changes involving many hundreds or thousands of records are not feasible with a manually edited knowledge graph. (I know, not necessarily common, but it does arise as this case shows.) It also makes it hard, if not close to impossible, to make substantial modifications or additions to an existing knowledge graph in order to tailor it for your own domain purposes, the reason why we began this CWPK series in the first place. Addressing the four (1), (3), (6), and (7) problem areas will take the longest share of time to create the new version.

One of these options (3) will require us to develop a new, separate routine (see below).

C. Propagate changes to other input files ((1), (2), (4))

With regard to replacing hyphens with underscores (1), this problem not only occurs when a property or class is declared, but all subsequent references to it. To make a global search-and-replace replacement of underscores for hyphens means all build files must be checked and processed. Any time changes are made to key input files (i.e., the ones of the struct variety), it is important to check appropriate other input files for consistency. We also need to maintain a mapping between the two ID forms so changed such that older URIs continue to point to the correct resources.

D. Re-build

Once all input files are modified and checked, we are ready to start the re-build.

General Processing Notes

The basic build process we are following is what was listed in the last installment, CWPK #47, applied in relation to our plan of attack.

I am recording notable observations from the pursuit of these steps. I am also logging time to provide a sense of overall set-up and processing times. There are, however, three areas that warrant separate discussion after this overall section.

As I progress through various steps, I tend to do two things. First, after a major step in the runs I bring up the interim build of KBpedia in Protégé and check to see if the assignments are being made properly. Depending on the nature of the step at-hand, I will look at different things. Second, especially in the early iterations of a build, I may backup my target ontology. Either I do this by stipulating a different output file in the routine, or create a physical file backup directly. Either way, I do this at these early phases to prevent having to go back to Square One with a particular build if the new build step proves a failure. With annotations, for example, revisions are added to what is already in the knowledge graph, as opposed to replacing the existing entries. This may not be the outcome you want.

The changes needed to KKO (A) above are straightforward to implement. We bring KKO into Protégé and make the changes. Only when the KKO baseline meets our requirements do we begin the formal build process.

The hyphen changes (1) were rather simple to do, but affected much in the four input files (two structural, two annotations for classes and properties). Though some identifiers had more than one hyphen, there were more than 7 K replacements for classes, and more than 13 K replacements for properties, for a total exceeding 20 K replacements across all build files (this amount will go up as we subsequently bring in the mappings to external sources as well; see next installment). I began with the structure files, since they have fewer fields and there were some open tasks on processing specific annotations.

This is a good example of a bulk move with a spreadsheet (see CWPK #36). Since there are fields such as alternative labels or definitions for which hyphens or dashes are fine, we do not want to do a global search-and-replace for underscores. Using the spreadsheet, the answer is to highlight the columns of interest (while using the menu-based search and replace) and only replace within the highlighted selection. If you make a mistake, Undo.

At the same time, I typically assign a name to the major block on the spreadsheet and then sort on various fields (columns) to check for things like open entries, strange characters (that often appear at the top or bottom of sorts), fields that improperly split in earlier steps (look for long ones), or other patterns to which your eye rapidly finds. If I EVER find an error, I try to fix it right then and there. It slows first iterations, but, over time, always fixing problems as discovered leads to cleaner and cleaner inputs.

Starting with the initial class backbone file (Generals_struct_out.csv) and routine (class_struct_builder), after getting the setting configurations set, I begin the run. It fails. This is actually to be expected, since it is an occasion worthy of celebration when a given large routine runs to completion without error on its first try!

On failures, one of the nice things about Python is a helpful ‘traceback’ on where the error occurred. Since we are processing tens of thousands of items at this class build point, we need to pinpoint in the code where the fail was occurring and add some print statements, especially ones that repeat to screen what items are currently going through the processing loop at the point of fail. Then, when you run again, you can see where in your input file the error likely occurs. Then, go back to the input file, and make the correction there.

Depending on the scope of your prior changes, these start-and-stop iterations of run-fail-inspect-correct may occur multiple times. You will eventually work your way through the input file if you are unlucky. But, you perhaps may not even notice any of this if you are lucky! (Of course, these matters are really not so much a matter of luck, since outcomes are improved by attention to detail.)

After a couple of iterations of minor corrections, first the classes and then the properties load properly with all sub- relationships intact. Pretty cool! I can smell the finish line.

In the shift to annotations, I basically wanted to load what had previously been tested and ingested without problems, and then concentrate on the new areas. The class annotation uploads went smoothly (only one hiccup for a mis-labeled resource). Great, so I can now take a quick detour to get rid of the superfluous links to OCyc (3) before facing the final step of bringing in the property annotations.

Another Cleaning Task

Before we can complete the third of our build steps involving the class_annot_builder function, we set for ourselves the removal of the open-source Cyc (OCyc) internal links in definitions. These all have the form of:

  \<\a href="http://sw.opencyc.org/concept/Mx4rvVjk55wpEbGdrcN5Y29ycA">IndependentCountry\<\/a>

My desire is to remove all of the href link markup, but leave the label text between the <\a\> tags. I know I can use regular expressions to recognize a sub-string like the above, but I am no more than a toddler when it comes to formulating regex. Like many other areas in Python, I begin a search for modules that may make this task a bit easier.

I soon discovered there are multiple approaches, and my quick diligence suggests either the beautifulsoup or bleach modules may be best suited. I make the task slightly more complicated by wanting to limit the removal to OCyc links only, and to leave all other href’s.

I chose beautifulsoup because it is a widely used and respected library for Web scraping and many data processing tasks. I also realized this was a one-off occasion, so while I did write a routine, I chose not to include it in the utils module. I also excised the ‘definitions’ column from our input files, made the changes to it, and then uploaded the changes. In this manner, I was able to sidestep some of the general file manipulation requirements that a more commonly used utility would demand. Here is the resulting code:

import csv
from bs4 import BeautifulSoup                                    # Part of the Anaconda distro

in_file = 'C:/1-PythonProjects/kbpedia/v300/build_ins/working/def_old.csv'
out_file = 'C:/1-PythonProjects/kbpedia/v300/build_ins/working/def_new.csv'

output = open(out_file, 'w+', encoding='utf8', newline='')
x = 0
with open(in_file, 'r', encoding='utf8') as f:
    reader = csv.reader(f)
    for row in reader:
        line = str(row)
        soup = BeautifulSoup(line)                               # You can feed bs4 with lines, docs, etc.
        tags = soup.select('a[href^="http://sw.opencyc.org/"]')  # The key for selecting out the OCyc stuff
        if tags != []:
            for item in tags:                                    # Some entries have no tags, others a few
                item.unwrap()                                    # The main method for getting the text within tags
                item_text = soup.get_text()                      # The text after tags removed
        else:
            item_text = line
        item_text = item_text.replace("['","")                   # A bunch of 'hacky' cleanup of the output
        item_text = item_text.replace("']","")
        item_text = item_text.replace('["', '')
        item_text = item_text.replace('"]', '')
        item_text = item_text.replace("', '", ",")
        print(item_text)
        print(item_text, file=output)
        x = x + 1
    print(x, 'total items processed.')
    output.close()
    print('Definition modifications are complete.')

Figuring out this routine took more time than I planned. Part of the reason is that the ‘definitions’ in KBpedia are the longest and most complicated strings, with many clauses and formatting and quoted sections. So I had quoting conflicts that caused some of the 58 K entries to skip or combine with other lines. I wanted to make sure the correspondence was kept accurate. Another issue was figuring out the exact beautifulsoup syntax for identifying the specific OCyc links (with variable internal references) and extracting out the internal text for the link.

Nonetheless, beautifulsoup is a powerful utility, and I am glad I spent some time learning how to get to first twitch with it.

Updates to Domain and Range

Since the earlier version (2.50) of KBpedia did not have proper loads of domain and range, once I re-established those specifications I foresaw that ingest of these fields might be a problem. The reasons for this supposition are the variety of data types that one might encounter, plus we were dealing with object and data properties, which have a bit more structure and stronger semantics, as well as annotations, which pose different issues in language checks and longer strings.

I was not surprised, then, when this step proved to be the most challenging of the update.

First, indeed, there were more domain and range options as this revised routine indicates (compare to the smaller version in CWPK #47:

### KEY CONFIG SETTINGS (see build_deck in config.py) ###                  
# 'kb_src'        : 'standard'                                        
# 'loop_list'     : file_dict.values(),                           # see 'in_file'
# 'loop'          : 'property_loop',
# 'in_file'       : 'C:/1-PythonProjects/kbpedia/v300/build_ins/properties/prop_annot_out.csv',
# 'out_file'      : 'C:/1-PythonProjects/kbpedia/v300/target/ontologies/kbpedia_reference_concepts.csv',

def prop_annot_build(**build_deck):
    print('Beginning KBpedia property annotation build . . .')
    xsd = kb.get_namespace('http://w3.org/2001/XMLSchema#')
    wgs84 = kb.get_namespace('http://www.opengis.net/def/crs/OGC/1.3/CRS84')    
    loop_list = build_deck.get('loop_list')
    loop = build_deck.get('loop')
    out_file = build_deck.get('out_file')
    x = 1
    if loop is not 'property_loop':
        print("Needs to be a 'property_loop'; returning program.")
        return
    for loopval in loop_list:
        print('   . . . processing', loopval) 
        in_file = loopval
        with open(in_file, 'r', encoding='utf8') as input:
            is_first_row = True
            reader = csv.DictReader(input, delimiter=',', fieldnames=['id', 'prefLabel', 'subPropertyOf', 'domain',  
                                   'range', 'functional', 'altLabel', 'definition', 'editorialNote'])                 
            for row in reader:
                r_id = row['id']                
                r_pref = row['prefLabel']
                r_dom = row['domain']
                r_rng = row['range']
                r_alt = row['altLabel']
                r_def = row['definition']
                r_note = row['editorialNote']
                r_id = r_id.replace('rc.', '')
                id = getattr(rc, r_id)
                if id == None:
                    continue
                if is_first_row:                                       
                    is_first_row = False
                    continue
                id.prefLabel.append(r_pref)
                i_dom = r_dom.split('||')
                if i_dom != ['']: 
                    for item in i_dom:                            # We need to accommodate different namespaces           
                        if 'kko.' in item:
                            item = item.replace('kko.', '')
                            item = getattr(kko, item)
                            id.domain.append(item) 
                        elif 'owl.' in item:
                            item = item.replace('owl.', '')
                            item = getattr(owl, item)
                            id.domain.append(item)
                        elif item == ['']:
                            continue    
                        elif item != '':
                            item = getattr(rc, item)
                            if item == None:
                                continue
                            else:
                                id.domain.append(item) 
                        else:
                            print('No domain assignment:', 'Item no:', x, item)
                            continue                             
                if 'owl.' in r_rng:                               # A tremendous number of range options   
                    r_rng = r_rng.replace('owl.', '')             # xsd datatypes are only partially supported
                    r_rng = getattr(owl, r_rng)
                    id.range.append(r_rng)
                elif 'string' in r_rng:    
                    id.range = [str]
                elif 'decimal' in r_rng:
                    id.range = [float]
                elif 'anyuri' in r_rng:
                    id.range = [normstr]
                elif 'boolean' in r_rng:    
                    id.range = [bool]
                elif 'datetime' in r_rng:    
                    id.range = [datetime.datetime]   
                elif 'date' in r_rng:    
                    id.range = [datetime.date]      
                elif 'time' in r_rng:    
                    id.range = [datetime.time] 
                elif 'wgs84.' in r_rng:
                    r_rng = r_rng.replace('wgs84.', '')
                    r_rng = getattr(wgs84, r_rng)
                    id.range.append(r_rng)        
                elif r_rng == ['']:
                    print('r_rng = empty:', r_rng)
                else:
                    print('r_rng = else:', r_rng, id)
#                    id.range.append(r_rng)
                i_alt = r_alt.split('||')    
                if i_alt != ['']: 
                    for item in i_alt:
                        id.altLabel.append(item)
                id.definition.append(r_def)        
                i_note = r_note.split('||')
                if i_note != ['']:   
                    for item in i_note:
                        id.editorialNote.append(item)
                x = x + 1        
    kb.save(out_file, format="rdfxml") 
    print('KBpedia property annotation build is complete.')

Second, a number of the range types — xsd.anyURI, xsd.hexBinary, and wgs84 — are not supported internally by owlready2, and there is no facility to add them directly to the system. I have made outreach to the responsive developer of owlready2, Jean-Baptiste Lamy, to see whether we can fill this gap before we go live with KBpedia v. 300. (Update: Within two weeks, Jean-Baptiste responded with a fix and new definition capabilities.) Meanwhile, there are relatively few instances of this gap, so we are in pretty good shape to move forward as is. Only a handful of resources are affected by these gaps, out of a total of 58 K.

URI Changes

The changing of an identifier for a knowledge graph resource is not encouraged. Most semantic technology advice is simply to pick permanent or persistent URIs. There is thus little discussion or guidance as to what is best practice when an individual resource ID does need to change. Our change from hyphens to underscores (1) is one such example of when an ID needs to change.

The best point of intervention is at the Web server, since our premise for knowledge graphs is Web-accessible information obtained via (generally) HTTP. While we could provide internal knowledge graph representations to capture the mapping between old and new URIs, an external request in the old form still needs to get a completion response for the new form. The best way to achieve that is via content negotiation by the server.

Under circumstances where prior versions of your knowledge graph were in broad use, the recommended approach would be to follow the guidelines of the W3C (the standards-setting body for semantic technologies) for how to publish a semantic Web vocabulary. This guidance is further supplemented with recipes for how to publish linked data under the rubric of ‘cool URIs‘. Following these guidances is much easier than updating URIs in place.

However, because of decisions yet to be documented to not implement linked data (see CWPK #60 when it is published in about three weeks), the approach we will be taking is much simpler. We will generate a mapping (correspondence) file between the older, retired URIs (the ones with the hyphens) with the new URIs (the ones with the underscores). We will announce this correspondence file at time of v 300 release, which we have earmarked to occur at the conclusion of this CWPK series. The responsibility for URI updates, if needed, will be placed on existing KBpedia users. This decision violates the recommended best practice of never changing URIs, but we deem it manageable based on our current user base and their willingness to make those modifications directly. Posting this correspondence file will be one of the last steps before KBpedia v 300 goes fully ‘live’.

So, we completed the full build, but kept a copy of the one-step-last-removed to return to if (when) we get a better processing of range.

The effort was greater than I anticipated. Actual processing time for a full re-build across all steps was about 90 min. There was perhaps another 8-12 hrs in working through developing the code and solving (or mostly so) the edge cases.

This is the first time I have done this re-build process with Python, but it is a process I have used and learned to improve for nearly a decade. I’m pretty pleased about the build process itself, but am absolutely thrilled with the learning that has taken place to give me tools at-hand. I’m feeling really positive about how this CWPK series is unfolding.

Part IV Conclusion

This brings to a close Part IV in our CWPK series. When I first laid out the plan for this series, I told myself that eventual public release of the series and its installments depended on being able to fully ’roundtrip’ KBpedia. I was somewhat confident setting out that this milestone could be achieved. Today, I know it to be so, and so now can begin the next steps of releasing the installments and their accompanying Jupyter Notebook pages. Successfully achieving the roundtrip milestone in this objective means we began to publish the start of our CWPK series on July 27, 2020. Woohoo!

In terms of the overall plan, we are about 2/3 of the way through the entire anticipated series. We next tackle the remaining steps in completing a full, public release of the knowledge graph. Then, we use the completed KBpedia v 300 to put the knowledge graph through its paces, doing some analysis, some graphing, and some machine learning. As of this moment in time, we have a target of 75 total installments in this Cooking with Python and KBpedia series, which we hope to wrap up by mid-November or so. Please keep with us for the journey!

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site. The cowpoke Python code listing covering the series is also available from GitHub.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Posted by AI3's author, Mike Bergman Posted on October 6, 2020 at 10:32 am in CWPK, KBpedia, Semantic Web Tools | Comments (0)
The URI link reference to this post is: https://www.mkbergman.com/2394/cwpk-48-case-study-a-sweeping-refactoring/
The URI to trackback this post is: https://www.mkbergman.com/2394/cwpk-48-case-study-a-sweeping-refactoring/trackback/