{
"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
}