jakobrunge/tigramite

tp.plot_mediation_graph bug?

Master-Chandler opened this issue · 19 comments

when I use tp.plot_mediation_graph over a map, I found that the node is opacity, only with var_names, and the lag-time is not over the middle of a link edge. Is this a bug?

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1,1,1,projection=ccrs.PlateCarree(central_longitude=180)) # 创建一个1x1的子图,在第1个位置添加一个Axes对象
ax.set_extent([-180, 180, -90, 90],crs=ccrs.PlateCarree(central_longitude=180))
ax.coastlines()
node_pos = {'x':np.linspace(-120,120,5),'y':np.linspace(-60,60,5)}
tp.plot_mediation_graph(
var_names=var_names,
path_val_matrix=graph_data['path_val_matrix'],
path_node_array=graph_data['path_node_array'],
node_size=0.15,
arrow_linewidth=12.0,
fig_ax=(fig,ax),
figsize=(8, 6),
node_pos=node_pos,
cmap_nodes=plt.get_cmap('terrain'),
alpha = 0.8,
standard_color_nodes='black',
); plt.show()

1677506035145

The master is now updated, also on pip. Does this problem persist?

The master is now updated, also on pip. Does this problem persist?

It doesn't seem to work completely, and the position of the colorbars seems worse.
1681188880046

Does network_lower_bound help to adjust the colorbar position? The position of link labels is difficult to assess because it depends on projections and the fancyarrowpatch of matplotlib. In essence, it is hard to get the position of the center of the curved arrow.

Try again, just updated, but no guarantee. The issue is likely with your underlying map and hard to fix. You could convert the map to an image...

Try again, just updated, but no guarantee. The issue is likely with your underlying map and hard to fix. You could convert the map to an image...

Unfortunately, the lagged labels are also in the beginning of the curved arrow, and the position of colorbars can be modified by the hyperparameter network_lower_bound.

The positioning of lag labels with underlying map projections is difficult. I suggest using an image as a map instead.

network_lower_bound was removed, but you can still adapt the figure afterwards using matplotlib's standard adjust_figure(...).

The positioning of lag labels with underlying map projections is difficult. I suggest using an image as a map instead.

network_lower_bound was removed, but you can still adapt the figure afterwards using matplotlib's standard adjust_figure(...).

This has nothing to do with whether I use a map projection or not. Even if I turn off the projection, as long as I still use the node_pos parameter, the lag label will never be in the middle of the curved arrow. When I comment out the node_pos parameter, the lag label is in the middle of the curve arrow.

I don't think it has to do with the node_pos, have you tried other positionings? Or try a simpler example? The issue is that matplotlib fancyarrowpatch is a bit unpredictable in its arrow positioning and then it is hard to determine the middle of the arrow, see the code...

I don't think it has to do with the node_pos, have you tried other positionings? Or try a simpler example? The issue is that matplotlib fancyarrowpatch is a bit unpredictable in its arrow positioning and then it is hard to determine the middle of the arrow, see the code...

This is the result of a toy model. The node positions are within 6, and the problem also exists.
1681907748587

What do you mean by "within 6"? It doesn't look that bad now...

What do you mean by "within 6"? It doesn't look that bad now...

node_pos = {'x':[1,5,6,3,0],'y':[1,2,6,4,5]}. The distance between the lag label and the begining of the curved arrow seems to be a constant value. When I set small node_pos numbers (range(0, 7)), rather than latitude/longitude scale (90S-90N/180W-180E), the graph will be better. However, the problem also exists.

I updated the link label to be the nearest to the midpoint between the source and target node, try again, also with underlying maps!

I updated the link label to be the nearest to the midpoint between the source and target node, try again, also with underlying maps!

It does not work. This is a simple python script, and you can try it.

# Imports
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cartopy.util as cutil
# %matplotlib inline     
## use `%matplotlib notebook` for interactive figures
# plt.style.use('ggplot')
import sklearn

import tigramite
from tigramite import data_processing as pp
from tigramite.toymodels import structural_causal_processes as toys
from tigramite import plotting as tp
from tigramite.pcmci import PCMCI
# from tigramite.independence_tests import ParCorr, GPDC, CMIknn, CMIsymb
from tigramite.independence_tests.parcorr import ParCorr
from tigramite.independence_tests.gpdc import GPDC
from tigramite.independence_tests.cmiknn import CMIknn
from tigramite.independence_tests.cmisymb import CMIsymb

from tigramite.models import LinearMediation, Prediction

import _pickle as cPickle
import sys
from datetime import datetime, date

np.random.seed(42)

####################################################################
np.random.seed(1)
data = np.random.randn(500, 5)
for t in range(1, 500):
    data[t, 0] += 0.4*data[t-1, 1]**2
    data[t, 2] += 0.3*data[t-2, 1]**2
    data[t, 3] += 0.3*data[t-3, 1]**3
    data[t, 4] += 0.3*data[t-2, 1]**1
var_names = [r'$X^0$', r'$X^1$', r'$X^2$', r'$X^3$', r'$X^4$']

# Initialize dataframe object, specify time axis and variable names
dataframe = pp.DataFrame(data, 
                         var_names=var_names)

parcorr = ParCorr(significance='analytic')
pcmci = PCMCI(
    dataframe=dataframe, 
    cond_ind_test=parcorr,
    verbosity=1)

pcmci.verbosity = 1
true_parents = pcmci.run_pc_stable(tau_max=4,pc_alpha=0.2)




med = LinearMediation(dataframe=dataframe)
med.fit_model(all_parents=true_parents, tau_max=4)


i=4; tau=3; j=2
graph_data = med.get_mediation_graph_data(i=i, tau=tau, j=j)
# tp.plot_mediation_time_series_graph(
#     var_names=var_names,
#     path_node_array=graph_data['path_node_array'],
#     tsg_path_val_matrix=graph_data['tsg_path_val_matrix'],
#     node_size=0.06,
#     arrow_linewidth=9,
#     )

fig = plt.figure(figsize=(8, 6))
projection = ccrs.PlateCarree(central_longitude=180)
ax = fig.add_subplot(1,1,1)#,projection=projection)  # 创建一个1x1的子图,在第1个位置添加一个Axes对象

# ax.set_extent([0, 359, -90, 90],crs=projection)
# # # ax.coastlines()
# ax.add_feature(ccrs.cartopy.feature.COASTLINE, facecolor=None)
# ax.add_feature(cfeature.LAND, zorder=-8, facecolor=None)
# ax.add_feature(cfeature.OCEAN, zorder=-8)
# ax.gridlines()
node_pos = {'x':[10,50,60,30,0],'y':[10,20,60,40,50]}


tp.plot_mediation_graph(
                    var_names=var_names,
                    path_val_matrix=graph_data['path_val_matrix'], 
                    path_node_array=graph_data['path_node_array'],
                    node_size=12,
                    # arrow_linewidth=8.0,
                    fig_ax=(fig,ax),
                    # figsize=(8, 6),
                    node_pos=node_pos,
                    # alpha = 0.8,
                    # vmin_edges=-0.6,
                    # vmax_edges=0.6,
                    # vmin_nodes=-0.6,
                    # vmax_nodes=0.6,

                    ); plt.show()


I updated the master with a new argument for node_pos in order to transform the node and link coordinates, including the lag label. It only works if the node_pos are given in rectangular coordinates:
node_pos = {'x':np.array([10,-20,80,-50,80]),
'y':np.array([-10,70,60,-40,50]),
'transform':ccrs.PlateCarree(),
}
You can still use other projections for the map...

I updated the master with a new argument for node_pos in order to transform the node and link coordinates, including the lag label. It only works if the node_pos are given in rectangular coordinates: node_pos = {'x':np.array([10,-20,80,-50,80]), 'y':np.array([-10,70,60,-40,50]), 'transform':ccrs.PlateCarree(), } You can still use other projections for the map...

It works successfully! How can I turn off the black line in the colored curved arrow?
1682230972702

Now also fixed.

Now also fixed.

Thank you for solving all my problems!