import graphistry
import pandas as pd
import numpy as np

# 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: Silk Road Bitcoin Embezzling Visualization
End of explanation
"""


transactions = pd.read_csv('../../data/transactions.csv')
transactions['Date'] = pd.to_datetime(transactions['Date'],unit='ms') #coerce date format
print('# transactions', len(transactions))
transactions[:3]

"""
Explanation: Data: Load transactions CSV with Pandas
End of explanation
"""


g = graphistry.edges(transactions).bind(source='Source', destination='Destination')

g.plot()

"""
Explanation: Visualization 1: Quick Visualization & Analysis
Task: Spot the embezzling
1. Use the histogram tool to filter for only tainted transactions
2. Turn on the Setting "Prune Isolated Nodes" to hide wallets with no remaining transactions
3. Use the filters or excludes tool to only show transactions over 1000 or 1000. 
4. Verify that money flowed from Ross Ulbricht to Carl Force, and explore where else it flowed.
End of explanation
"""


wallet_in = transactions\
  .groupby('Destination')\
  .agg({'isTainted': lambda x: 1 if x.sum() > 0 else 0, 'Amount $': np.sum})\
  .reset_index().rename(columns={'Destination': 'wallet', 'isTainted': 'isTaintedWallet'})

#not all wallets received money, tag these
wallet_in['Receivables'] = True

wallet_in[:3]

"""
Explanation: Visualization 2: Summarizing Wallets
Compute how much wallets received
End of explanation
"""


wallet_out = transactions\
  .groupby('Source')\
  .agg({'isTainted': np.sum, 'Amount $': np.max})\
  .reset_index().rename(columns={'Source': 'wallet', 'isTainted': 'isTaintedWallet'})

#not all wallets received money, tag these
wallet_out['Payables'] = True

wallet_out[:3]

"""
Explanation: Compute how much wallets sent
End of explanation
"""


wallets = pd.merge(wallet_in, wallet_out, how='outer')
wallets['Receivables'] = wallets['Receivables'].fillna(False)
wallets['Payables'] = wallets['Payables'].fillna(False)
print('# Wallets only sent or only received', len(wallet_in) + len(wallet_out) - len(wallets))
wallets[:3]

"""
Explanation: Join data
End of explanation
"""


g.nodes(wallets).bind(node='wallet', point_color='isTaintedWallet').plot()

"""
Explanation: Plot
Bind color to whether tainted
End of explanation
"""


