<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 In this notebook, we demonstrate how to create and modify a Titan graph in python, and then visualize the result using Graphistry's visual graph explorer.
We assume the gremlin server for our Titan graph is hosted locally on port 8182
- This notebook utilizes the python modules aiogremlin and asyncio.
- The GremlinClient class of aiogremlin communicates asynchronously with the gremlin server using websockets via asyncio coroutines.
- This implementation allows you to submit additional requests to the server before any responses are recieved, which is much faster than synchronous request / response cycles. 
- For more information about these modules, please visit
Step1:  Functions for graph modification
Step2:  Functions for translating a graph to node and edge lists
Step3:  Let's start with an empty graph
Step4:  And then populate it with the Graphistry team members and some of thier relationships
Step5:  Now, let's convert our graph database to a pandas DataFrame, so it can be uploaded into our tool
Step6:  And color the nodes based on their "type" property
Step7:  Finally, let's vizualize the results!
<ASSISTANT_TASK:>
Python Code:
import asyncio
import aiogremlin
# Create event loop and initialize gremlin client
loop = asyncio.get_event_loop()
client = aiogremlin.GremlinClient(url='ws://localhost:8182/', loop=loop)  # Default url
Explanation: In this notebook, we demonstrate how to create and modify a Titan graph in python, and then visualize the result using Graphistry's visual graph explorer.
We assume the gremlin server for our Titan graph is hosted locally on port 8182
- This notebook utilizes the python modules aiogremlin and asyncio.
- The GremlinClient class of aiogremlin communicates asynchronously with the gremlin server using websockets via asyncio coroutines.
- This implementation allows you to submit additional requests to the server before any responses are recieved, which is much faster than synchronous request / response cycles. 
- For more information about these modules, please visit:
    - aiogremlin: http://aiogremlin.readthedocs.org/en/latest/index.html
    - asyncio: https://pypi.python.org/pypi/asyncio
End of explanation
@asyncio.coroutine
def add_vertex_routine(name, label):
    yield from client.execute("graph.addVertex(label, l, 'name', n)", bindings={"l":label, "n":name})
def add_vertex(name, label):
    loop.run_until_complete(add_vertex_routine(name, label))
@asyncio.coroutine
def add_relationship_routine(who, relationship, whom):
    yield from client.execute("g.V().has('name', p1).next().addEdge(r, g.V().has('name', p2).next())", bindings={"p1":who, "p2":whom, "r":relationship})
    
def add_relationship(who, relationship, whom):
    loop.run_until_complete(add_relationship_routine(who, relationship, whom))
@asyncio.coroutine
def remove_all_vertices_routine():
    resp = yield from client.submit("g.V()")
    results = []
    while True:
        msg = yield from resp.stream.read();
        if msg is None:
            break
        if msg.data is None:
            break
        for vertex in msg.data:
            yield from client.submit("g.V(" + str(vertex['id']) + ").next().remove()")
            
def remove_all_vertices():
    results = loop.run_until_complete(remove_all_vertices_routine())
@asyncio.coroutine
def remove_vertex_routine(name):
    return client.execute("g.V().has('name', n).next().remove()", bindings={"n":name})
def remove_vertex(name):
    return loop.run_until_complete(remove_vertex_routine(name));
Explanation: Functions for graph modification
End of explanation
@asyncio.coroutine
def get_node_list_routine():
    resp = yield from client.submit("g.V().as('node')\
                          .label().as('type')\
                          .select('node').values('name').as('name')\
                          .select('name', 'type')")
    results = [];
    while True:
        msg = yield from resp.stream.read();
        if msg is None:
            break;
        if msg.data is None:
            break;
        else:
            results.extend(msg.data)
    return results
def get_node_list():
    results =  loop.run_until_complete(get_node_list_routine())
    return results
@asyncio.coroutine
def get_edge_list_routine():
    resp = yield from client.submit("g.E().as('edge')\
                          .label().as('relationship')\
                          .select('edge').outV().values('name').as('source')\
                          .select('edge').inV().values('name').as('dest')\
                          .select('source', 'relationship', 'dest')")
    
    results = [];
    while True:
        msg = yield from resp.stream.read();
        if msg is None:
            break;
        if msg.data is None:
            break;
        else:
            results.extend(msg.data)
    return results
def get_edge_list():
    results =  loop.run_until_complete(get_edge_list_routine())
    return results
Explanation: Functions for translating a graph to node and edge lists:
- Currently, our API can only upload data from a pandas DataFrame, but we plan to implement more flexible uploads in the future.
- For now, we can rely on the following functions to create the necessary DataFrames from our graph.
End of explanation
remove_all_vertices()
Explanation: Let's start with an empty graph:
End of explanation
add_vertex("Paden", "Person")
add_vertex("Thibaud", "Person")
add_vertex("Leo", "Person")
add_vertex("Matt", "Person")
add_vertex("Brian", "Person")
add_vertex("Quinn", "Person")
add_vertex("Paul", "Person")
add_vertex("Lee", "Person")
add_vertex("San Francisco", "Place")
add_vertex("Oakland", "Place")
add_vertex("Berkeley", "Place")
add_vertex("Turkey", "Thing")
add_vertex("Rocks", "Thing")
add_vertex("Motorcycles", "Thing")
add_relationship("Paden", "lives in", "Oakland")
add_relationship("Quinn", "lives in", "Oakland")
add_relationship("Thibaud", "lives in", "Berkeley")
add_relationship("Matt", "lives in", "Berkeley")
add_relationship("Leo", "lives in", "San Francisco")
add_relationship("Paul", "lives in", "San Francisco")
add_relationship("Brian", "lives in", "Oakland")
add_relationship("Paden", "eats", "Turkey")
add_relationship("Quinn", "cooks", "Turkey")
add_relationship("Thibaud", "climbs", "Rocks")
add_relationship("Matt", "climbs", "Rocks")
add_relationship("Brian", "rides", "Motorcycles")
add_vertex("Graphistry", "Work")
add_relationship("Paden", "works at", "Graphistry")
add_relationship("Thibaud", "works at", "Graphistry")
add_relationship("Matt", "co-founded", "Graphistry")
add_relationship("Leo", "co-founded", "Graphistry")
add_relationship("Paul", "works at", "Graphistry")
add_relationship("Quinn", "works at", "Graphistry")
add_relationship("Brian", "works at", "Graphistry")
Explanation: And then populate it with the Graphistry team members and some of thier relationships:
End of explanation
import pandas
nodes = pandas.DataFrame(get_node_list())
edges = pandas.DataFrame(get_edge_list())
Explanation: Now, let's convert our graph database to a pandas DataFrame, so it can be uploaded into our tool:
End of explanation
# Assign different color to each type in a round robin fashion. 
# For more information and coloring options please visit: https://graphistry.github.io/docs/legacy/api/0.9.2/api.html
unique_types = list(nodes['type'].unique())
nodes['color'] = nodes['type'].apply(lambda x: unique_types.index(x) % 11)
nodes
edges
Explanation: And color the nodes based on their "type" property:
End of explanation
import graphistry
# To specify Graphistry account & server, use:
# graphistry.register(api=3, username='...', password='...', protocol='https', server='hub.graphistry.com')
# For more options, see https://github.com/graphistry/pygraphistry#configure
g = graphistry.bind(source="source", destination="dest", node='name', point_color='color', edge_title='relationship')
g.plot(edges, nodes)
Explanation: Finally, let's vizualize the results!
End of explanation
<END_TASK>