<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Visualize CSV Mini-App
Jupyter
Step1:  1. Upload csv
Use a file by uploading it or via URL. 
Run help(pd.read_csv) for more options.
File Upload
Step2:  2. Optional
Step3:  3. Configure
Step4:  4. Plot
Step5:  Alternative
<ASSISTANT_TASK:>
Python Code:
#!pip install graphistry -q
import pandas as pd
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
Explanation: Visualize CSV Mini-App
Jupyter: File -> Make a copy
  Colab: File -> Save a copy in Drive
Run notebook cells by pressing shift-enter
Either edit annd run top cells one-by-one, or edit and run the self-contained version at the bottom
End of explanation
file_path = './data/honeypot.csv'
df = pd.read_csv(file_path)
print('# rows', len(df))
df.sample(min(len(df), 3))
Explanation: 1. Upload csv
Use a file by uploading it or via URL. 
Run help(pd.read_csv) for more options.
File Upload: Jupyter Notebooks
If circle on top right not green, click kernel -> reconnect
Go to file directory (/tree) by clicking the Jupyter logo
Navigate to the directory page containing your notebook
Press the upload button on the top right
File Upload: Google Colab
Open the left sidebar by pressing the right arrow on the left
Go to the Files tab
Press UPLOAD
Make sure goes into /content
File Upload: URL
Uncomment below line and put in the actual data url
Run help(pd.read_csv) for more options
End of explanation
df = df.rename(columns={
#    'attackerIP': 'src_ip',
#    'victimIP': 'dest_ip'
})
df.sample(3)
Explanation: 2. Optional: Clean up CSV
End of explanation
#Pick 'A', 'B', or 'C'
mode = 'B' 
max_rows = 1000
### 'A' == mode
my_src_col = 'attackerIP'
my_dest_col = 'victimIP'
### 'B' == mode
node_cols = ['attackerIP', 'victimIP', 'vulnName']
categories = { #optional
    'ip': ['attacker_IP', 'victimIP']
    #, 'user': ['owner', 'seller'],
}
### 'C' == mode
edges = {
      'attackerIP': [ 'victimIP', 'victimPort', 'vulnName'],
      'victimIP': [ 'victimPort'],
      'vulnName': [ 'victimIP' ]
}
categories = { #optional
      'ip': ['attackerIP', 'victimIP']
       #, user': ['owner', 'seller'], ...
}
Explanation: 3. Configure: Visualize with 3 kinds of graphs
Set mode and the corresponding values:
Mode "A". See graph from table of (src,dst) edges
Mode "B". See hypergraph: Draw row as node and connect it to entities in same row
Pick which cols to make nodes
If multiple cols share same type (e.g., "src_ip", "dest_ip" are both "ip"), unify them
Mode "C". See by creating multiple nodes, edges per row
Pick how different column values point to other column values 
If multiple cols share same type (e.g., "src_ip", "dest_ip" are both "ip"), unify them
End of explanation
g = None
hg = None
num_rows = min(max_rows, len(df))
if mode == 'A':
    g = graphistry.edges(df.sample(num_rows)).bind(source=my_src_col, destination=my_dest_col)
elif mode == 'B':
    hg = graphistry.hypergraph(df.sample(num_rows), node_cols, opts={'CATEGORIES': categories})
    g = hg['graph']
elif mode == 'C':
    nodes = list(edges.keys())
    for dests in edges.values():
        for dest in dests:
            nodes.append(dest)
    node_cols = list(set(nodes))
    hg = graphistry.hypergraph(df.sample(num_rows), node_cols, direct=True, opts={'CATEGORIES': categories, 'EDGES': edges})
    g = hg['graph']
  
#hg
print(len(g._edges))
g.plot()
Explanation: 4. Plot: Upload & render!
See UI guide: https://labs.graphistry.com/graphistry/ui.html
End of explanation
#!pip install graphistry -q
import pandas as pd
import graphistry
#graphistry.register(key='MY_KEY', server='labs.graphistry.com')
##########
#1. Load
file_path = './data/honeypot.csv'
df = pd.read_csv(file_path)
print(df.columns)
print('rows:', len(df))
print(df.sample(min(len(df),3)))
##########
#2. Clean
#df = df.rename(columns={'attackerIP': 'src_ip', 'victimIP: 'dest_ip', 'victimPort': 'protocol'})
    
##########
#3. Config - Pick 'A', 'B', or 'C'
mode = 'C' 
max_rows = 1000
### 'A' == mode
my_src_col = 'attackerIP'
my_dest_col = 'victimIP'
### 'B' == mode
node_cols = ['attackerIP', 'victimIP', 'victimPort', 'vulnName']
categories = { #optional
    'ip': ['src_ip', 'dest_ip']
    #, 'user': ['owner', 'seller'],
}
### 'C' == mode
edges = {
    'attackerIP': [ 'victimIP', 'victimPort', 'vulnName'],
    'victimIP': [ 'victimPort' ],
    'vulnName': ['victimIP' ]
}
categories = { #optional
    'ip': ['attackerIP', 'victimIP']
    #, 'user': ['owner', 'seller'], ...
}
##########
#4. Plot
g = None
hg = None
num_rows = min(max_rows, len(df))
if mode == 'A':
    g = graphistry.edges(df.sample(num_rows)).bind(source=my_src_col, destination=my_dest_col)
elif mode == 'B':
    hg = graphistry.hypergraph(df.sample(num_rows), node_cols, opts={'CATEGORIES': categories})
    g = hg['graph']
elif mode == 'C':
    nodes = list(edges.keys())
    for dests in edges.values():
        for dest in dests:
            nodes.append(dest)
    node_cols = list(set(nodes))
    hg = graphistry.hypergraph(df.sample(num_rows), node_cols, direct=True, opts={'CATEGORIES': categories, 'EDGES': edges})
    g = hg['graph']
  
g.plot()
Explanation: Alternative: Combined
Split into data loading and cleaning/configuring/plotting.
End of explanation
<END_TASK>