{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Entanglement Examples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Entanglement allows you to query, create, and connect `Objects` in a knowledge graph. Let's add some top level imports that we'll need to get started" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "PROJ: proj_create_from_database: Cannot find proj.db\n" ] } ], "source": [ "import geodesic\n", "from geodesic.entanglement import Object, get_objects, add_connections, get_traits, Connection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, let's get a project, or subgraph, that we want to work with" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'name': 'docs-example',\n", " 'alias': 'Docs Example Project',\n", " 'description': 'Test project for illustration purposes',\n", " 'owner': 'auth0|611c3d206a08f0006c8a9290',\n", " 'keywords': '',\n", " 'uid': 'b96a3c8f8104b671d19ff7dbad5b7026992d7643'}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "geodesic.set_active_project('docs-example')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any time we create an object, it will default to this project. First, let's try seeing what's in there. We should start with nothing." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "objects = get_objects()\n", "objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's create a new `Object`. Recall that only a few classes of `Object` are available:\n", "\n", "* `Entity`\n", "* `Dataset`\n", "* `Observable`\n", "* `Concept`\n", "* `Property`\n", "* `Link`\n", "* `Model`\n", "* `Event`\n", "\n", "`Dataset` and `Model` are their own topic, but let's create a simple graph by creating an imaginary farm. " ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "entity:agriculture:*:farm:whispering-pines-farm" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Here's a location. We can index points and polygons. This could just as easily be a Shapely geometry or anything that fullfils __geo_interface__\n", "geometry = {'type': 'Point', 'coordinates': [-104.84, 39.64]}\n", "\n", "# Some arbitrary imaginary metadata\n", "item = {\n", " \"owner\": \"Farmer Bill\",\n", " \"address\": \"123 Farmingville Drive, Aurora CO 80014\",\n", " \"new info\": \"valid\"\n", "}\n", "\n", "farm = Object(\n", " name=\"whispering-pines-farm\",\n", " description=\"Farmer Bill's farm. It grows food.\",\n", " object_class='Entity', \n", " domain=\"agriculture\",\n", " category=\"*\",\n", " type=\"farm\",\n", " item=item,\n", " geometry=geometry\n", ")\n", "\n", "farm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we've created a new Object, but not yet saved it to the graph. You can work with this object, edit as necessary to make sure it stores the data you want. " ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "POINT (-104.84 39.64)\n" ] }, { "data": { "image/svg+xml": "", "text/plain": [ "" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(farm.geometry)\n", "farm.geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can inspect the raw contents, which is what will be sent to the backend when you actually create the object. " ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': 'b96a3c8f8104b671d19ff7dbad5b7026992d7643',\n", " 'name': 'whispering-pines-farm',\n", " 'description': \"Farmer Bill's farm. It grows food.\",\n", " 'class': 'Entity',\n", " 'domain': 'agriculture',\n", " 'category': '*',\n", " 'type': 'farm',\n", " 'item': {'owner': 'Farmer Bill',\n", " 'address': '123 Farmingville Drive, Aurora CO 80014',\n", " 'new info': 'valid'},\n", " 'geometry': {'type': 'Point', 'coordinates': [-104.84, 39.64]}}" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict(farm)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One quick technical note: Even though we created it using the `Object` class, the type of `farm` is actually `Entity`. When you create an `Object`, it actually returns the class corresponding to whatever `object_class` you passed in." ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "geodesic.entanglement.object.Entity" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(farm)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's save this object to the graph.\n", "\n", "Note that in order to make connections on objects in the graph they must first be saved. Until saved they are just a local \n", "object and not yet in the Geodesic Platform." ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "farm.save()" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[entity:agriculture:*:farm:whispering-pines-farm]" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "objects = get_objects()\n", "objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now you can see the object is in the graph. Let's take a look at what's returned" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': 'b96a3c8f8104b671d19ff7dbad5b7026992d7643',\n", " 'uid': '0x2732',\n", " 'class': 'Entity',\n", " 'domain': 'agriculture',\n", " 'category': '*',\n", " 'type': 'farm',\n", " 'name': 'whispering-pines-farm',\n", " 'geometry': {'coordinates': [-104.84, 39.64], 'type': 'Point'},\n", " 'item': {'address': '123 Farmingville Drive, Aurora CO 80014',\n", " 'owner': 'Farmer Bill'},\n", " 'description': \"Farmer Bill's farm. It grows food.\"}" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict(objects[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "you can see that it's nearly the same object as what we sent, but now has the addition of a `uid` field. This uniquely identifies this object and can be used to get a specfic object:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "entity:agriculture:*:farm:whispering-pines-farm" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "obj = Object(uid='0x2721')\n", "obj.load()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see how different ways of querying the graph can find (or not find) this `Object` again" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[entity:agriculture:*:farm:whispering-pines-farm]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_objects(search='pines')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[entity:agriculture:*:farm:whispering-pines-farm]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_objects(search='farm')" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[entity:agriculture:*:farm:whispering-pines-farm]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_objects(search='farmer')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from shapely.geometry import box\n", "\n", "get_objects(geometry=box(0, 0, 1, 1), spatial_predicate='intersects') # note: intersects is the default" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[entity:agriculture:*:farm:whispering-pines-farm]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_objects(geometry=box(-104.85, 39.60, -104.83, 39.7), spatial_predicate='intersects') # note: intersects is the default" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_objects(search='farmer', project='global')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We've added only one object so far, but now let's add another" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "link:*:*:*:farm-info" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "link = Object(\n", " name=\"farm-info\",\n", " description=\"a link to information about farms\",\n", " object_class='Link',\n", " item={\n", " 'href': 'https://en.wikipedia.org/wiki/Farm'\n", " }\n", ")\n", "link" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "link.save()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': 'b96a3c8f8104b671d19ff7dbad5b7026992d7643',\n", " 'name': 'farm-info',\n", " 'description': 'a link to information about farms',\n", " 'class': 'Link',\n", " 'item': {'href': 'https://en.wikipedia.org/wiki/Farm'},\n", " 'uid': '0x2729'}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict(link)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, I'm going to add a connection back to that original farm" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "entity:agriculture:*:farm:whispering-pines-farm --links--> link:*:*:*:farm-info" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "farm.connect_with(\n", " predicate={\n", " 'name': 'links'\n", " }, \n", " object=link\n", ")" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "g = get_objects(as_graph=True)" ] } ], "metadata": { "kernelspec": { "display_name": "geodesic-dev", "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.9.15 (main, Nov 24 2022, 14:31:59) \n[GCC 11.2.0]" }, "vscode": { "interpreter": { "hash": "3d2bf83ed2a6da8a0631fea44d33ce4d4db244cea4ef89c6233c9ac35e49a783" } }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }