{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "b6feee37", "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", "HTML(\"\"\"\"\"\")" ] }, { "cell_type": "markdown", "id": "c09fa7b0", "metadata": {}, "source": [ "# Transforming John Ruskin Collection Data to Linked Art \n", "\n", "This notebook transforms collections data to a Linked Art representation for artworks by John Ruskin. The data origin collections data published in various formats by museums and galleries. \n", "\n", "- CSV\n", " - National Gallery of Art (NGA), Washington, USA\n", " - Cleveland Museum of Art, USA\n", "- JSON\n", " - The Tate Museum, UK\n", " - Harvard Museum, USA \n", " - Rijksmuseum, Netherlands\n", "- HTML \n", " - Ashmolean Museum, UK\n", " \n", "\n", "\n", "## Transformation Process\n", "The transformation process common to all data sources:\n", "- read collection data into Python dictionary\n", "- create a mapping between entities in the Python dictionary and entities in the Linked Art data model\n", "- use the mapping together with `createObjDesc()`, `cromulent` Python library, and custom coding in the `createObjProp()` function, to create a Linked Art JSON-LD representation\n", "- write to file" ] }, { "cell_type": "code", "execution_count": 2, "id": "a7498e6b", "metadata": {}, "outputs": [], "source": [ "# output directory for files created\n", "outputdir = \"./data/ruskin/output/json/\"\n", "\n", "images = {}" ] }, { "cell_type": "markdown", "id": "50354532", "metadata": {}, "source": [ "## National Gallery of Art (NGA), Washington, United States\n", "\n", "The collection data exists into two files:\n", "- CSV data file containing artwork description [data file](./data/nga/input/nga_ruskin.csv)\n", "- CSV data file containing detailed digital image information for artworks https://raw.githubusercontent.com/NationalGalleryOfArt/opendata/main/data/published_images.csv\n", "\n", "\n", " #### Further Reading \n", " \n", " - National Gallery of Art https://www.nga.gov/\n", " - NGA GitHub https://github.com/NationalGalleryOfArt" ] }, { "cell_type": "markdown", "id": "e2153311", "metadata": {}, "source": [ "### Load NGA Collection Data into DataFrame" ] }, { "cell_type": "code", "execution_count": 3, "id": "f6b866a4", "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
objectidaccessionedaccessionnumlocationidtitledisplaydatebeginyearendyearvisualbrowsertimespanmedium...visualbrowserclassificationparentidisvirtualdepartmentabbrportfolioseriesvolumewatermarkslastdetectedmodificationcustomprinturl
07023811987.73.2NaNTower of the Cathedral at Sensc. 1845184518451826 to 1850pen and brown ink, brush and black ink, black ......drawingNaN0CG-ENaNNaNNaNNaN2019-10-28 22:01:34.883-04NaN
17036711988.20.38NaNTree Studymid-1850s184518551826 to 1850pen and black ink with blue-gray and gray wash......drawingNaN0CG-ENaNNaNNaNNaN2020-04-10 22:01:40.093-04NaN
27287011991.88.1NaNThe Garden of San Miniato near Florence1845184518451826 to 1850watercolor and pen and black ink, heightened w......drawingNaN0CG-ENaNNaNNaNNaN2019-10-28 22:01:34.883-04NaN
37614011995.52.158NaNOrnamental Study with Acanthus Motif for \"The ...1849184918491826 to 1850pen and brown ink with watercolor and graphite......drawingNaN0CG-ENaNNaNNaNNaN2019-10-28 22:01:34.883-04NaN
\n", "

4 rows × 28 columns

\n", "
" ], "text/plain": [ " objectid accessioned accessionnum locationid \\\n", "0 70238 1 1987.73.2 NaN \n", "1 70367 1 1988.20.38 NaN \n", "2 72870 1 1991.88.1 NaN \n", "3 76140 1 1995.52.158 NaN \n", "\n", " title displaydate beginyear \\\n", "0 Tower of the Cathedral at Sens c. 1845 1845 \n", "1 Tree Study mid-1850s 1845 \n", "2 The Garden of San Miniato near Florence 1845 1845 \n", "3 Ornamental Study with Acanthus Motif for \"The ... 1849 1849 \n", "\n", " endyear visualbrowsertimespan \\\n", "0 1845 1826 to 1850 \n", "1 1855 1826 to 1850 \n", "2 1845 1826 to 1850 \n", "3 1849 1826 to 1850 \n", "\n", " medium ... \\\n", "0 pen and brown ink, brush and black ink, black ... ... \n", "1 pen and black ink with blue-gray and gray wash... ... \n", "2 watercolor and pen and black ink, heightened w... ... \n", "3 pen and brown ink with watercolor and graphite... ... \n", "\n", " visualbrowserclassification parentid isvirtual departmentabbr portfolio \\\n", "0 drawing NaN 0 CG-E NaN \n", "1 drawing NaN 0 CG-E NaN \n", "2 drawing NaN 0 CG-E NaN \n", "3 drawing NaN 0 CG-E NaN \n", "\n", " series volume watermarks lastdetectedmodification customprinturl \n", "0 NaN NaN NaN 2019-10-28 22:01:34.883-04 NaN \n", "1 NaN NaN NaN 2020-04-10 22:01:40.093-04 NaN \n", "2 NaN NaN NaN 2019-10-28 22:01:34.883-04 NaN \n", "3 NaN NaN NaN 2019-10-28 22:01:34.883-04 NaN \n", "\n", "[4 rows x 28 columns]" ] }, "execution_count": 3, "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", "fileNGA = 'data/nga/input/nga_ruskin.csv'\n", "\n", "dataFrameNGA = pd.read_csv(fileNGA)\n", "dataFrameNGA.head()" ] }, { "cell_type": "markdown", "id": "2b84b8a1", "metadata": {}, "source": [ "### Load NGA Digital Image File into DataFrame\n", "\n", "The data file containing detailed digital image data is loaded into a pandas dataframe `dataFrameNGAImages`" ] }, { "cell_type": "code", "execution_count": 4, "id": "efdadbe1", "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", " \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", "
uuidiiifurliiifthumburlviewtypesequencewidthheightmaxpixelscreatedmodifieddepictstmsobjectidassistivetext
000004dec-8300-4487-8d89-562d0126b6a1https://api.nga.gov/iiif/00004dec-8300-4487-8d...https://api.nga.gov/iiif/00004dec-8300-4487-8d...primary0.026234000640.02010-09-07 15:08:48-042022-04-21 12:57:43.657-0411975NaN
100007f61-4922-417b-8f27-893ea328206chttps://api.nga.gov/iiif/00007f61-4922-417b-8f...https://api.nga.gov/iiif/00007f61-4922-417b-8f...primary0.033654332NaN2013-07-05 15:41:08-042022-05-23 14:59:28-0417387NaN
20000bd8c-39de-4453-b55d-5e28a9beed38https://api.nga.gov/iiif/0000bd8c-39de-4453-b5...https://api.nga.gov/iiif/0000bd8c-39de-4453-b5...primary0.035004688NaN2013-08-05 14:31:59-042022-05-23 15:05:58-0419245NaN
30000e5a4-7d32-4c2a-97c6-a6b571c9fd71https://api.nga.gov/iiif/0000e5a4-7d32-4c2a-97...https://api.nga.gov/iiif/0000e5a4-7d32-4c2a-97...primary0.022523000NaN2013-03-18 14:39:55-042022-05-17 18:19:25-04153987NaN
40001668a-dd1c-48e8-9267-b6d1697d43c8https://api.nga.gov/iiif/0001668a-dd1c-48e8-92...https://api.nga.gov/iiif/0001668a-dd1c-48e8-92...primary0.034464448NaN2014-01-02 14:50:50-052022-05-23 15:39:38-0423830NaN
\n", "
" ], "text/plain": [ " uuid \\\n", "0 00004dec-8300-4487-8d89-562d0126b6a1 \n", "1 00007f61-4922-417b-8f27-893ea328206c \n", "2 0000bd8c-39de-4453-b55d-5e28a9beed38 \n", "3 0000e5a4-7d32-4c2a-97c6-a6b571c9fd71 \n", "4 0001668a-dd1c-48e8-9267-b6d1697d43c8 \n", "\n", " iiifurl \\\n", "0 https://api.nga.gov/iiif/00004dec-8300-4487-8d... \n", "1 https://api.nga.gov/iiif/00007f61-4922-417b-8f... \n", "2 https://api.nga.gov/iiif/0000bd8c-39de-4453-b5... \n", "3 https://api.nga.gov/iiif/0000e5a4-7d32-4c2a-97... \n", "4 https://api.nga.gov/iiif/0001668a-dd1c-48e8-92... \n", "\n", " iiifthumburl viewtype sequence \\\n", "0 https://api.nga.gov/iiif/00004dec-8300-4487-8d... primary 0.0 \n", "1 https://api.nga.gov/iiif/00007f61-4922-417b-8f... primary 0.0 \n", "2 https://api.nga.gov/iiif/0000bd8c-39de-4453-b5... primary 0.0 \n", "3 https://api.nga.gov/iiif/0000e5a4-7d32-4c2a-97... primary 0.0 \n", "4 https://api.nga.gov/iiif/0001668a-dd1c-48e8-92... primary 0.0 \n", "\n", " width height maxpixels created \\\n", "0 2623 4000 640.0 2010-09-07 15:08:48-04 \n", "1 3365 4332 NaN 2013-07-05 15:41:08-04 \n", "2 3500 4688 NaN 2013-08-05 14:31:59-04 \n", "3 2252 3000 NaN 2013-03-18 14:39:55-04 \n", "4 3446 4448 NaN 2014-01-02 14:50:50-05 \n", "\n", " modified depictstmsobjectid assistivetext \n", "0 2022-04-21 12:57:43.657-04 11975 NaN \n", "1 2022-05-23 14:59:28-04 17387 NaN \n", "2 2022-05-23 15:05:58-04 19245 NaN \n", "3 2022-05-17 18:19:25-04 153987 NaN \n", "4 2022-05-23 15:39:38-04 23830 NaN " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fileNGAimages = \"https://raw.githubusercontent.com/NationalGalleryOfArt/opendata/main/data/published_images.csv\"\n", "dataFrameNGAImages = pd.read_csv(fileNGAimages)\n", "dataFrameNGAImages.head()" ] }, { "cell_type": "markdown", "id": "3fd2055c", "metadata": {}, "source": [ "### Remove Byte Order Marks and Define Data Mapping\n", "\n", "Remove Byte Order Marks and create Python dictionary containing data mapping for each input file." ] }, { "cell_type": "code", "execution_count": 5, "id": "ac618108", "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", " \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", " \n", " \n", " \n", " \n", " \n", "
0
idobjectid
accession_numberaccessionnum
accession_date
classificationclassification
titletitle
alt_title
notes
date_createddisplaydate
date_created_earliestbeginyear
date_created_latestendyear
created_period
created_dynasty
created_inscriptions
created_notes
created_provenance
creatorattribution
physical_mediummedium
physical_style
physical_technique
physical_description
physical_dimensionsdimensions
credit_linecreditline
collectiondepartmentabbr
current_status
current_owner
homepage
\n", "
" ], "text/plain": [ " 0\n", "id objectid\n", "accession_number accessionnum\n", "accession_date \n", "classification classification\n", "title title\n", "alt_title \n", "notes \n", "date_created displaydate\n", "date_created_earliest beginyear\n", "date_created_latest endyear\n", "created_period \n", "created_dynasty \n", "created_inscriptions \n", "created_notes \n", "created_provenance \n", "creator attribution\n", "physical_medium medium\n", "physical_style \n", "physical_technique \n", "physical_description \n", "physical_dimensions dimensions\n", "credit_line creditline\n", "collection departmentabbr\n", "current_status \n", "current_owner \n", "homepage " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "\n", "\n", "# remove BOM\n", "\n", "removeBOM = open(fileNGA, mode='r', encoding='utf-8-sig').read()\n", "open(fileNGA, mode='w', encoding='utf-8').write(removeBOM)\n", "\n", "\n", "# data mapping between Linked Art data model and NGA data entities\n", "mapp = {\n", " \"id\":\"objectid\",\n", " \"accession_number\":\"accessionnum\",\n", " \"accession_date\": \"\",\n", " \"classification\" : \"classification\",\n", " \"title\": \"title\",\n", " \"alt_title\": \"\",\n", " \"notes\": \"\",\n", " \"date_created\":\"displaydate\",\n", " \"date_created_earliest\": \"beginyear\",\n", " \"date_created_latest\": \"endyear\",\n", " \"created_period\":\"\",\n", " \"created_dynasty\":\"\",\n", " \"created_inscriptions\":\"\",\n", " \"created_notes\": \"\",\n", " \"created_provenance\" : \"\",\n", " \"creator\":\"attribution\",\n", " \"physical_medium\": \"medium\",\n", " \"physical_style\": \"\",\n", " \"physical_technique\": \"\",\n", " \"physical_description\": \"\",\n", " \"physical_dimensions\": \"dimensions\",\n", " \"created_provenance\": \"\" ,\n", " \"credit_line\": \"creditline\",\n", " \"collection\" : \"departmentabbr\",\n", " \"current_status\" : \"\",\n", " \"current_owner\" : \"\",\n", " \"homepage\": \"\"\n", "}\n", "\n", "# display transposed dataframe of data mapping\n", "display(pd.DataFrame(mapp, index=[0]).T)" ] }, { "cell_type": "markdown", "id": "fd388f00", "metadata": {}, "source": [ "### Transform to JSON-LD \n", "\n", "This next step uses the following to transform the collections data to Linked Art JSON-LD\n", "- the data mapping\n", "- custom coding in createObjProp()\n", "- cromulant Python library\n", "- custom coding in la including createObjDescription()\n", "\n", "The URLs for the artwork digital images are in a separate file. With custom coding in `createObjProp()` the rows in the two collection data files are mapped to extract the digital image url.\n", "\n", "
\n",
    "    matchImages = dataFrameNGAImages.query('depictstmsobjectid == ' + objProp[\"id\"] )\n",
    "    objProp[\"image_url\"] = matchImages[\"iiifurl\"].iloc[0]  + \"/full/!500,500/0/default.jpg\"\n",
    "
\n", "\n", "\n", "Additional custom code creates a web page URL for the artwork:\n", "\n", "
\n",
    "objProp[\"homepage\"] = \"https://www.nga.gov/collection/art-object-page.\" + id + \".html\"   \n",
    "
" ] }, { "cell_type": "code", "execution_count": 6, "id": "fbb40f16", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Tower of the Cathedral at Sens'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
idaccession_numbertitledate_createddate_created_earliestdate_created_latestphysical_mediumphysical_dimensionscreatorcredit_lineclassificationcollectionimage_urlhomepage
0702381987.73.2Tower of the Cathedral at Sensc. 184518451845pen and brown ink, brush and black ink, black ...sheet: 40.7 x 30.6 cm (16 x 12 1/16 in.){'id': 'https://www.nga.gov/collection/creator...Gift of William B. O'NealDrawingCG-Ehttps://api.nga.gov/iiif/49a6128c-8d5a-4b00-be...https://www.nga.gov/collection/art-object-page...
\n", "
" ], "text/plain": [ " id accession_number title date_created \\\n", "0 70238 1987.73.2 Tower of the Cathedral at Sens c. 1845 \n", "\n", " date_created_earliest date_created_latest \\\n", "0 1845 1845 \n", "\n", " physical_medium \\\n", "0 pen and brown ink, brush and black ink, black ... \n", "\n", " physical_dimensions \\\n", "0 sheet: 40.7 x 30.6 cm (16 x 12 1/16 in.) \n", "\n", " creator \\\n", "0 {'id': 'https://www.nga.gov/collection/creator... \n", "\n", " credit_line classification collection \\\n", "0 Gift of William B. O'Neal Drawing CG-E \n", "\n", " image_url \\\n", "0 https://api.nga.gov/iiif/49a6128c-8d5a-4b00-be... \n", "\n", " homepage \n", "0 https://www.nga.gov/collection/art-object-page... " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Tree Study'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
idaccession_numbertitledate_createddate_created_earliestdate_created_latestphysical_mediumphysical_dimensionscreatorcredit_lineclassificationcollectionimage_urlhomepage
0703671988.20.38Tree Studymid-1850s18451855pen and black ink with blue-gray and gray wash...overall: 28.4 x 38.1 cm (11 3/16 x 15 in.){'id': 'https://www.nga.gov/collection/creator...Gift of John Nichols Estabrook and Dorothy Coo...DrawingCG-Ehttps://api.nga.gov/iiif/9310c903-7099-4138-b3...https://www.nga.gov/collection/art-object-page...
\n", "
" ], "text/plain": [ " id accession_number title date_created date_created_earliest \\\n", "0 70367 1988.20.38 Tree Study mid-1850s 1845 \n", "\n", " date_created_latest physical_medium \\\n", "0 1855 pen and black ink with blue-gray and gray wash... \n", "\n", " physical_dimensions \\\n", "0 overall: 28.4 x 38.1 cm (11 3/16 x 15 in.) \n", "\n", " creator \\\n", "0 {'id': 'https://www.nga.gov/collection/creator... \n", "\n", " credit_line classification \\\n", "0 Gift of John Nichols Estabrook and Dorothy Coo... Drawing \n", "\n", " collection image_url \\\n", "0 CG-E https://api.nga.gov/iiif/9310c903-7099-4138-b3... \n", "\n", " homepage \n", "0 https://www.nga.gov/collection/art-object-page... " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Garden of San Miniato near Florence'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
idaccession_numbertitledate_createddate_created_earliestdate_created_latestphysical_mediumphysical_dimensionscreatorcredit_lineclassificationcollectionimage_urlhomepage
0728701991.88.1The Garden of San Miniato near Florence184518451845watercolor and pen and black ink, heightened w...Overall: 34.2 x 49.2 cm (13 7/16 x 19 3/8 in.)...{'id': 'https://www.nga.gov/collection/creator...Patrons' Permanent FundDrawingCG-Ehttps://api.nga.gov/iiif/f6ef48d3-3512-4f46-ac...https://www.nga.gov/collection/art-object-page...
\n", "
" ], "text/plain": [ " id accession_number title \\\n", "0 72870 1991.88.1 The Garden of San Miniato near Florence \n", "\n", " date_created date_created_earliest date_created_latest \\\n", "0 1845 1845 1845 \n", "\n", " physical_medium \\\n", "0 watercolor and pen and black ink, heightened w... \n", "\n", " physical_dimensions \\\n", "0 Overall: 34.2 x 49.2 cm (13 7/16 x 19 3/8 in.)... \n", "\n", " creator credit_line \\\n", "0 {'id': 'https://www.nga.gov/collection/creator... Patrons' Permanent Fund \n", "\n", " classification collection \\\n", "0 Drawing CG-E \n", "\n", " image_url \\\n", "0 https://api.nga.gov/iiif/f6ef48d3-3512-4f46-ac... \n", "\n", " homepage \n", "0 https://www.nga.gov/collection/art-object-page... " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Ornamental Study with Acanthus Motif for \"The Stones of Venice\"'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
idaccession_numbertitledate_createddate_created_earliestdate_created_latestphysical_mediumphysical_dimensionscreatorcredit_lineclassificationcollectionimage_urlhomepage
0761401995.52.158Ornamental Study with Acanthus Motif for \"The ...184918491849pen and brown ink with watercolor and graphite...overall: 20.1 x 16.6 cm (7 15/16 x 6 9/16 in.){'id': 'https://www.nga.gov/collection/creator...Gift of William B. O'NealDrawingCG-Ehttps://api.nga.gov/iiif/bc567179-9c1e-4493-b7...https://www.nga.gov/collection/art-object-page...
\n", "
" ], "text/plain": [ " id accession_number title \\\n", "0 76140 1995.52.158 Ornamental Study with Acanthus Motif for \"The ... \n", "\n", " date_created date_created_earliest date_created_latest \\\n", "0 1849 1849 1849 \n", "\n", " physical_medium \\\n", "0 pen and brown ink with watercolor and graphite... \n", "\n", " physical_dimensions \\\n", "0 overall: 20.1 x 16.6 cm (7 15/16 x 6 9/16 in.) \n", "\n", " creator \\\n", "0 {'id': 'https://www.nga.gov/collection/creator... \n", "\n", " credit_line classification collection \\\n", "0 Gift of William B. O'Neal Drawing CG-E \n", "\n", " image_url \\\n", "0 https://api.nga.gov/iiif/bc567179-9c1e-4493-b7... \n", "\n", " homepage \n", "0 https://www.nga.gov/collection/art-object-page... " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import cromulent \n", "except:\n", " %pip install cromulent\n", " import cromulent\n", " \n", "from cromulent.model import factory\n", "from lib import linkedart as la\n", "\n", "import csv\n", "\n", "# baseURI for JSON-LD document\n", "baseURI = \"https://www.nga.gov/collection/\"\n", "fileNGA = 'data/nga/input/nga_ruskin.csv'\n", "\n", "# list to hold file names for use with jsonld visualisation dropdown\n", "selectOptions = []\n", "selectOptions = [('Please select an artwork', '')]\n", "\n", "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", " \n", " # custom code to populate the creator property\n", " if prop == \"creator\":\n", " objProp[prop] = [{\"id\": baseURI +\"creatorid/\" + obj[mapp[\"id\"]] ,\"name\": obj[key],\"role\":\"Artist\"}]\n", " else:\n", " objProp[prop] = obj[key]\n", " \n", " # custom code to populate the image_url property\n", " matchImages = dataFrameNGAImages.query('depictstmsobjectid == ' + objProp[\"id\"] )\n", " objProp[\"image_url\"] = matchImages[\"iiifurl\"].iloc[0] + \"/full/!500,500/0/default.jpg\"\n", " \n", " # custom code to define the homepage properity\n", " objProp[\"homepage\"] = \"https://www.nga.gov/collection/art-object-page.\" + objProp[\"id\"] + \".html\"\n", " \n", " return objProp \n", "\n", " \n", "allObjects = csv.DictReader(open(fileNGA, mode='r',encoding='utf-8'))\n", "\n", "for obj in allObjects:\n", " # create object property dictionary\n", " objProp = createObjProp(obj,mapp)\n", " \n", " id = objProp[\"id\"]\n", " filename = id + \".json\"\n", "\n", " # create obj description\n", " objLA = la.createObjDesc(objProp,la.objTypes,baseURI + id)\n", "\n", " # write to file \n", " \n", " text_file = open(outputdir + filename, \"wt\")\n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " text_file.close()\n", " \n", " selectOptions.append( ( objProp[\"title\"] + \" (\" + filename + \")\" , filename))\n", " \n", " # display title and table for illustration\n", " display(objProp[\"title\"])\n", " display(pd.DataFrame(objProp, index=[0]))\n", " " ] }, { "cell_type": "markdown", "id": "273a7ef7", "metadata": {}, "source": [ "### Explore the Linked Art JSON-LD files\n", "\n", "Select an artwork from the dropdown to view \n", "- the artwork image\n", "- a visualisation of the Linked Art JSON-LD representation created above" ] }, { "cell_type": "code", "execution_count": 8, "id": "aee97523", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ac77c8991a8e42f397cd3b526f4368b0", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), ('Tower of the Cathedral at Sens (70238.json)', '70238.jso…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import ipywidgets\n", "except:\n", " %pip install ipywidgets\n", " import ipywidgets\n", "\n", "from ipywidgets import Layout, FileUpload \n", "from IPython.display import display, IFrame, HTML, Image\n", "\n", "import os\n", "\n", "try:\n", " import json\n", "except:\n", " %pip install json\n", " import json \n", " \n", "from IPython.core.display import Javascript \n", " \n", "def dropdown_eventhandler(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#visnga';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + \"/\" + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworknga').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworknga').src = '';\"))\n", " \n", "\n", "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "19706cba", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "d588ad01", "metadata": {}, "source": [ "## Cleveland Museum of Art (CMA)\n", "\n", "The Cleveland Museum of Art (CMA) has published its collection data in a GitHub Repository. \n", "\n", "\n", "\n", "### Works by John Ruskin in CMA Collection Data\n", "\n", "There is a single artwork by John Ruskin in the Cleveland Museum of Art (CMA) collection data available.\n", "\n", "The extract this record, the following method was used:\n", "- download [collection data file](https://github.com/ClevelandMuseumArt/openaccess/blob/master/data.csv) from CMA's GitHub repository\n", "- use [OpenRefine](https://openrefine.org/) to identify and extract relevant records\n", " - create a text facet for the Creator field to \n", " - identify artworks by John Ruskin using facet\n", " - export record \n", " - save CSV file [CMA Ruskin data file](./data/cma/input/ruskin.csv) \n", "\n", "\n", "#### Further Reading \n", "- Cleveland Museum of Art http://www.clevelandart.org/\n", "- CMA GitHub open data repository https://github.com/ClevelandMuseumArt/openaccess\n", "- CSV data file https://github.com/ClevelandMuseumArt/openaccess/blob/master/data.csv\n", "- [CMA Ruskin data file](./data/cma/input/ruskin.csv) \n", "- [OpenRefine](https://openrefine.org/) \n" ] }, { "cell_type": "code", "execution_count": 9, "id": "873f62a9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "

Video - Using OpenRefine to extract Ruskin record from CMA data

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEABALDBgYFhwaGRodHRwfIy0mIiIiJC4tJiklLy8xNS0nLSs3PlBFNThNOSsvR2FFS1NWW1xbN0FlbWRYbVBZW1cBERISGRYZLxsbLVo9NzpjV1dXV11aV1dXV1dXV11XV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV11XV1dXV1dXY//AABEIAWgB4AMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAAAQQCAwUHBv/EAEUQAAIBAgQCBgcFBgUEAQUAAAABAgMRBBIhMUFRFSJUYZPRBRMycYGRoXJzsbLBBhQjNELwNVJiguEkM0PxdFNjosLS/8QAGAEBAQEBAQAAAAAAAAAAAAAAAAECAwT/xAAfEQEAAgICAwEBAAAAAAAAAAAAARECEhNRMUFhAyH/2gAMAwEAAhEDEQA/APPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXqfoXGSipRwuIlGSumqU2mns07GXQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0Fjux4nwZ+QHPB0Ogsd2PE+DPyHQWO7HifBn5Ac8HQ6Cx3Y8T4M/IdBY7seJ8GfkBzwdDoLHdjxPgz8h0FjuyYnwZ+QHrfomuqfo3DTd2lQp7fZRngfTEK85QjFpqN77q3fyMfQdRfuOGTV/wCDBf8A4osYelSpRkqccuZtv3nWNam4/rjMZ7xMT/OlTEenYU6s4OnJxhJwurXc1GEmrO2lprW+6ehC/aOg02oVXZqMrRXVm5qGRu9r3ku434vB0KynmhaU1aU4pZraaX/2r5IyeEwz3oU9kvYjtF3ivg9Uc6l1tRX7TU/WJOElB01UzX1ytX1jtvZaN7rhdrKf7QZalnRkoJpXlpK7pyqNKPug1q0Wv3DCWt+7UrWtb1cdrNW+UmvizKWEwr3oU3e28I8E0vo2vcKlba8J6cpVqipRjUz8U4+z7VnJq6SeR/TmjKt6XjCEqkqVT1ads6y2fXUL2ve2t/cmbKWGw8JKUKMIyV7OMIp676mDwdC7bjJ63s5OyeZSdley6yTFSWh+mKWZxtPSt6puyteyblv7Kckr8+7U3VfSNKFT1bcm1vaLaWidrrjZrRa6orL0ZhVFx9VdOOXVtu1lHRt6O0Y676GdbBUKknKUZNuzfWaTatra9r9WOvcKktnD0tQf9UrXir5ZWeZJrW23WW+xaq1owV5Oy/4v+CZz+jMNp1JdXbry7u//AEr5FypKErZo3yu6vzs1f6iktm8RTW84r4oPEQW8o/Mrww9GO0Hw48tjXKlQhrklvze/zNapa/Cals7mRQo4qlTVoxkle9u978TPpCHKX0GmXS2uAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLgKfSEOUvoOkIcpfQaZdFwuAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLgKfSEOUvoOkIcpfQaZdFwuAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLgKfSEOUvoOkIcpfQaZdFwuAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLgKfSEOUvoOkIcpfQaZdFwuAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLgKfSEOUvoOkIcpfQaZdFwuAp9IQ5S+g6Qhyl9Bpl0XC4Cn0hDlL6DpCHKX0GmXRcLNR2RzX6VjG2fPFPM4uyd1G+ZtJaaJv8A50N9TGwkrWkvgvMpyp0G7uCvmzewtZWau9dd3uNMui4WKPpSnOSjGcnd2Ty6c1rbiWvWNcefLkygvVa9Va79Ra33vqZwrQT2ffaKXC3MaZdFwyreklTlPNmUKavKdtErX4Rt9SOlqV2nKaa36vDM4t7bZlY1S9U5ZnFOX+ZwV9NtbkU6NFaRprfNpTT15795NMui4WaXpBTSa9ZrLKup3Xu9NF3s2V8V6uGZt2TS0V3rLLtbX4GiLSvaElfe0Phz5JGUpJpLLP4w77p78yayW09N0tetO8XK6y6pRbTdrb6XtvqX8NWU9U21rutU07NfNMoVMPTmpKVJvMmpfw9Wnur372b6NaNPTLJK1kstl8NS6yW1fs9/J0Puaf5StQxmPhTo+soupOUM0+UZZb20S4rbXfdl39n4pYLDPnRp/lR0CT5IcinjsXKrGLoZaeeKlKz1i4NtpcOtZd3EyrTxjlTyaRaqSnsn7UfVx1i9cremm251QRXCpY7HqVpUMycktrNLPUV21/pUPn3nSpTqSo05VYqM2k5RX9La2+BbInFPcsDlYqrVi3ki5aRy6aXUnnTfDq2/Q1SxOIT/AO3or3tFtb2zfLhudf1Me/5j1Me/5nTeOmac2tOs4txWWX8PTTRuSz62eye9uDK371ilFp0tVH2rN9a3Jb66acr7M7fqY9/zHqY9/wAxGcdLTmwr1XGTdOzT0Vn36d/DXbXuNznPMlbqtu+nBbFz1Me/5j1Me/5k2gpoNGL2XvL3qY9/zNOIppOH2v0LjlFpMPkJLGLEV8im811FttRjG8Mrjd5W7ZtkrNa3uYYCGKc6Gf10X6uKk224qPq5Jtp6Z8+V6q/wufRVfSihOUXBNRb9lpvLGMm3b/bs7P3h+maWaMck7yllVknrpvrprKC11vJDkKfOqniVLC61nlfWu5a/xNc1tF1desndaKzLmKrYlTqON/VqcIq1PNLI4pyml/U76W73vY7M/S1JVXTyyupRi3ZWvJtJ784snG+koUXBShKWeLleOWyScI6ttcakddt29EOQ1fO/vXpC8F6pdZRzPL7Lkkuf9Mk5PuaLnoyvXlKqq0bKL6jy2TV3z7rc13vhcf7R0NvV1b5VP2V7LV972e8dv8yLVX0nTjThUyScZwU00lona19e8sfpNmrSDZP0vSSbyydr/wCW+mm17/3rYmHpODqqm4NXeX+l63aadnpqv70v03npNWoFjHYz1Mqayxalu27PeK0W79rh8bXuaemKaSzU5p2V11Xa9+T1Wm/6mOb4asQWo4yMqMqsI7JtKTSvyvy+Jqr49wp0qip5lO97Pa0JS053y2Ly+6NWoGdD0kp0adTLBOc3BLNo7Skrxdtb5b8NCV6RvQ9bkinezWaNlpf2tnpyLH6TPo1awWKONUoTnk9l7Ravrwd7WlzRpfpmknFZJ3k8qsovXTez01cVrxkiT+tejViC7g8TCtTVSKaT4O19Pcb7LkTm+Grlg6llyFlyHN8NXLB1LLkLLkOb4auWDqWXIWXIc3w1csHUsuQsuQ5vhq5YOpZchZchzfDVywdSy5Cy5Dm+Grlg6llyFlyHN8NXLB1LLkLLkOb4auWC5LErLGSjo38V8DKnXUpZctnxvYc3w1USvjKc5RioNq0ruzaurPk1xsdapiIxSdnqr8L/ACMXi469V3V+HFb/AIP5Dm+GrhVKeKu3GaS1stHo3G17rV6S+DXHUynTxXCcXfNyW97Wdr2Wnfc7f73Dl+HK4rYjKqTjBNVJKLbdrJ8e8nIuri5MVr10nrbSPL3c9vqX8ApWtNtScbNp8bK7Vrd5YxWMUIpxg5fxYUpXTjbPKMcyuususttHzNWCx/rMOq0oe042grXWbLaLbe6zWe2zJOdxREKzo4xq/rYqV1L2m4pu+ZW0vFNRt73sZzWM1cZpPrW1TSvJNX6urtfutsjPpii1pCT1stEtXe3uXVevu5otyxEcsmo6qKl3a7a/AxOMw0rYb95U3nqdRqf+VtNybi1pwTtZmyu3aClLM0tW0ld6a2Rpj6YpSaUYNttLWyWrS3vydy9SrRlOcEneFr6aa8nxLETjNzCT/Wv0L/h+H+4h+VG+y5Gn0R/IUPuYflROMxCpUqlRq6hFytzsr2JA22XIWXIpVPSlOM5QldSUmlydoqW/+4L0rS/1X5KL1et7c7WZbF2y5Cy5FGt6UhBq6eR01UzdzdkrcxU9L0IrM3LLeyeV2b1btztlfyFi9ZchZcinh/SdOpNU7SjN5rJrfLKSev8AtZHS1G7V5OzadovS1rv3aixdsuQsuRQl6VjkqzjCUlBRa4ZszaVu7TcwXpmCdpRklZttapW/5shY6VlyI07jnV/S1JweWUleyUsrtdq6TfDQ41aFaVX1Sj/Evp3d9+Xedvy/Lkv+08n7/vl+eURGN2+rS1XvRli/6PtfoasPGUYwUpZpK15Wtdm3Gf0fa/Q5e3q9MbvluTd8kaI0YRlKcYKM52zSyvWysilgfRaoyjL1k55VZZo665m7tLnOT2JSupfuRDl3IjMu/wCTIctVv8nzQoZtvivmQ5PkipLB0/VunTXqlmzdVPfMpcfs2MsFQ9TTUM0pdZybalduUnJ73fHmKFnM97fEm/cjRCjTU3UUEpySUpWd2o7f37uRRh6MmlZ4mrLTjn/zX4S/521toJgdW75IXfJHIl6LqNP/AKuvqrXs/wDMmnv8Pj8DPo2V7qvWSvdJZktmraPa7v8AjfS0odNyfJDM+X4lN4eUqiqSnKLVlki5OFk78UvwN0KNNSlNQSnJJSkk7tLYtDfd8kLvkjj9ETyNLFVlJxyufWvbNdPfdbXLNHCzpzlJVJ1FJWyzcrLm1o/l/wAEoX7vkiHJ8kcqn6JlGMYxxFVKNtk1xva17fS/w0NmHwEqc4y9fWklFJxlmab01d78n8y0OlmfIXfI0RoU1KUlBKU7ZpJO7srI58PRMlFR/ea9kopWc17Nu/itP+dWmB17vkMz5HH6Ilt+8VbXm3G0rPNrqr8Hyt8Nb5S9Fzaa/eq6fPrd99L8dG/pZaKUOrmd7WJzPkaZQjKLhJOcXHK8yeqtrc01sKpRhCEpUowasoKS0StbS398GWoFzM+QzPkcuXo2TTvia2Z31WZJXd/Zvtuvj3IypYKVOoqiqTqSSkrTcrdZp99rWS2JQ6WZ8iMzvaxzI+jZJq1eqkmnl61tFa2j+P43NuFwShTlTqSlWU/ac09bpK30RaF/M+QzPkUcVgY1Iwim6cYNWUU7WVtPoY4DAOjK/rako5WsrTypuWbMKHQzPkiMzvaxGb3/ACZrqwjNSjOOaMlZpp6pihuzPkMz5FDGYCNWMIpunGOyinsrafQwwmCnQbcakqiaaySzKKvJttaPXX8dRQ6WZ8hmfI5tDBTpwcI1ZyUoKGZuScLXWaCs1ezWmi6qNGI9FVHF5MRUztNJvPZJ5dtb6ZbrXW+rZKHYzPkTmfIpUsHFU5053qQlupJ6K0VZW29m/vZGMwbqKKhUnRUU1/DT2ccq+W6LQu342VxmfI5fRcuq/wB5rZotNvXrJJLL3LS+nHmW8HSdKnGEpyqON+tJO71vr+AoWrvkLvkilUwUfUypUr0U7u8FK6babf0t7iu/RcmpXxNdtuTi9erfkttBMDq5nyRC02SV9zmwwVSMKkHVnUVSOVuea8erlbirO7e/Az/dZqEoKpNqTvnblmjt1UuTtwa3drEoX83cTd7WsUsJhPVSbdSdRtJNzTe0m/wdtORM8HBUnSpXoq9+opc03tZ62tvsWhbv3InM+Ry5ejJ3usTXXd1nrmvz+BjS9EuKSWIqqKy6LMr2txvxS1e+1rapyh0PRH8jQ+5h+VGyUU000mmrNPZrkzX6I/kaH3MPyoyruShJw1kk7e8QNccDQSSVKnZXt1VpfcwxHo6jUhlcEl3Jc7/iap4qum8tJtauLad7Zrar3a23Mq1evGatTzJqPVts79brfH3ad4G+WEpOKjKEZJJRV1fRbLUxeAoO/wDCp62v1Vw0X0b+ZolicRwp8tbS11XDhx+VzKpiayhBxpNyad1Z7rb3X7wN8MJSjLOqcFK7eZRV7u93f4v5vmI4Kir2pwV9+quJo9dXbmsqVozs7OzkrZX8ddDWq+Ji2nDMr2V1bS2+nN/j3AXIYSlHMlTgs2srRWr7yJYOi96cHv8A0rjv+JpVeu1O8EmoXi0m1e23e/dy7yf3itkv6vXMlaz2trb46X24gbXgqLVnShbe2VW0Vvw0NuVXvZX2vxtyKEcVib60eKVte+/6K+3HiWMLVqSbzxsrRto1rrmWvw/HiVFlbr3r8ScVvD7X6Mhbr3r8TLFbw+1+jHtUWHyJYRiymqdNuUZJ2yt6XdndNa/QyrRcotJ2bTSffwMkOIVReBqKWlVuPBNvayVm767b6btmzB4adO+ao53UUr81u/jf6FsMCg8DUeb+I1mzbSlpdNK2vem++PfpnLC1bNKra9TPxel08vDT/wBbFwAVMLhakJXlVc1Zrjrd3T+C/FlsAAyj+51NOvz1vK97rr776PTbX4F5gDXh6bjBRbu9efFtpa8k7fA2AAAABy3QlOFlidczd03tKNpLfbVtctORMcPVTusSktb/AKPX+9TRXq0IyjmhU/hpuKcrpJScLWv/AKX/AHsq0MPKlKajNONqaUXeVtErLa7VgOnQi4KWaeaN+rd7Lk2bzjQxWFjGUOsoudtNU2rPMmu62/L3nTw1dVI3SkrNq0t9G1+gG0kgkAAABVxybgv4nq+te/NpXS04XV33J8C0a6lJT3urO6admtLb+5sChWws3NyWIsm5Wjd6Xaut+5e675mSoVcr/wCoTlvB6WWttefFG6Poyir9V3k7ttu97Nb+5muPoeimt2ldpN8Xu/iBfACAAAAAACAQAEcSSOIEgAAAAMK0ZNNRdnz+JpxGHnOKSm1JKzabV9vLvtcsgCjQwVSM4ydVySbum3rf+/gXgAK3ob+Qw/3EPyozrOShJwScraJ8zX6F/wAPw/3EPyo2V1JwkoO0rO3vNIpurinl/hparNtZ6PT2tNba/iQquLdk6cUtLtWvvrpm5W+Znkrp3jdR0WWUlKSV5Xab/qta120Yr9709i91fa3G9uNtu+/cBmqmJyR6kVNt5uS1Vv6uV+e2xDqV1likpNQi5Sa1zXs1a6XfvwEo4hwg79dXulZXu0lfg7K5i1i2l7KfHayfd3W+N+4DbRqV3JZ4RjFJ343d3ZJ32tbhzNCqYvTqKzabfV0XFJZu76/LdNYjMlHSOWN28rd7q/xtfuMPV4iUZ5nlbyWytJaSea3+231An1mJcIvIlLP1krPq5Xr7XPvJqVcT1MtOLvHrvTR2eyzc0tO/fitShi1ezTvmavZ200X4/Q6KXffvAqKeIyrqpyza3SWltP6tPfd+5m7DSqOP8RJS0222V+L2d0bgUFuvevxMsVvD7X6MxW696/EyxW8Ptfox7BhBhGFQhxCHECQwGAAAAAAGAwAAAAAAUFPEqzyZtHdPL7X+mz9m/PUj12L0fqYaxbauurLXTfU0uGay/erKEYx9lxjdap3vq7cn9DOUbJ3xitdcdbrvvpe93p8loB0Kd3FOUbNpXXJ8jMq0KnqqUfWzTbzO6baa1lo3q7R/AzjjKTaSmm3a2/G1vd7S+aA3EkEgAAACAQAAAAgEAAAAAAEAgAI4kkcQJAAAAAAAAAAFX0J/h+H+4h+RG2qpOLUXaVtHyNPoT/D8N9xD8iNteDlCUU7NppO9tfeaRSnRxWqVRWs9dL3y87czL1WJSspp8r25LR6a63t9bmVGlXVRZppx4692uluL17u8iOGrdZuos2WUYvezduta3NbcAIhQr5akZT0cXld1mTffb/1w7jpYrZVFtv1d7K39PO/wtxCoYm+tRWttd91tbcNdePESwlX1ORVNed3tks1e3+bX6AZVqFd5bVGrZrvTXVZG1a2y+pMYYjJNOcczl1WktFy2931NM8NiXmaqRu721dkmlbS3NN/Q316NZybhNJX0120ttbg9e/YDX6rFXt6xZedlf2vdvYyhHE5o3ccqfWStqrvu00t8viYxw1eyj6xJRtqnq9OOnO3yN2HpVIvrzzX+netANSpYhynedk1NRs1o3bK9uFn8yKdLEqUeunG7cr2bs5bXttl+vcXwUFuvevxMsVvD7X6MxW696/EyxW8Ptfox7BhBhGFQhxCHECQwGAAAAAAGAwAAAAAAcerVpQThKkravrTtezdNa200S+a72bMM6MtqeXKnl6z1UWpW+qdu58jY54xxlaNNO2ltXfXX2rcv70NlV4n1jyqnkWz4ysno+67+neBThj6LhCE6crWeVKV0rKS9rTS3HhfhYsYOhh6sW1RSyyas9nbZ72fv/Hc24SWIvaqo5bPVb5r6LfkWwIRJBIAAAAgEAAAAIBAAAAAABAIACOJJHECQAAAAAAAAABU9B/4dhvuIfkRtr1VCEptNqKbst3bgjV6C/wAOw3/x4fkRnjKsYUpzkrxjFuS/0rf6G4/qNS9IUnazbu0lZN3bdl+vfZM2PGU05LNrHR6PTVL9V8zlU/S2FacnSyvV2yq7d3L5u8ZX/wBa7zfLG4aUk3TvmlZtw2af/wDV/ianDKPSLax9JpuLby5bpRd1mdlox0hR0eeydrNppO/J2/8ARVqekqFOdRTg4qN80sunUs76e81z9IYGzUoq2W7Tp7r2bJW13t8Rpl0rofvlPMo3d2k1o7Wlt+nzRjP0hRi7Odne1rPV3a0011TRpxGMw0atpq9RKLXVu2rq1uerRXWOwcZybvmbbd4veMpLT/cpfFe4aZdC/LG01ZNu7UZWyu9pOyb+Zh0nRtfM7c8srLW1m7b3VrFZ4/CSsst9EknTeqspWWnBWZrq+k8HFS6t8rm7KO8oxzOz2vZ6ajTLoXukIP2VKS6uqWnWbSte19VwuWyngqlCo5+rjZxeWXVs7q9vhuXDMxMeQW696/EyxW8PtfozFbr3r8TLFbw+1+jHsGEGEYVCHEIcQJDAYAAAAAAYDAAAAAAByfVU2m1ipJ5dZX3XPffv7/gTGnSVLJHEuOuZSjJXWn4cbGKq09/3Wfdpre+qf97myh6ubnL1DjaCtmvwvpZcrLvA2YOhTU5ThVcr2ur301tfXX/gvnKo1VBVJKm4u0Gld2vd9Xbm2+XW3sdCnWzTlHK1ltrwd1wYGwkgkAAAAQCAAAAEAgAAAAAAgEABHEkjiBIAAAAAAAAAAqegv8Ow3/x4fkRYaTTTV090aP2fV/R+F+4p/kRe9Su/5mrRUeGpt3dODf2VyS/BL5IRw1NbU4L3RRb9Su/5j1K7/mXYpVdCF28kbvd2V37/AJIx/dKVreqp2tb2Vstl7i56ld/zHqV3/MbCpPD05XcoQldWd4p3XJ9weHpveEHuvZWz3XxLfqV3/MepXf8AMbCo8NTas6cGuWVW4eS+SI/daW/q4cf6Vx3+Zc9Su/5j1K7/AJjYpWp0oQvljGN9XZJXfwMzd6ld/wAx6ld/zJY0rde9fiZYreH2v0ZsVJGrFbw+1+jEeRLCDCMqhDiEOIEhgMAAAAAAMBgAAAAYAFGlCupXnUjJWkrJ21u7W5WX4GTjXyxVOcX1F1nreWt37tvr3GlUcPUi7N2btorWzua0051JK68zJyp06izuaUY5Lys4O93d2/F7fEDY3U/+okoqLbTVt3e+ml1lN2HbjBKpJZrtb97svfbT4FWjgaU6byTk4zjGKae2TTTTR6am1+joXi7yTWV6W1cW3d6cczAtEkEgAAACAQAAAAgEAAAAAAEAgAI4kkcQJAAAAAAAAAAFb9nv5DC/cU/yI6Bz/wBnv5DCfcU/yI6IAAAAAAAAAAAAAAK+K3h9r9GWCvit4fa/Rlx8pIwgwiKhDiEOIEhgMAAAAAAMBgAAAAAA5frJdVfu2a7SaUHFR1vZt7pPjsyauMm7v90m7Wesbt6acNH+GpNKjiEnavCTaypt3s4t34O73X/ommsS8yVak2klpa8Xztbuf96AbKGInmjBUHCN3rrZKzfKy1t8+PC6U6lDEOGWNVX161le1lyjzzfNa6WdtWtvtvr+IAkiLT1TunqmSAAAAIBAAAACAQAAAAAAQCAAjiSRxAkAAAAAAAAAAVv2d/kMJ9xT/IjonO/Z3+Qwn3FP8iOiAAAAAAAAAAAAAACvit4fa/Rlgr4reH2v0ZcfKSMIMIioQ4hDiBIYDAAAAAADAYAAAAAAOLQqYVPOnOLglO8us03eL566q/vViakcLN1JfxHKKc5Jaezd221er7/cWIuq/wDxQta6vTtxffvb8TLPVs/4KcnK0rJK8Pj8V8O8CjJYVRUpup7burJZWt7pLTS3/Gpaw+Fw84unHM8sru64pJb25JbG3BKbl/EpQjaKtaKWvLjxv7tC7GCWyS9yAiMbKy2WhkQSAAAAIBAAAACAQAAAAAAQCAAjiSRxAkAAAAABBIAAAVv2d/kMJ9xT/IjonO/Z3+Qwn3FP8iOiAAAAAAAAAAAAAACviPap/a/Rlg0Yj2qf2v0ZcfKSySd3pz4Bx7jYwiCtVc1UpqMW49bO7K3ct7393J919ldPK8qvLK7JWvfgtdDbEcQrnN4pStljJLZ6JPRavlrd2t3e/bg3Wd/XRS0hy9r+q1n7vqXSJAc1yxV5Wgl7WXMo8na9nzUbdzd9jY5YiztBN+t45f8At3Wy93P/AIL4Ap4NVf8AypezyV813d6d2XTh3lvKuSJAGMorkjnt4jTqPjfSFs2llv7Fr67/AIHRkSBowqk4LOrSu+V7Xdr20vaxuyrkiQBGVckQ4rkjIhgc2dbFZUo0VfIrtte3xSV9tuPHuM5V8RluqCcs9rXXs6a797+XeVqVHR5MWoxvqrWV2la93e9734v4G6P8OnJvE5syyqVnK0tlZJvXVAZSnievanFNWy7a6q735X0/E24WdZyaqU4xSWkk93fe3eU40ErWxaSirJPRqOiSeq1WnDffkKGGk24rFXmk9Iu/V1XPu+FgOsoq70QyrkjGlFpJN5mkk3zdtzYBGVckMq5IkARlXJGis5JxyxzdbrLTbK+ffYsFbFYZ1cqUnHLNSdr6q22jXMCoq+L6rdCPG6TXNWd78rm2dXEZpWoxyq9m2rvlx+P0MZej6kqbjKs5NyunKO2/C/8Adg8BWv8AzMrXfDhwW/1At4dScIuaSlZZlbjxNiitdERSi4xSbzNK1+feZLiAyrkhlXJEgCMq5IZVyRIAwUVroTlXJBcTICMq5IjKr7IyI4gMq5IZVyRIAjKuSGVckSAMMqvsjLKuSI4mQEZVyQyrkiQBzv2d/kMJ9xT/ACI6Jzv2d/kMJ9xT/KjogAAAAAAAAAAAAAA0Yj2qf2v0ZvNGI9qn9r9GXHyktz2CD2CIpEcREcQJIkSRICQAAAAESJIkSAAAAxZkQwORUqU3NxdF3UZu6nZ/9xp7e5v424my1NR1pWUZpWTbTSaindrnFadyM08WtUlLR3Ususrf02tZX56hVMZZXhTu1quT10vm93zfKzClGvQnJN0Em1Z9d7Sk7256ylbnZ91+nhKNNxjUimm0v6m7f6fcao1MXlbdOGa6tG6tbW739xnhXiM8VNQUFH+laX0034a/3oBbW7MjFbsyAAAAQuJJC4gSAABC4kkLiBIAAAADFcTIxXEyAEcSSOIEgAAAAMeJkY8TIAAAOd+zv8hhPuKf5UdE537O/wAhhPuKf5EdEAAAAAAAAAAAAAAGjEe1T+1+jN5oxHtU/tfoy4+UluewQewRFIjiIjiBJEiSJASAAAAAiRJEiQAAAEMkhgcajBOLk8XbT/M9E9E3d8b/AD+RPq6bzZsW3rfWTVrcVqY/vFBpf9PNpxT2urXWnfzsuKNlCdOo+th3HLC7lL5tX+L394Gc6UUoxeJnmck1Z6uMrJL3Xtr7zfgsB6l3U5S0d09ndp3tz3+ZXnXhCdlh5NU1ZNLbLbLb5s34f0g6k1H1U4q17y0100+rAuLdmRit2ZAAAAIXEkhcQJAAAhcSSFxAkAAAABiuJkYriZACOJJHECQAAAAGPEyMeJkAAAHO/Z3+Qwn3FP8AKjonO/Z3+Qwn3FP8qOiAAAAAAAAAAAAAADRiPap/a/Rm80Yj2qf2v0ZcfKS3PYIPYIikRxERxAkiRJEgJAAAAARIkiRIAAACGSQwOdSjWjPrTjkaaUc2t23bX+9uGxneqkoqpF9RxzNrN63+/wBCqvUxyyk5xcLXaS/8efVtX3UZJ662sZKhQlON5zTclUinbRtvTTbVa99gNsoYlRknOKbUFDXim7rXi9OJtqrEtvJKCWluPK//AO307zVUpxUVK9SSdbM11d7tZXf+lNcOXI34HEUXFU6cto3UbWaXu4b/AIAWY95kYrdmQAAACFxJIXECQAAIXEkhcQJAAAAAYriZGK4mQAjiSRxAkAAAABjxMjHiZAAABzv2d/kMJ9xT/KjonO/Z3+Qwn3FP8qOiAAAAAAAAAAAAAADRiPap/a/Rm80Yj2qf2v0ZcfKS3PYIPYIikSOJMRxAkiRJEgJAAAAARIkiRIAAACGSQwOV+8T6qeHzZnZpQaUW+Db3Su9Vo7mM8U0m1g5WSVurq47pbaa204amVKjiUnavCTayJt7OLd+Du91/6MqaxTzJVqUpJJaWvF8W1bmn/egGdGtJzjD1DjFybbab4N323vbfnx4XYUYRd4xinzSSKdWhiXDLGqr3fW0vay/087/TXSzvRaStfbR6/iAW7MjGEk9U7p6poyAAAAQuJJC4gSAABC4kkLiBIAAAADFcTIxXEyAEcSSOIEgAAAAMeJkY8TIAAAOd+zv8hhPuKf5UdE537O/yGE+4p/kR0QAAAAAAAAAAAAAAaMR7VP7X6M3mjEe1T+1+jLj5SW57BB7BEUiOIiOIEkSJIkBIAAAACJEkSJAAAAQySGBw8PPCJ+sTqRcEp5pLM03eLtvrqrpaaqwqRwsnUleo5RvOSWlrXdtld6vv9xYi6sm/4ULWur07bNrny/EycquV2oRcnKzdtMnxs3y+D7gKTjhVBSnKp7bdrJZXHe6Ssla3/Baw+Ew84ulFyeWV3dcUlHe3JLYs4Om2+vThG0Y2tG2t5X/BPuuW4witkl7kBEIpaLZWRmYrdmQAAACFxJIXECQAAIXEkhcQJAAAAAYriZGK4mQAjiSRxAkAAAABjxMjHiZAAABzf2d/kMJ9xT/KjonhlH0vi6cVCGJrwitoxqSSXuSZn07je14jxZ+YHuAPD+ncb2vEeLPzHTuN7XiPFn5ge4A8P6dxva8R4s/MdO43teI8WfmB7gDw/p3G9rxHiz8x07je14jxZ+YHuAPD+ncb2vEeLPzHTuN7XiPFn5ge4A8P6dxva8R4s/MdO43teI8WfmB7gaMR7VP7X6M8W6dxva8R4s/MP03je14jT/7s/MsTQ9wewR4h07ju14nxp+Y6dx3a8T40/Mg9viOJ4h07ju14nxZ+Y6dx3a8T4s/MD3AiR4h07ju14nxp+Y6dx3a8T4s/MD3AHh/TuO7XifGn5jp3HdrxPjT8wPbweIdO47teJ8afmOncd2vE+LPzA9ukSeIdO47teJ8WfmOncd2vE+LPzA9vB4h07ju14nxZ+Y6dx3a8T4s/MD28hniPTuO7XifFn5jp3HdrxPiz8wPbweIdO47teJ8WfmOncd2vE+LPzA9vB4h07ju14nxZ+Y6dx3a8T4s/MD25bsk8Q6dx3a8T4s/MdO47teJ8WfmB7eDxDp3HdrxPiz8x07ju14nxZ+YHt5C4niPTuO7XifFn5jp3HdrxPiz8wPbweIdO47teJ8WfmOncd2vE+NPzA9wIXE8Q6dx3a8T40/MdO47teJ8WfmB7gDw/p3HdrxPjT8x07ju14nxp+YHuAPD+ncd2vE+NPzHTuO7XifGn5ge3LiZHh/TuO7XifFn5jp3HdrxPjT8wPcCOJ4h07ju14nxp+Y6dx3a8T4s/MD3AHh/TuO7XifGn5jp3HdrxPjT8wPcAeH9O47teJ8afmOncd2vE+NPzA9u4mR4f07ju14nxZ+Y6dx3a8T40/MD3Ag8Q6dx3a8T40/MiXpvGyTTxeIaejTqzs18wKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/Z\n", "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import YouTubeVideo, HTML\n", "\n", "display(HTML(\"

Video - Using OpenRefine to extract Ruskin record from CMA data

\"))\n", "\n", "YouTubeVideo('npVMbybZ3p8', width=1024, height=576)" ] }, { "cell_type": "markdown", "id": "624d1296", "metadata": {}, "source": [ "### Collection Data for John Ruskin\n", "\n", "The following table shows the relevant collection input data for illustration, and a digital image of the artwork is shown beneath.\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "05a28564", "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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0
id154494
accession_number1989.14
share_license_statusCC0
tombstoneBudding Sycamore, c. 1876. John Ruskin (Britis...
current_locationNaN
titleBudding Sycamore
title_in_original_languageNaN
seriesNaN
series_in_original_languageNaN
creation_datec. 1876
creation_date_earliest1871
creation_date_latest1881
creatorsJohn Ruskin (British, 1819-1900), artist
cultureEngland, 19th century
techniqueblack and gray wash, gouache, and graphite
support_materialsthick, moderately textured cream wove paper
departmentDrawings
collectionDR - British
typeDrawing
measurementsSheet: 34.8 x 44.8 cm (13 11/16 x 17 5/8 in.)
state_of_the_workNaN
edition_of_the_workNaN
creditlineAndrew R. and Martha Holden Jennings Fund
copyrightNaN
inscriptionssigned and inscribed, in brown ink, at lower r...
exhibitionsCURRENT: The Year in Review for 1989 (Feb 06, ...
provenanceG.R. Roxburgh (?-?); (Artemis Fine Arts, Londo...
find_spotNaN
related_worksNaN
former_accession_numbers[]
fun_factThis drawing was used as an illustration in Jo...
digital_descriptionThe most influential art critic in Britain dur...
wall_descriptionThe most influential art critic in Britain dur...
external_resources{'wikidata': [], 'internet_archive': []}
citationsCook, Edward Tyas and Alexander Wedderburn. <e...
catalogue_raisonneNaN
urlhttps://clevelandart.org/art/1989.14
image_webhttps://openaccess-cdn.clevelandart.org/1989.1...
image_printhttps://openaccess-cdn.clevelandart.org/1989.1...
image_fullhttps://openaccess-cdn.clevelandart.org/1989.1...
updated_at2021-03-27 12:16:10.046000
\n", "
" ], "text/plain": [ " 0\n", "id 154494\n", "accession_number 1989.14\n", "share_license_status CC0\n", "tombstone Budding Sycamore, c. 1876. John Ruskin (Britis...\n", "current_location NaN\n", "title Budding Sycamore\n", "title_in_original_language NaN\n", "series NaN\n", "series_in_original_language NaN\n", "creation_date c. 1876\n", "creation_date_earliest 1871\n", "creation_date_latest 1881\n", "creators John Ruskin (British, 1819-1900), artist\n", "culture England, 19th century\n", "technique black and gray wash, gouache, and graphite\n", "support_materials thick, moderately textured cream wove paper\n", "department Drawings\n", "collection DR - British\n", "type Drawing\n", "measurements Sheet: 34.8 x 44.8 cm (13 11/16 x 17 5/8 in.)\n", "state_of_the_work NaN\n", "edition_of_the_work NaN\n", "creditline Andrew R. and Martha Holden Jennings Fund\n", "copyright NaN\n", "inscriptions signed and inscribed, in brown ink, at lower r...\n", "exhibitions CURRENT: The Year in Review for 1989 (Feb 06, ...\n", "provenance G.R. Roxburgh (?-?); (Artemis Fine Arts, Londo...\n", "find_spot NaN\n", "related_works NaN\n", "former_accession_numbers []\n", "fun_fact This drawing was used as an illustration in Jo...\n", "digital_description The most influential art critic in Britain dur...\n", "wall_description The most influential art critic in Britain dur...\n", "external_resources {'wikidata': [], 'internet_archive': []}\n", "citations Cook, Edward Tyas and Alexander Wedderburn. " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "try:\n", " from PIL import Image\n", "except:\n", " %pip install Pillow\n", " from PIL import Image\n", " \n", "import requests\n", "\n", "url = \"https://openaccess-cdn.clevelandart.org/1989.14/1989.14_web.jpg\"\n", "image = Image.open(requests.get(url, stream=True).raw)\n", "\n", "print(\"Budding Sycamore\")\n", "image" ] }, { "cell_type": "markdown", "id": "97157ea9", "metadata": {}, "source": [ "### Remove Byte Order Marks and Define Data Mapping\n", "\n", "`mapp` holds the data mapping between entities in the Linked Art data model and the CMA data model" ] }, { "cell_type": "code", "execution_count": 12, "id": "b3a96abd", "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", " \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", " \n", " \n", " \n", " \n", " \n", "
0
idid
accession_numberaccession_number
accession_date
classificationtype
titletitle
alt_titletitle_in_original_language
notestombstone
date_createdcreation_date
date_created_earliestcreation_date_earliest
date_created_latestcreation_date_latest
created_periodculture
created_dynasty
created_inscriptionsinscriptions
created_notesfun_fact
creatorNaN
physical_mediumMedium
physical_style
physical_techniquetechnique
physical_description
physical_dimensionsmeasurements
created_provenanceprovenance
credit_linecreditline
collectiondepartment
current_statuscurrent_location
current_owner
homepageurl
\n", "
" ], "text/plain": [ " 0\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 NaN\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_owner \n", "homepage url" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "\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", "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\":\"creator\",\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_owner\": \"\",\n", " \"creator\": {\"name\": \"John Ruskin\"},\n", " \"homepage\": \"url\"\n", " \n", " \n", "}\n", "\n", "# display transposed dataframe of data mapping\n", "display(pd.DataFrame(mapp, index=[0]).T)" ] }, { "cell_type": "markdown", "id": "5793ed01", "metadata": {}, "source": [ "### Transform Collections Data to Linked Art JSON-LD\n", "\n", "This next step uses the following to transform the collections data to Linked Art JSON-LD\n", "\n", "- the data mapping\n", "- custom coding in createObjProp()\n", "- `cromulant` Python library\n", "- custom coding in `la` including createObjDescription()" ] }, { "cell_type": "code", "execution_count": 13, "id": "a76779e6", "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", " \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", "
0
id154494
accession_number1989.14
notesBudding Sycamore, c. 1876. John Ruskin (Britis...
current_status
titleBudding Sycamore
alt_title
date_createdc. 1876
date_created_earliest1871
date_created_latest1881
created_periodEngland, 19th century
physical_techniqueblack and gray wash, gouache, and graphite
collectionDrawings
classificationDrawing
physical_dimensionsSheet: 34.8 x 44.8 cm (13 11/16 x 17 5/8 in.)
credit_lineAndrew R. and Martha Holden Jennings Fund
created_inscriptionssigned and inscribed, in brown ink, at lower r...
created_provenanceG.R. Roxburgh (?-?); (Artemis Fine Arts, Londo...
created_notesThis drawing was used as an illustration in Jo...
homepagehttps://www.nga.gov/collection/art-object-page...
image_urlhttps://clevelandart.org/art/154494
creator{'id': 'https://clevelandart.org/art/creatorid...
\n", "
" ], "text/plain": [ " 0\n", "id 154494\n", "accession_number 1989.14\n", "notes Budding Sycamore, c. 1876. John Ruskin (Britis...\n", "current_status \n", "title Budding Sycamore\n", "alt_title \n", "date_created c. 1876\n", "date_created_earliest 1871\n", "date_created_latest 1881\n", "created_period England, 19th century\n", "physical_technique black and gray wash, gouache, and graphite\n", "collection Drawings\n", "classification Drawing\n", "physical_dimensions Sheet: 34.8 x 44.8 cm (13 11/16 x 17 5/8 in.)\n", "credit_line Andrew R. and Martha Holden Jennings Fund\n", "created_inscriptions signed and inscribed, in brown ink, at lower r...\n", "created_provenance G.R. Roxburgh (?-?); (Artemis Fine Arts, Londo...\n", "created_notes This drawing was used as an illustration in Jo...\n", "homepage https://www.nga.gov/collection/art-object-page...\n", "image_url https://clevelandart.org/art/154494\n", "creator {'id': 'https://clevelandart.org/art/creatorid..." ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "file = './data/cma/input/ruskin.csv'\n", "\n", "# open collection data input file \n", "allObjects = csv.DictReader(open(file, mode='r',encoding='utf-8'))\n", "\n", "# iterate through row - only 1 in this case \n", "for obj in allObjects:\n", " \n", " # create object property dictionary\n", " objProp = createObjProp(obj,mapp)\n", "\n", " id = objProp[\"id\"]\n", " object_uri = baseURI + id\n", " \n", " # define \"image_url\" property\n", " objProp[\"image_url\"] = \"https://clevelandart.org/art/\" + id\n", " \n", " objProp[\"creator\"] = [{\"id\": baseURI +\"creatorid/JohnRuskin\" ,\"name\": \"John Ruskin\",\"role\":\"Artist\"}]\n", " \n", " # create Linked Art representation using `la` and cromulent\n", " objLA = la.createObjDesc(objProp,la.objTypes,object_uri)\n", " \n", " # write Linked Art to file \n", " text_file = open(outputdir + \"/\" + id + \".json\", \"wt\")\n", " \n", " # use cromulent to write file \n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " \n", " text_file.close()\n", " \n", " display(pd.DataFrame(objProp, index=[0]).T)\n", " \n", " \n", "# custom coding to create dictionary to be used to create Linked Art JSON-LD\n", "def createObjProp(obj,mapp):\n", " objProp = {}\n", " \n", " # iterate through keys in csv collection data input file\n", " csv_keys = list(obj.keys())\n", " for key in csv_keys:\n", " # iterate through the data mapping\n", " for prop in mapp:\n", " if key == mapp[prop]:\n", " \n", " if prop == \"classification\":\n", " objProp[prop] = \"Drawing\"\n", " ## define custom mapping for the creator property\n", " else:\n", " objProp[prop] = obj[key]\n", " return objProp " ] }, { "cell_type": "code", "execution_count": 14, "id": "9f6e57b6", "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/154494.json';var selector = '#viscma';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "with open('./src/js/visld.js', 'r') as _jscript:\n", " code = _jscript.read() + \"var file = '\" + outputdir + \"154494.json';var selector = '#viscma';visjsonld(file, selector); \"\n", " display(Javascript(code))" ] }, { "cell_type": "markdown", "id": "ff76773f", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "b5d5b83f", "metadata": {}, "source": [ "## Tate Museum\n", "\n", "The Tate, is located in the UK and has three items by John Ruskin in its Collection data, published in its GitHub repository. The date are available in separate JSON files and in a CSV file. The exercise will use the [CSV file](https://github.com/tategallery/collection/blob/master/artwork_data.csv). \n", "\n", "- ruskin-an-olive-spray-and-two-leaf-outlines\n", " - [web page](https://www.tate.org.uk/art/artworks/ruskin-an-olive-spray-and-two-leaf-outlines-n02726)\n", " - [data file](https://raw.githubusercontent.com/tategallery/collection/master/artworks/n/027/n02726-13031.json)\n", "- ruskin-the-north-west-angle-of-the-facade-of-st-marks-venice\n", " - [web page](https://www.tate.org.uk/art/artworks/ruskin-the-north-west-angle-of-the-facade-of-st-marks-venice-n02972) \n", " - [data file](https://raw.githubusercontent.com/tategallery/collection/master/artworks/n/029/n02972-13032.json) \n", "- ruskin-view-of-bologna\n", " - [web page](https://www.tate.org.uk/art/artworks/ruskin-view-of-bologna-n03507) \n", " - [data file](https://raw.githubusercontent.com/tategallery/collection/master/artworks/n/035/n03507-13033.json) \n", " \n", " #### Further Reading \n", " \n", "- [The Tate Collection GitHub repository](https://github.com/tategallery/collection)\n", "- [The Tate Collection web page for artist John Ruskin](https://www.tate.org.uk/search?type=artwork&q=john+ruskin)\n", "- [The Tate data file for artist John Ruskin](https://github.com/tategallery/collection/blob/master/artists/r/ruskin-john-465.json)\n", "- [The Tate data file for artworks CSV file ](https://github.com/tategallery/collection/blob/master/artwork_data.csv)\n" ] }, { "cell_type": "markdown", "id": "6d662c5b", "metadata": {}, "source": [ "### Collection Data for Ruskin\n", "\n", "The collection data contained in the CSV file is extracted using OpenRefine in the same process as was used for the CMA data above. The resulting CSV file is shown below:" ] }, { "cell_type": "code", "execution_count": 41, "id": "2f91855c", "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", " \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_numberartistartistRoleartistIdtitledateTextmediumcreditLineyearacquisitionYeardimensionswidthheightdepthunitsinscriptionthumbnailCopyrightthumbnailUrlurl
013031N02726Ruskin, Johnartist465An Olive Spray and Two Leaf Outlinesbefore 1877Graphite, watercolour and ink on paperPresented by Sir Claude Phillips in memory of ...1831.01910support: 375 x 279 mm375279NaNmmNaNNaNhttp://www.tate.org.uk/art/images/work/N/N02/N...http://www.tate.org.uk/art/artworks/ruskin-an-...
113032N02972Ruskin, Johnartist465The North-West Angle of the Facade of St Mark’...date not knownWatercolour and graphite on paperPresented by the Art Fund 1914NaN1914support: 940 x 610 mm940610NaNmmNaNNaNhttp://www.tate.org.uk/art/images/work/N/N02/N...http://www.tate.org.uk/art/artworks/ruskin-the...
213033N03507Ruskin, Johnartist465View of Bolognac.1845–6Ink and watercolour on paperPurchased 19201845.01920support: 343 x 489 mm343489NaNmmNaNNaNhttp://www.tate.org.uk/art/images/work/N/N03/N...http://www.tate.org.uk/art/artworks/ruskin-vie...
\n", "
" ], "text/plain": [ " id accession_number artist artistRole artistId \\\n", "0 13031 N02726 Ruskin, John artist 465 \n", "1 13032 N02972 Ruskin, John artist 465 \n", "2 13033 N03507 Ruskin, John artist 465 \n", "\n", " title dateText \\\n", "0 An Olive Spray and Two Leaf Outlines before 1877 \n", "1 The North-West Angle of the Facade of St Mark’... date not known \n", "2 View of Bologna c.1845–6 \n", "\n", " medium \\\n", "0 Graphite, watercolour and ink on paper \n", "1 Watercolour and graphite on paper \n", "2 Ink and watercolour on paper \n", "\n", " creditLine year acquisitionYear \\\n", "0 Presented by Sir Claude Phillips in memory of ... 1831.0 1910 \n", "1 Presented by the Art Fund 1914 NaN 1914 \n", "2 Purchased 1920 1845.0 1920 \n", "\n", " dimensions width height depth units inscription \\\n", "0 support: 375 x 279 mm 375 279 NaN mm NaN \n", "1 support: 940 x 610 mm 940 610 NaN mm NaN \n", "2 support: 343 x 489 mm 343 489 NaN mm NaN \n", "\n", " thumbnailCopyright thumbnailUrl \\\n", "0 NaN http://www.tate.org.uk/art/images/work/N/N02/N... \n", "1 NaN http://www.tate.org.uk/art/images/work/N/N02/N... \n", "2 NaN http://www.tate.org.uk/art/images/work/N/N03/N... \n", "\n", " url \n", "0 http://www.tate.org.uk/art/artworks/ruskin-an-... \n", "1 http://www.tate.org.uk/art/artworks/ruskin-the... \n", "2 http://www.tate.org.uk/art/artworks/ruskin-vie... " ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "baseURI = \"https://www.tate.org.uk/art/artworks/\"\n", "file = './data/tate/tate-artwork_data.csv'\n", "\n", "mpg = pd.read_csv(file)\n", "mpg.head()\n" ] }, { "cell_type": "markdown", "id": "d109cd3b", "metadata": {}, "source": [ "### Data Mapping for The Tate\n", "\n", "The `mapp` below shows the data mapping between entities in The Tate data model and Linked Art data model" ] }, { "cell_type": "code", "execution_count": 42, "id": "292c9fb0", "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0
idid
accession_numberaccession_number
accession_dateacquisitionYear
classification
titletitle
alt_title
notes
date_createddateText
date_created_earliestyear
date_created_latestyear
created_period
created_dynasty
created_inscriptionsinscription
created_notes
creatorartist
physical_mediummedium
physical_style
physical_technique
physical_description
physical_dimensionsdimensions
created_provenance
credit_linecreditLine
collectionDepartment
current_status
current_ownerTate Museum
image_urlthumbnailUrl
homepageurl
\n", "
" ], "text/plain": [ " 0\n", "id id\n", "accession_number accession_number\n", "accession_date acquisitionYear\n", "classification \n", "title title\n", "alt_title \n", "notes \n", "date_created dateText\n", "date_created_earliest year\n", "date_created_latest year\n", "created_period \n", "created_dynasty \n", "created_inscriptions inscription\n", "created_notes \n", "creator artist\n", "physical_medium medium\n", "physical_style \n", "physical_technique \n", "physical_description \n", "physical_dimensions dimensions\n", "created_provenance \n", "credit_line creditLine\n", "collection Department\n", "current_status \n", "current_owner Tate Museum\n", "image_url thumbnailUrl\n", "homepage url" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mapp = {\n", " \"id\":\"id\",\n", " \"accession_number\":\"accession_number\",\n", " \"accession_date\": \"acquisitionYear\",\n", " \"classification\" : \"\",\n", " \"title\": \"title\",\n", " \"alt_title\": \"\",\n", " \"notes\": \"\",\n", " \"date_created\":\"dateText\",\n", " \"date_created_earliest\": \"year\",\n", " \"date_created_latest\": \"year\",\n", " \"created_period\":\"\",\n", " \"created_dynasty\":\"\",\n", " \"created_inscriptions\":\"inscription\",\n", " \"created_notes\": \"\",\n", " \"creator\":\"artist\",\n", " \"physical_medium\": \"medium\",\n", " \"physical_style\": \"\",\n", " \"physical_technique\": \"\",\n", " \"physical_description\": \"\",\n", " \"physical_dimensions\": \"dimensions\",\n", " \"created_provenance\": \"\" ,\n", " \"credit_line\": \"creditLine\",\n", " \"collection\" : \"Department\",\n", " \"current_status\" : \"\",\n", " \"current_owner\": \"Tate Museum\",\n", " \"image_url\":\"thumbnailUrl\",\n", " \"homepage\" : \"url\"\n", "}\n", "\n", "# display transposed dataframe of data mapping\n", "display(pd.DataFrame(mapp, index=[0]).T)" ] }, { "cell_type": "markdown", "id": "024c2dbf", "metadata": {}, "source": [ "### Transform Tate Collection Data to Linked Art \n", "\n", "This next step uses the following to transform the collections data to Linked Art JSON-LD\n", "\n", "- the data mapping `mapp`\n", "- custom coding in createObjProp()\n", "- `cromulant` Python library\n", "- custom coding in `la` including createObjDescription()" ] }, { "cell_type": "code", "execution_count": 43, "id": "2246e9fd", "metadata": {}, "outputs": [], "source": [ "file = './data/tate/tate-artwork_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", "selectOptions = []\n", "selectOptions.append((\"Please select an artwork\", \"\"))\n", "\n", "\n", "# open collection data input file \n", "allObjects = csv.DictReader(open(file, mode='r',encoding='utf-8'))\n", "\n", "# iterate through row - only 1 in this case \n", "for obj in allObjects:\n", " \n", " # create object property dictionary\n", " objProp = createObjProp(obj,mapp)\n", " id = objProp[\"id\"]\n", " object_uri = baseURI + id\n", " \n", " objProp[\"classification\"] = \"Painting\"\n", " \n", " \n", " objProp[\"creator\"] = [{\"id\": baseURI +\"creatorid/\" + obj[\"artistId\"] ,\"name\": \"John Ruskin\",\"role\":\"Artist\"}]\n", " \n", " # create Linked Art representation using `la` and cromulent\n", " objLA = la.createObjDesc(objProp,la.objTypes,object_uri)\n", " \n", " # write Linked Art to file \n", " filename = id + \".json\"\n", " text_file = open(outputdir + \"/\" + filename, \"wt\")\n", "\n", " # use cromulent to write file \n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " \n", " text_file.close()\n", " \n", " # create drop down options for jsonld vis\n", " title = objProp[\"title\"] + \" (\" + filename + \")\" \n", " selectOptions.append((title,filename))\n", " \n", " \n", "# custom coding to create dictionary to be used to create Linked Art JSON-LD\n", "def createObjProp(obj,mapp):\n", " objProp = {}\n", " \n", " # iterate through keys in csv collection data input file\n", " csv_keys = list(obj.keys())\n", " for key in csv_keys:\n", " # iterate through the data mapping\n", " for prop in mapp:\n", " if key == mapp[prop]:\n", " \n", " objProp[prop] = obj[key]\n", " return objProp " ] }, { "cell_type": "markdown", "id": "3ba51b86", "metadata": {}, "source": [ "### Visualisation of the Linked Art JSON-LD\n", "\n", "The Linked Art JSON-LD representation can be viewed in a data visualisation below. Select an artwork from the dropdown menu." ] }, { "cell_type": "code", "execution_count": 45, "id": "ec115e19", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "39adf2f7e06b4d71870556375206ba5f", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), ('An Olive Spray and Two Leaf Outlines (13031.json)', '130…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/13031.json';var selector = '#vistate';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworktate').src = 'http://www.tate.org.uk/art/images/work/N/N02/N02726_8.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def dropdown_eventhandler_tate(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " outputdir = \"./data/ruskin/output/json/\"\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#vistate';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworktate').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworktate').src = '';\"))\n", " \n", "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler_tate, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "7861a748", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "ddadd2f0", "metadata": {}, "source": [ "## Harvard Art Museum\n", "\n", "The Havard Art Museum collection includes several works by John Ruskin:\n", "\n", "[Harvard Art Museum John Ruskin page](https://harvardartmuseums.org/collections/person/28419?person=28419)\n", "\n", "\n", "- The collection data are available via an [API](https://github.com/harvardartmuseums/api-docs)\n", " - An API key is needed to query the API.\n", "\n", "To retrieve the collection data for John Ruskin, the API is called with the following code \n", "\n", "
\n",
    "uri = \"https://api.harvardartmuseums.org/object?person=28419&apikey=\" + key\n",
    "
\n", "\n", "\n", "The script below iterates through the results and writes the JSON response to local JSON files.\n", "\n", "#### Further Reading\n", "\n", "- [Harvard Art Museum API documentation](https://github.com/harvardartmuseums/api-docs)\n", "- [Harvard Art Museum John Ruskin page](https://harvardartmuseums.org/collections/person/28419?person=28419)" ] }, { "cell_type": "code", "execution_count": 46, "id": "2f2529a0", "metadata": {}, "outputs": [], "source": [ "import urllib3\n", "\n", "http = urllib3.PoolManager()\n", "\n", "keyfile = \"data/ruskin/input/key.txt\"\n", "\n", "# Find all of the objects with the word \"cat\" in the title and return only a few fields per record\n", "r = http.request('GET', 'https://api.harvardartmuseums.org/object',\n", " fields = {\n", " 'apikey': '8def5994-1631-4345-bed0-f9385bdd67c7',\n", " 'person':28419 ,\n", " })" ] }, { "cell_type": "code", "execution_count": 47, "id": "d546f981", "metadata": {}, "outputs": [], "source": [ "try:\n", " import requests\n", "except:\n", " %pip install requests\n", " import requests\n", "\n", "apidocs = \"https://github.com/harvardartmuseums/api-docs\"\n", "\n", "keyfile = \"data/ruskin/input/key.txt\"\n", "key = open(keyfile, mode='r', encoding='utf-8-sig').read()\n", "uri = \"https://api.harvardartmuseums.org/object?person=28419&apikey=\" + key\n", "\n", "for page in range(1, 11):\n", " response = requests.get(uri + \"&page=\" + str(page))\n", " json_data = response.json()\n", " text_file = open( \"./data/harvard/input/\" + str(page) + \".json\", \"wt\")\n", " n = text_file.write(json.dumps(json_data, indent=2))\n", " text_file.close()\n", " \n", " " ] }, { "cell_type": "markdown", "id": "74e8cec9", "metadata": {}, "source": [ "### Example Collection Data Returned\n", "\n", "An example record returned by the API is shown below" ] }, { "cell_type": "code", "execution_count": 48, "id": "5f47be4b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"copyright\": null,\n", " \"contextualtextcount\": 0,\n", " \"creditline\": \"Harvard Art Museums/Fogg Museum, Transfer from the Fine Arts Department, Harvard University\",\n", " \"accesslevel\": 1,\n", " \"dateoflastpageview\": \"2021-05-27\",\n", " \"classificationid\": 23,\n", " \"division\": \"European and American Art\",\n", " \"markscount\": 0,\n", " \"publicationcount\": 0,\n", " \"totaluniquepageviews\": 17,\n", " \"contact\": \"am_europeanamerican@harvard.edu\",\n", " \"colorcount\": 9,\n", " \"rank\": 195836,\n", " \"state\": null,\n", " \"id\": 93100,\n", " \"verificationleveldescription\": \"Good. Object is well described and information is vetted\",\n", " \"period\": null,\n", " \"images\": [\n", " {\n", " \"date\": \"2008-06-13\",\n", " \"copyright\": \"President and Fellows of Harvard College\",\n", " \"imageid\": 312241,\n", " \"idsid\": 20460228,\n", " \"format\": \"image/jpeg\",\n", " \"description\": null,\n", " \"technique\": null,\n", " \"renditionnumber\": \"INV195646\",\n", " \"displayorder\": 1,\n", " \"baseimageurl\": \"https://nrs.harvard.edu/urn-3:HUAM:INV195646_dynmc\",\n", " \"alttext\": null,\n", " \"width\": 822,\n", " \"publiccaption\": null,\n", " \"iiifbaseuri\": \"https://ids.lib.harvard.edu/ids/iiif/20460228\",\n", " \"height\": 1024\n", " }\n", " ],\n", " \"worktypes\": [\n", " {\n", " \"worktypeid\": \"288\",\n", " \"worktype\": \"print\"\n", " }\n", " ],\n", " \"imagecount\": 1,\n", " \"totalpageviews\": 22,\n", " \"accessionyear\": null,\n", " \"standardreferencenumber\": null,\n", " \"signed\": null,\n", " \"classification\": \"Prints\",\n", " \"relatedcount\": 0,\n", " \"verificationlevel\": 3,\n", " \"primaryimageurl\": \"https://nrs.harvard.edu/urn-3:HUAM:INV195646_dynmc\",\n", " \"titlescount\": 1,\n", " \"peoplecount\": 2,\n", " \"style\": null,\n", " \"lastupdate\": \"2022-04-28T05:29:34-0400\",\n", " \"commentary\": \"Reproduction: See \\\"Works of John Ruskin,\\\" Library edition, edited by E. T. Cook and Alexander Wedderburn, London, Allen 1903, vol iii, opp. p. 338\\r\\n\",\n", " \"periodid\": null,\n", " \"technique\": \"Etching\",\n", " \"edition\": null,\n", " \"description\": null,\n", " \"medium\": null,\n", " \"lendingpermissionlevel\": 0,\n", " \"title\": \"Foreground Study\",\n", " \"accessionmethod\": null,\n", " \"colors\": [\n", " {\n", " \"color\": \"#e1e1c8\",\n", " \"spectrum\": \"#e9715f\",\n", " \"hue\": \"Green\",\n", " \"percent\": 0.5369444444444444,\n", " \"css3\": \"#dcdcdc\"\n", " },\n", " {\n", " \"color\": \"#c8c8c8\",\n", " \"spectrum\": \"#8c5fa8\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.21694444444444444,\n", " \"css3\": \"#c0c0c0\"\n", " },\n", " {\n", " \"color\": \"#afafaf\",\n", " \"spectrum\": \"#8c5fa8\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.07805555555555556,\n", " \"css3\": \"#a9a9a9\"\n", " },\n", " {\n", " \"color\": \"#969696\",\n", " \"spectrum\": \"#8761aa\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.0595,\n", " \"css3\": \"#a9a9a9\"\n", " },\n", " {\n", " \"color\": \"#7d7d7d\",\n", " \"spectrum\": \"#8362aa\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.044833333333333336,\n", " \"css3\": \"#808080\"\n", " },\n", " {\n", " \"color\": \"#646464\",\n", " \"spectrum\": \"#7866ad\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.037,\n", " \"css3\": \"#696969\"\n", " },\n", " {\n", " \"color\": \"#4b4b4b\",\n", " \"spectrum\": \"#3db657\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.01877777777777778,\n", " \"css3\": \"#2f4f4f\"\n", " },\n", " {\n", " \"color\": \"#323232\",\n", " \"spectrum\": \"#2eb45d\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.006333333333333333,\n", " \"css3\": \"#2f4f4f\"\n", " },\n", " {\n", " \"color\": \"#191919\",\n", " \"spectrum\": \"#1eb264\",\n", " \"hue\": \"Grey\",\n", " \"percent\": 0.0016111111111111111,\n", " \"css3\": \"#000000\"\n", " }\n", " ],\n", " \"provenance\": null,\n", " \"groupcount\": 0,\n", " \"dated\": \"19th century\",\n", " \"department\": \"Department of Prints\",\n", " \"dateend\": 0,\n", " \"people\": [\n", " {\n", " \"role\": \"Artist\",\n", " \"birthplace\": null,\n", " \"gender\": \"male\",\n", " \"displaydate\": \"c. 1820 - 1897\",\n", " \"prefix\": null,\n", " \"culture\": \"British\",\n", " \"displayname\": \"James Charles Armytage\",\n", " \"alphasort\": \"Armytage, James Charles\",\n", " \"name\": \"James Charles Armytage\",\n", " \"personid\": 33686,\n", " \"deathplace\": null,\n", " \"displayorder\": 1\n", " },\n", " {\n", " \"role\": \"Artist after\",\n", " \"birthplace\": \"London, England\",\n", " \"gender\": \"male\",\n", " \"displaydate\": \"1819 - 1900\",\n", " \"prefix\": \"After\",\n", " \"culture\": \"British\",\n", " \"displayname\": \"After John Ruskin\",\n", " \"alphasort\": \"Ruskin, John\",\n", " \"name\": \"John Ruskin\",\n", " \"personid\": 28419,\n", " \"deathplace\": \"Brantwood, England\",\n", " \"displayorder\": 2\n", " }\n", " ],\n", " \"url\": \"https://www.harvardartmuseums.org/collections/object/93100\",\n", " \"dateoffirstpageview\": \"2009-05-19\",\n", " \"century\": \"19th century\",\n", " \"objectnumber\": \"FA5\",\n", " \"labeltext\": null,\n", " \"datebegin\": 0,\n", " \"culture\": \"British\",\n", " \"exhibitioncount\": 0,\n", " \"imagepermissionlevel\": 0,\n", " \"mediacount\": 0,\n", " \"objectid\": 93100,\n", " \"techniqueid\": 116,\n", " \"dimensions\": \"plate: 253 x 163 cm (99 5/8 x 64 3/16 in.)\",\n", " \"seeAlso\": [\n", " {\n", " \"id\": \"https://iiif.harvardartmuseums.org/manifests/object/93100\",\n", " \"type\": \"IIIF Manifest\",\n", " \"format\": \"application/json\",\n", " \"profile\": \"http://iiif.io/api/presentation/2/context.json\"\n", " }\n", " ]\n", "}\n" ] } ], "source": [ "response = requests.get(uri + \"&page=1\")\n", "json_data = response.json()\n", "print(json.dumps(json_data[\"records\"][0], indent=2))\n" ] }, { "cell_type": "markdown", "id": "034947fb", "metadata": {}, "source": [ "### Map Harvard Art Museum data model to Linked Art data model\n", "\n", "The next step is to map the collection data model to the Linked Art data model with `mapp`:" ] }, { "cell_type": "code", "execution_count": 49, "id": "c1953625", "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0
idid
accession_numberobjectnumber
accession_dateaccessionyear
classificationclassification
titletitle
alt_title
notescommentary
date_createddated
date_created_earliest
date_created_latest
created_periodperiod
created_dynastycentury
created_inscriptions
created_notes
creatorpeople
physical_mediummedium
physical_style
physical_techniquetechnique
physical_descriptiondescription
physical_dimensionsdimensions
created_provenanceprovenance
credit_linecreditline
collectiondivision
current_status
current_ownerHarvard Museum of Art
image_urlprimaryimageurl
homepageurl
\n", "
" ], "text/plain": [ " 0\n", "id id\n", "accession_number objectnumber\n", "accession_date accessionyear\n", "classification classification\n", "title title\n", "alt_title \n", "notes commentary\n", "date_created dated\n", "date_created_earliest \n", "date_created_latest \n", "created_period period\n", "created_dynasty century\n", "created_inscriptions \n", "created_notes \n", "creator people\n", "physical_medium medium\n", "physical_style \n", "physical_technique technique\n", "physical_description description\n", "physical_dimensions dimensions\n", "created_provenance provenance\n", "credit_line creditline\n", "collection division\n", "current_status \n", "current_owner Harvard Museum of Art\n", "image_url primaryimageurl\n", "homepage url" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import pandas as pd\n", "except:\n", " %pip install pandas\n", " import pandas as pd\n", " \n", "mapp = {\n", " \"id\":\"id\",\n", " \"accession_number\":\"objectnumber\",\n", " \"accession_date\": \"accessionyear\",\n", " \"classification\" : \"\",\n", " \"title\": \"title\",\n", " \"alt_title\": \"\",\n", " \"notes\": \"commentary\",\n", " \"date_created\":\"dated\",\n", " \"date_created_earliest\": \"\",\n", " \"date_created_latest\": \"\",\n", " \"created_period\":\"period\",\n", " \"created_dynasty\":\"century\",\n", " \"created_inscriptions\":\"\",\n", " \"created_notes\": \"\",\n", " \"creator\":\"people\",\n", " \"physical_medium\": \"medium\",\n", " \"physical_style\": \"\",\n", " \"physical_technique\": \"technique\",\n", " \"physical_description\": \"description\",\n", " \"physical_dimensions\": \"dimensions\",\n", " \"created_provenance\": \"provenance\" ,\n", " \"credit_line\": \"creditline\",\n", " \"collection\" : \"division\",\n", " \"classification\": \"classification\",\n", " \"current_status\" : \"\",\n", " \"current_owner\": \"Harvard Museum of Art\",\n", " \"image_url\":\"primaryimageurl\",\n", " \"homepage\" : \"url\"\n", "}\n", "\n", "# display transposed dataframe of data mapping\n", "display(pd.DataFrame(mapp, index=[0]).T)" ] }, { "cell_type": "markdown", "id": "35f5cd2d", "metadata": {}, "source": [ "### Transform Harvard Collection Data to Linked Art \n", "\n", "This next step uses the following to transform the collections data to Linked Art JSON-LD\n", "\n", "- the JSON files downloaded further to call to Harvard API\n", "- the data mapping\n", "- custom coding in createObjProp()\n", "- `cromulant` Python library\n", "- custom coding in `la` including createObjDescription()\n", "\n", "\n", "The script below\n", "- iterates through the Harvard JSON files\n", "- read file into json object\n", "- iterate through records\n", "- create objProp for record using mapping and collection data\n", "- additional coding\n", " - define image_url\n", " - if creator field is not empty\n", " - create linked art representation\n", " - write to file " ] }, { "cell_type": "code", "execution_count": 50, "id": "4158fe3f", "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", " \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", "
0
credit_lineHarvard Art Museums/Fogg Museum, Gift of Samue...
collectionEuropean and American Art
id298628
created_periodNone
accession_date1919
classificationDrawings
image_urlhttps://nrs.harvard.edu/urn-3:HUAM:38491_dynmc
notesA portion of this drawing is engraved, in reve...
physical_techniqueNone
physical_descriptionNone
physical_mediumGraphite, brown ink, and brown wash on cream w...
titleStudy of Portal and Carved Pinnacles, Cathedra...
created_provenanceCharles Eliot Norton, to; his daughters Sara, ...
date_created_earliest1848
date_created_latest1848
date_created1848
creator{'id': 'https://harvardartmuseums.org/collecti...
homepagehttps://www.harvardartmuseums.org/collections/...
created_dynasty19th century
accession_number1919.504
physical_dimensions48.1 x 36.2 cm (18 15/16 x 14 1/4 in.)
current_ownerNaN
\n", "
" ], "text/plain": [ " 0\n", "credit_line Harvard Art Museums/Fogg Museum, Gift of Samue...\n", "collection European and American Art\n", "id 298628\n", "created_period None\n", "accession_date 1919\n", "classification Drawings\n", "image_url https://nrs.harvard.edu/urn-3:HUAM:38491_dynmc\n", "notes A portion of this drawing is engraved, in reve...\n", "physical_technique None\n", "physical_description None\n", "physical_medium Graphite, brown ink, and brown wash on cream w...\n", "title Study of Portal and Carved Pinnacles, Cathedra...\n", "created_provenance Charles Eliot Norton, to; his daughters Sara, ...\n", "date_created_earliest 1848\n", "date_created_latest 1848\n", "date_created 1848\n", "creator {'id': 'https://harvardartmuseums.org/collecti...\n", "homepage https://www.harvardartmuseums.org/collections/...\n", "created_dynasty 19th century\n", "accession_number 1919.504\n", "physical_dimensions 48.1 x 36.2 cm (18 15/16 x 14 1/4 in.)\n", "current_owner NaN" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import re\n", "import json\n", "from lib import linkedart as la\n", "try:\n", " import cromulent \n", "except:\n", " %pip install cromulent\n", " import cromulent\n", " \n", "from cromulent.model import factory\n", "baseURI = \"https://www.harvardartmuseums.org/collections/object/\"\n", "outputdir = \"./data/ruskin/output/json/\"\n", "\n", "\n", "images = {}\n", "selectOptions = []\n", "selectOptions.append((\"Please select an artwork\", \"\"))\n", "\n", "\n", "def createObjPropHarvard(obj,mapp):\n", "\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 key == \"dated\":\n", " \n", " # look for year in value \n", " years = re.findall('(\\d{4})', obj[key])\n", " if len(years) == 1:\n", " #objProp[\"date\"] = years[0]\n", " objProp[\"date_created_earliest\"] = years[0]\n", " objProp[\"date_created_latest\"] = years[0]\n", " elif len(years) == 2:\n", " # objProp[\"dated\"] = str(years[0]) + \"-\" + str(years[1])\n", " objProp[\"date_created_earliest\"] = years[0]\n", " objProp[\"date_created_latest\"] = years[1]\n", " else:\n", " # use Ruskins birth/death years\n", " objProp[\"date_created_earliest\"] = 1819\n", " objProp[\"date_created_latest\"] = 1900\n", " \n", " if prop == \"creator\":\n", " objProp[\"creator\"] = \"\"\n", " for person in obj[key]:\n", " \n", " if \"personid\" in person and person[\"personid\"] == 28419 and person[\"role\"] == \"Artist\": \n", " objProp[prop] = [{\n", " \"id\": \"https://harvardartmuseums.org/collections/person/\" + str(person[\"personid\"]),\n", " \"name\": person[\"displayname\"],\n", " \"role\": \"Artist\"\n", " \n", " }] \n", " else:\n", " objProp[prop] = obj[key]\n", " \n", " objProp[\"current_owner\"] = {\"name\":\"Harvard Art Museum\",\n", " \"location\":\"Cambridge, MA\",\n", " \"type\": \"http://vocab.getty.edu/aat/300312281\" ,\n", " \"type_label\": \"\"}\n", " return objProp \n", "\n", "# iterates through the Harvard JSON files\n", "for x in range(1,11):\n", " \n", " filename = str(x) + \".json\"\n", " with open(\"./data/harvard/input/\" + filename) as json_file:\n", " \n", " # read file into json object\n", " data = json.load(json_file)\n", " \n", " # iterate through records\n", " for obj in data[\"records\"]:\n", " \n", " # check that there is person description with \"role\": \"Artist\" and \"personid\": 28419, ie Ruskin\n", " isjohnruskin = False\n", " for person in obj[\"people\"]:\n", " if person[\"role\"] == \"Artist\" and person[\"personid\"] == 28419:\n", " isjohnruskin = True\n", " if isjohnruskin == False:\n", " continue\n", " \n", " # create objProp for record using mapping and collection data\n", " objProp=createObjPropHarvard(obj,mapp)\n", " id = str(objProp[\"id\"])\n", " \n", " # define image_url \n", " if \"image_url\" in objProp and objProp[\"image_url\"] != \"\":\n", " images[\"https://www.harvardartmuseums.org/collections/object/\" + id] = objProp[\"image_url\"]\n", " \n", " # define creator\n", " if objProp[\"creator\"] != \"\":\n", " \n", " # create drop down options for jsonld vis\n", " title = objProp[\"title\"] + \" (\" + id + \".json)\" \n", " selectOptions.append((title, id + \".json\"))\n", " \n", " # create obj description\n", " objLA = la.createObjDesc(objProp, la.objTypes, baseURI + id)\n", " \n", " # write to file \n", " text_file = open(outputdir + \"/\" + id + \".json\", \"wt\")\n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " text_file.close()\n", " \n", " # print for illustration\n", "print(objProp[\"title\"])\n", "display(pd.DataFrame(objProp, index=[0]).T)\n", " \n", " \n", " \n", " \n", " \n" ] }, { "cell_type": "markdown", "id": "25cb7deb", "metadata": {}, "source": [ "### Visualisation of the Linked Art JSON-LD\n", "\n", "The Linked Art JSON-LD representation can be viewed in a data visualisation below. Select an artwork from the dropdown menu." ] }, { "cell_type": "code", "execution_count": 52, "id": "14893235", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ac530dde568a40f38b662af483f824d4", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), ('Pass of Faido (262409.json)', '262409.json'), ('Château …" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import ipywidgets\n", "except:\n", " %pip install ipywidgets\n", " import ipywidgets\n", "\n", "from ipywidgets import Layout, FileUpload \n", "from IPython.display import display, IFrame, HTML, Image, Javascript\n", "\n", "def dropdown_eventhandler_tate(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " outputdir = \"./data/ruskin/output/json/\"\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#visharv';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworkharv').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworkharv').src = '';\"))\n", " \n", "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler_tate, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "65f358dc", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "2a727369", "metadata": {}, "source": [ "## Rijksmuseum\n", "\n", "The Rijksmuseum has an API can that can be queried for collection data. To query the API, it is necessary to register for a key.\n", "\n", "The API query used:\n", "
\n",
    "\"https://www.rijksmuseum.nl/api/nl/collection?key=\" + key + \"&involvedMaker=John+Ruskin\"\n",
    "
\n", "\n", "The Rijksmuseum has two artworks, with digital images, by John Ruskin in its collection data.\n", "\n", "\n", "#### Further Reading\n", "\n", "- [Rijksmuseum](https://www.rijksmuseum.nl)\n", "- [Rijksmuseum API](https://www.rijksmuseum.nl/api)\n", "- [John Ruskin artworks at Rijksmuseum](https://www.rijksmuseum.nl/en/search?q=ruskin&f=1&p=1&ps=12&principalMaker=John%20Ruskin&st=Objects&ii=0)" ] }, { "cell_type": "code", "execution_count": null, "id": "370f3d5c", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 53, "id": "4a349f5f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"links\": {\n", " \"self\": \"http://www.rijksmuseum.nl/api/nl/collection/RP-T-1957-335\",\n", " \"web\": \"http://www.rijksmuseum.nl/nl/collectie/RP-T-1957-335\"\n", " },\n", " \"id\": \"nl-RP-T-1957-335\",\n", " \"objectNumber\": \"RP-T-1957-335\",\n", " \"title\": \"Gezicht op S. Anastasia te Verona, over de Adige\",\n", " \"hasImage\": true,\n", " \"principalOrFirstMaker\": \"John Ruskin\",\n", " \"longTitle\": \"Gezicht op S. Anastasia te Verona, over de Adige, John Ruskin, 1829 - 1900\",\n", " \"showImage\": true,\n", " \"permitDownload\": true,\n", " \"webImage\": {\n", " \"guid\": \"c366d216-9aa1-4cb5-bbe5-fefa51f8e641\",\n", " \"offsetPercentageX\": 0,\n", " \"offsetPercentageY\": 0,\n", " \"width\": 2500,\n", " \"height\": 1695,\n", " \"url\": \"https://lh3.googleusercontent.com/X0Xc5cER3eTrpNyqH4kg3ne-ewai_nBqFdSI-EZPZ4N-lE6rn1OAUBckEHQSFyafcGcFpiX99QU4STEXWbB43KsnAbi3=s0\"\n", " },\n", " \"headerImage\": {\n", " \"guid\": \"84416aa1-5880-4751-ab94-72000580cd03\",\n", " \"offsetPercentageX\": 0,\n", " \"offsetPercentageY\": 0,\n", " \"width\": 1920,\n", " \"height\": 460,\n", " \"url\": \"https://lh3.googleusercontent.com/LEfvA4m-B8Y6ty0tj8iC4epKOv1-VTT14KIY4NuLVnhsVHlpk4c3FHBJ6pkFpKN4dVmHQOpizc5JP3koX0okT34BwQ8=s0\"\n", " },\n", " \"productionPlaces\": []\n", "}\n", "{\n", " \"links\": {\n", " \"self\": \"http://www.rijksmuseum.nl/api/nl/collection/RP-T-1987-19\",\n", " \"web\": \"http://www.rijksmuseum.nl/nl/collectie/RP-T-1987-19\"\n", " },\n", " \"id\": \"nl-RP-T-1987-19\",\n", " \"objectNumber\": \"RP-T-1987-19\",\n", " \"title\": \"Bergkam aan het Meer van Gen\\u00e8ve\",\n", " \"hasImage\": true,\n", " \"principalOrFirstMaker\": \"John Ruskin\",\n", " \"longTitle\": \"Bergkam aan het Meer van Gen\\u00e8ve, John Ruskin, 1829 - 1900\",\n", " \"showImage\": true,\n", " \"permitDownload\": true,\n", " \"webImage\": {\n", " \"guid\": \"0e3e19b4-5c72-43b5-a027-d81c199361cc\",\n", " \"offsetPercentageX\": 0,\n", " \"offsetPercentageY\": 0,\n", " \"width\": 2500,\n", " \"height\": 1504,\n", " \"url\": \"https://lh3.ggpht.com/SOPNNYPF1S5Ij-DKCcm7AoweEHz--rJ0VPCh5WZdFbCKEPNnSI9ZAzYQz_nxKVtuurYAnOEvSFfYv5ZNcX-Ma7TwNH0=s0\"\n", " },\n", " \"headerImage\": {\n", " \"guid\": \"f9f9b94a-8f96-4b17-aa76-979fd3cbb7b0\",\n", " \"offsetPercentageX\": 0,\n", " \"offsetPercentageY\": 0,\n", " \"width\": 1920,\n", " \"height\": 460,\n", " \"url\": \"https://lh6.ggpht.com/iR0kI_bGMikvoHFedRGwp0Kj_Iz0Qy06y_P_KMhUA20DgMBJl1p0ZDSlfwWXG9ZttMupnD6Gw3BINvhhCkofAHPe-Vwf=s0\"\n", " },\n", " \"productionPlaces\": []\n", "}\n" ] } ], "source": [ "# local data directory\n", "rijksdir = \"data/rijks/json/\"\n", "\n", "\n", "# base URI for JSON-LD representation\n", "baseURI = \"http://www.rijksmuseum.nl/nl/collectie/\"\n", "\n", "# API key\n", "keyfile = \"data/ruskin/input/keyrijks.txt\"\n", "key = open(keyfile, mode='r', encoding='utf-8-sig').read()\n", "# API Query\n", "url = \"https://www.rijksmuseum.nl/api/nl/collection?key=\" + key + \"&involvedMaker=John+Ruskin\"\n", "\n", "# query result to data var\n", "response = requests.get(url)\n", "data = response.json()\n", "\n", "# iterate through data results\n", "for artwork in data[\"artObjects\"]:\n", " \n", " # if no image, do not include \n", " if artwork[\"hasImage\"] == False:\n", " continue\n", " \n", " # if artist is not john ruskin continue\n", " if artwork[\"principalOrFirstMaker\"] != \"John Ruskin\":\n", " continue\n", " \n", " # write json file to local rijks data directory\n", " text_file = open( rijksdir + artwork[\"id\"] + \".json\", \"wt\")\n", " text_file.write(json.dumps(artwork, indent=2))\n", " \n", " print(json.dumps(artwork, indent=2))\n", " text_file.close()" ] }, { "cell_type": "markdown", "id": "a36da195", "metadata": {}, "source": [ "### Mapping to Linked Art Data Model" ] }, { "cell_type": "code", "execution_count": 54, "id": "dc56b845", "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", " \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", " \n", " \n", " \n", " \n", " \n", "
0
idid
accession_numberobjectNumber
classification
titletitle
alt_titlelongTitle
notes
date_created
date_created_earliest
date_created_latest
created_period
created_dynasty
created_inscriptions
created_notes
creatorprincipalOrFirstMaker
physical_medium
physical_style
physical_technique
physical_description
physical_dimensions
created_provenance
credit_line
collection
current_status
current_owner
image_url
homepage
\n", "
" ], "text/plain": [ " 0\n", "id id\n", "accession_number objectNumber\n", "classification \n", "title title\n", "alt_title longTitle\n", "notes \n", "date_created \n", "date_created_earliest \n", "date_created_latest \n", "created_period \n", "created_dynasty \n", "created_inscriptions \n", "created_notes \n", "creator principalOrFirstMaker\n", "physical_medium \n", "physical_style \n", "physical_technique \n", "physical_description \n", "physical_dimensions \n", "created_provenance \n", "credit_line \n", "collection \n", "current_status \n", "current_owner \n", "image_url \n", "homepage " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# data mapping \n", "mapp = {\n", " \n", " \"id\":\"id\",\n", " \"accession_number\":\"objectNumber\",\n", " \"classification\" : \"\",\n", " \"title\": \"title\",\n", " \"alt_title\": \"longTitle\",\n", " \"notes\": \"\",\n", " \"date_created\":\"\",\n", " \"date_created_earliest\": \"\",\n", " \"date_created_latest\": \"\",\n", " \"created_period\":\"\",\n", " \"created_dynasty\":\"\",\n", " \"created_inscriptions\":\"\",\n", " \"created_notes\": \"\",\n", " \"creator\":\"principalOrFirstMaker\",\n", " \"physical_medium\": \"\",\n", " \"physical_style\": \"\",\n", " \"physical_technique\": \"\",\n", " \"physical_description\": \"\",\n", " \"physical_dimensions\": \"\",\n", " \"created_provenance\": \"\" ,\n", " \"credit_line\": \"\",\n", " \"collection\" : \"\",\n", " \"classification\": \"\",\n", " \"current_status\" : \"\",\n", " \"current_owner\": \"\",\n", " \"image_url\":\"\",\n", " \"homepage\" : \"\"\n", "}\n", "\n", "# display transposed dataframe of data mapping\n", "display(pd.DataFrame(mapp, index=[0]).T)" ] }, { "cell_type": "code", "execution_count": 55, "id": "cc348a15", "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", "
idaccession_numbertitlecreatoralt_titlecurrent_ownerimage_urlclassificationhomepage
0nl-RP-T-1987-19RP-T-1987-19Bergkam aan het Meer van Genève{'id': 'http://www.rijksmuseum.nl/nl/collectie...Bergkam aan het Meer van Genève, John Ruskin, ...NaNhttps://lh3.ggpht.com/SOPNNYPF1S5Ij-DKCcm7Aowe...Paintinghttp://www.rijksmuseum.nl/nl/collectie/RP-T-19...
\n", "
" ], "text/plain": [ " id accession_number title \\\n", "0 nl-RP-T-1987-19 RP-T-1987-19 Bergkam aan het Meer van Genève \n", "\n", " creator \\\n", "0 {'id': 'http://www.rijksmuseum.nl/nl/collectie... \n", "\n", " alt_title current_owner \\\n", "0 Bergkam aan het Meer van Genève, John Ruskin, ... NaN \n", "\n", " image_url classification \\\n", "0 https://lh3.ggpht.com/SOPNNYPF1S5Ij-DKCcm7Aowe... Painting \n", "\n", " homepage \n", "0 http://www.rijksmuseum.nl/nl/collectie/RP-T-19... " ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
idaccession_numbertitlecreatoralt_titlecurrent_ownerimage_urlclassificationhomepage
0nl-RP-T-1957-335RP-T-1957-335Gezicht op S. Anastasia te Verona, over de Adige{'id': 'http://www.rijksmuseum.nl/nl/collectie...Gezicht op S. Anastasia te Verona, over de Adi...NaNhttps://lh3.googleusercontent.com/X0Xc5cER3eTr...Paintinghttp://www.rijksmuseum.nl/nl/collectie/RP-T-19...
\n", "
" ], "text/plain": [ " id accession_number \\\n", "0 nl-RP-T-1957-335 RP-T-1957-335 \n", "\n", " title \\\n", "0 Gezicht op S. Anastasia te Verona, over de Adige \n", "\n", " creator \\\n", "0 {'id': 'http://www.rijksmuseum.nl/nl/collectie... \n", "\n", " alt_title current_owner \\\n", "0 Gezicht op S. Anastasia te Verona, over de Adi... NaN \n", "\n", " image_url classification \\\n", "0 https://lh3.googleusercontent.com/X0Xc5cER3eTr... Painting \n", "\n", " homepage \n", "0 http://www.rijksmuseum.nl/nl/collectie/RP-T-19... " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import os\n", "\n", "selectOptions = []\n", "selectOptions.append((\"Please select an artwork\", \"\"))\n", "\n", "\n", "\n", "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[\"creator\"] = \"\"\n", " for person in obj[key]:\n", " \n", " if \"personid\" in person and person[\"personid\"] == 28419 and person[\"role\"] == \"Artist\": \n", " objProp[prop] = [{ \"id\": str(person[\"personid\"]), \"name\": person[\"displayname\"], \"role\": \"Artist\" }] \n", " else:\n", " objProp[prop] = obj[key]\n", " \n", " \n", " objProp[\"current_owner\"] = {\n", " \"name\":\"Rijksmuseum\",\n", " \"location\":\"Amsterdam, Netherlands\",\n", " \"type\": \"http://vocab.getty.edu/aat/300312281\" ,\n", " \"type_label\": \"Museum\"\n", " }\n", " \n", " objProp[\"image_url\"] = obj[\"webImage\"][\"url\"]\n", " \n", " return objProp \n", "\n", "\n", "file_list=os.listdir(rijksdir)\n", "for file in file_list:\n", " with open(rijksdir + file) as json_file:\n", " obj = json.load(json_file)\n", " objProp=createObjProp(obj,mapp)\n", " \n", " objProp[\"creator\"] = [{ \"id\": \"http://www.rijksmuseum.nl/nl/collectie/28419\" , \"name\": \"John Ruskin\", \"role\": \"Artist\" }]\n", " objProp[\"classification\"] = \"Painting\"\n", " objProp[\"homepage\"] = obj[\"links\"][\"web\"]\n", " \n", " if objProp[\"creator\"] != \"\":\n", " \n", " id = str(objProp[\"id\"])\n", " \n", " object_uri = \"http://www.rijksmuseum.nl/nl/collectie/\" + str(objProp[\"accession_number\"])\n", " \n", " # create drop down options for jsonld vis\n", " title = objProp[\"title\"] + \" (\" + id + \".json)\" \n", " selectOptions.append((title, id + \".json\"))\n", " \n", " \n", " # create obj description\n", " objLA = la.createObjDesc(objProp,la.objTypes,object_uri)\n", " # write to file \n", " text_file = open(outputdir + id + \".json\", \"wt\")\n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " text_file.close()\n", " \n", " print(objProp[\"title\"])\n", " display(pd.DataFrame(objProp, index=[0]))\n" ] }, { "cell_type": "markdown", "id": "0a357f36", "metadata": {}, "source": [ "### Visualisation of the Linked Art JSON-LD\n", "\n", "The Linked Art JSON-LD representation can be viewed in a data visualisation below. Select an artwork from the dropdown menu." ] }, { "cell_type": "code", "execution_count": 56, "id": "528015fc", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "38e3adebdbf54de79e7ca8f5f7fde336", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), ('Bergkam aan het Meer van Genève (nl-RP-T-1987-19.json)',…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import ipywidgets\n", "except:\n", " %pip install ipywidgets\n", " import ipywidgets\n", "\n", "from ipywidgets import Layout, FileUpload \n", "from IPython.display import display, IFrame, HTML, Image, Javascript\n", "\n", "def dropdown_eventhandler_tate(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " outputdir = \"./data/ruskin/output/json/\"\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#visrijks';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworkrijks').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworkrijks').src = '';\"))\n", " \n", "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler_tate, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "b945fd4f", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "419759b5", "metadata": {}, "source": [ "## Ashmolean Museum\n", "\n", "The Ashmolean Museum in Oxford, UK holds many artworks by the artist John Ruskin. At present, to retrieve collection data for the artworks it was necessary to screenscrape the web pages for the artworks. This was achieved with the Python library `BeautifulSoup`. From the documentation:\n", "\n", "
\n", "Beautiful Soup is a Python library for pulling data out of HTML and XML files. It works with your favorite parser to provide idiomatic ways of navigating, searching, and modifying the parse tree. \n", "
\n", " \n", " \n", "The HTML was derived from a collections search via https://collections.ashmolean.org/collection/search with the HTML page saved locally to a [data file]( ./data/ashmolean/ash.html).\n", "\n", "#### Further Reading\n", "\n", "- [BeautifulSoup Python library](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)\n", "- [Ashmolean Museum Collection search](https://collections.ashmolean.org/collection/search)\n", "- [Ruskin search as HTML file](./data/ashmolean/ash.html)" ] }, { "cell_type": "code", "execution_count": 57, "id": "059ba51f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'The Tower of Gloucester Cathedral'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159710The Tower of Gloucester Cathedral{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.087https://collections.ashmolean.org/media/ashmol...1832NaN18321832
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159710 \n", "\n", " title \\\n", "0 The Tower of Gloucester Cathedral \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.087 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1832 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1832 1832 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Near Bassano, Brenner'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b.../48683Near Bassano, Brenner{'id': 'https://collections.ashmolean.org/coll...WA1949.253https://collections.ashmolean.org/media/ashmol...1835NaN18351835
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... /48683 \n", "\n", " title creator \\\n", "0 Near Bassano, Brenner {'id': 'https://collections.ashmolean.org/coll... \n", "\n", " accession_number image_url \\\n", "0 WA1949.253 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest date_created_latest \n", "0 1835 NaN 1835 1835 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Bergamo and the Alps, from the road to Brescia'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b.../48682Bergamo and the Alps, from the road to Brescia{'id': 'https://collections.ashmolean.org/coll...WA1949.252https://collections.ashmolean.org/media/ashmol...1835NaN18351835
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... /48682 \n", "\n", " title \\\n", "0 Bergamo and the Alps, from the road to Brescia \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1949.252 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1835 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1835 1835 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Bellagio, Lago di Como'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b.../48685Bellagio, Lago di Como{'id': 'https://collections.ashmolean.org/coll...WA1949.255https://collections.ashmolean.org/media/ashmol...1835NaN18351835
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... /48685 \n", "\n", " title creator \\\n", "0 Bellagio, Lago di Como {'id': 'https://collections.ashmolean.org/coll... \n", "\n", " accession_number image_url \\\n", "0 WA1949.255 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest date_created_latest \n", "0 1835 NaN 1835 1835 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'End of the Lake of Lecco'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b.../48684End of the Lake of Lecco{'id': 'https://collections.ashmolean.org/coll...WA1949.254https://collections.ashmolean.org/media/ashmol...1835NaN18351835
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... /48684 \n", "\n", " title \\\n", "0 End of the Lake of Lecco \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1949.254 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1835 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1835 1835 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Axmouth Landslip from Dolands Farm'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...125702Axmouth Landslip from Dolands Farm{'id': 'https://collections.ashmolean.org/coll...WA2000.86https://collections.ashmolean.org/media/ashmol...c. 1839NaN18391839
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 125702 \n", "\n", " title \\\n", "0 Axmouth Landslip from Dolands Farm \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA2000.86 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1839 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1839 1839 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study for Detail of the Piazza delle Erbe, Verona'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159601Study for Detail of the Piazza delle Erbe, Verona{'id': 'https://collections.ashmolean.org/coll...WA.RS.REF.062https://collections.ashmolean.org/media/ashmol...19 May 1841NaN18411841
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159601 \n", "\n", " title \\\n", "0 Study for Detail of the Piazza delle Erbe, Verona \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.REF.062 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 19 May 1841 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1841 1841 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Palazzo Contarini-Fasan, Venice'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159604The Palazzo Contarini-Fasan, Venice{'id': 'https://collections.ashmolean.org/coll...WA.RS.REF.065https://collections.ashmolean.org/media/ashmol...6 - 16 May 1841NaN18411841
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159604 \n", "\n", " title \\\n", "0 The Palazzo Contarini-Fasan, Venice \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.REF.065 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 6 - 16 May 1841 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1841 1841 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Outline of Leaves of Oak, touched with Colour'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159452Outline of Leaves of Oak, touched with Colour{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.253.ahttps://collections.ashmolean.org/media/ashmol...1842 - 1844NaN18421844
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159452 \n", "\n", " title \\\n", "0 Outline of Leaves of Oak, touched with Colour \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.253.a \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1842 - 1844 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1842 1844 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Quick Study of Leaf Contour: Bramble'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159803Quick Study of Leaf Contour: Bramble{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.280https://collections.ashmolean.org/media/ashmol...probably 1843NaN18431843
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159803 \n", "\n", " title \\\n", "0 Quick Study of Leaf Contour: Bramble \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.280 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably 1843 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1843 1843 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Leaf Contour: Laburnum'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159804Leaf Contour: Laburnum{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.281https://collections.ashmolean.org/media/ashmol...probably 1843NaN18431843
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159804 \n", "\n", " title creator \\\n", "0 Leaf Contour: Laburnum {'id': 'https://collections.ashmolean.org/coll... \n", "\n", " accession_number image_url \\\n", "0 WA.RS.RUD.281 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest date_created_latest \n", "0 probably 1843 NaN 1843 1843 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Stone Pines at Sestri, Gulf of Genoa'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159365Stone Pines at Sestri, Gulf of Genoa{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.022https://collections.ashmolean.org/media/ashmol...30 April 1845NaN18451845
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159365 \n", "\n", " title \\\n", "0 Stone Pines at Sestri, Gulf of Genoa \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.022 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 30 April 1845 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1845 1845 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Part of the Façade of the destroyed Church of San Michele in Foro, Lucca, as it appeared in 1845'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159407Part of the Façade of the destroyed Church of ...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.083https://collections.ashmolean.org/media/ashmol...May 1845NaN18451845
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159407 \n", "\n", " title \\\n", "0 Part of the Façade of the destroyed Church of ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.083 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... May 1845 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1845 1845 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Rough Sketch of Tree Growth: Macugnaga'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159476Rough Sketch of Tree Growth: Macugnaga{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.296.ahttps://collections.ashmolean.org/media/ashmol...4 August 1845NaN18451845
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159476 \n", "\n", " title \\\n", "0 Rough Sketch of Tree Growth: Macugnaga \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.296.a \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 4 August 1845 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1845 1845 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"Drawing of the Background of Raphael's 'Virgin and Child with the Infant Saint John' (The 'Madonna del Cardellino')\"" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159572Drawing of the Background of Raphael's 'Virgin...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.269https://collections.ashmolean.org/media/ashmol...probably June 1845NaN18451845
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159572 \n", "\n", " title \\\n", "0 Drawing of the Background of Raphael's 'Virgin... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.269 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably June 1845 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1845 1845 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study of the Marble Inlaying on the Front of the Casa Loredan, Venice'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159660Study of the Marble Inlaying on the Front of t...{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.022https://collections.ashmolean.org/media/ashmol...September - October 1845NaN18451845
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159660 \n", "\n", " title \\\n", "0 Study of the Marble Inlaying on the Front of t... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.022 \n", "\n", " image_url \\\n", "0 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest \\\n", "0 September - October 1845 NaN 1845 \n", "\n", " date_created_latest \n", "0 1845 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Gryphon bearing the south Shaft of the west Entrance of the Duomo, Verona'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159405The Gryphon bearing the south Shaft of the wes...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.081https://collections.ashmolean.org/media/ashmol...11 May 1846NaN18461846
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159405 \n", "\n", " title \\\n", "0 The Gryphon bearing the south Shaft of the wes... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.081 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 11 May 1846 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1846 1846 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Part of the Façade of the destroyed Church of San Michele in Foro, Lucca, sketched in colour'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159408Part of the Façade of the destroyed Church of ...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.084https://collections.ashmolean.org/media/ashmol...30 June - 1 July 1846NaN18461846
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159408 \n", "\n", " title \\\n", "0 Part of the Façade of the destroyed Church of ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.084 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 30 June - 1 July 1846 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1846 1846 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Lateral View of the Façade San Michele in Foro, Lucca'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159409Lateral View of the Façade San Michele in Foro...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.085https://collections.ashmolean.org/media/ashmol...30 June - 1 July 1846NaN18461846
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159409 \n", "\n", " title \\\n", "0 Lateral View of the Façade San Michele in Foro... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.085 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 30 June - 1 July 1846 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1846 1846 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Sculpture of a Dragon filling a Quatrefoil on the North Entrance of Rouen Cathedral'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159671The Sculpture of a Dragon filling a Quatrefoil...{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.042.ahttps://collections.ashmolean.org/media/ashmol...October 1848NaN18481848
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159671 \n", "\n", " title \\\n", "0 The Sculpture of a Dragon filling a Quatrefoil... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.042.a \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... October 1848 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1848 1848 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Euphemia (Effie) Ruskin'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...101252Euphemia (Effie) Ruskin{'id': 'https://collections.ashmolean.org/coll...WA1961.37https://collections.ashmolean.org/media/ashmol...1846 - 1851NaN18461851
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 101252 \n", "\n", " title creator \\\n", "0 Euphemia (Effie) Ruskin {'id': 'https://collections.ashmolean.org/coll... \n", "\n", " accession_number image_url \\\n", "0 WA1961.37 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest date_created_latest \n", "0 1846 - 1851 NaN 1846 1851 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"Ivy-Leaved Toadflax ('Oxford Ivy')\"" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159362Ivy-Leaved Toadflax ('Oxford Ivy'){'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.019https://collections.ashmolean.org/media/ashmol...1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159362 \n", "\n", " title \\\n", "0 Ivy-Leaved Toadflax ('Oxford Ivy') \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.019 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Part of the Palazzo Priuli, Venice'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159536Part of the Palazzo Priuli, Venice{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.210https://collections.ashmolean.org/media/ashmol...probably 1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159536 \n", "\n", " title \\\n", "0 Part of the Palazzo Priuli, Venice \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.210 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study for Detail of the Sarcophagus and Canopy of the Tomb of Mastino II della Scala at Verona'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159598Study for Detail of the Sarcophagus and Canopy...{'id': 'https://collections.ashmolean.org/coll...WA.RS.REF.059https://collections.ashmolean.org/media/ashmol...1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159598 \n", "\n", " title \\\n", "0 Study for Detail of the Sarcophagus and Canopy... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.REF.059 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Exterior of the Ducal Palace, Venice'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159606The Exterior of the Ducal Palace, Venice{'id': 'https://collections.ashmolean.org/coll...WA.RS.REF.067https://collections.ashmolean.org/media/ashmol...1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159606 \n", "\n", " title \\\n", "0 The Exterior of the Ducal Palace, Venice \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.REF.067 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study of the North Gable of the Tomb of Mastino II della Scala, Verona'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159712Study of the North Gable of the Tomb of Mastin...{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.095https://collections.ashmolean.org/media/ashmol...probably June 1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159712 \n", "\n", " title \\\n", "0 Study of the North Gable of the Tomb of Mastin... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.095 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably June 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study of one of the Pinnacles of the Tomb of Mastino II della Scala, Verona'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159714Study of one of the Pinnacles of the Tomb of M...{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.097.ahttps://collections.ashmolean.org/media/ashmol...probably January 1852NaN18521852
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159714 \n", "\n", " title \\\n", "0 Study of one of the Pinnacles of the Tomb of M... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.097.a \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably January 1852 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1852 1852 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'John Ruskin'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b.../59248John Ruskin{'id': 'https://collections.ashmolean.org/coll...WA2013.67https://collections.ashmolean.org/media/ashmol...1853 - 1854NaN18531854
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... /59248 \n", "\n", " title creator \\\n", "0 John Ruskin {'id': 'https://collections.ashmolean.org/coll... \n", "\n", " accession_number image_url \\\n", "0 WA2013.67 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest date_created_latest \n", "0 1853 - 1854 NaN 1853 1854 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"Etching of Turner's Drawing of 'Rietz, near Saumur'\"" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159417Etching of Turner's Drawing of 'Rietz, near Sa...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.101https://collections.ashmolean.org/media/ashmol...before 1860NaN18601860
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159417 \n", "\n", " title \\\n", "0 Etching of Turner's Drawing of 'Rietz, near Sa... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.101 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... before 1860 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1860 1860 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Pine Forest on Mont Cenis'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159576Pine Forest on Mont Cenis{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.275https://collections.ashmolean.org/media/ashmol...1854 - 1856NaN18541856
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159576 \n", "\n", " title \\\n", "0 Pine Forest on Mont Cenis \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.275 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1854 - 1856 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1854 1856 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a Window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176324Design for a Window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.47https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176324 \n", "\n", " title \\\n", "0 Design for a Window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.47 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176325Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.49https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176325 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.49 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176326Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.51https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176326 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.51 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176327Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.52https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176327 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.52 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176328Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.53https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176328 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.53 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176329Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.54https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176329 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.54 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176330Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.55https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176330 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.55 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176331Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.56https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176331 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.56 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Design for a window in the University Museum, Oxford'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...176332Design for a window in the University Museum, ...{'id': 'https://collections.ashmolean.org/coll...WA1931.50https://collections.ashmolean.org/media/ashmol...c. 1855NaN18551855
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 176332 \n", "\n", " title \\\n", "0 Design for a window in the University Museum, ... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA1931.50 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... c. 1855 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1855 1855 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"Study in Neutral Tint of Turner's 'The Pass of Faido'\"" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159582Study in Neutral Tint of Turner's 'The Pass of...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.287https://collections.ashmolean.org/media/ashmol...1846 - 1865NaN18461865
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159582 \n", "\n", " title \\\n", "0 Study in Neutral Tint of Turner's 'The Pass of... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.287 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1846 - 1865 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1846 1865 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study of a few Blades of Grass as they Grew'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159350Study of a few Blades of Grass as they Grew{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.006https://collections.ashmolean.org/media/ashmol...probably spring 1856NaN18561856
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159350 \n", "\n", " title \\\n", "0 Study of a few Blades of Grass as they Grew \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.006 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably spring 1856 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1856 1856 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Fribourg, Switzerland: Pen sketch'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159427Fribourg, Switzerland: Pen sketch{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.114.ahttps://collections.ashmolean.org/media/ashmol...July or August - September 1856NaN18561856
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159427 \n", "\n", " title \\\n", "0 Fribourg, Switzerland: Pen sketch \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.114.a \n", "\n", " image_url \\\n", "0 https://collections.ashmolean.org/media/ashmol... \n", "\n", " date_created current_owner date_created_earliest \\\n", "0 July or August - September 1856 NaN 1856 \n", "\n", " date_created_latest \n", "0 1856 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Study of Young Leaves of Plane, in Light and Shade'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159453Study of Young Leaves of Plane, in Light and S...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.254https://collections.ashmolean.org/media/ashmol...probably 1857NaN18571857
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159453 \n", "\n", " title \\\n", "0 Study of Young Leaves of Plane, in Light and S... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.254 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably 1857 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1857 1857 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Finished Study of Agrimony Leaves'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159454Finished Study of Agrimony Leaves{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.255.ahttps://collections.ashmolean.org/media/ashmol...probably 1857NaN18571857
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159454 \n", "\n", " title \\\n", "0 Finished Study of Agrimony Leaves \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.255.a \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably 1857 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1857 1857 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\"Tracing of Turner's 'Hospice of the Great Saint Bernard'\"" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159730Tracing of Turner's 'Hospice of the Great Sain...{'id': 'https://collections.ashmolean.org/coll...WA.RS.RUD.150https://collections.ashmolean.org/media/ashmol...probably 1857NaN18571857
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159730 \n", "\n", " title \\\n", "0 Tracing of Turner's 'Hospice of the Great Sain... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.RUD.150 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... probably 1857 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1857 1857 " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'The Courtyard of a Late Gothic Wooden House at Abbeville'" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
classificationhomepageidtitlecreatoraccession_numberimage_urldate_createdcurrent_ownerdate_created_earliestdate_created_latest
0https://collections.ashmolean.org/collection/b...159340The Courtyard of a Late Gothic Wooden House at...{'id': 'https://collections.ashmolean.org/coll...WA.RS.ED.062https://collections.ashmolean.org/media/ashmol...1858NaN18581858
\n", "
" ], "text/plain": [ " classification homepage id \\\n", "0 https://collections.ashmolean.org/collection/b... 159340 \n", "\n", " title \\\n", "0 The Courtyard of a Late Gothic Wooden House at... \n", "\n", " creator accession_number \\\n", "0 {'id': 'https://collections.ashmolean.org/coll... WA.RS.ED.062 \n", "\n", " image_url date_created \\\n", "0 https://collections.ashmolean.org/media/ashmol... 1858 \n", "\n", " current_owner date_created_earliest date_created_latest \n", "0 NaN 1858 1858 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import requests\n", "\n", "try:\n", " from bs4 import BeautifulSoup\n", "except:\n", " %pip install bs4\n", " from bs4 import BeautifulSoup\n", " \n", "import re\n", "\n", "#cromulent\n", "from cromulent.model import factory\n", " \n", "# custom linked art coding\n", "from lib import linkedart as la\n", "\n", "selectOptions = []\n", "selectOptions.append((\"Please select an artwork\", \"\"))\n", "\n", "\n", "baseURI = \"https://collections.ashmolean.org/collection/\"\n", "ash_file = './data/ashmolean/ash.html'\n", "\n", "# open HTML file\n", "html_text = open(ash_file, 'r').read()\n", "\n", "# create soup\n", "soup = BeautifulSoup(html_text, 'html.parser')\n", "\n", "# iterate through artwork descriptions in HTML\n", "for artwork in soup.find_all('div',attrs={\"class\":\"list-inner\"}):\n", " \n", " # title\n", " title = artwork.find('h3').string\n", " \n", " # id\n", " id = artwork.find('h3').find('a').get('href')\n", " id = id[-6:]\n", " \n", " # creator\n", " creator = [{\"id\": \"https://collections.ashmolean.org/collection/search/trigger/person_id/value/7800\", \"name\":\"John Ruskin\",\"role\":\"Artist\"}]\n", " \n", " # accession number\n", " accession_number = artwork.find('span').string\n", " accession_number = accession_number.replace(\"Accession no. \", \"\")\n", " \n", " # image url\n", " image_url = artwork.find(\"img\").get(\"src\")\n", " \n", " # date created\n", " date_created = artwork.find(\"p\").string\n", " date_created = date_created.replace(\"Date: \",\"\")\n", " \n", " objProp = {\n", " \"classification\":\"\",\n", " \"homepage\":\"https://collections.ashmolean.org/collection/browse-9148/object/\" + id,\n", " \"id\":id,\n", " \"title\":title,\n", " \"creator\":creator,\n", " \"accession_number\":accession_number,\n", " \"image_url\":image_url,\n", " \"date_created\":date_created,\n", " \"current_owner\" : {\"name\":\"Ashmolean Museum\",\n", " \"location\":\"Oxford, England, UK\",\n", " \"type\": \"http://vocab.getty.edu/aat/300312281\" ,\n", " \"type_label\": \"\"}\n", " }\n", " \n", " # look for year in value \n", " years = re.findall('(\\d{4})', date_created)\n", " if len(years) == 1:\n", " \n", " objProp[\"date_created_earliest\"] = years[0]\n", " objProp[\"date_created_latest\"] = years[0]\n", " elif len(years) == 2: \n", " objProp[\"date_created_earliest\"] = years[0]\n", " objProp[\"date_created_latest\"] = years[1]\n", " else:\n", " # use Ruskins birth/death years\n", " objProp[\"date_created_earliest\"] = 1819\n", " objProp[\"date_created_latest\"] = 1900\n", " \n", " \n", " object_uri = baseURI + id\n", " \n", " # create drop down options for jsonld vis\n", " title = objProp[\"title\"] + \" (\" + objProp[\"id\"] + \".json)\" \n", " selectOptions.append((title, objProp[\"id\"] + \".json\"))\n", " \n", " objLA = la.createObjDesc(objProp,la.objTypes,object_uri)\n", " \n", " # write to file \n", " text_file = open(outputdir + objProp[\"id\"] + \".json\", \"wt\")\n", " n = text_file.write(factory.toString(objLA, compact=False))\n", " text_file.close()\n", " \n", " display(objProp[\"title\"])\n", " display(pd.DataFrame(objProp, index=[0]))\n", "\n", "\n" ] }, { "cell_type": "markdown", "id": "8db4205c", "metadata": {}, "source": [ "### Visualisation of the Linked Art JSON-LD\n", "\n", "The Linked Art JSON-LD representation can be viewed in a data visualisation below. Select an artwork from the dropdown menu." ] }, { "cell_type": "code", "execution_count": 59, "id": "ad214896", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0927da6656d244c5baccbbcb2f4d01bf", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), ('The Tower of Gloucester Cathedral (159710.json)', '15971…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " import ipywidgets\n", "except:\n", " %pip install ipywidgets\n", " import ipywidgets\n", "\n", "from ipywidgets import Layout, FileUpload \n", "from IPython.display import display, IFrame, HTML, Image, Javascript\n", "\n", "def dropdown_eventhandler_tate(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " outputdir = \"./data/ruskin/output/json/\"\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#visash';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworkash').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworkash').src = '';\"))\n", " \n", "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler_tate, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "9b27c591", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "d97776b3", "metadata": {}, "source": [ "# Transformation - End Result - Linked Art JSON-LD Files for Artworks by John Ruskin\n", "\n", "The result of the transformation is a collection of Linked Art JSON-LD files for artworks by John Ruskin from various collections.\n", "\n", "You can explore the Linked Art representation below in the JSON-LD visualisation:\n", "- select an artwork from the dropdown menu to view the image and associated Linked Art JSON-LD visualisation" ] }, { "cell_type": "code", "execution_count": 60, "id": "98bbb823", "metadata": {}, "outputs": [], "source": [ "file_list=os.listdir(outputdir)\n", " \n", "#for file in file_list:\n", " # display(HTML(\"\" + file + \"\"))\n" ] }, { "cell_type": "code", "execution_count": 61, "id": "0a8b52eb", "metadata": {}, "outputs": [], "source": [ "import ipywidgets\n", "from ipywidgets import Layout, FileUpload \n", "from IPython.display import display, IFrame, HTML, Image\n", "import os\n", "import json\n", "from IPython.core.display import Javascript \n", "\n", "\n", "def dropdown_eventhandler(change):\n", " with open('./src/js/visld.js', 'r') as _jscript:\n", " code = _jscript.read() + \"var file = '\" + outputdir + change.new + \"';var selector = '#visfinal';visjsonld(file, selector); \"\n", " display(Javascript(code))\n", " \n", " with open( outputdir + \"/\" + change.new) as json_file:\n", " \n", " artwork = json.load(json_file)\n", " if (\"representation\" in artwork):\n", " image = artwork[\"representation\"][0][\"id\"]\n", " display(Javascript(\"document.getElementById('artworkfinal').src = '\" + image + \"';\"))\n", " else:\n", " display(Javascript(\"document.getElementById('artworkfinal').src = '';\"))\n", " \n", "\n", "# directory that will contain updated Ruskin artwork representations including geo coords\n", "dir = outputdir = \"./data/ruskin/output/json/\"\n", "\n", "file_list=os.listdir(dir)\n", "\n", "selectOptions = []\n", "selectOptions.append((\"Please select an artwork\", \"\"))\n", "\n", "\n", "# for each linked art json file\n", "for file in file_list:\n", " # open file\n", " with open( dir + \"/\" + file) as json_file:\n", " artwork = json.load(json_file) \n", " if artwork.get('_label') != None:\n", " title = artwork[\"_label\"] + \" (\" + file + \")\"\n", " else:\n", " title = \" (\" + file + \")\"\n", " \n", " selectOptions.append((title,file))" ] }, { "cell_type": "code", "execution_count": 62, "id": "545070b2", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "8d3cbbb64bd5479a947232c6d7fd88f8", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(options=(('Please select an artwork', ''), (\"Engraving of Ruskin's Drawing of the Petal Vault of a Sc…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/298606.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://nrs.harvard.edu/urn-3:HUAM:VRS48818_dynmc';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159835.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_WAL_01-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159589.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_297-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159531.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_198-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159474.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_RUD_293-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/298597.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://nrs.harvard.edu/urn-3:HUAM:VRS48802_dynmc';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159527.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_193-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/293768.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://nrs.harvard.edu/urn-3:HUAM:80339_dynmc';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159507.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_165_a-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159357.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_014-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159429.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_116-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159413.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_093-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159833.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_UF_09-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159599.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_REF_060-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159366.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_023-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159799.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_RUD_276-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159760.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_RUD_225-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/299092.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://nrs.harvard.edu/urn-3:HUAM:VRS48790_dynmc';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159367.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_024-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159412.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_ED_089_a-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/159701.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://collections.ashmolean.org/media/ashmole6_collection/w800/Collections/Single_Objects/WA/WA_RS/WA_RS_RUD_061-a-L.jpg';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "require.config({paths: {\n", " d3: \"http://d3js.org/d3.v3.min\"\n", "}});\n", "\n", "function visjsonld(file, selector){\n", " \n", " require([\"d3\"], function(d3) {\n", " \n", " d3.json(file, (err, jsonld) => {\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:#446a7f')\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 ? 'navy' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'white' : 'white';\n", " } else {\n", " return d._children ? 'white' : '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", " \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 ? '#78BE21' : '#78BE21';\n", " })\n", " .style('fill', function(d) {\n", " if (d.isIdNode) {\n", " return d._children ? 'navy' : '#78BE21';\n", " } else {\n", " return d._children ? 'navy' : '#78BE21';\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', 'white');\n", " nodeUpdate.select('text').style('font-size', '12px');\n", " \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", "\n", "\n", "\n", "})}\n", "var file = './data/ruskin/output/json/297164.json';var selector = '#visfinal';visjsonld(file, selector); " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "document.getElementById('artworkfinal').src = 'https://nrs.harvard.edu/urn-3:HUAM:779024';" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "selectObject = ipywidgets.Dropdown(options=selectOptions)\n", "selectObject.observe(dropdown_eventhandler, names='value')\n", "\n", "display(selectObject)" ] }, { "cell_type": "markdown", "id": "1427656b", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "5f4208fb", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "finalized": { "timestamp": 1651267300605, "trusted": true }, "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" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { "027591e6aa434392aca1b010a7799135": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {} }, "08e00802ee6143c3a78361e4b8fa8b09": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "Please select an artwork", "Tower of the Cathedral at Sens (70238.json)", "Tree Study (70367.json)", "The Garden of San Miniato near Florence (72870.json)", "Ornamental Study with Acanthus Motif for \"The Stones of Venice\" (76140.json)" ], "index": 1, "layout": "IPY_MODEL_027591e6aa434392aca1b010a7799135", "style": "IPY_MODEL_daff003b51fe4b55977b389dd761376d" } }, "ac77c8991a8e42f397cd3b526f4368b0": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "Please select an artwork", "Tower of the Cathedral at Sens (70238.json)", "Tree Study (70367.json)", "The Garden of San Miniato near Florence (72870.json)", "Ornamental Study with Acanthus Motif for \"The Stones of Venice\" (76140.json)" ], "index": 0, "layout": "IPY_MODEL_c0ae8de4ad2d4576b448bd2999d84282", "style": "IPY_MODEL_ecd5c3986d744e80b5e302ecf7257909" } }, "c0ae8de4ad2d4576b448bd2999d84282": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {} }, "daff003b51fe4b55977b389dd761376d": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "ecd5c3986d744e80b5e302ecf7257909": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }