{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "163b4597", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "try:\n", " import IPython\n", "except:\n", " %pip install IPython\n", " import IPython \n", "from IPython.display import display, IFrame, HTML, Javascript\n", "from IPython.core.display import display, HTML\n", "\n", "HTML(\"\"\"\"\"\")\n", "\n" ] }, { "cell_type": "markdown", "id": "11e94730", "metadata": {}, "source": [ "# Collections Data to Linked Art \n", "# Cleveland Museum of Art - Simplified\n", "\n", "This notebook provides a guided step through the process of transforming Cultural Heritage collections data to Linked Art JSON-LD." ] }, { "cell_type": "markdown", "id": "c0e616a9", "metadata": {}, "source": [ "## Transform Collections Data to Linked Art \n", "\n", "### Read Input Data\n", "\n", "- The first step is to read in the collections data. For this notebook the data has been sourced from the Cleveland Museum of Art GitHub repository. \n", "- There is a small admin step to remove Byte Order Mark (BOM) characters from the input file. The data are in CSV format. \n", "- The following code reads the file and displays the first row from the CSV file.\n", "\n", "#### Further Reading\n", "- Cleveland Museum of Art https://www.clevelandart.org\n", "- Cleveland Museum of Art GitHub repository https://github.com/ClevelandMuseumArt/openaccess\n", "- Byte Order Mark https://en.wikipedia.org/wiki/Byte_order_mark\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "cf022629", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idaccession_numbershare_license_statustombstonecurrent_locationtitletitle_in_original_languageseriesseries_in_original_languagecreation_date...digital_descriptionwall_descriptionexternal_resourcescitationscatalogue_raisonneurlimage_webimage_printimage_fullupdated_at
0745392015.449CC0A Miller's Carriage, c. 1895. Albert-Charles L...NaNA Miller's CarriageNaNNaNNaNc. 1895...NaNNaN{'wikidata': [], 'internet_archive': ['https:/...NaNNaNhttps://clevelandart.org/art/2015.449https://openaccess-cdn.clevelandart.org/2015.4...https://openaccess-cdn.clevelandart.org/2015.4...https://openaccess-cdn.clevelandart.org/2015.4...2021-06-29 06:35:50.572000
\n", "

1 rows × 41 columns

\n", "
" ], "text/plain": [ " id accession_number share_license_status \\\n", "0 74539 2015.449 CC0 \n", "\n", " tombstone current_location \\\n", "0 A Miller's Carriage, c. 1895. Albert-Charles L... NaN \n", "\n", " title title_in_original_language series \\\n", "0 A Miller's Carriage NaN NaN \n", "\n", " series_in_original_language creation_date ... digital_description \\\n", "0 NaN c. 1895 ... NaN \n", "\n", " wall_description external_resources \\\n", "0 NaN {'wikidata': [], 'internet_archive': ['https:/... \n", "\n", " citations catalogue_raisonne url \\\n", "0 NaN NaN https://clevelandart.org/art/2015.449 \n", "\n", " image_web \\\n", "0 https://openaccess-cdn.clevelandart.org/2015.4... \n", "\n", " image_print \\\n", "0 https://openaccess-cdn.clevelandart.org/2015.4... \n", "\n", " image_full \\\n", "0 https://openaccess-cdn.clevelandart.org/2015.4... \n", "\n", " updated_at \n", "0 2021-06-29 06:35:50.572000 \n", "\n", "[1 rows x 41 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "try:\n", " import pandas as pd\n", "except:\n", " %pip install pandas\n", " import pandas as pd\n", " \n", "\n", "file = './data/cma/input/data.csv'\n", "\n", "#remove BOM\n", "s = open(file, mode='r', encoding='utf-8-sig').read()\n", "open(file, mode='w', encoding='utf-8').write(s)\n", "\n", "mpg = pd.read_csv(file,nrows=1,low_memory=False)\n", "mpg.head()" ] }, { "cell_type": "markdown", "id": "6cccc82e", "metadata": {}, "source": [ "### Convert CSV to Python dictionary \n", "\n", "The Python `csv` module (including csv.DictReader) is used to read the CSV file and create an object that maps the information in each row to a dict whose keys are fieldnames. An example record in the `dict` object is shown below. You'll note that the fields names are now dictionary keys.\n", "\n", "---- \n", "##### Further reading\n", "\n", "Python CSV module https://docs.python.org/3/library/csv.html" ] }, { "cell_type": "code", "execution_count": 3, "id": "1a9babfc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"id\": \"74539\",\n", " \"accession_number\": \"2015.449\",\n", " \"share_license_status\": \"CC0\",\n", " \"tombstone\": \"A Miller's Carriage, c. 1895. Albert-Charles Lebourg (French, 1849-1928). Black and white chalk with stumping ; sheet: 33.2 x 49.7 cm (13 1/16 x 19 9/16 in.). The Cleveland Museum of Art, Bequest of Muriel Butkin 2015.449\",\n", " \"current_location\": \"\",\n", " \"title\": \"A Miller's Carriage\",\n", " \"title_in_original_language\": \"\",\n", " \"series\": \"\",\n", " \"series_in_original_language\": \"\",\n", " \"creation_date\": \"c. 1895\",\n", " \"creation_date_earliest\": \"1890\",\n", " \"creation_date_latest\": \"1900\",\n", " \"creators\": \"Albert-Charles Lebourg (French, 1849-1928), artist\",\n", " \"culture\": \"France, 19th-20th century\",\n", " \"technique\": \"Black and white chalk with stumping \",\n", " \"support_materials\": \"gray laid paper\",\n", " \"department\": \"Drawings\",\n", " \"collection\": \"DR - French\",\n", " \"type\": \"Drawing\",\n", " \"measurements\": \"Sheet: 33.2 x 49.7 cm (13 1/16 x 19 9/16 in.)\",\n", " \"state_of_the_work\": \"\",\n", " \"edition_of_the_work\": \"\",\n", " \"creditline\": \"Bequest of Muriel Butkin\",\n", " \"copyright\": \"\",\n", " \"inscriptions\": \"Verso: upper right in green ink: 80355 / circular estate stamp (Lugt 1664b) \",\n", " \"exhibitions\": \" **LEGACY: Exposition de Lebourg, Mus\\u00e9e de Rouen, 1932\",\n", " \"provenance\": \"\",\n", " \"find_spot\": \"\",\n", " \"related_works\": \"\",\n", " \"former_accession_numbers\": \"[]\",\n", " \"fun_fact\": \"\",\n", " \"digital_description\": \"\",\n", " \"wall_description\": \"\",\n", " \"external_resources\": \"{'wikidata': [], 'internet_archive': ['https://archive.org/details/clevelandart-2015.449-a-miller-s-carriage']}\",\n", " \"citations\": \"\",\n", " \"catalogue_raisonne\": \"\",\n", " \"url\": \"https://clevelandart.org/art/2015.449\",\n", " \"image_web\": \"https://openaccess-cdn.clevelandart.org/2015.449/2015.449_web.jpg\",\n", " \"image_print\": \"https://openaccess-cdn.clevelandart.org/2015.449/2015.449_print.jpg\",\n", " \"image_full\": \"https://openaccess-cdn.clevelandart.org/2015.449/2015.449_full.tif\",\n", " \"updated_at\": \"2021-06-29 06:35:50.572000\"\n", "}\n" ] } ], "source": [ "\n", "try:\n", " import csv\n", "except:\n", " %pip install csv\n", " import csv\n", "\n", "try:\n", " import json\n", "except:\n", " %pip install json\n", " import json \n", " \n", "\n", "allObjects = csv.DictReader(open(file, mode='r',encoding='utf-8'))\n", "\n", "for obj in allObjects:\n", " print(json.dumps(obj,indent=2))\n", " break " ] }, { "cell_type": "markdown", "id": "db2ff2f8", "metadata": {}, "source": [ "### Create field mapping\n", "\n", "The next step involves a manual mapping process where entities in the collections data are mapped to their corresponding representation in Linked Art.\n", "\n", "This is achieved with a python dictionary `mapp`, where the field names in the input data are mapped to variable names that are used later in a mapping/transformation function.\n", "\n", "The `mapp` dictionary is shown below and also shown in table format beneath: \n", "- keys are the variables used in mapping functions\n", "- values are the input data field names" ] }, { "cell_type": "code", "execution_count": 4, "id": "f137b0c6", "metadata": {}, "outputs": [], "source": [ "mapp = {\n", " \"id\":\"id\",\n", " \"accession_number\":\"accession_number\",\n", " \"accession_date\": \"\",\n", " \"classification\" : \"type\",\n", " \"title\": \"title\",\n", " \"alt_title\": \"title_in_original_language\",\n", " \"notes\": \"tombstone\",\n", " \"date_created\":\"creation_date\",\n", " \"date_created_earliest\": \"creation_date_earliest\",\n", " \"date_created_latest\": \"creation_date_latest\",\n", " \"created_period\":\"culture\",\n", " \"created_dynasty\":\"\",\n", " \"created_inscriptions\":\"inscriptions\",\n", " \"created_notes\": \"fun_fact\",\n", " \"creator\":\"creators\",\n", " \"physical_medium\": \"Medium\",\n", " \"physical_style\": \"\",\n", " \"physical_technique\": \"technique\",\n", " \"physical_description\": \"\",\n", " \"physical_dimensions\": \"measurements\",\n", " \"created_provenance\": \"provenance\" ,\n", " \"credit_line\": \"creditline\",\n", " \"collection\" : \"department\",\n", " \"current_status\" : \"current_location\",\n", " \"current_location\": \"current_location\",\n", " \"homepage\": \"url\"\n", " }" ] }, { "cell_type": "markdown", "id": "5225bdbd", "metadata": {}, "source": [ "### Use the mapping to create an artwork property dictionary\n", "\n", "The `mapp` dictionary will now be used, together with the collection data, to create a dictionary containing a key:value pair for an artwork described in the collection data, where the key is the variable name used in a transformation function later on, and the value is the collection data property value for the artwork.\n", "\n", "\n", "The process involves:\n", "- Iteration through the collection data dictionary `mapp` \n", "- create a dictionary `objProp` with the artwork properties mapped with call to `createObjProp` \n", "\n", "An example of the resulting dictionary `objProp` can be viewed in a table below.\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "a23cc7f7", "metadata": {}, "outputs": [], "source": [ "def createObjProp(obj,mapp):\n", " objProp = {}\n", " csv_keys = list(obj.keys())\n", " for key in csv_keys:\n", " for prop in mapp:\n", " if key == mapp[prop]:\n", " if prop == \"creator\":\n", " objProp[prop] = {\"name\": obj[key], \"id\":\"\",\"role\":\"artist\"}\n", " else:\n", " objProp[prop] = obj[key]\n", " \n", " objProp[\"current_owner\"] = {\"name\":\"Cleveland Museum of Art\",\n", " \"location\":\"Cleveland,Ohio\",\n", " \"type\": \"http://vocab.getty.edu/aat/300312281\" ,\n", " \"type_label\": \"\"}\n", " return objProp\n", "\n", "\n", "objProp={}\n", "\n", "for obj in allObjects:\n", " objProp = createObjProp(obj,mapp)\n", " break\n", " \n" ] }, { "cell_type": "markdown", "id": "37447541", "metadata": {}, "source": [ "### Include Code to transform mapped collections data to Linked Art\n", "\n", "The following code is usually in a separate file, but shown here for illustration.\n", "\n", "The code includes `cromulent` - written by Rob Sanderson - further information at https://github.com/linked-art/crom\n", "\n", "There are also functions that take the `objProp` dictionary as input, to transform a description of artworks in the collections data to a representation in Linked Art JSON-LD." ] }, { "cell_type": "code", "execution_count": 6, "id": "db68ed9a", "metadata": {}, "outputs": [], "source": [ "try:\n", " import cromulent\n", "except:\n", " %pip install cromulent\n", " import cromulent\n", "\n", "from cromulent.model import factory, Actor, Production, BeginningOfExistence, EndOfExistence, TimeSpan, Place\n", "from cromulent.model import InformationObject, Phase, VisualItem \n", "from cromulent.vocab import Painting, Drawing,Miniature,add_art_setter, PrimaryName, Name, CollectionSet, instances, Sculpture \n", "from cromulent.vocab import aat_culture_mapping, AccessionNumber, Height, Width, SupportPart, Gallery, MuseumPlace \n", "from cromulent.vocab import BottomPart, Description, RightsStatement, MuseumOrg, Purchase\n", "from cromulent.vocab import Furniture, Mosaic, Photograph, Coin, Vessel, Graphic, Enamel, Embroidery, PhotographPrint\n", "from cromulent.vocab import PhotographAlbum, PhotographBook, PhotographColor, PhotographBW, Negative, Map, Clothing, Furniture\n", "from cromulent.vocab import Sample, Architecture, Armor, Book, DecArts, Implement, Jewelry, Manuscript, SiteInstallation, Text, Print\n", "from cromulent.vocab import TimeBasedMedia, Page, Folio, Folder, Box, Envelope, Binder, Case, FlatfileCabinet\n", "from cromulent.vocab import HumanMadeObject,Tapestry,LocalNumber\n", "from cromulent.vocab import Type,Set\n", "from cromulent.vocab import TimeSpan, Actor, Group, Acquisition, Place\n", "from cromulent.vocab import Production, TimeSpan, Actor\n", "from cromulent.vocab import LinguisticObject,DigitalObject, DigitalService\n", "\n", "\n", "\n", "\"\"\"\n", "Dictionary of Object Types defined in Linked Art\n", "\"\"\"\n", "\n", "\n", "objTypes = {\n", "\"Painting\": Painting(),\n", "\"Sculpture\": Sculpture(),\n", "\"Drawing\": Drawing(),\n", "\"Miniature\": Miniature(),\n", "\"Tapestry\": Tapestry(),\n", "\"Furniture\": Furniture(),\n", "\"Furnishings\": DecArts(),\n", "\"Mosaic\": Mosaic(),\n", "\"Photograph\": Photograph(),\n", "\"Coin\": Coin(),\n", "\"Vessel\": Vessel(),\n", "\"Graphic\": Graphic(),\n", "\"Enamel\": Enamel(),\n", "\"Embroidery\": Embroidery(),\n", "\"PhotographPrint\": PhotographPrint(),\n", "\"PhotographAlbum\": PhotographAlbum(),\n", "\"PhotographBook\": PhotographBook(),\n", "\"PhotographColor\": PhotographColor(),\n", "\"PhotographBW\": PhotographBW(),\n", "\"Negative\": Negative(),\n", "\"Map\": Map(),\n", "\"Clothing\": Clothing(),\n", "\"Sample\": Sample(),\n", "\"Architecture\": Architecture(),\n", "\"Armor\": Armor(),\n", "\"Book\": Book(),\n", "\"DecArts\": DecArts(),\n", "\"Implement\": Implement(),\n", "\"Jewelry\": Jewelry(),\n", "\"Manuscript\": Manuscript(),\n", "\"SiteInstallation\": SiteInstallation(),\n", "\"Text\": Text(),\n", "\"Print\": Print(),\n", "\"TimeBasedMedia\": TimeBasedMedia(),\n", "\"Page\": Page(),\n", "\"Folio\": Folio(),\n", "\"Folder\": Folder(),\n", "\"Box\": Box(),\n", "\"Envelope\": Envelope(),\n", "\"Binder\": Binder(),\n", "\"Case\": Case(),\n", "\"FlatfileCabinet\": FlatfileCabinet()\n", "}\n", "\n", "def createObjProp(obj,docProp):\n", " objProp = {\"creator\":[]}\n", "\n", " for prop in obj[\"atom\"]: \n", " propName = prop[\"@name\"]\n", " propValue = \"\"\n", " if \"#text\" in prop:\n", " propValue = prop[\"#text\"]\n", " if propName in list(docProp.keys()):\n", " propId = docProp[propName]\n", " objProp[propId] = propValue\n", " \n", "\n", " # alternative titles\n", "\n", " for table in obj[\"table\"]:\n", " if table[\"@name\"] == \"AltTitles\": \n", " alt_title = table[\"tuple\"][\"atom\"][\"#text\"]\n", " objProp[\"alt_title\"] = alt_title\n", " \n", "\n", " if table[\"@name\"] == \"Creator1\": \n", " crerole = creid = crename = \"\"\n", " if \"atom\" in table[\"tuple\"]:\n", " for atom in table[\"tuple\"][\"atom\"]:\n", " if atom[\"@name\"] == \"CreRole\":\n", " crerole = atom[\"#text\"]\n", " if atom[\"@name\"] == \"irn\":\n", " creid = atom[\"#text\"]\n", " if atom[\"@name\"] == \"SummaryData\":\n", " crename = atom[\"#text\"]\n", " creator = {\"id\":creid,\"name\":crename,\"role\":crerole}\n", " objProp[\"creator\"].append(creator)\n", " \n", " return objProp\n", "\n", "def objPrimaryname(objProp,object_uri):\n", " primaryname = None\n", " title = objProp[\"title\"]\n", " id = str(objProp[\"id\"])\n", " primaryname = PrimaryName( object_uri + \"/primary-name\",\n", " value=title)\n", " return primaryname\n", "\n", "def objAlternatename(objProp,object_uri):\n", " alternateName = None\n", " if \"alt_title\" in objProp:\n", " alt_title = objProp[\"alt_title\"]\n", " alternatename = AlternateName(object_uri + \"/alternate-name\",value=alt_title)\n", " return alternateName\n", "\n", "def objHomepage(objProp,object_uri):\n", "\n", " homepage = None\n", " homepageId = objProp[\"homepage\"]\n", " if homepageId != \"\":\n", " homepage = LinguisticObject(homepageId, label=\"Homepage for the Object\")\n", " homepage.classified_as = Type(\"http://vocab/getty.edu/aat/300264578\", label=\"Web pages (documents)\")\n", " homepage.classified_as = Type(\"http://vocab.getty.edu/aat/300266277\", label=\"home pages\")\n", " homepage.format = \"text/html\"\n", " return homepage\n", "\n", "\n", "def objProvenance(objProp,object_uri):\n", "\n", " prov = None\n", " if \"created_provenance\" in objProp:\n", " provenance = objProp[\"created_provenance\"]\n", " if provenance !=\"\":\n", " prov = LinguisticObject(object_uri + \"/provenance-statement\", \n", " value=provenance,\n", " label=\"Provenance Statement about the Object\"\n", " )\n", " prov.classified_as = Type(\"http://vocab.getty.edu/aat/300055863\", label=\"provenance (history of ownership)\")\n", " prov.classified_as = Type(\"http://vocab.getty.edu/aat/300418049\", label=\"brief texts\")\n", " return prov\n", "\n", "\n", "def objAccession(objProp, object_uri):\n", " accession = None\n", " accession_number = objProp[\"accession_number\"]\n", " if accession_number != \"\":\n", " accession = AccessionNumber(accession_number,value=accession_number)\n", " return accession\n", "\n", "def objLocalnumber(objProp,object_uri):\n", " localnumber = None\n", " id = str(objProp[\"id\"])\n", " if id != \"\":\n", " localnumber = LocalNumber(id,value=id)\n", " return localnumber\n", "\n", "def objCollection(objProp,object_uri):\n", " coll = None\n", " if \"collection\" in objProp:\n", " collection = objProp[\"collection\"]\n", " coll = Set(object_uri +\"/collection/\" + collection, \n", " label= collection)\n", " coll.classified_as = Type(\"http://vocab.getty.edu/aat/300025976\", \n", " label=\"collections (object groupings)\")\n", " return coll\n", "\n", "\n", "\n", "def objCredit(objProp,object_uri):\n", " credit = None\n", " propCredit = \"credit_line\"\n", " \n", " if propCredit in objProp:\n", " credit_line = objProp[propCredit]\n", " if credit_line != \"\":\n", " credit = LinguisticObject(object_uri + \"/credit-line\", \n", " value=credit_line,\n", " label=\"Credit Line for the Object\"\n", " )\n", " credit.classified_as = Type(\"http://vocab.getty.edu/aat/300026687\", label=\"acknowledgements\")\n", " credit.classified_as = Type(\"http://vocab.getty.edu/aat/300418049\", label=\"brief texts\")\n", " return credit\n", "\n", "\n", "\n", "def objProduction(objProp,object_uri):\n", "\n", " prod = None\n", "\n", " date_created = \"date_created\"\n", " created_earliest = \"date_created_earliest\"\n", " created_latest = \"date_created_latest\"\n", "\n", " if date_created in objProp:\n", " prod = Production(object_uri + \"/production\", label=\"Production of the Object\") \n", " \n", " labelTimespan = \"date unknown\"\n", " if objProp[date_created] != \"\":\n", " labelTimespan = objProp[date_created]\n", " \n", " timespan = TimeSpan(object_uri + \"/production/timespan\", label=labelTimespan)\n", " \n", " if created_earliest in objProp:\n", " timespan.begin_of_the_begin = objProp[created_earliest]\n", " if created_latest in objProp:\n", " timespan.end_of_the_end = objProp[created_latest]\n", " \n", " prod.timespan = timespan\n", "\n", " propCreator = \"creator\" \n", " if propCreator in objProp:\n", " id = label = \"\"\n", " creator = objProp[propCreator]\n", " for prop in creator:\n", " if \"id\" == prop:\n", " id = creator[\"id\"]\n", " if \"name\" == prop:\n", " label = creator[\"name\"]\n", " if label != \"\": \n", " actor = Actor(id,label)\n", " prod.carried_out_by = actor\n", " \n", " return prod\n", "\n", "def objCurrentowner(objProp,object_uri):\n", " current_owner = None\n", " if \"current_owner\" in objProp and objProp[\"current_owner\"][\"name\"] != \"\":\n", " cowner = objProp[\"current_owner\"][\"name\"]\n", " current_owner = Group( \"http://vocab.getty.edu/ulan/500300517\",label=cowner)\n", " current_owner.classified_as = Type( \"http://vocab.getty.edu/aat/300312281\",label=\"museums (institutions)\")\n", " \n", " \n", " acquisition = objAcquisition(objProp,object_uri)\n", " if acquisition is not None:\n", " current_owner.acquired_title_through = acquisition \n", " return current_owner \n", "\n", "def objAcquisition(objProp,object_uri):\n", " acquisition = None\n", " if \"accession_date\" in objProp and objProp[\"accession_date\"] != \"\":\n", " acquisition = Acquisition(object_uri + \"/IMA-acquisition\", label = \"Acquisition of the Object\")\n", " acquisition.classified_as = Type(\"http://vocab.getty.edu/aat/300157782\",\n", " label=\"acquisition (collections management)\")\n", " \n", " if \"name_location\" in objProp[\"current_owner\"]:\n", " acquisition.took_place_at = Place(\"http://vocab.getty.edu/tgn/7012924\", \n", " label=objProp[\"current_owner\"][\"name_location\"]) \n", " acquisition.timespan = objAcquisitionTimespan(object_uri,objProp[\"accession_date\"])\n", " return acquisition\n", "\n", "def objAcquisitionTimespan(object_uri,accession_date):\n", " timespan = None\n", " end = begin = \"\"\n", " accession_date = str(accession_date)\n", " if len(accession_date) == 4:\n", " begin = accession_date + \"-01-01T00:00:00.000Z\"\n", " end = accession_date + \"-12-31T00:00:00.000Z\"\n", " \n", " elif len(accession_date) == 8:\n", " begin = accession_date + \"01T00:00:00.000Z\"\n", " end = accession_date \n", " if '-02-' in accession_date:\n", " end = end + \"28\"\n", " if ('-01-','-03-','-05-','-07-','-08-','-09-','-10-','-12-') in accession_date:\n", " end = end + \"31\"\n", " if ('-04-','-06-','-09-','-11-'):\n", " end = end + \"30\" \n", " end = end + \"T00:00:00\"\n", " \n", " elif len(accession_date) == 10:\n", " begin = accession_date + \"T00:00:00.000Z\"\n", " end = accession_date + \"T00:00:00.000Z\" \n", " else:\n", " begin = end = \"\"\n", " \n", " timespan = TimeSpan(object_uri + \"/IMA-acquisition/timespan\", label=accession_date)\n", " \n", " if begin != \"\":\n", " timespan.begin_of_the_begin = begin\n", " if end != \"\":\n", " timespan.end_of_the_end = end\n", " return timespan\n", " \n", "\n", "def objCustody(objProp,object_uri):\n", " \n", " custody = None\n", "\n", " if \"current_status\" in objProp and objProp[\"current_status\"] != \"\" :\n", " current_status = objProp[\"current_status\"]\n", " current_owner = checkCurrentOwner(current_status)\n", " \n", " if current_owner == False:\n", " name = objProp[\"current_owner\"][\"name\"]\n", " type = objProp[\"current_owner\"][\"type\"]\n", " label = objProp[\"current_owner\"][\"type_label\"]\n", " \n", " custody = Group(label=name)\n", " custody.classified_as = Type(type, \n", " label=label)\n", " return custody\n", "\n", "\n", "def objDigitalObject(objProp,object_uri):\n", " vi = None\n", " url = objProp[\"image_url\"]\n", " vi = VisualItem(url, label=\"Digital image of artwork\")\n", "\n", " do = DigitalObject(url,label=\"Image of artwork\")\n", " do.classified_as = Type(\"http://vocab.getty.edu/aat/300215302\",\"Digital Image\")\n", " do.access_point = DigitalObject(url)\n", "\n", " if \"iiif\" in url.lower():\n", " ds = DigitalService()\n", " ds.access_point = DigitalObject(url)\n", " ds.conforms_to = InformationObject(\"http://iiif.io/api/image\")\n", " do.digitally_available_via = ds\n", " \n", " vi.digitally_shown_by = do\n", "\n", " return vi\n", " \n", "\n", "def createObjDesc(objProp,objTypes,object_uri):\n", " objLA = None\n", " objLA = HumanMadeObject() # linked art object\n", "\n", " for otype in objTypes:\n", " if otype in objProp[\"classification\"]:\n", " objLA = objTypes[otype] \n", " break\n", " \n", " objLA.id = object_uri\n", " objLA._label = objProp[\"title\"]\n", " \n", " # DIGITAL OBJECT\n", " if \"image_url\" in objProp and objProp[\"image_url\"] != \"\":\n", " dig = objDigitalObject(objProp,object_uri)\n", " if dig is not None:\n", " objLA.representation = []\n", " objLA.representation.append(dig)\n", "\n", "\n", " # IDENTIFIED_BY \n", " accession = objAccession(objProp,object_uri)\n", " localnumber = objLocalnumber(objProp,object_uri)\n", " primaryname = objPrimaryname(objProp,object_uri)\n", " \n", " listIds = (accession,localnumber,primaryname)\n", " identified_by = False\n", " for id in listIds:\n", " if id is not None:\n", " identified_by = True\n", " break\n", " if identified_by == True:\n", " objLA.identified_by = []\n", " \n", " for id in listIds:\n", " if id is not None:\n", " objLA.identified_by.append(id)\n", " \n", " # REFERRED_TO_BY\n", " objLA.referred_to_by = None\n", " prov = objProvenance(objProp,object_uri)\n", " credit = objCredit(objProp,object_uri)\n", " referred_to_by = False\n", " if prov is not None or credit is not None:\n", " referred_to_by = True\n", " if referred_to_by == True:\n", " objLA.referred_to_by = []\n", " if prov is not None:\n", " objLA.referred_to_by.append(prov) # provenance \n", " if credit is not None:\n", " objLA.referred_to_by.append(credit) # credit line\n", " \n", " # SUBJECT_OF \n", " objLA.subject_of = None \n", " homepage = None \n", " homepage = objHomepage(objProp,object_uri)\n", " if homepage is not None:\n", " objLA.subject_of = homepage # home page\n", " \n", " # PRODUCED_BY\n", " objLA.produced_by = None \n", " if \"creator\" in objProp:\n", " prod = None\n", " prod = objProduction(objProp,object_uri)\n", " objLA.produced_by = None\n", " if prod is not None:\n", " objLA.produced_by = prod # production\n", "\n", " # MEMBER_OF\n", " objLA.member_of = None \n", " if \"collection\" in objProp:\n", " coll = None\n", " coll = objCollection(objProp,object_uri)\n", " if coll is not None:\n", " objLA.member_of = coll # collection\n", "\n", " # CURRENT_KEEPER\n", " objLA.current_owner = None \n", " custody = None\n", " custody = objCustody(objProp,object_uri)\n", " if custody is not None:\n", " objLA.current_owner = custody\n", " \n", " # CURRENT_OWNER\n", " if \"current_owner\" in objProp and objProp[\"current_owner\"] != \"\":\n", " current_owner = objCurrentowner(objProp,object_uri)\n", " if current_owner is not None:\n", " objLA.current_owner = current_owner\n", " \n", " return objLA\n", "\n", "def checkCurrentOwner(current_status):\n", " currentowner = False\n", " if current_status != \"\":\n", " checkObjStatus = ('Accessioned','Partial Accession')\n", " for status in checkObjStatus:\n", " if status == current_status:\n", " currentowner = True\n", " if 'IMA-Owned' in current_status:\n", " currentowner = True\n", " return currentowner\n" ] }, { "cell_type": "markdown", "id": "9308d838", "metadata": {}, "source": [ "### Generate Linked Art JSON-LD and write to file\n", "\n", "Making use of the code above, the final part of the transformation process takes the `objProp` dictionary with the mapped artwork properties, and returns Linked Art JSON-LD, that is then saved to a file." ] }, { "cell_type": "code", "execution_count": 7, "id": "01ef203c", "metadata": {}, "outputs": [], "source": [ "# baseURI for JSON-LD document\n", "baseURI = \"https://clevelandart.org/art/\"\n", "\n", "id = obj[mapp.get(\"id\")]\n", "object_uri = baseURI + id\n", " \n", "objLA = None\n", "objLA = createObjDesc(objProp,objTypes,object_uri)\n", " \n", "# write to file \n", "text_file = open( id + \".json\", \"wt\")\n", "n = text_file.write(factory.toString(objLA, compact=False))\n", "text_file.close()\n", " " ] }, { "cell_type": "markdown", "id": "f99cb23b", "metadata": {}, "source": [ "### Linked Art\n", "\n", "An example of the Linked Art JSON-LD representation of an artwork is shown below.\n", "\n", "To more easily view the representation, you may like to copy and paste the text below into the JSON-LD Playground website that offers a visualisation option - visit https://json-ld.org/playground/" ] }, { "cell_type": "code", "execution_count": 8, "id": "4d2ef5c0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"@context\": \"https://linked.art/ns/v1/linked-art.json\",\n", " \"id\": \"https://clevelandart.org/art/74540\",\n", " \"type\": \"HumanMadeObject\",\n", " \"_label\": \"Leda and the Swan\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300033973\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Drawing\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300435443\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Type of Work\"\n", " }\n", " },\n", " \"identified_by\": [\n", " {\n", " \"id\": \"http://lod.example.org/museum/Identifier/2015.451\",\n", " \"type\": \"Identifier\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300312355\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Accession Number\"\n", " },\n", " \"content\": \"2015.451\"\n", " },\n", " {\n", " \"id\": \"http://lod.example.org/museum/Identifier/74540\",\n", " \"type\": \"Identifier\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300404621\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Owner-Assigned Number\"\n", " },\n", " \"content\": \"74540\"\n", " },\n", " {\n", " \"id\": \"https://clevelandart.org/art/74540/primary-name\",\n", " \"type\": \"Name\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300404670\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Primary Name\"\n", " },\n", " \"content\": \"Leda and the Swan\"\n", " }\n", " ],\n", " \"referred_to_by\": [\n", " {\n", " \"id\": \"https://clevelandart.org/art/74540/credit-line\",\n", " \"type\": \"LinguisticObject\",\n", " \"_label\": \"Credit Line for the Object\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300418049\",\n", " \"type\": \"Type\",\n", " \"_label\": \"brief texts\"\n", " },\n", " \"content\": \"Bequest of Muriel Butkin\"\n", " }\n", " ],\n", " \"member_of\": {\n", " \"id\": \"https://clevelandart.org/art/74540/collection/Drawings\",\n", " \"type\": \"Set\",\n", " \"_label\": \"Drawings\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300025976\",\n", " \"type\": \"Type\",\n", " \"_label\": \"collections (object groupings)\"\n", " }\n", " },\n", " \"subject_of\": {\n", " \"id\": \"https://clevelandart.org/art/2015.451\",\n", " \"type\": \"LinguisticObject\",\n", " \"_label\": \"Homepage for the Object\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300266277\",\n", " \"type\": \"Type\",\n", " \"_label\": \"home pages\"\n", " },\n", " \"format\": \"text/html\"\n", " },\n", " \"produced_by\": {\n", " \"id\": \"https://clevelandart.org/art/74540/production\",\n", " \"type\": \"Production\",\n", " \"_label\": \"Production of the Object\",\n", " \"timespan\": {\n", " \"id\": \"https://clevelandart.org/art/74540/production/timespan\",\n", " \"type\": \"TimeSpan\",\n", " \"_label\": \"date unknown\"\n", " },\n", " \"carried_out_by\": {\n", " \"type\": \"Actor\",\n", " \"_label\": \"Adolphe Yvon (French, 1817-1893), artist\"\n", " }\n", " },\n", " \"current_owner\": {\n", " \"id\": \"http://vocab.getty.edu/ulan/500300517\",\n", " \"type\": \"Group\",\n", " \"_label\": \"Cleveland Museum of Art\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300312281\",\n", " \"type\": \"Type\",\n", " \"_label\": \"museums (institutions)\"\n", " }\n", " }\n", "}\n" ] } ], "source": [ "print(factory.toString(objLA, compact=False))\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "fc8ec588", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "HTML('
')" ] }, { "cell_type": "code", "execution_count": 12, "id": "07fb82cd", "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "\n", "\n", "function visjsonld(jsonld, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " var config = {};\n", " \n", " var h = config.h || 800\n", " , w = config.w || 3000\n", " , maxLabelWidth = config.maxLabelWidth || 200\n", " , transitionDuration = config.transitionDuration || 750\n", " , transitionEase = config.transitionEase || 'cubic-in-out'\n", " , minRadius = config.minRadius || 5\n", " , scalingFactor = config.scalingFactor || 2;\n", " \n", " var i = 0;\n", "\n", " var tree = d3.layout.tree()\n", " .size([h, w]);\n", " \n", " var diagonal = d3.svg.diagonal()\n", " .projection(function(d) { return [d.y, d.x]; });\n", " \n", " d3.select(selector).selectAll(\"svg\").remove();\n", " \n", " var svg = d3.select(selector).append('svg')\n", " .attr('width', w)\n", " .attr('height', h)\n", " .attr('style', 'background-color:#80CBC4 ')\n", " .append('g')\n", " .attr('transform', 'translate(' + maxLabelWidth + ',0)');\n", " \n", " var root = jsonldTree(jsonld);\n", " root.x0 = h / 2;\n", " root.y0 = 0;\n", " root.children.forEach(collapse);\n", " \n", " function changeSVGWidth(newWidth) {\n", " if (w !== newWidth) {\n", " d3.select(selector + ' > svg').attr('width', newWidth);\n", " }\n", " }\n", " \n", " function jsonldTree(source) {\n", " var tree = {};\n", " \n", " if ('@id' in source) {\n", " tree.isIdNode = true;\n", " tree.name = source['@id'];\n", " if (tree.name.length > maxLabelWidth / 9) {\n", " tree.valueExtended = tree.name;\n", " tree.name = '...' + tree.valueExtended.slice(-Math.floor(maxLabelWidth / 9));\n", " }\n", " } else {\n", " tree.isIdNode = true;\n", " tree.isBlankNode = true;\n", " // random id, can replace with actual uuid generator if needed\n", " tree.name = '_' + Math.random().toString(10).slice(-7);\n", " }\n", " \n", " var children = [];\n", " Object.keys(source).forEach(function(key) {\n", " if (key === '@id' || key === '@context' || source[key] === null) return;\n", " \n", " var valueExtended, value;\n", " if (typeof source[key] === 'object' && !Array.isArray(source[key])) {\n", " children.push({\n", " name: key,\n", " children: [jsonldTree(source[key])]\n", " });\n", " } else if (Array.isArray(source[key])) {\n", " children.push({\n", " name: key,\n", " children: source[key].map(function(item) {\n", " if (typeof item === 'object') {\n", " return jsonldTree(item);\n", " } else {\n", " return { name: item };\n", " }\n", " })\n", " });\n", " } else {\n", " valueExtended = source[key];\n", " value = valueExtended;\n", " if (value.length > maxLabelWidth / 9) {\n", " value = value.slice(0, Math.floor(maxLabelWidth / 2)) + '...';\n", " children.push({\n", " name: key,\n", " value: value,\n", " valueExtended: valueExtended\n", " });\n", " } else {\n", " children.push({\n", " name: key,\n", " value: value\n", " });\n", " }\n", " }\n", " });\n", " \n", " if (children.length) {\n", " tree.children = children;\n", " }\n", " \n", " return tree;\n", " }\n", " \n", " function update(source) {\n", " var nodes = tree.nodes(root).reverse();\n", " var links = tree.links(nodes);\n", " \n", " nodes.forEach(function(d) { d.y = d.depth * maxLabelWidth; });\n", " \n", " var node = svg.selectAll('g.node')\n", " .data(nodes, function(d) { return d.id || (d.id = ++i); });\n", " \n", " var nodeEnter = node.enter()\n", " .append('g')\n", " .attr('class', 'node')\n", " .attr('transform', function(d) { return 'translate(' + source.y0 + ',' + source.x0 + ')'; })\n", " .on('click', click);\n", " \n", " nodeEnter.append('circle')\n", " .attr('r', 0)\n", " .style('stroke-width', function(d) {\n", " return d.isIdNode ? '2px' : '1px';\n", " })\n", " .style('stroke', function(d) {\n", " return d.isIdNode ? '#F7CA18' : '#4ECDC4';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? '#F5D76E' : 'white';\n", " } else {\n", " return d._children ? '#86E2D5' : 'white';\n", " }\n", " })\n", " \n", " \n", " nodeEnter.append('text')\n", " .attr('x', function(d) {\n", " var spacing = computeRadius(d) + 5;\n", " return d.children || d._children ? -spacing : spacing;\n", " })\n", " .attr('dy', '4')\n", " .attr('text-anchor', function(d) { return d.children || d._children ? 'end' : 'start'; })\n", " .text(function(d) { return d.name + (d.value ? ': ' + d.value : ''); })\n", " .style('fill-opacity', 0)\n", ";\n", " \n", " var maxSpan = Math.max.apply(Math, nodes.map(function(d) { return d.y + maxLabelWidth; }));\n", " if (maxSpan + maxLabelWidth + 20 > w) {\n", " changeSVGWidth(maxSpan + maxLabelWidth);\n", " d3.select(selector).node().scrollLeft = source.y0;\n", " }\n", " \n", " var nodeUpdate = node.transition()\n", " .duration(transitionDuration)\n", " .ease(transitionEase)\n", " .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });\n", " \n", " nodeUpdate.select('circle')\n", " .attr('r', function(d) { return computeRadius(d); })\n", " .style('stroke-width', function(d) {\n", " return d.isIdNode ? '2px' : '1px';\n", " })\n", " .style('stroke', function(d) {\n", " return d.isIdNode ? '#F7CA18' : '#4ECDC4';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? '#F5D76E' : 'white';\n", " } else {\n", " return d._children ? '#86E2D5' : 'navy';\n", " }\n", " });\n", " \n", " nodeUpdate.select('text').style('fill-opacity', 1);\n", " nodeUpdate.select('text').style('font-family', \"'Open Sans', 'Helvetica Neue', Helvetica, sans-serif\");\n", " nodeUpdate.select('text').style('fill', '#333333');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " var nodeExit = node.exit().transition()\n", " .duration(transitionDuration)\n", " .ease(transitionEase)\n", " .attr('transform', function(d) { return 'translate(' + source.y + ',' + source.x + ')'; })\n", " .remove();\n", " \n", " nodeExit.select('circle').attr('r', 0);\n", " nodeExit.select('text').style('fill-opacity', 0);\n", " \n", " var link = svg.selectAll('path.link')\n", " .data(links, function(d) { return d.target.id; });\n", " \n", " link.enter().insert('path', 'g')\n", " .attr('class', 'link')\n", " .attr('style', 'fill: none;stroke: #DADFE1;stroke-width: 1px;')\n", " .attr('d', function(d) {\n", " var o = { x: source.x0, y: source.y0 };\n", " return diagonal({ source: o, target: o });\n", " });\n", " \n", " link.transition()\n", " .duration(transitionDuration)\n", " .ease(transitionEase)\n", " .attr('d', diagonal);\n", " \n", " link.exit().transition()\n", " .duration(transitionDuration)\n", " .ease(transitionEase)\n", " .attr('d', function(d) {\n", " var o = { x: source.x, y: source.y };\n", " return diagonal({ source: o, target: o });\n", " })\n", " .remove();\n", " \n", " nodes.forEach(function(d) {\n", " d.x0 = d.x;\n", " d.y0 = d.y;\n", " });\n", " }\n", " \n", " function computeRadius(d) {\n", " if (d.children || d._children) {\n", " return minRadius + (numEndNodes(d) / scalingFactor);\n", " } else {\n", " return minRadius;\n", " }\n", " }\n", " \n", " function numEndNodes(n) {\n", " var num = 0;\n", " if (n.children) {\n", " n.children.forEach(function(c) {\n", " num += numEndNodes(c);\n", " });\n", " } else if (n._children) {\n", " n._children.forEach(function(c) {\n", " num += numEndNodes(c);\n", " });\n", " } else {\n", " num++;\n", " }\n", " return num;\n", " }\n", " \n", " function click(d) {\n", " if (d.children) {\n", " d._children = d.children;\n", " d.children = null;\n", " } else {\n", " d.children = d._children;\n", " d._children = null;\n", " }\n", " \n", " update(d);\n", " \n", " // fast-forward blank nodes\n", " if (d.children) {\n", " d.children.forEach(function(child) {\n", " if (child.isBlankNode && child._children) {\n", " click(child);\n", " }\n", " });\n", " }\n", " }\n", " \n", " function collapse(d) {\n", " if (d.children) {\n", " d._children = d.children;\n", " d._children.forEach(collapse);\n", " d.children = null;\n", " }\n", " }\n", " \n", " update(root);\n", " \n", " \n", " })\n", " }\n", "var data = {\n", " \"@context\": \"https://linked.art/ns/v1/linked-art.json\",\n", " \"id\": \"https://clevelandart.org/art/74540\",\n", " \"type\": \"HumanMadeObject\",\n", " \"_label\": \"Leda and the Swan\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300033973\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Drawing\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300435443\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Type of Work\"\n", " }\n", " },\n", " \"identified_by\": [\n", " {\n", " \"id\": \"http://lod.example.org/museum/Identifier/2015.451\",\n", " \"type\": \"Identifier\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300312355\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Accession Number\"\n", " },\n", " \"content\": \"2015.451\"\n", " },\n", " {\n", " \"id\": \"http://lod.example.org/museum/Identifier/74540\",\n", " \"type\": \"Identifier\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300404621\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Owner-Assigned Number\"\n", " },\n", " \"content\": \"74540\"\n", " },\n", " {\n", " \"id\": \"https://clevelandart.org/art/74540/primary-name\",\n", " \"type\": \"Name\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300404670\",\n", " \"type\": \"Type\",\n", " \"_label\": \"Primary Name\"\n", " },\n", " \"content\": \"Leda and the Swan\"\n", " }\n", " ],\n", " \"referred_to_by\": [\n", " {\n", " \"id\": \"https://clevelandart.org/art/74540/credit-line\",\n", " \"type\": \"LinguisticObject\",\n", " \"_label\": \"Credit Line for the Object\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300418049\",\n", " \"type\": \"Type\",\n", " \"_label\": \"brief texts\"\n", " },\n", " \"content\": \"Bequest of Muriel Butkin\"\n", " }\n", " ],\n", " \"member_of\": {\n", " \"id\": \"https://clevelandart.org/art/74540/collection/Drawings\",\n", " \"type\": \"Set\",\n", " \"_label\": \"Drawings\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300025976\",\n", " \"type\": \"Type\",\n", " \"_label\": \"collections (object groupings)\"\n", " }\n", " },\n", " \"subject_of\": {\n", " \"id\": \"https://clevelandart.org/art/2015.451\",\n", " \"type\": \"LinguisticObject\",\n", " \"_label\": \"Homepage for the Object\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300266277\",\n", " \"type\": \"Type\",\n", " \"_label\": \"home pages\"\n", " },\n", " \"format\": \"text/html\"\n", " },\n", " \"produced_by\": {\n", " \"id\": \"https://clevelandart.org/art/74540/production\",\n", " \"type\": \"Production\",\n", " \"_label\": \"Production of the Object\",\n", " \"timespan\": {\n", " \"id\": \"https://clevelandart.org/art/74540/production/timespan\",\n", " \"type\": \"TimeSpan\",\n", " \"_label\": \"date unknown\"\n", " },\n", " \"carried_out_by\": {\n", " \"type\": \"Actor\",\n", " \"_label\": \"Adolphe Yvon (French, 1817-1893), artist\"\n", " }\n", " },\n", " \"current_owner\": {\n", " \"id\": \"http://vocab.getty.edu/ulan/500300517\",\n", " \"type\": \"Group\",\n", " \"_label\": \"Cleveland Museum of Art\",\n", " \"classified_as\": {\n", " \"id\": \"http://vocab.getty.edu/aat/300312281\",\n", " \"type\": \"Type\",\n", " \"_label\": \"museums (institutions)\"\n", " }\n", " }\n", "}; var selector = \"#example\"; visjsonld(data, selector); " ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import display,HTML,Javascript\n", "\n", "code2 = 'var data = ' + factory.toString(objLA, compact=False) + '; var selector = \"#example\"; visjsonld(data, selector); ' \n", "\n", "with open('src/js/visld2.js', 'r') as _jscript:\n", " code = _jscript.read() + code2\n", "\n", "Javascript(code)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "82991ad0", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "interpreter": { "hash": "40d3a090f54c6569ab1632332b64b2c03c39dcf918b08424e98f38b5ae0af88f" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 5 }