A future version of this paper should include a graphic like this. The numbers here are approximate and some are just guesses/placeholders. Ideally each number should have a reference. It is unlikely the equation will balance, and there should be losses (and gains?) to/from 'uncertainty'.
Code
```python
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
df = pd.DataFrame(columns=['value','source','target','meta'])
df.index.name = 'label'
df.loc['rain:freeze'] = [50/2, 'rain', 'GL', 'A2019'] # Alexander 2019
df.loc['snow:fall'] = [750, 'snow fall', 'GL', 'A2019'] # fudge from A2019
df.loc['DEFICIT'] = [160, 'DEFICIT', 'GL', '']
df.loc['condensation'] = [10, 'condensation', 'GL', 'guess']
df.loc['drifting_out'] = [100, 'GL', 'drift', 'guess']
df.loc['drifting_in'] = [100
, 'drift', 'GL', 'guess']
df.loc['rain:runoff'] = [50/2, 'rain', 'runoff', 'A2019']
df.loc['rain:runoff:liquid'] = [50/2, 'runoff', 'liquid', 'A2019']
df.loc['SMB (loss)'] = [400, 'GL', 'SMB (loss)', 'A2019']
df.loc['dynamics'] = [500, 'GL', 'dynamics', '']
df.loc['icebergs'] = [250, 'dynamics', 'icebergs', 'M2020 & E2014'] # Enderlin & Mankoff
df.loc['frontal melt'] = [250, 'dynamics', 'frontal melt', 'E2014']
df.loc['runoff'] = [400, 'SMB (loss)','runoff', '']
df.loc['refreeze'] = [250, 'GL','refreeze', '']
df.loc['refreeze1'] = [250, 'refreeze','GL', '']
# df.loc['runoff'] = [400, 'melt','runoff', '']
#df.loc['basal melt'] = [25, 'basal melt', 'liquid', 'K2020'] # Karlsson
df.loc['basal melt'] = [25, 'GL', 'basal melt', 'K2020'] # Karlsson
df.loc['basal melt1'] = [25, 'basal melt', 'runoff', 'K2020'] # Karlsson
df.loc['basal melt2'] = [25, 'runoff', 'liquid', 'K2020'] # Karlsson
# df.loc['basal melt2'] = [50, 'runoff', 'liquid', 'K2020']
df.loc['evaporation'] = [10, 'GL', 'evaporation', '']
df.loc['sublimation'] = [10, 'GL', 'sublimation', '']
# Sum all the liquid terms to a liquid budget (solid is just 'iceberg')
for i,v in enumerate(['runoff','frontal melt']):
df.loc[f'liquid_{v}'] = [df.loc[v]['value'], v, 'liquid', '']
# QC Check
for s in df['source'].unique():
if s in df['target'].unique():
sv = df[df['source'] == s]['value'].sum()
tv = df[df['target'] == s]['value'].sum()
if( sv != tv ):
print(f"Error: {s} inputs != outputs [{sv} != {tv}]")
# # Add numeric values in parentheses
for t in np.unique(df['source'].values.astype(str)):
v = (df[df["source"] == t]["value"].sum()).round().astype(int).astype(str)
df = df.replace(to_replace=t, value=f'{t} ({v})')
for t in np.unique(df['target'].values.astype(str)):
if t[-1] == ')': continue
v = (df[df["target"] == t]["value"].sum()).round().astype(int).astype(str)
df = df.replace(to_replace=t, value=f'{t} ({v})')
# print(df)
## Plotly
# uniqify columns: Convert strings to numbers. Sequential. Across columns
keys = np.unique(df[['source','target']].values.flatten().astype(str))
df = df.replace(to_replace=keys, value=np.arange(len(keys)))
fig = go.Figure(go.Sankey(
arrangement = "snap",
node = {
"label": keys,
'color': "#666666",
'pad':10}, # 10 Pixels
link = {
"source": df['source'].values,
"target": df['target'].values,
# "color": "#DDDDDD",
"value": df['value'].values}))
# fig.show()
fig.write_image("plotly.png")
# interactive HTML: drag to re-arrange and clean up, then screenshot.
fig.write_html("plotly.html")
```
A future version of this paper should include a graphic like this. The numbers here are approximate and some are just guesses/placeholders. Ideally each number should have a reference. It is unlikely the equation will balance, and there should be losses (and gains?) to/from 'uncertainty'.
Code
```python import numpy as np import pandas as pd import plotly.graph_objects as go import plotly.express as px df = pd.DataFrame(columns=['value','source','target','meta']) df.index.name = 'label' df.loc['rain:freeze'] = [50/2, 'rain', 'GL', 'A2019'] # Alexander 2019 df.loc['snow:fall'] = [750, 'snow fall', 'GL', 'A2019'] # fudge from A2019 df.loc['DEFICIT'] = [160, 'DEFICIT', 'GL', ''] df.loc['condensation'] = [10, 'condensation', 'GL', 'guess'] df.loc['drifting_out'] = [100, 'GL', 'drift', 'guess'] df.loc['drifting_in'] = [100 , 'drift', 'GL', 'guess'] df.loc['rain:runoff'] = [50/2, 'rain', 'runoff', 'A2019'] df.loc['rain:runoff:liquid'] = [50/2, 'runoff', 'liquid', 'A2019'] df.loc['SMB (loss)'] = [400, 'GL', 'SMB (loss)', 'A2019'] df.loc['dynamics'] = [500, 'GL', 'dynamics', ''] df.loc['icebergs'] = [250, 'dynamics', 'icebergs', 'M2020 & E2014'] # Enderlin & Mankoff df.loc['frontal melt'] = [250, 'dynamics', 'frontal melt', 'E2014'] df.loc['runoff'] = [400, 'SMB (loss)','runoff', ''] df.loc['refreeze'] = [250, 'GL','refreeze', ''] df.loc['refreeze1'] = [250, 'refreeze','GL', ''] # df.loc['runoff'] = [400, 'melt','runoff', ''] #df.loc['basal melt'] = [25, 'basal melt', 'liquid', 'K2020'] # Karlsson df.loc['basal melt'] = [25, 'GL', 'basal melt', 'K2020'] # Karlsson df.loc['basal melt1'] = [25, 'basal melt', 'runoff', 'K2020'] # Karlsson df.loc['basal melt2'] = [25, 'runoff', 'liquid', 'K2020'] # Karlsson # df.loc['basal melt2'] = [50, 'runoff', 'liquid', 'K2020'] df.loc['evaporation'] = [10, 'GL', 'evaporation', ''] df.loc['sublimation'] = [10, 'GL', 'sublimation', ''] # Sum all the liquid terms to a liquid budget (solid is just 'iceberg') for i,v in enumerate(['runoff','frontal melt']): df.loc[f'liquid_{v}'] = [df.loc[v]['value'], v, 'liquid', ''] # QC Check for s in df['source'].unique(): if s in df['target'].unique(): sv = df[df['source'] == s]['value'].sum() tv = df[df['target'] == s]['value'].sum() if( sv != tv ): print(f"Error: {s} inputs != outputs [{sv} != {tv}]") # # Add numeric values in parentheses for t in np.unique(df['source'].values.astype(str)): v = (df[df["source"] == t]["value"].sum()).round().astype(int).astype(str) df = df.replace(to_replace=t, value=f'{t} ({v})') for t in np.unique(df['target'].values.astype(str)): if t[-1] == ')': continue v = (df[df["target"] == t]["value"].sum()).round().astype(int).astype(str) df = df.replace(to_replace=t, value=f'{t} ({v})') # print(df) ## Plotly # uniqify columns: Convert strings to numbers. Sequential. Across columns keys = np.unique(df[['source','target']].values.flatten().astype(str)) df = df.replace(to_replace=keys, value=np.arange(len(keys))) fig = go.Figure(go.Sankey( arrangement = "snap", node = { "label": keys, 'color': "#666666", 'pad':10}, # 10 Pixels link = { "source": df['source'].values, "target": df['target'].values, # "color": "#DDDDDD", "value": df['value'].values})) # fig.show() fig.write_image("plotly.png") # interactive HTML: drag to re-arrange and clean up, then screenshot. fig.write_html("plotly.html") ```See also LaTeX examples for more control: https://us.mirrors.cicku.me/ctan/graphics/pgf/contrib/sankey/sankey.pdf