|
import sys |
|
import csv |
|
import networkx as nx |
|
from collections import defaultdict |
|
|
|
import matplotlib.pyplot as plt |
|
from matplotlib import animation |
|
|
|
|
|
def plot_alert(tx_csv): |
|
g = nx.Graph() |
|
edges = list() |
|
alert_st = dict() |
|
alert_ed = dict() |
|
acct_alert = defaultdict(set) |
|
e_suspicious = defaultdict(set) |
|
|
|
with open(tx_csv, "r") as rf: |
|
reader = csv.reader(rf) |
|
next(reader) |
|
|
|
for row in reader: |
|
step = int(row[0]) |
|
src = row[3] |
|
dst = row[6] |
|
isSAR = int(row[9]) > 0 |
|
alertID = int(row[10]) |
|
g.add_edge(src, dst) |
|
edges.append((step, src, dst)) |
|
acct_alert[src].add(alertID) |
|
acct_alert[dst].add(alertID) |
|
|
|
if isSAR: |
|
if alertID not in alert_st: |
|
alert_st[alertID] = step |
|
|
|
if alertID not in alert_ed or alert_ed[alertID] < step: |
|
alert_ed[alertID] = step |
|
|
|
e_suspicious[step].add((src, dst)) |
|
e_suspicious[step].add((dst, src)) |
|
|
|
pos = nx.spring_layout(g) |
|
sub_g = nx.DiGraph() |
|
|
|
steps = list(range(30)) |
|
|
|
def show_graph(i): |
|
if i != 0: |
|
plt.cla() |
|
|
|
def within_acct(acct): |
|
alertIDs = acct_alert[acct] |
|
return True in [alert_st.get(alert, -1) <= i <= alert_ed.get(alert, -1) for alert in alertIDs] |
|
|
|
new_edges = [(_src, _dst) for (st, _src, _dst) in edges if st == steps[i]] |
|
sub_g.add_edges_from(new_edges) |
|
nodes = sub_g.nodes() |
|
all_edges = sub_g.edges() |
|
node_colors = ["r" if within_acct(n) else "b" for n in nodes] |
|
edge_colors = ["r" if e in e_suspicious[i] else "k" for e in all_edges] |
|
|
|
plt.title("Step %d" % steps[i]) |
|
plt.xlim([-1.0, 1.0]) |
|
plt.ylim([-1.0, 1.0]) |
|
nx.draw_networkx_nodes(sub_g, pos, nodelist=nodes, node_color=node_colors, node_size=50) |
|
nx.draw_networkx_edges(sub_g, pos, edgelist=all_edges, edge_color=edge_colors, arrowsize=5, width=0.5) |
|
|
|
fig = plt.figure() |
|
anim = animation.FuncAnimation(fig, show_graph, frames=len(steps)) |
|
anim.save('tx.gif', writer='imagemagick', fps=1) |
|
|
|
|
|
if __name__ == "__main__": |
|
argv = sys.argv |
|
|
|
if len(argv) < 2: |
|
print("Usage: python %s [TxCSV]" % argv[0]) |
|
exit(1) |
|
|
|
plot_alert(argv[1]) |
|
|