diff --git a/README.md b/README.md index 47b8311e..d9aad00b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Tigramite is a causal time series analysis python package. It allows to efficiently reconstruct causal graphs from high-dimensional time series datasets and model the obtained causal dependencies for causal mediation and prediction analyses. Causal discovery is based on linear as well as non-parametric conditional independence tests applicable to discrete or continuously-valued time series. Also includes functions for high-quality plots of the results. Please cite the following papers depending on which method you use: - PCMCI: J. Runge, P. Nowack, M. Kretschmer, S. Flaxman, D. Sejdinovic, Detecting and quantifying causal associations in large nonlinear time series datasets. Sci. Adv. 5, eaau4996 (2019). https://advances.sciencemag.org/content/5/11/eaau4996 -- PCMCI+: J. Runge (2020): Discovering contemporaneous and lagged causal relations in autocorrelated nonlinear time series datasets. https://arxiv.org/abs/2003.03685 +- PCMCI+: J. Runge (2020): Discovering contemporaneous and lagged causal relations in autocorrelated nonlinear time series datasets. Proceedings of the 36th Conference on Uncertainty in Artificial Intelligence, UAI 2020,Toronto, Canada, 2019, AUAI Press, 2020. http://auai.org/uai2020/proceedings/579_main_paper.pdf - Generally: J. Runge (2018): Causal Network Reconstruction from Time Series: From Theoretical Assumptions to Practical Estimation. Chaos: An Interdisciplinary Journal of Nonlinear Science 28 (7): 075310. https://aip.scitation.org/doi/10.1063/1.5025050 - Nature Communications Perspective paper: https://www.nature.com/articles/s41467-019-10105-3 - Mediation class: J. Runge et al. (2015): Identifying causal gateways and mediators in complex spatio-temporal systems. Nature Communications, 6, 8502. http://doi.org/10.1038/ncomms9502 diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 7374a70d..61cfd652 100644 Binary files a/docs/_build/doctrees/environment.pickle and b/docs/_build/doctrees/environment.pickle differ diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index 7be9c117..1c7442dc 100644 Binary files a/docs/_build/doctrees/index.doctree and b/docs/_build/doctrees/index.doctree differ diff --git a/docs/_build/html/_modules/abc.html b/docs/_build/html/_modules/abc.html index a0b81dfb..580b4f31 100644 --- a/docs/_build/html/_modules/abc.html +++ b/docs/_build/html/_modules/abc.html @@ -93,7 +93,7 @@
__isabstractmethod__ = True
- def __init__(self, callable):
+ def __init__(self, callable):
callable.__isabstractmethod__ = True
super().__init__(callable)
@@ -116,7 +116,7 @@ Source code for abc
__isabstractmethod__ = True
- def __init__(self, callable):
+ def __init__(self, callable):
callable.__isabstractmethod__ = True
super().__init__(callable)
@@ -153,11 +153,11 @@ Source code for abc
try:
- from _abc import (get_cache_token, _abc_init, _abc_register,
+ from _abc import (get_cache_token, _abc_init, _abc_register,
_abc_instancecheck, _abc_subclasscheck, _get_dump,
_reset_registry, _reset_caches)
except ImportError:
- from _py_abc import ABCMeta, get_cache_token
+ from _py_abc import ABCMeta, get_cache_token
ABCMeta.__module__ = 'abc'
else:
class ABCMeta(type):
@@ -173,7 +173,7 @@ Source code for abc
implementations defined by the registering ABC be callable (not
even via super()).
"""
- def __new__(mcls, name, bases, namespace, **kwargs):
+ def __new__(mcls, name, bases, namespace, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
_abc_init(cls)
return cls
@@ -185,24 +185,24 @@ Source code for abc
"""
return _abc_register(cls, subclass)
- def __instancecheck__(cls, instance):
+ def __instancecheck__(cls, instance):
"""Override for isinstance(instance, cls)."""
return _abc_instancecheck(cls, instance)
- def __subclasscheck__(cls, subclass):
+ def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls)."""
return _abc_subclasscheck(cls, subclass)
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
- print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
- print(f"Inv. counter: {get_cache_token()}", file=file)
+ print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
+ print(f"Inv. counter: {get_cache_token()}", file=file)
(_abc_registry, _abc_cache, _abc_negative_cache,
_abc_negative_cache_version) = _get_dump(cls)
- print(f"_abc_registry: {_abc_registry!r}", file=file)
- print(f"_abc_cache: {_abc_cache!r}", file=file)
- print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file)
- print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}",
+ print(f"_abc_registry: {_abc_registry!r}", file=file)
+ print(f"_abc_cache: {_abc_cache!r}", file=file)
+ print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file)
+ print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}",
file=file)
def _abc_registry_clear(cls):
diff --git a/docs/_build/html/_modules/tigramite/data_processing.html b/docs/_build/html/_modules/tigramite/data_processing.html
index 4a09bbc4..d7d4a672 100644
--- a/docs/_build/html/_modules/tigramite/data_processing.html
+++ b/docs/_build/html/_modules/tigramite/data_processing.html
@@ -54,8 +54,8 @@ Source code for tigramite.data_processing
# Author: Jakob Runge <jakob@jakob-runge.com>
#
# License: GNU General Public License v3.0
-from __future__ import print_function
-from collections import defaultdict, OrderedDict
+from __future__ import print_function
+from collections import defaultdict, OrderedDict
import sys
import warnings
import copy
@@ -92,7 +92,7 @@ Source code for tigramite.data_processing
datatime : array-like, optional (default: None)
Timelabel array. If None, range(T) is used.
"""
- def __init__(self, data, mask=None, missing_flag=None, var_names=None,
+ def __init__(self, data, mask=None, missing_flag=None, var_names=None,
datatime=None):
self.values = data
@@ -413,7 +413,7 @@ Source code for tigramite.data_processing
Filtered data array.
"""
try:
- from scipy.signal import butter, filtfilt
+ from scipy.signal import butter, filtfilt
except:
print('Could not import scipy.signal for butterworth filtering!')
@@ -610,7 +610,7 @@ Source code for tigramite.data_processing
patt, patt_mask [, patt_time] : tuple of arrays
Tuple of converted pattern array and new length
"""
- from scipy.misc import factorial
+ from scipy.misc import factorial
# Import cython code
try:
@@ -1205,7 +1205,7 @@ Source code for tigramite.data_processing
vertices : list
List of nodes.
"""
- def __init__(self,vertices):
+ def __init__(self,vertices):
self.graph = defaultdict(list)
self.V = vertices
@@ -1446,19 +1446,22 @@ Source code for tigramite.data_processing
"found in links, use tau_max=None or larger "
"value" % max_lag)
- graph = np.zeros((N, N, tau_max + 1), dtype='uint8')
+ graph = np.zeros((N, N, tau_max + 1), dtype='<U3')
for j in links.keys():
for link_props in links[j]:
var, lag = link_props[0]
coeff = link_props[1]
if coeff != 0.:
- graph[var, j, abs(lag)] = 1
+ graph[var, j, abs(lag)] = "-->"
+ if lag == 0:
+ graph[j, var, 0] = "<--"
+
return graph
class _Logger(object):
"""Class to append print output to a string which can be saved"""
- def __init__(self):
+ def __init__(self):
self.terminal = sys.stdout
self.log = "" # open("log.dat", "a")
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/cmiknn.html b/docs/_build/html/_modules/tigramite/independence_tests/cmiknn.html
index ae9b8200..7c080bff 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/cmiknn.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/cmiknn.html
@@ -55,14 +55,14 @@ Source code for tigramite.independence_tests.cmiknn
#
# License: GNU General Public License v3.0
-from __future__ import print_function
-from scipy import special, stats, spatial
+from __future__ import print_function
+from scipy import special, stats, spatial
import numpy as np
-from .independence_tests_base import CondIndTest
+from .independence_tests_base import CondIndTest
try:
- from tigramite import tigramite_cython_code
+ from tigramite import tigramite_cython_code
except:
print("Could not import packages for CMIknn and GPDC estimation")
@@ -152,7 +152,7 @@ Source code for tigramite.independence_tests.cmiknn
"""
return self._measure
- def __init__(self,
+ def __init__(self,
knn=0.2,
shuffle_neighbors=5,
significance='shuffle_test',
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/cmisymb.html b/docs/_build/html/_modules/tigramite/independence_tests/cmisymb.html
index 352dcb09..75c73fee 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/cmisymb.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/cmisymb.html
@@ -55,11 +55,11 @@ Source code for tigramite.independence_tests.cmisymb
#
# License: GNU General Public License v3.0
-from __future__ import print_function
+from __future__ import print_function
import warnings
import numpy as np
-from .independence_tests_base import CondIndTest
+from .independence_tests_base import CondIndTest
[docs]class CMIsymb(CondIndTest):
r"""Conditional mutual information test based on discrete estimator.
@@ -108,7 +108,7 @@ Source code for tigramite.independence_tests.cmisymb
"""
return self._measure
- def __init__(self,
+ def __init__(self,
n_symbs=None,
significance='shuffle_test',
sig_blocklength=1,
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html b/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
index e90f6dcd..ce2baf63 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
@@ -55,18 +55,18 @@ Source code for tigramite.independence_tests.gpdc
#
# License: GNU General Public License v3.0
-from __future__ import print_function
+from __future__ import print_function
import numpy as np
-from .independence_tests_base import CondIndTest
+from .independence_tests_base import CondIndTest
try:
- from sklearn import gaussian_process
+ from sklearn import gaussian_process
except:
print("Could not import sklearn for Gaussian process tests")
try:
- from tigramite import tigramite_cython_code
+ from tigramite import tigramite_cython_code
except:
print("Could not import packages for CMIknn and GPDC estimation")
@@ -111,7 +111,7 @@ Source code for tigramite.independence_tests.gpdc
verbosity : int, optional (default: 0)
Level of verbosity.
"""
- def __init__(self,
+ def __init__(self,
null_samples,
cond_ind_test,
gp_version='new',
@@ -465,7 +465,7 @@ Source code for tigramite.independence_tests.gpdc
"""
return self._measure
- def __init__(self,
+ def __init__(self,
null_dist_filename=None,
gp_version='new',
gp_params=None,
@@ -736,7 +736,7 @@ Source code for tigramite.independence_tests.gpdc
Returns
-------
pval : float or numpy.nan
- P-value.
+ p-value.
"""
# GP regression approximately doesn't cost degrees of freedom
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/independence_tests_base.html b/docs/_build/html/_modules/tigramite/independence_tests/independence_tests_base.html
index 378ccd06..a68fcdad 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/independence_tests_base.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/independence_tests_base.html
@@ -55,13 +55,13 @@ Source code for tigramite.independence_tests.independence_tests_base
#
# License: GNU General Public License v3.0
-from __future__ import print_function
+from __future__ import print_function
import warnings
import math
import abc
import numpy as np
import six
-from hashlib import sha1
+from hashlib import sha1
[docs]@six.add_metaclass(abc.ABCMeta)
@@ -133,7 +133,7 @@ Source code for tigramite.independence_tests.independence_tests_base
"""
pass
- def __init__(self,
+ def __init__(self,
mask_type=None,
significance='analytic',
fixed_thres=0.1,
@@ -873,7 +873,7 @@ Source code for tigramite.independence_tests.independence_tests_base
Optimal block length.
"""
# Inject a dependency on siganal, optimize
- from scipy import signal, optimize
+ from scipy import signal, optimize
# Get the shape of the array
dim, T = array.shape
# Initiailize the indices
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/oracle_conditional_independence.html b/docs/_build/html/_modules/tigramite/independence_tests/oracle_conditional_independence.html
index 43d31e01..2d2863b4 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/oracle_conditional_independence.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/oracle_conditional_independence.html
@@ -55,10 +55,10 @@ Source code for tigramite.independence_tests.oracle_conditional_independence
#
# License: GNU General Public License v3.0
-from __future__ import print_function
+from __future__ import print_function
import numpy as np
-from collections import defaultdict, OrderedDict
+from collections import defaultdict, OrderedDict
[docs]class OracleCI:
@@ -86,7 +86,7 @@ Source code for tigramite.independence_tests.oracle_conditional_independence
"""
return self._measure
- def __init__(self,
+ def __init__(self,
link_coeffs,
observed_vars=None,
verbosity=0):
@@ -725,7 +725,7 @@ Source code for tigramite.independence_tests.oracle_conditional_independence
if __name__ == '__main__':
import tigramite.plotting as tp
- from matplotlib import pyplot as plt
+ from matplotlib import pyplot as plt
def lin_f(x): return x
# N = 20
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/parcorr.html b/docs/_build/html/_modules/tigramite/independence_tests/parcorr.html
index a0af2fad..3c860372 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/parcorr.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/parcorr.html
@@ -55,12 +55,12 @@ Source code for tigramite.independence_tests.parcorr
#
# License: GNU General Public License v3.0
-from __future__ import print_function
-from scipy import stats
+from __future__ import print_function
+from scipy import stats
import numpy as np
import sys
-from .independence_tests_base import CondIndTest
+from .independence_tests_base import CondIndTest
[docs]class ParCorr(CondIndTest):
r"""Partial correlation test.
@@ -98,7 +98,7 @@ Source code for tigramite.independence_tests.parcorr
"""
return self._measure
- def __init__(self, **kwargs):
+ def __init__(self, **kwargs):
self._measure = 'par_corr'
self.two_sided = True
self.residual_based = True
diff --git a/docs/_build/html/_modules/tigramite/models.html b/docs/_build/html/_modules/tigramite/models.html
index d1218c12..d7b1ad59 100644
--- a/docs/_build/html/_modules/tigramite/models.html
+++ b/docs/_build/html/_modules/tigramite/models.html
@@ -55,13 +55,13 @@ Source code for tigramite.models
#
# License: GNU General Public License v3.0
-from __future__ import print_function
-from copy import deepcopy
+from __future__ import print_function
+from copy import deepcopy
import numpy as np
-from tigramite.data_processing import DataFrame
-from tigramite.pcmci import PCMCI
+from tigramite.data_processing import DataFrame
+from tigramite.pcmci import PCMCI
try:
import sklearn
@@ -103,7 +103,7 @@ Source code for tigramite.models
Level of verbosity.
"""
- def __init__(self,
+ def __init__(self,
dataframe,
model,
data_transform=sklearn.preprocessing.StandardScaler(),
@@ -341,7 +341,7 @@ Source code for tigramite.models
Level of verbosity.
"""
- def __init__(self,
+ def __init__(self,
dataframe,
model_params=None,
data_transform=sklearn.preprocessing.StandardScaler(),
@@ -990,7 +990,7 @@ Source code for tigramite.models
Level of verbosity.
"""
- def __init__(self,
+ def __init__(self,
dataframe,
train_indices,
test_indices,
diff --git a/docs/_build/html/_modules/tigramite/pcmci.html b/docs/_build/html/_modules/tigramite/pcmci.html
index da8d8def..ad66f34a 100644
--- a/docs/_build/html/_modules/tigramite/pcmci.html
+++ b/docs/_build/html/_modules/tigramite/pcmci.html
@@ -55,11 +55,11 @@ Source code for tigramite.pcmci
#
# License: GNU General Public License v3.0
-from __future__ import print_function
+from __future__ import print_function
import warnings
import itertools
-from collections import defaultdict
-from copy import deepcopy
+from collections import defaultdict
+from copy import deepcopy
import numpy as np
import scipy.stats
@@ -127,7 +127,7 @@ Source code for tigramite.pcmci
different times and a link indicates a conditional dependency that can be
interpreted as a causal dependency under certain assumptions (see paper).
Assuming stationarity, the links are repeated in time. The parents
- :math:`\\mathcal{P}` of a variable are defined as the set of all nodes
+ :math:`\mathcal{P}` of a variable are defined as the set of all nodes
with a link towards it (blue and red boxes in Figure).
The different PCMCI methods estimate causal links by iterative
@@ -147,7 +147,7 @@ Source code for tigramite.pcmci
.. [5] J. Runge,
Discovering contemporaneous and lagged causal relations in
autocorrelated nonlinear time series datasets
- https://arxiv.org/abs/2003.03685
+ http://www.auai.org/~w-auai/uai2020/proceedings/579_main_paper.pdf
Parameters
----------
@@ -185,7 +185,7 @@ Source code for tigramite.pcmci
Time series sample length.
"""
- def __init__(self, dataframe,
+ def __init__(self, dataframe,
cond_ind_test,
selected_variables=None,
verbosity=0):
@@ -358,7 +358,7 @@ Source code for tigramite.pcmci
already_removed : bool
Whether parent was already removed.
"""
- link_marker = {True:"o--o", False:"-->"}
+ link_marker = {True:"o-o", False:"-->"}
abstau = abs(parent[1])
if self.verbosity > 1:
@@ -1584,7 +1584,7 @@ Source code for tigramite.pcmci
List of ambiguous triples.
"""
if graph is not None:
- sig_links = (graph > 0)
+ sig_links = (graph != "")*(graph != "<--")
elif q_matrix is not None:
sig_links = (q_matrix <= alpha_level)
else:
@@ -1613,19 +1613,19 @@ Source code for tigramite.pcmci
conf_matrix[p[0], j, abs(p[1])][0],
conf_matrix[p[0], j, abs(p[1])][1])
if graph is not None:
- if p[1] == 0 and graph[j, p[0], 0] == 1:
+ if p[1] == 0 and graph[j, p[0], 0] == "o-o":
string += " | unoriented link"
- if graph[p[0], j, abs(p[1])] == 2:
+ if graph[p[0], j, abs(p[1])] == "x-x":
string += " | unclear orientation due to conflict"
print(string)
- link_marker = {True:"o--o", False:"-->"}
+ link_marker = {True:"o-o", False:"-->"}
if ambiguous_triples is not None and len(ambiguous_triples) > 0:
print("\n## Ambiguous triples:\n")
for triple in ambiguous_triples:
(i, tau), k, j = triple
- print(" (%s % d) %s %s o--o %s" % (
+ print(" (%s % d) %s %s o-o %s" % (
self.var_names[i], tau, link_marker[tau==0],
self.var_names[k],
self.var_names[j]))
@@ -1752,7 +1752,7 @@ Source code for tigramite.pcmci
2: [((2, -1), 0.8), ((1, -2), -0.6)]}
>>> data, _ = pp.var_process(links_coeffs, T=1000)
>>> # Data must be array of shape (time, variables)
- >>> print data.shape
+ >>> print (data.shape)
(1000, 3)
>>> dataframe = pp.DataFrame(data)
>>> cond_ind_test = ParCorr()
@@ -1764,17 +1764,16 @@ Source code for tigramite.pcmci
## Significant parents at alpha = 0.05:
Variable 0 has 1 link(s):
- (0 -1): pval = 0.00000 | val = 0.632
+ (0 -1): pval = 0.00000 | val = 0.588
Variable 1 has 2 link(s):
- (1 -1): pval = 0.00000 | val = 0.653
-
- (0 -1): pval = 0.00000 | val = 0.444
+ (1 -1): pval = 0.00000 | val = 0.606
+ (0 -1): pval = 0.00000 | val = 0.447
Variable 2 has 2 link(s):
- (2 -1): pval = 0.00000 | val = 0.623
+ (2 -1): pval = 0.00000 | val = 0.618
+ (1 -2): pval = 0.00000 | val = -0.499
- (1 -2): pval = 0.00000 | val = -0.533
Parameters
----------
@@ -1880,7 +1879,8 @@ Source code for tigramite.pcmci
"""Runs PCMCIplus time-lagged and contemporaneous causal discovery for
time series.
- Method described in [5]_: https://arxiv.org/abs/2003.03685
+ Method described in [5]_:
+ http://www.auai.org/~w-auai/uai2020/proceedings/579_main_paper.pdf
Notes
-----
@@ -1923,20 +1923,20 @@ Source code for tigramite.pcmci
links based on PC rules.
In contrast to PCMCI, the relevant output of PCMCIplus is the
- array ``graph``. Its entries are interpreted as follows:
+ array ``graph``. Its string entries are interpreted as follows:
- * ``graph[i,j,tau]=1`` for :math:`\\tau>0` denotes a directed, lagged
+ * ``graph[i,j,tau]=-->`` for :math:`\\tau>0` denotes a directed, lagged
causal link from :math:`i` to :math:`j` at lag :math:`\\tau`
- * ``graph[i,j,0]=1`` and ``graph[j,i,0]=0`` denotes a directed,
+ * ``graph[i,j,0]=-->`` (and ``graph[j,i,0]=<--``) denotes a directed,
contemporaneous causal link from :math:`i` to :math:`j`
- * ``graph[i,j,0]=1`` and ``graph[j,i,0]=1`` denotes an unoriented,
+ * ``graph[i,j,0]=o-o`` (and ``graph[j,i,0]=o-o``) denotes an unoriented,
contemporaneous adjacency between :math:`i` and :math:`j` indicating
that the collider and orientation rules could not be applied (Markov
equivalence)
- * ``graph[i,j,0]=2`` and ``graph[j,i,0]=2`` denotes a conflicting,
+ * ``graph[i,j,0]=x-x`` and (``graph[j,i,0]=x-x``) denotes a conflicting,
contemporaneous adjacency between :math:`i` and :math:`j` indicating
that the directionality is undecided due to conflicting orientation
rules
@@ -1984,7 +1984,7 @@ Source code for tigramite.pcmci
Examples
--------
- >>> import numpy
+ >>> import numpy as np
>>> from tigramite.pcmci import PCMCI
>>> from tigramite.independence_tests import ParCorr
>>> import tigramite.data_processing as pp
@@ -1997,12 +1997,10 @@ Source code for tigramite.pcmci
2: [((2, -1), 0.7, lin_f), ((1, 0), 0.6, lin_f)],
3: [((3, -1), 0.7, lin_f), ((2, 0), -0.5, lin_f)],
}
- >>> # Specify dynamical noise term distributions
- >>> noises = [np.random.randn for j in links.keys()]
>>> data, nonstat = pp.structural_causal_process(links,
- T=1000, noises=noises, seed=7)
+ T=1000, seed=7)
>>> # Data must be array of shape (time, variables)
- >>> print data.shape
+ >>> print (data.shape)
(1000, 4)
>>> dataframe = pp.DataFrame(data)
>>> cond_ind_test = ParCorr()
@@ -2011,23 +2009,20 @@ Source code for tigramite.pcmci
>>> pcmci.print_results(results, alpha_level=0.01)
## Significant links at alpha = 0.01:
- Variable 0 has 1 link(s):
- (0 -1): pval = 0.00000 | val = 0.676
-
- Variable 1 has 2 link(s):
- (1 -1): pval = 0.00000 | val = 0.602
-
- (0 -1): pval = 0.00000 | val = 0.599
-
- Variable 2 has 2 link(s):
- (1 0): pval = 0.00000 | val = 0.486
+ Variable 0 has 1 link(s):
+ (0 -1): pval = 0.00000 | val = 0.676
- (2 -1): pval = 0.00000 | val = 0.466
+ Variable 1 has 2 link(s):
+ (1 -1): pval = 0.00000 | val = 0.602
+ (0 -1): pval = 0.00000 | val = 0.599
- Variable 3 has 2 link(s):
- (3 -1): pval = 0.00000 | val = 0.524
+ Variable 2 has 2 link(s):
+ (1 0): pval = 0.00000 | val = 0.486
+ (2 -1): pval = 0.00000 | val = 0.466
- (2 0): pval = 0.00000 | val = -0.449
+ Variable 3 has 2 link(s):
+ (3 -1): pval = 0.00000 | val = 0.524
+ (2 0): pval = 0.00000 | val = -0.449
Parameters
----------
@@ -2209,6 +2204,7 @@ Source code for tigramite.pcmci
exclude_contemporaneous=False)
# Store the parents in the pcmci member
self.all_parents = lagged_parents
+
# Cache the resulting values in the return dictionary
return_dict = {'graph': graph,
'val_matrix': val_matrix,
@@ -2380,8 +2376,11 @@ Source code for tigramite.pcmci
skeleton_results['val_matrix'][j, i, 0] = \
skeleton_results['val_matrix'][i, j, 0]
+ # Convert numerical graph matrix to string
+ graph_str = self.convert_to_string_graph(final_graph)
+
pc_results = {
- 'graph': final_graph,
+ 'graph': graph_str,
'p_matrix': skeleton_results['p_matrix'],
'val_matrix': skeleton_results['val_matrix'],
'sepset': colliders_step_results['sepset'],
@@ -2545,9 +2544,9 @@ Source code for tigramite.pcmci
Total number of triples.
"""
(i, tau), k, j = triple
- link_marker = {True:"o--o", False:"-->"}
+ link_marker = {True:"o-o", False:"-->"}
- print("\n Triple (%s % d) %s %s o--o %s (%d/%d)" % (
+ print("\n Triple (%s % d) %s %s o-o %s (%d/%d)" % (
self.var_names[i], tau, link_marker[tau==0], self.var_names[k],
self.var_names[j], index + 1, n_triples))
@@ -2744,7 +2743,7 @@ Source code for tigramite.pcmci
(i, -abstau)))
# Store max. p-value and corresponding value to return
- if pval > pvalues[i, j, abstau]:
+ if pval >= pvalues[i, j, abstau]:
pvalues[i, j, abstau] = pval
val_matrix[i, j, abstau] = val
@@ -3184,7 +3183,7 @@ Source code for tigramite.pcmci
if self.verbosity > 1 and len(v_structures) > 0:
print("\nOrienting links among colliders:")
- link_marker = {True:"o--o", False:"-->"}
+ link_marker = {True:"o-o", False:"-->"}
# Now go through list of v-structures and (optionally) detect conflicts
oriented_links = []
@@ -3192,14 +3191,14 @@ Source code for tigramite.pcmci
(i, tau), k, j = itaukj
if self.verbosity > 1:
- print("\n Collider (%s % d) %s %s o--o %s:" % (
+ print("\n Collider (%s % d) %s %s o-o %s:" % (
self.var_names[i], tau, link_marker[
tau==0], self.var_names[k],
self.var_names[j]))
if (k, j) not in oriented_links and (j, k) not in oriented_links:
if self.verbosity > 1:
- print(" Orient %s o--o %s as %s --> %s " % (
+ print(" Orient %s o-o %s as %s --> %s " % (
self.var_names[j], self.var_names[k], self.var_names[j],
self.var_names[k]))
graph[k, j, 0] = 0
@@ -3221,7 +3220,7 @@ Source code for tigramite.pcmci
if (i, k) not in oriented_links and (
k, i) not in oriented_links:
if self.verbosity > 1:
- print(" Orient %s o--o %s as %s --> %s " % (
+ print(" Orient %s o-o %s as %s --> %s " % (
self.var_names[i], self.var_names[k],
self.var_names[i], self.var_names[k]))
graph[k, i, 0] = 0
@@ -3250,7 +3249,7 @@ Source code for tigramite.pcmci
}
def _find_triples_rule1(self, graph):
- """Find triples i_tau --> k_t o--o j_t with i_tau -/- j_t.
+ """Find triples i_tau --> k_t o-o j_t with i_tau -/- j_t.
Excludes conflicting links.
@@ -3312,8 +3311,8 @@ Source code for tigramite.pcmci
return triples
def _find_chains_rule3(self, graph):
- """Find chains i_t o--o k_t --> j_t and i_t o--o l_t --> j_t with
- i_t o--o j_t and k_t -/- l_t.
+ """Find chains i_t o-o k_t --> j_t and i_t o-o l_t --> j_t with
+ i_t o-o j_t and k_t -/- l_t.
Excludes conflicting links.
@@ -3384,7 +3383,7 @@ Source code for tigramite.pcmci
N = graph.shape[0]
def rule1(graph, oriented_links):
- """Find (unambiguous) triples i_tau --> k_t o--o j_t with
+ """Find (unambiguous) triples i_tau --> k_t o-o j_t with
i_tau -/- j_t and orient as i_tau --> k_t --> j_t.
"""
triples = self._find_triples_rule1(graph)
@@ -3399,7 +3398,7 @@ Source code for tigramite.pcmci
k, j) not in oriented_links:
if self.verbosity > 1:
print(
- " R1: Found (%s % d) --> %s o--o %s, "
+ " R1: Found (%s % d) --> %s o-o %s, "
"orient as %s --> %s" % (
self.var_names[i], tau, self.var_names[k],
self.var_names[j],
@@ -3419,7 +3418,7 @@ Source code for tigramite.pcmci
return triples_left, graph, oriented_links
def rule2(graph, oriented_links):
- """Find (unambiguous) triples i_t --> k_t --> j_t with i_t o--o j_t
+ """Find (unambiguous) triples i_t --> k_t --> j_t with i_t o-o j_t
and orient as i_t --> j_t.
"""
@@ -3439,7 +3438,7 @@ Source code for tigramite.pcmci
if self.verbosity > 1:
print(
" R2: Found %s --> %s --> %s with %s "
- "o--o %s, orient as %s --> %s" % (
+ "o-o %s, orient as %s --> %s" % (
self.var_names[i], self.var_names[k],
self.var_names[j],
self.var_names[i], self.var_names[j],
@@ -3458,8 +3457,8 @@ Source code for tigramite.pcmci
return triples_left, graph, oriented_links
def rule3(graph, oriented_links):
- """Find (unambiguous) chains i_t o--o k_t --> j_t
- and i_t o--o l_t --> j_t with i_t o--o j_t
+ """Find (unambiguous) chains i_t o-o k_t --> j_t
+ and i_t o-o l_t --> j_t with i_t o-o j_t
and k_t -/- l_t: Orient as i_t --> j_t.
"""
# First find all chains i_t -- k_t --> j_t with i_t -- j_t
@@ -3483,8 +3482,8 @@ Source code for tigramite.pcmci
i, j) not in oriented_links:
if self.verbosity > 1:
print(
- " R3: Found %s o--o %s --> %s and %s o--o "
- "%s --> %s with %s o--o %s and %s -/- %s, "
+ " R3: Found %s o-o %s --> %s and %s o-o "
+ "%s --> %s with %s o-o %s and %s -/- %s, "
"orient as %s --> %s" % (
self.var_names[i], self.var_names[k],
self.var_names[j], self.var_names[i],
@@ -3549,7 +3548,7 @@ Source code for tigramite.pcmci
"""
for j in variable_order:
- adj_j = np.where(circle_cpdag[:,j,0])[0].tolist()
+ adj_j = np.where(circle_cpdag[:,j,0] == "o-o")[0].tolist()
# Make sure the node has any adjacencies
all_adjacent = len(adj_j) > 0
@@ -3559,7 +3558,7 @@ Source code for tigramite.pcmci
return (j, adj_j)
else:
for (var1, var2) in itertools.combinations(adj_j, 2):
- if circle_cpdag[var1, var2, 0] == 0:
+ if circle_cpdag[var1, var2, 0] == "":
all_adjacent = False
break
@@ -3621,13 +3620,13 @@ Source code for tigramite.pcmci
# Turn circle component CPDAG^C into a DAG with no unshielded colliders.
circle_cpdag = np.copy(cpdag_graph)
# All lagged links are directed by time, remove them here
- circle_cpdag[:,:,1:] = 0
+ circle_cpdag[:,:,1:] = ""
# Also remove conflicting links
- circle_cpdag[circle_cpdag==2] = 0
- # Find undirected links
- for i, j, tau in zip(*np.where(circle_cpdag)):
- if circle_cpdag[j,i,0] == 0:
- circle_cpdag[i,j,0] = 0
+ circle_cpdag[circle_cpdag=="x-x"] = ""
+ # Find undirected links, remove directed links
+ for i, j, tau in zip(*np.where(circle_cpdag != "")):
+ if circle_cpdag[i,j,0] == "-->":
+ circle_cpdag[i,j,0] = ""
# Iterate through simplicial nodes
simplicial_node = self._get_simplicial_node(circle_cpdag,
@@ -3639,9 +3638,9 @@ Source code for tigramite.pcmci
# component PAG
(j, adj_j) = simplicial_node
for var in adj_j:
- dag[var, j, 0] = 1
- dag[j, var, 0] = 0
- circle_cpdag[var, j, 0] = circle_cpdag[j, var, 0] = 0
+ dag[var, j, 0] = "-->"
+ dag[j, var, 0] = "<--"
+ circle_cpdag[var, j, 0] = circle_cpdag[j, var, 0] = ""
# Iterate
simplicial_node = self._get_simplicial_node(circle_cpdag,
@@ -3725,18 +3724,22 @@ Source code for tigramite.pcmci
dag = self._get_dag_from_cpdag(
cpdag_graph=results[pc_alpha_here]['graph'],
variable_order=variable_order)
- parents = self.return_significant_links(
- pq_matrix=results[pc_alpha_here]['p_matrix'],
- val_matrix=results[pc_alpha_here]['val_matrix'],
- alpha_level=pc_alpha_here,
- include_lagzero_links=True)['link_dict']
+
+ # = self.return_significant_links(
+ # pq_matrix=results[pc_alpha_here]['p_matrix'],
+ # val_matrix=results[pc_alpha_here]['val_matrix'],
+ # alpha_level=pc_alpha_here,
+ # include_lagzero_links=True)['link_dict']
# Compute the best average score when the model selection
# is applied to all N variables
for j in range(self.N):
+ parents = []
+ for i, tau in zip(*np.where(dag[:,j,:] == "-->")):
+ parents.append((i, -tau))
score[iscore] += \
self.cond_ind_test.get_model_selection_criterion(
- j, parents[j], tau_max)
+ j, parents, tau_max)
score[iscore] /= float(self.N)
# Record the optimal alpha value
@@ -3790,236 +3793,37 @@ Source code for tigramite.pcmci
if __name__ == '__main__':
- from tigramite.independence_tests import ParCorr, CMIknn
+ from tigramite.independence_tests import ParCorr, CMIknn
import tigramite.data_processing as pp
import tigramite.plotting as tp
np.random.seed(43)
-
- ## Generate some time series from a structural causal process
+ # Example process to play around with
+ # Each key refers to a variable and the incoming links are supplied
+ # as a list of format [((var, -lag), coeff, function), ...]
def lin_f(x): return x
def nonlin_f(x): return (x + 5. * x ** 2 * np.exp(-x ** 2 / 20.))
- auto_coeff = 0.95
- coeff = 0.4
- T = 500
-
- # links ={0: [((0, -1), auto_coeff, lin_f),
- # ((1, -1), coeff, lin_f)
- # ],
- # 1: [((1, -1), auto_coeff, lin_f),
- # ],
- # 2: [((2, -1), auto_coeff, lin_f),
- # ((3, 0), -coeff, lin_f),
- # ],
- # 3: [((3, -1), auto_coeff, lin_f),
- # ((1, -2), coeff, lin_f),
- # ],
- # 4: [((4, -1), auto_coeff, lin_f),
- # ((3, 0), coeff, lin_f),
- # ],
- # 5: [((5, -1), 0.5*auto_coeff, lin_f),
- # ((6, 0), coeff, lin_f),
- # ],
- # 6: [((6, -1), 0.5*auto_coeff, lin_f),
- # ((5, -1), -coeff, lin_f),
- # ],
- # 7: [((7, -1), auto_coeff, lin_f),
- # ((8, 0), -coeff, lin_f),
- # ],
- # 8: [],
- # }
-
- # links = {0: [((0, -1), 0.8, lin_f), ((1, -1), 0.6, lin_f)],
- # 1: [((1, -1), 0., lin_f)],
- # 2: [((2, -1), 0., lin_f), ((1, 0), 0.6, lin_f)],
- # 3: [((3, -1), 0., lin_f), ((2, 0), -0.5, lin_f)],
- # }
- links = {0: [((0, -1), 0., lin_f), ((1, 0), 0.6, lin_f)],
- 1: [((1, -1), 0., lin_f), ((2, 0), 0., lin_f), ((2, -1), 0.6, lin_f)],
- 2: [((2, -1), 0.8, lin_f), ((1, -1), -0.5, lin_f)]
+ links = {0: [((0, -1), 0.9, lin_f)],
+ 1: [((1, -1), 0.8, lin_f), ((0, -1), 0.8, lin_f)],
+ 2: [((2, -1), 0.7, lin_f), ((1, 0), 0.6, lin_f)],
+ 3: [((3, -1), 0.7, lin_f), ((2, 0), -0.5, lin_f)],
}
-
- noises = [np.random.randn for j in links.keys()]
data, nonstat = pp.structural_causal_process(links,
- T=300, noises=noises, seed=7)
+ T=1000, seed=7)
+
+ # Data must be array of shape (time, variables)
+ print(data.shape)
+ dataframe = pp.DataFrame(data)
+ cond_ind_test = ParCorr()
+ pcmci = PCMCI(dataframe=dataframe, cond_ind_test=cond_ind_test)
+ results = pcmci.run_pcmciplus(tau_min=0, tau_max=2, pc_alpha=0.01)
+ pcmci.print_results(results, alpha_level=0.01)
+
- # data[10, 1] = 999.
- # data_mask = data>0.4
- verbosity = 2
- dataframe = pp.DataFrame(data) #, missing_flag=999., mask=data_mask,)
- pcmci = PCMCI(dataframe=dataframe,
- cond_ind_test=ParCorr(verbosity=0),
- verbosity=2,
- )
- results = pcmci.run_mci(
- selected_links=None,
- tau_min=0,
- tau_max=2,
- )
- print (pcmci.results)
-
-
- # lagmat.savefig("/home/rung_ja/work/sandbox/lags_final.pdf")
-
-
- # print(results['graph'])
-
- # link_matrix = results['most_frequent_links']
- # link_width = results['link_frequency']
- # print(link_matrix.shape, val_matrix.shape, link_width.shape, conf_matrix.shape)
- # print(link_matrix[:,:,0])
- # print(link_width[:,:,0])
-
- # tp.plot_time_series_graph(
- # val_matrix=val_matrix,
- # link_matrix=link_matrix,
- # link_width = link_width,
- # link_colorbar_label='MCI',
- # cmap_edges='OrRd',
- # save_name="/home/rung_ja/work/sandbox/tsg_final.pdf",
- # )
-
-
- # results = pcmci.run_pcalg_non_timeseries_data(pc_alpha=0.01,
- # max_conds_dim=None, max_combinations=None,
- # contemp_collider_rule='conservative',
- # conflict_resolution=True)
- # selected_links = {0: [(0, -1)],
- # 1: [(1, -1), (0, -1)],
- # 2: [(2, -1), (1, 0)],
- # 3: [(3, -1), (2, 0)],
- # }
-
- # results = pcmci.run_pc_stable(
- # selected_links=None,
- # tau_min=1,
- # tau_max=1,
- # pc_alpha=0.001,
- # )
- # print(results)
-
- # results = pcmci.run_pcmci(
- # selected_links=None,
- # tau_min=0,
- # tau_max=2,
- # pc_alpha=None,
- # max_conds_dim=None,
- # max_conds_py=None,
- # max_conds_px=None,
- # fdr_method='none',
- # )
- # pcmci.print_significant_links(p_matrix=results['p_matrix'],
- # val_matrix=results['val_matrix'],
- # alpha_level=0.05)
-
- # results = pcmci.get_lagged_dependencies(
- # selected_links=None,
- # tau_min=0,
- # tau_max=2,
- # val_only=True
- # # parents=None,
- # # max_conds_py=None,
- # # max_conds_px=None,
- # )
-
- # print (results)
-
- # results = pcmci.run_pcmciplus(
- # selected_links=None,
- # tau_min=0,
- # tau_max=3,
- # pc_alpha=None,
- # contemp_collider_rule='majority',
- # conflict_resolution=True,
- # reset_lagged_links=False,
- # max_conds_dim=None,
- # max_conds_py=None,
- # max_conds_px=None,
- # max_conds_px_lagged=0,
- # fdr_method='none'
- # )
- # pcmci.print_results(results, alpha_level=0.01)
-
- # graph_bool = results['graph']
- # print(graph_bool[:,:,0])
- # print(graph_bool[:,:,1])
-
- # graph = np.zeros(graph_bool.shape, dtype='<U3')
- # graph[:] = ""
- # graph[:,:,1:][graph_bool[:,:,1:]==1] = "-->"
- # graph[:,:,0][np.logical_and(graph_bool[:,:,0]==1, graph_bool[:,:,0].T==1)] = "o-o"
- # for (i,j) in zip(*np.where(np.logical_and(graph_bool[:,:,0]==1, graph_bool[:,:,0].T==0))):
- # graph[i,j,0] = "-->"
- # graph[j,i,0] = "<--"
-
- # # np.logical_or(true_graphs=="-->", true_graphs=="<--")
-
- # print(graph[:,:,0])
- # print(graph[:,:,1]) # dag_member = pcmci._get_dag_from_cpdag(cpdag_graph=results['graph'])
- # print(dag_member[:,:,0])
- # print(dag_member[:,:,1])
-
- # print("Graph")
- # print(results['graph'])
- # print("p_matrix")
- # print(results['p_matrix'].round(4))
- # print("val_matrix")
- # print(results['val_matrix'].round(2))
- # print("Contemp graph")
- # print(results['graph'][:, :, 0])
- # print("Contemp p_matrix")
- # print(results['p_matrix'][:, :, 0].round(4))
- # print("Contemp val_matrix")
- # print(results['val_matrix'][:, :, 0].round(2))
-
- # results = pcmci.run_pcalg(
- # pc_alpha=pc_alpha,
- # tau_min=0, tau_max=tau_max,
- # contemp_collider_rule='majority', #'conservative', #None, #'majority',
- # conflict_resolution=True,)
- # results['val_matrix'] = results['graph']
-
- # print(results['p_matrix'].round(2))
- # link_matrix = pcmci.return_significant_parents(
- # pq_matrix=results['p_matrix'],
- # # val_matrix=results['val_matrix'],
- # alpha_level=pc_alpha)['link_matrix']
-
- # link_matrix[:,:,0] = 0
- # print(link_matrix.astype('int'))
- # print(contemp_pcmci_results['val_matrix'].round(2))
- # tp.plot_time_series_graph(
- # val_matrix=results['val_matrix'],
- # link_matrix=link_matrix,
- # link_colorbar_label='MCI',
- # cmap_edges='OrRd',
- # save_name="/home/rung_ja/work/sandbox/tsg_final.pdf",
- # )
- # pc_results = pcmci.run_pcalg(
- # pc_alpha=pc_alpha,
- # tau_min=0, tau_max=5,
- # ci_test='par_corr',
- # print(results['graph'])
-
- # np.random.seed(42)
- # val_matrix = np.random.rand(3,3,4)
- # link_matrix = np.abs(val_matrix) > .9
-
- # tp.plot_time_series_graph(
- # val_matrix=val_matrix,
- # sig_thres=None,
- # link_matrix=link_matrix,
- # var_names=range(len(val_matrix)),
- # undirected_style='dashed',
- # save_name="/home/rung_ja/work/sandbox/tsg_contemp.pdf",
-
- # )
-
- # Test order
diff --git a/docs/_build/html/_modules/tigramite/plotting.html b/docs/_build/html/_modules/tigramite/plotting.html
index 2314772f..f9d01bca 100644
--- a/docs/_build/html/_modules/tigramite/plotting.html
+++ b/docs/_build/html/_modules/tigramite/plotting.html
@@ -57,16 +57,20 @@ Source code for tigramite.plotting
import numpy as np
import matplotlib
-from matplotlib.colors import ListedColormap
+from matplotlib.colors import ListedColormap
import matplotlib.transforms as transforms
-from matplotlib import pyplot, ticker
-from matplotlib.ticker import FormatStrFormatter
+from matplotlib import pyplot, ticker
+from matplotlib.ticker import FormatStrFormatter
import matplotlib.patches as mpatches
+from matplotlib.collections import PatchCollection
+
import sys
+from operator import sub
import networkx as nx
import tigramite.data_processing as pp
-
-from copy import deepcopy
+from copy import deepcopy
+import matplotlib.path as mpath
+import matplotlib.patheffects as PathEffects
# TODO: Add proper docstrings to internal functions...
@@ -77,28 +81,28 @@ Source code for tigramite.plotting
# Set negative values to small positive number
# (zero would be interpreted as non-significant in some functions)
if np.ndim(cmi) == 0:
- if cmi < 0.:
- cmi = 1E-8
+ if cmi < 0.0:
+ cmi = 1e-8
else:
- cmi[cmi < 0.] = 1E-8
+ cmi[cmi < 0.0] = 1e-8
- return np.sqrt(1. - np.exp(-2. * cmi))
+ return np.sqrt(1.0 - np.exp(-2.0 * cmi))
def _par_corr_to_cmi(par_corr):
"""Transformation of partial correlation to CMI scale."""
- return -0.5 * np.log(1. - par_corr**2)
+ return -0.5 * np.log(1.0 - par_corr ** 2)
-def _myround(x, base=5, round_mode='updown'):
+def _myround(x, base=5, round_mode="updown"):
"""Rounds x to a float with precision base."""
- if round_mode == 'updown':
+ if round_mode == "updown":
return base * round(float(x) / base)
- elif round_mode == 'down':
+ elif round_mode == "down":
return base * np.floor(float(x) / base)
- elif round_mode == 'up':
+ elif round_mode == "up":
return base * np.ceil(float(x) / base)
return base * round(float(x) / base)
@@ -108,10 +112,9 @@ Source code for tigramite.plotting
"""Makes nice axes."""
if where is None:
- where = ['left', 'bottom']
+ where = ["left", "bottom"]
if color is None:
- color = {'left': 'black', 'right': 'black',
- 'bottom': 'black', 'top': 'black'}
+ color = {"left": "black", "right": "black", "bottom": "black", "top": "black"}
if type(skip) == int:
skip_x = skip_y = skip
@@ -121,48 +124,48 @@ Source code for tigramite.plotting
for loc, spine in ax.spines.items():
if loc in where:
- spine.set_position(('outward', 5)) # outward by 10 points
+ spine.set_position(("outward", 5)) # outward by 10 points
spine.set_color(color[loc])
- if loc == 'left' or loc == 'right':
+ if loc == "left" or loc == "right":
pyplot.setp(ax.get_yticklines(), color=color[loc])
pyplot.setp(ax.get_yticklabels(), color=color[loc])
- if loc == 'top' or loc == 'bottom':
+ if loc == "top" or loc == "bottom":
pyplot.setp(ax.get_xticklines(), color=color[loc])
- elif loc in [item for item in ['left', 'bottom', 'right', 'top']
- if item not in where]:
- spine.set_color('none') # don't draw spine
+ elif loc in [
+ item for item in ["left", "bottom", "right", "top"] if item not in where
+ ]:
+ spine.set_color("none") # don't draw spine
else:
- raise ValueError('unknown spine location: %s' % loc)
+ raise ValueError("unknown spine location: %s" % loc)
# ax.xaxis.get_major_formatter().set_useOffset(False)
# turn off ticks where there is no spine
- if 'top' in where and 'bottom' not in where:
- ax.xaxis.set_ticks_position('top')
+ if "top" in where and "bottom" not in where:
+ ax.xaxis.set_ticks_position("top")
ax.set_xticks(ax.get_xticks()[::skip_x])
- elif 'bottom' in where:
- ax.xaxis.set_ticks_position('bottom')
+ elif "bottom" in where:
+ ax.xaxis.set_ticks_position("bottom")
ax.set_xticks(ax.get_xticks()[::skip_x])
else:
- ax.xaxis.set_ticks_position('none')
+ ax.xaxis.set_ticks_position("none")
ax.xaxis.set_ticklabels([])
- if 'right' in where and 'left' not in where:
- ax.yaxis.set_ticks_position('right')
+ if "right" in where and "left" not in where:
+ ax.yaxis.set_ticks_position("right")
ax.set_yticks(ax.get_yticks()[::skip_y])
- elif 'left' in where:
- ax.yaxis.set_ticks_position('left')
+ elif "left" in where:
+ ax.yaxis.set_ticks_position("left")
ax.set_yticks(ax.get_yticks()[::skip_y])
else:
- ax.yaxis.set_ticks_position('none')
+ ax.yaxis.set_ticks_position("none")
ax.yaxis.set_ticklabels([])
- ax.patch.set_alpha(0.)
+ ax.patch.set_alpha(0.0)
def _get_absmax(val_matrix):
"""Get value at absolute maximum in lag function array.
-
For an (N, N, tau)-array this comutes the lag of the absolute maximum
along the tau-axis and stores the (positive or negative) value in
the (N,N)-array absmax."""
@@ -173,26 +176,30 @@ Source code for tigramite.plotting
return val_matrix[i, j, absmax_indices]
-def _add_timeseries(fig, axes, i, time, dataseries, label,
- use_mask=False,
- mask=None,
- missing_flag=None,
- grey_masked_samples=False,
- data_linewidth=1.,
- skip_ticks_data_x=1,
- skip_ticks_data_y=1,
- unit=None,
- last=False,
- time_label='',
- label_fontsize=10,
- color='black',
- grey_alpha=1.,
- ):
+def _add_timeseries(
+ fig,
+ axes,
+ i,
+ time,
+ dataseries,
+ label,
+ use_mask=False,
+ mask=None,
+ missing_flag=None,
+ grey_masked_samples=False,
+ data_linewidth=1.0,
+ skip_ticks_data_x=1,
+ skip_ticks_data_y=1,
+ unit=None,
+ last=False,
+ time_label="",
+ label_fontsize=10,
+ color="black",
+ grey_alpha=1.0,
+):
"""Adds a time series plot to an axis.
-
Plot of dataseries is added to axis. Allows for proper visualization of
masked data.
-
Parameters
----------
fig : figure instance
@@ -247,55 +254,78 @@ Source code for tigramite.plotting
ax = axes
if missing_flag is not None:
- dataseries_nomissing = np.ma.masked_where(dataseries==missing_flag,
- dataseries)
+ dataseries_nomissing = np.ma.masked_where(
+ dataseries == missing_flag, dataseries
+ )
else:
dataseries_nomissing = np.ma.masked_where(
- np.zeros(dataseries.shape),
- dataseries)
+ np.zeros(dataseries.shape), dataseries
+ )
if use_mask:
maskdata = np.ma.masked_where(mask, dataseries_nomissing)
- if grey_masked_samples == 'fill':
- ax.fill_between(time, maskdata.min(), maskdata.max(),
- where=mask, color='grey',
- interpolate=True,
- linewidth=0., alpha=grey_alpha)
- elif grey_masked_samples == 'data':
- ax.plot(time, dataseries_nomissing,
- color='grey', marker='.', markersize=data_linewidth,
- linewidth=data_linewidth, clip_on=False,
- alpha=grey_alpha)
-
- ax.plot(time, maskdata,
- color=color, linewidth=data_linewidth, marker='.',
- markersize=data_linewidth, clip_on=False)
+ if grey_masked_samples == "fill":
+ ax.fill_between(
+ time,
+ maskdata.min(),
+ maskdata.max(),
+ where=mask,
+ color="grey",
+ interpolate=True,
+ linewidth=0.0,
+ alpha=grey_alpha,
+ )
+ elif grey_masked_samples == "data":
+ ax.plot(
+ time,
+ dataseries_nomissing,
+ color="grey",
+ marker=".",
+ markersize=data_linewidth,
+ linewidth=data_linewidth,
+ clip_on=False,
+ alpha=grey_alpha,
+ )
+
+ ax.plot(
+ time,
+ maskdata,
+ color=color,
+ linewidth=data_linewidth,
+ marker=".",
+ markersize=data_linewidth,
+ clip_on=False,
+ )
else:
- ax.plot(time, dataseries_nomissing,
- color=color, linewidth=data_linewidth, clip_on=False)
+ ax.plot(
+ time,
+ dataseries_nomissing,
+ color=color,
+ linewidth=data_linewidth,
+ clip_on=False,
+ )
if last:
- _make_nice_axes(ax, where=['left', 'bottom'], skip=(
- skip_ticks_data_x, skip_ticks_data_y))
- ax.set_xlabel(r'%s' % time_label, fontsize=label_fontsize)
- else:
_make_nice_axes(
- ax, where=['left'], skip=(skip_ticks_data_x, skip_ticks_data_y))
+ ax, where=["left", "bottom"], skip=(skip_ticks_data_x, skip_ticks_data_y)
+ )
+ ax.set_xlabel(r"%s" % time_label, fontsize=label_fontsize)
+ else:
+ _make_nice_axes(ax, where=["left"], skip=(skip_ticks_data_x, skip_ticks_data_y))
# ax.get_xaxis().get_major_formatter().set_useOffset(False)
- ax.xaxis.set_major_formatter(FormatStrFormatter('%.0f'))
+ ax.xaxis.set_major_formatter(FormatStrFormatter("%.0f"))
ax.label_outer()
ax.set_xlim(time[0], time[-1])
- trans = transforms.blended_transform_factory(
- fig.transFigure, ax.transAxes)
+ trans = transforms.blended_transform_factory(fig.transFigure, ax.transAxes)
if unit:
- ax.set_ylabel(r'%s [%s]' % (label, unit), fontsize=label_fontsize)
+ ax.set_ylabel(r"%s [%s]" % (label, unit), fontsize=label_fontsize)
else:
- ax.set_ylabel(r'%s' % (label), fontsize=label_fontsize)
+ ax.set_ylabel(r"%s" % (label), fontsize=label_fontsize)
# ax.text(.02, .5, r'%s [%s]' % (label, unit), fontsize=label_fontsize,
# horizontalalignment='left', verticalalignment='center',
@@ -307,21 +337,21 @@ Source code for tigramite.plotting
pyplot.tight_layout()
-[docs]def plot_timeseries(dataframe=None,
- save_name=None,
- fig_axes=None,
- figsize=None,
- var_units=None,
- time_label='time',
- use_mask=False,
- grey_masked_samples=False,
- data_linewidth=1.,
- skip_ticks_data_x=1,
- skip_ticks_data_y=2,
- label_fontsize=8,
- ):
+[docs]def plot_timeseries(
+ dataframe=None,
+ save_name=None,
+ fig_axes=None,
+ figsize=None,
+ var_units=None,
+ time_label="time",
+ use_mask=False,
+ grey_masked_samples=False,
+ data_linewidth=1.0,
+ skip_ticks_data_x=1,
+ skip_ticks_data_y=2,
+ label_fontsize=12,
+):
"""Create and save figure of stacked panels with time series.
-
Parameters
----------
dataframe : data object, optional
@@ -365,11 +395,10 @@ Source code for tigramite.plotting
T, N = data.shape
if var_units is None:
- var_units = ['' for i in range(N)]
+ var_units = ["" for i in range(N)]
if fig_axes is None:
- fig, axes = pyplot.subplots(N, sharex=True,
- figsize=figsize)
+ fig, axes = pyplot.subplots(N, sharex=True, figsize=figsize)
else:
fig, axes = fig_axes
@@ -378,24 +407,27 @@ Source code for tigramite.plotting
mask_i = None
else:
mask_i = mask[:, i]
- _add_timeseries(fig=fig, axes=axes, i=i,
- time=datatime,
- dataseries=data[:, i],
- label=var_names[i],
- use_mask=use_mask,
- mask=mask_i,
- missing_flag=missing_flag,
- grey_masked_samples=grey_masked_samples,
- data_linewidth=data_linewidth,
- skip_ticks_data_x=skip_ticks_data_x,
- skip_ticks_data_y=skip_ticks_data_y,
- unit=var_units[i],
- last=(i == N - 1),
- time_label=time_label,
- label_fontsize=label_fontsize,
- )
-
- fig.subplots_adjust(bottom=0.15, top=.9, left=0.15, right=.95, hspace=.3)
+ _add_timeseries(
+ fig=fig,
+ axes=axes,
+ i=i,
+ time=datatime,
+ dataseries=data[:, i],
+ label=var_names[i],
+ use_mask=use_mask,
+ mask=mask_i,
+ missing_flag=missing_flag,
+ grey_masked_samples=grey_masked_samples,
+ data_linewidth=data_linewidth,
+ skip_ticks_data_x=skip_ticks_data_x,
+ skip_ticks_data_y=skip_ticks_data_y,
+ unit=var_units[i],
+ last=(i == N - 1),
+ time_label=time_label,
+ label_fontsize=label_fontsize,
+ )
+
+ fig.subplots_adjust(bottom=0.15, top=0.9, left=0.15, right=0.95, hspace=0.3)
pyplot.tight_layout()
if save_name is not None:
@@ -403,12 +435,11 @@ Source code for tigramite.plotting
else:
return fig, axes
+
[docs]def plot_lagfuncs(val_matrix, name=None, setup_args={}, add_lagfunc_args={}):
"""Wrapper helper function to plot lag functions.
-
Sets up the matrix object and plots the lagfunction, see parameters in
setup_matrix and add_lagfuncs.
-
Parameters
----------
val_matrix : array_like
@@ -420,7 +451,6 @@ Source code for tigramite.plotting
setup_matrix.
add_lagfunc_args : dict
Arguments for adding a lag function matrix, see doc of add_lagfuncs.
-
Returns
-------
matrix : object
@@ -439,13 +469,12 @@ Source code for tigramite.plotting
return matrix
-[docs]class setup_matrix():
- """Create matrix of lag function panels.
+[docs]class setup_matrix:
+ """Create matrix of lag function panels.
Class to setup figure object. The function add_lagfuncs(...) allows to plot
the val_matrix of shape (N, N, tau_max+1). Multiple lagfunctions can be
overlaid for comparison.
-
Parameters
----------
N : int
@@ -481,20 +510,25 @@ Source code for tigramite.plotting
Fontsize of variable labels.
"""
- def __init__(self, N, tau_max,
- var_names=None,
- figsize=None,
- minimum=-1,
- maximum=1,
- label_space_left=0.1,
- label_space_top=.05,
- legend_width=.15,
- legend_fontsize=10,
- x_base=1., y_base=0.5,
- plot_gridlines=False,
- lag_units='',
- lag_array=None,
- label_fontsize=10):
+ def __init__(
+ self,
+ N,
+ tau_max,
+ var_names=None,
+ figsize=None,
+ minimum=-1,
+ maximum=1,
+ label_space_left=0.1,
+ label_space_top=0.05,
+ legend_width=0.15,
+ legend_fontsize=10,
+ x_base=1.0,
+ y_base=0.5,
+ plot_gridlines=False,
+ lag_units="",
+ lag_array=None,
+ label_fontsize=10,
+ ):
self.tau_max = tau_max
@@ -509,7 +543,6 @@ Source code for tigramite.plotting
else:
self.x_base = x_base
-
self.legend_width = legend_width
self.legend_fontsize = legend_fontsize
@@ -531,76 +564,98 @@ Source code for tigramite.plotting
# Plot process labels
if j == 0:
trans = transforms.blended_transform_factory(
- self.fig.transFigure, self.axes_dict[(i, j)].transAxes)
- self.axes_dict[(i, j)].text(0.01, .5, '%s' %
- str(var_names[i]),
- fontsize=label_fontsize,
- horizontalalignment='left',
- verticalalignment='center',
- transform=trans)
+ self.fig.transFigure, self.axes_dict[(i, j)].transAxes
+ )
+ self.axes_dict[(i, j)].text(
+ 0.01,
+ 0.5,
+ "%s" % str(var_names[i]),
+ fontsize=label_fontsize,
+ horizontalalignment="left",
+ verticalalignment="center",
+ transform=trans,
+ )
if i == 0:
trans = transforms.blended_transform_factory(
- self.axes_dict[(i, j)].transAxes, self.fig.transFigure)
- self.axes_dict[(i, j)].text(.5, .99, r'${\to}$ ' + '%s' %
- str(var_names[j]),
- fontsize=label_fontsize,
- horizontalalignment='center',
- verticalalignment='top',
- transform=trans)
+ self.axes_dict[(i, j)].transAxes, self.fig.transFigure
+ )
+ self.axes_dict[(i, j)].text(
+ 0.5,
+ 0.99,
+ r"${\to}$ " + "%s" % str(var_names[j]),
+ fontsize=label_fontsize,
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
# Make nice axis
_make_nice_axes(
- self.axes_dict[(i, j)], where=['left', 'bottom'],
- skip=(1, 1))
+ self.axes_dict[(i, j)], where=["left", "bottom"], skip=(1, 1)
+ )
if x_base is not None:
self.axes_dict[(i, j)].xaxis.set_major_locator(
- ticker.FixedLocator(np.arange(0, self.tau_max + 1,
- x_base)))
- if x_base / 2. % 1 == 0:
+ ticker.FixedLocator(np.arange(0, self.tau_max + 1, x_base))
+ )
+ if x_base / 2.0 % 1 == 0:
self.axes_dict[(i, j)].xaxis.set_minor_locator(
- ticker.FixedLocator(np.arange(0, self.tau_max +
- 1,
- x_base / 2.)))
+ ticker.FixedLocator(
+ np.arange(0, self.tau_max + 1, x_base / 2.0)
+ )
+ )
if y_base is not None:
self.axes_dict[(i, j)].yaxis.set_major_locator(
ticker.FixedLocator(
- np.arange(_myround(minimum, y_base, 'down'),
- _myround(maximum, y_base, 'up') +
- y_base, y_base)))
+ np.arange(
+ _myround(minimum, y_base, "down"),
+ _myround(maximum, y_base, "up") + y_base,
+ y_base,
+ )
+ )
+ )
self.axes_dict[(i, j)].yaxis.set_minor_locator(
ticker.FixedLocator(
- np.arange(_myround(minimum, y_base, 'down'),
- _myround(maximum, y_base, 'up') +
- y_base, y_base / 2.)))
+ np.arange(
+ _myround(minimum, y_base, "down"),
+ _myround(maximum, y_base, "up") + y_base,
+ y_base / 2.0,
+ )
+ )
+ )
self.axes_dict[(i, j)].set_ylim(
- _myround(minimum, y_base, 'down'),
- _myround(maximum, y_base, 'up'))
+ _myround(minimum, y_base, "down"),
+ _myround(maximum, y_base, "up"),
+ )
if j != 0:
self.axes_dict[(i, j)].get_yaxis().set_ticklabels([])
self.axes_dict[(i, j)].set_xlim(0, self.tau_max)
if plot_gridlines:
- self.axes_dict[(i, j)].grid(True, which='major',
- color='black',
- linestyle='dotted',
- dashes=(1, 1),
- linewidth=.05,
- zorder=-5)
+ self.axes_dict[(i, j)].grid(
+ True,
+ which="major",
+ color="black",
+ linestyle="dotted",
+ dashes=(1, 1),
+ linewidth=0.05,
+ zorder=-5,
+ )
plot_index += 1
-[docs] def add_lagfuncs(self, val_matrix,
- sig_thres=None,
- conf_matrix=None,
- color='black',
- label=None,
- two_sided_thres=True,
- marker='.',
- markersize=5,
- alpha=1.,
- ):
+[docs] def add_lagfuncs(
+ self,
+ val_matrix,
+ sig_thres=None,
+ conf_matrix=None,
+ color="black",
+ label=None,
+ two_sided_thres=True,
+ marker=".",
+ markersize=5,
+ alpha=1.0,
+ ):
"""Add lag function plot from val_matrix array.
-
Parameters
----------
val_matrix : array_like
@@ -627,57 +682,75 @@ Source code for tigramite.plotting
if label is not None:
self.labels.append((label, color, marker, markersize, alpha))
-
for ij in list(self.axes_dict):
i = ij[0]
j = ij[1]
- maskedres = np.copy(val_matrix[i, j, int(i == j):])
- self.axes_dict[(i, j)].plot(range(int(i == j), self.tau_max + 1),
- maskedres,
- linestyle='', color=color,
- marker=marker, markersize=markersize,
- alpha=alpha, clip_on=False)
+ maskedres = np.copy(val_matrix[i, j, int(i == j) :])
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ maskedres,
+ linestyle="",
+ color=color,
+ marker=marker,
+ markersize=markersize,
+ alpha=alpha,
+ clip_on=False,
+ )
if conf_matrix is not None:
- maskedconfres = np.copy(conf_matrix[i, j, int(i == j):])
- self.axes_dict[(i, j)].plot(range(int(i == j),
- self.tau_max + 1),
- maskedconfres[:, 0],
- linestyle='', color=color,
- marker='_',
- markersize=markersize - 2,
- alpha=alpha, clip_on=False)
- self.axes_dict[(i, j)].plot(range(int(i == j),
- self.tau_max + 1),
- maskedconfres[:, 1],
- linestyle='', color=color,
- marker='_',
- markersize=markersize - 2,
- alpha=alpha, clip_on=False)
-
- self.axes_dict[(i, j)].plot(range(int(i == j), self.tau_max + 1),
- np.zeros(self.tau_max + 1 -
- int(i == j)),
- color='black', linestyle='dotted',
- linewidth=.1)
+ maskedconfres = np.copy(conf_matrix[i, j, int(i == j) :])
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ maskedconfres[:, 0],
+ linestyle="",
+ color=color,
+ marker="_",
+ markersize=markersize - 2,
+ alpha=alpha,
+ clip_on=False,
+ )
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ maskedconfres[:, 1],
+ linestyle="",
+ color=color,
+ marker="_",
+ markersize=markersize - 2,
+ alpha=alpha,
+ clip_on=False,
+ )
+
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ np.zeros(self.tau_max + 1 - int(i == j)),
+ color="black",
+ linestyle="dotted",
+ linewidth=0.1,
+ )
if sig_thres is not None:
- maskedsigres = sig_thres[i, j, int(i == j):]
-
- self.axes_dict[(i, j)].plot(range(int(i == j), self.tau_max + 1),
- maskedsigres,
- color=color, linestyle='solid',
- linewidth=.1, alpha=alpha)
+ maskedsigres = sig_thres[i, j, int(i == j) :]
+
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ maskedsigres,
+ color=color,
+ linestyle="solid",
+ linewidth=0.1,
+ alpha=alpha,
+ )
if two_sided_thres:
- self.axes_dict[(i, j)].plot(range(int(i == j),
- self.tau_max + 1),
- -sig_thres[i, j, int(i == j):],
- color=color, linestyle='solid',
- linewidth=.1, alpha=alpha)
+ self.axes_dict[(i, j)].plot(
+ range(int(i == j), self.tau_max + 1),
+ -sig_thres[i, j, int(i == j) :],
+ color=color,
+ linestyle="solid",
+ linewidth=0.1,
+ alpha=alpha,
+ )
# pyplot.tight_layout()
[docs] def savefig(self, name=None):
"""Save matrix figure.
-
Parameters
----------
name : str, optional (default: None)
@@ -687,52 +760,75 @@ Source code for tigramite.plotting
# Trick to plot legend
if len(self.labels) > 0:
axlegend = self.fig.add_subplot(111, frameon=False)
- axlegend.spines['left'].set_color('none')
- axlegend.spines['right'].set_color('none')
- axlegend.spines['bottom'].set_color('none')
- axlegend.spines['top'].set_color('none')
+ axlegend.spines["left"].set_color("none")
+ axlegend.spines["right"].set_color("none")
+ axlegend.spines["bottom"].set_color("none")
+ axlegend.spines["top"].set_color("none")
axlegend.set_xticks([])
axlegend.set_yticks([])
# self.labels.append((label, color, marker, markersize, alpha))
for item in self.labels:
-
label = item[0]
color = item[1]
marker = item[2]
markersize = item[3]
alpha = item[4]
- axlegend.plot([], [], linestyle='', color=color,
- marker=marker, markersize=markersize,
- label=label, alpha=alpha)
- axlegend.legend(loc='upper left', ncol=1,
- bbox_to_anchor=(1.05, 0., .1, 1.),
- borderaxespad=0, fontsize=self.legend_fontsize
- ).draw_frame(False)
-
- self.fig.subplots_adjust(left=self.label_space_left, right=1. -
- self.legend_width,
- top=1. - self.label_space_top,
- hspace=0.35, wspace=0.35)
+ axlegend.plot(
+ [],
+ [],
+ linestyle="",
+ color=color,
+ marker=marker,
+ markersize=markersize,
+ label=label,
+ alpha=alpha,
+ )
+ axlegend.legend(
+ loc="upper left",
+ ncol=1,
+ bbox_to_anchor=(1.05, 0.0, 0.1, 1.0),
+ borderaxespad=0,
+ fontsize=self.legend_fontsize,
+ ).draw_frame(False)
+
+ self.fig.subplots_adjust(
+ left=self.label_space_left,
+ right=1.0 - self.legend_width,
+ top=1.0 - self.label_space_top,
+ hspace=0.35,
+ wspace=0.35,
+ )
pyplot.figtext(
- 0.5, 0.01, r'lag $\tau$ [%s]' % self.lag_units,
- horizontalalignment='center', fontsize=self.label_fontsize)
+ 0.5,
+ 0.01,
+ r"lag $\tau$ [%s]" % self.lag_units,
+ horizontalalignment="center",
+ fontsize=self.label_fontsize,
+ )
else:
self.fig.subplots_adjust(
- left=self.label_space_left, right=.95,
- top=1. - self.label_space_top,
- hspace=0.35, wspace=0.35)
+ left=self.label_space_left,
+ right=0.95,
+ top=1.0 - self.label_space_top,
+ hspace=0.35,
+ wspace=0.35,
+ )
pyplot.figtext(
- 0.55, 0.01, r'lag $\tau$ [%s]' % self.lag_units,
- horizontalalignment='center', fontsize=self.label_fontsize)
+ 0.55,
+ 0.01,
+ r"lag $\tau$ [%s]" % self.lag_units,
+ horizontalalignment="center",
+ fontsize=self.label_fontsize,
+ )
if self.lag_array is not None:
assert self.lag_array.shape == np.arange(self.tau_max + 1).shape
for ij in list(self.axes_dict):
i = ij[0]
j = ij[1]
- self.axes_dict[(i, j)].set_xticklabels(self.lag_array[::self.x_base])
+ self.axes_dict[(i, j)].set_xticklabels(self.lag_array[:: self.x_base])
if name is not None:
self.fig.savefig(name)
@@ -741,448 +837,747 @@ Source code for tigramite.plotting
def _draw_network_with_curved_edges(
- fig, ax,
- G, pos,
+ fig,
+ ax,
+ G,
+ pos,
node_rings,
- node_labels, node_label_size, node_alpha=1., standard_size=100,
- standard_cmap='OrRd', standard_color='lightgrey', log_sizes=False,
- cmap_links='YlOrRd', cmap_links_edges='YlOrRd', links_vmin=0.,
- links_vmax=1., links_edges_vmin=0., links_edges_vmax=1.,
- links_ticks=.2, links_edges_ticks=.2, link_label_fontsize=8,
- arrowstyle='simple', arrowhead_size=3., curved_radius=.2, label_fontsize=4,
- label_fraction=.5, link_colorbar_label='link',
+ node_labels,
+ node_label_size,
+ node_alpha=1.0,
+ standard_size=100,
+ node_aspect=None,
+ standard_cmap="OrRd",
+ standard_color="lightgrey",
+ log_sizes=False,
+ cmap_links="YlOrRd",
+ cmap_links_edges="YlOrRd",
+ links_vmin=0.0,
+ links_vmax=1.0,
+ links_edges_vmin=0.0,
+ links_edges_vmax=1.0,
+ links_ticks=0.2,
+ links_edges_ticks=0.2,
+ link_label_fontsize=8,
+ arrowstyle="->, head_width=0.4, head_length=1",
+ arrowhead_size=3.0,
+ curved_radius=0.2,
+ label_fontsize=4,
+ label_fraction=0.5,
+ link_colorbar_label="link",
# link_edge_colorbar_label='link_edge',
- inner_edge_curved=False, inner_edge_style='solid',
- network_lower_bound=0.2, show_colorbar=True,
- ):
+ inner_edge_curved=False,
+ inner_edge_style="solid",
+ network_lower_bound=0.2,
+ show_colorbar=True,
+):
"""Function to draw a network from networkx graph instance.
-
Various attributes are used to specify the graph's properties.
-
This function is just a beta-template for now that can be further
customized.
"""
- from matplotlib.patches import FancyArrowPatch, Circle, Ellipse
+ from matplotlib.patches import FancyArrowPatch, Circle, Ellipse
- ax.spines['left'].set_color('none')
- ax.spines['right'].set_color('none')
- ax.spines['bottom'].set_color('none')
- ax.spines['top'].set_color('none')
+ ax.spines["left"].set_color("none")
+ ax.spines["right"].set_color("none")
+ ax.spines["bottom"].set_color("none")
+ ax.spines["top"].set_color("none")
ax.set_xticks([])
ax.set_yticks([])
N = len(G)
- def draw_edge(ax, u, v, d, seen, arrowstyle='simple', outer_edge=True):
+ # This fixes a positioning bug in matplotlib.
+ ax.scatter(0, 0, zorder=-10, alpha=0)
+
+ def draw_edge(
+ ax,
+ u,
+ v,
+ d,
+ seen,
+ arrowstyle="->, head_width=0.4, head_length=1",
+ outer_edge=True,
+ ):
# avoiding attribute error raised by changes in networkx
- if hasattr(G, 'node'):
+ if hasattr(G, "node"):
# works with networkx 1.10
- n1 = G.node[u]['patch']
- n2 = G.node[v]['patch']
+ n1 = G.node[u]["patch"]
+ n2 = G.node[v]["patch"]
else:
# works with networkx 2.4
- n1 = G.nodes[u]['patch']
- n2 = G.nodes[v]['patch']
+ n1 = G.nodes[u]["patch"]
+ n2 = G.nodes[v]["patch"]
if outer_edge:
- rad = -1.*curved_radius
-# facecolor = d['outer_edge_color']
-# edgecolor = d['outer_edge_edgecolor']
+ rad = -1.0 * curved_radius
if cmap_links is not None:
- facecolor = data_to_rgb_links.to_rgba(d['outer_edge_color'])
+ facecolor = data_to_rgb_links.to_rgba(d["outer_edge_color"])
else:
- if d['outer_edge_color'] is not None:
- facecolor = d['outer_edge_color']
+ if d["outer_edge_color"] is not None:
+ facecolor = d["outer_edge_color"]
else:
facecolor = standard_color
- width = d['outer_edge_width']
- alpha = d['outer_edge_alpha']
+ width = d["outer_edge_width"]
+ alpha = d["outer_edge_alpha"]
if (u, v) in seen:
rad = seen.get((u, v))
- rad = (rad + np.sign(rad) * 0.1) * -1.
+ rad = (rad + np.sign(rad) * 0.1) * -1.0
arrowstyle = arrowstyle
# link_edge = d['outer_edge_edge']
- linestyle = 'solid'
- linewidth = 0.
+ linestyle = d.get("outer_edge_style")
- if d.get('outer_edge_attribute', None) == 'spurious':
- facecolor = 'grey'
+ if d.get("outer_edge_attribute", None) == "spurious":
+ facecolor = "grey"
- if d.get('outer_edge_type') in ['<-o', '<--']:
+ if d.get("outer_edge_type") in ["<-o", "<--", "<-x"]:
n1, n2 = n2, n1
- if d.get('outer_edge_type') in ["o-o", "o--", "--o", "---"]:
- arrowstyle = 'simple,head_length=0.0001'
- elif d.get('outer_edge_type') == '<->':
- arrowstyle = '<->, head_width=0.15, head_length=0.3'
- linewidth = 4
+ if d.get("outer_edge_type") in [
+ "o-o",
+ "o--",
+ "--o",
+ "---",
+ "x-x",
+ "x--",
+ "--x",
+ "o-x",
+ "x-o",
+ ]:
+ arrowstyle = "-"
+ # linewidth = width*factor
+ elif d.get("outer_edge_type") == "<->":
+ arrowstyle = "<->, head_width=0.4, head_length=1"
+ # linewidth = width*factor
+ elif d.get("outer_edge_type") in ["o->", "-->", "<-o", "<--", "<-x", "x->"]:
+ arrowstyle = "->, head_width=0.4, head_length=1"
else:
- rad = -1. * inner_edge_curved * curved_radius
+ rad = -1.0 * inner_edge_curved * curved_radius
if cmap_links is not None:
- facecolor = data_to_rgb_links.to_rgba(d['inner_edge_color'])
+ facecolor = data_to_rgb_links.to_rgba(d["inner_edge_color"])
else:
- if d['inner_edge_color'] is not None:
- facecolor = d['inner_edge_color']
+ if d["inner_edge_color"] is not None:
+ facecolor = d["inner_edge_color"]
else:
facecolor = standard_color
- width = d['inner_edge_width']
- alpha = d['inner_edge_alpha']
- # if 'oriented' in d and d['oriented']:
- # arrowstyle = arrowstyle
- # else:
- # link_edge = d['inner_edge_edge']
-
- linestyle = 'solid'
- linewidth = 0.
+ width = d["inner_edge_width"]
+ alpha = d["inner_edge_alpha"]
- if d.get('inner_edge_attribute', None) == 'spurious':
- facecolor = 'grey'
- # linestyle = 'dashed'
-
- if d.get('inner_edge_type') in ['<-o', '<--']:
+ if d.get("inner_edge_attribute", None) == "spurious":
+ facecolor = "grey"
+ if d.get("inner_edge_type") in ["<-o", "<--", "<-x"]:
n1, n2 = n2, n1
- if d.get('inner_edge_type') in ["o-o", "o--", "--o", "---"]:
- arrowstyle = 'simple,head_length=0.0001'
- elif d.get('inner_edge_type') == '<->':
- arrowstyle = '<->, head_width=0.15, head_length=0.3'
- linewidth = 4
- else:
- arrowstyle = arrowstyle
-
-
- connectionstyle='arc3,rad=%s'
-
- e = FancyArrowPatch(n1.center, n2.center,
- arrowstyle= arrowstyle,
- connectionstyle=connectionstyle % rad,
- mutation_scale=width,
- lw=linewidth,
- alpha=alpha,
- linestyle=linestyle,
- color=facecolor,
- clip_on=False,
- patchA=n1, patchB=n2,
- # zorder=-2
- )
- ax.add_patch(e)
-
- radius=np.sqrt(standard_size)*.005
- # Transformation found here: https://stackoverflow.com/a/9232513/13011987
- x0, y0 = ax.transAxes.transform((0, 0)) # lower left in pixels
- x1, y1 = ax.transAxes.transform((1, 1)) # upper right in pixes
- dx = x1 - x0
- dy = y1 - y0
- maxd = max(dx, dy)
- width = radius * maxd / dx
- height = radius * maxd / dy
-
- circlePath = e.get_path().deepcopy()
- vertices = circlePath.vertices
- #vertices[:,0] = vertices[:,0] * maxd / dx
- #vertices[:,1] = vertices[:,1] * maxd / dy
- m,n = vertices.shape
-
- if "angle3" in connectionstyle or "arc3" in connectionstyle:
- vertices = vertices[:int(m/2),:]
-
- #start = n1.center
- #end = n2.center
+ if d.get("inner_edge_type") in [
+ "o-o",
+ "o--",
+ "--o",
+ "---",
+ "x-x",
+ "x--",
+ "--x",
+ "o-x",
+ "x-o",
+ ]:
+ arrowstyle = "-"
+ elif d.get("inner_edge_type") == "<->":
+ arrowstyle = "<->, head_width=0.4, head_length=1"
+ elif d.get("inner_edge_type") in ["o->", "-->", "<-o", "<--", "<-x", "x->"]:
+ arrowstyle = "->, head_width=0.4, head_length=1"
+
+ linestyle = d.get("inner_edge_style")
+
+ coor1 = n1.center
+ coor2 = n2.center
+
+ marker_size = width ** 2
+ figuresize = fig.get_size_inches()
+
+ e_p = FancyArrowPatch(
+ coor1,
+ coor2,
+ arrowstyle=arrowstyle,
+ connectionstyle=f"arc3,rad={rad}",
+ mutation_scale=width,
+ lw=width / 2,
+ alpha=alpha,
+ linestyle=linestyle,
+ color=facecolor,
+ clip_on=False,
+ patchA=n1,
+ patchB=n2,
+ shrinkA=0,
+ shrinkB=0,
+ zorder=-1,
+ )
+
+ ax.add_artist(e_p)
+ path = e_p.get_path()
+ vertices = path.vertices.copy()
+ m, n = vertices.shape
start = vertices[0]
end = vertices[-1]
- start_correction = vertices[1]
- end_correction = vertices[-2]
-
- start = start + (start_correction-start)*radius*3
- end = end + (end_correction-end)*radius*3
+ # This must be added to avoid rescaling of the plot, when no 'o'
+ # or 'x' is added to the graph.
+ ax.scatter(*start, zorder=-10, alpha=0)
if outer_edge:
- if d.get('outer_edge_type') in ['o->', 'o--']:
- circle_start = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_start)
-
- elif d.get('outer_edge_type') in ['<-o', '--o']:
- circle_end = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_end)
-
- elif d.get('outer_edge_type') == 'o-o':
- circle_start = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- circle_end = Ellipse(end, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_start)
- ax.add_patch(circle_end)
- else:
- if d.get('inner_edge_type') in ['o->', 'o--']:
- circle_start = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_start)
-
- elif d.get('inner_edge_type') in ['<-o', '--o']:
- circle_end = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_end)
+ if d.get("outer_edge_type") in ["o->", "o--"]:
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ elif d.get("outer_edge_type") == "<-o":
+ circle_marker_end = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "--o":
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") in ["x--", "x->"]:
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ elif d.get("outer_edge_type") == "<-x":
+ circle_marker_end = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "--x":
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "o-o":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "x-x":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "o-x":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "x-o":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
- elif d.get('inner_edge_type') == 'o-o':
- circle_start = Ellipse(start, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- circle_end = Ellipse(end, width=width, height=height, fill=True, facecolor='white', edgecolor=facecolor, zorder=3)
- ax.add_patch(circle_start)
- ax.add_patch(circle_end)
-
- if d['label'] is not None and outer_edge:
+ else:
+ if d.get("inner_edge_type") in ["o->", "o--"]:
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ elif d.get("outer_edge_type") == "<-o":
+ circle_marker_end = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "--o":
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("inner_edge_type") in ["x--", "x->"]:
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ elif d.get("outer_edge_type") == "<-x":
+ circle_marker_end = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("outer_edge_type") == "--x":
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("inner_edge_type") == "o-o":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("inner_edge_type") == "x-x":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("inner_edge_type") == "o-x":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+ elif d.get("inner_edge_type") == "x-o":
+ circle_marker_start = ax.scatter(
+ *start,
+ marker="X",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_start)
+ circle_marker_end = ax.scatter(
+ *end,
+ marker="o",
+ s=marker_size,
+ facecolor="w",
+ edgecolor=facecolor,
+ zorder=1,
+ )
+ ax.add_collection(circle_marker_end)
+
+ if d["label"] is not None and outer_edge:
# Attach labels of lags
trans = None # patch.get_transform()
- path = e.get_path()
+ path = e_p.get_path()
verts = path.to_polygons(trans)[0]
if len(verts) > 2:
label_vert = verts[1, :]
- l = d['label']
+ l = d["label"]
string = str(l)
- ax.text(label_vert[0], label_vert[1], string,
- fontsize=link_label_fontsize,
- verticalalignment='center',
- horizontalalignment='center')
+ txt = ax.text(
+ label_vert[0],
+ label_vert[1],
+ string,
+ fontsize=link_label_fontsize,
+ verticalalignment="center",
+ horizontalalignment="center",
+ color="w",
+ zorder=1,
+ )
+ txt.set_path_effects(
+ [PathEffects.withStroke(linewidth=2, foreground="k")]
+ )
return rad
- # Fix lower left and upper right corner (networkx unfortunately rescales
- # the positions...)
- # c = Circle((0, 0), radius=.01, alpha=1., fill=False,
- # linewidth=0., transform=fig.transFigure)
- # ax.add_patch(c)
- # c = Circle((1, 1), radius=.01, alpha=1., fill=False,
- # linewidth=0., transform=fig.transFigure)
- # ax.add_patch(c)
+ # Collect all edge weights to get color scale
+ all_links_weights = []
+ all_links_edge_weights = []
+ for (u, v, d) in G.edges(data=True):
+ if u != v:
+ if d["outer_edge"] and d["outer_edge_color"] is not None:
+ all_links_weights.append(d["outer_edge_color"])
+ if d["inner_edge"] and d["inner_edge_color"] is not None:
+ all_links_weights.append(d["inner_edge_color"])
+
+ if cmap_links is not None and len(all_links_weights) > 0:
+ if links_vmin is None:
+ links_vmin = np.array(all_links_weights).min()
+ if links_vmax is None:
+ links_vmax = np.array(all_links_weights).max()
+ data_to_rgb_links = pyplot.cm.ScalarMappable(
+ norm=None, cmap=pyplot.get_cmap(cmap_links)
+ )
+ data_to_rgb_links.set_array(np.array(all_links_weights))
+ data_to_rgb_links.set_clim(vmin=links_vmin, vmax=links_vmax)
+ # Create colorbars for links
+
+ # setup colorbar axes.
+ if show_colorbar:
+ cax_e = pyplot.axes(
+ [
+ 0.55,
+ ax.figbox.bounds[1] + 0.02,
+ 0.4,
+ 0.025 + (len(all_links_edge_weights) == 0) * 0.035,
+ ],
+ frameon=False,
+ )
+
+ cb_e = pyplot.colorbar(
+ data_to_rgb_links, cax=cax_e, orientation="horizontal"
+ )
+ # try:
+ cb_e.set_ticks(
+ np.arange(
+ _myround(links_vmin, links_ticks, "down"),
+ _myround(links_vmax, links_ticks, "up") + links_ticks,
+ links_ticks,
+ )
+ )
+ # except:
+ # print('no ticks given')
+
+ cb_e.outline.remove()
+ cax_e.set_xlabel(
+ link_colorbar_label, labelpad=1, fontsize=label_fontsize, zorder=-10
+ )
##
# Draw nodes
##
node_sizes = np.zeros((len(node_rings), N))
for ring in list(node_rings): # iterate through to get all node sizes
- if node_rings[ring]['sizes'] is not None:
- node_sizes[ring] = node_rings[ring]['sizes']
+ if node_rings[ring]["sizes"] is not None:
+ node_sizes[ring] = node_rings[ring]["sizes"]
+
else:
node_sizes[ring] = standard_size
-
max_sizes = node_sizes.max(axis=1)
total_max_size = node_sizes.sum(axis=0).max()
node_sizes /= total_max_size
node_sizes *= standard_size
-# print 'node_sizes ', node_sizes
+
+ def get_aspect(ax):
+ # Total figure size
+ figW, figH = ax.get_figure().get_size_inches()
+ # print(figW, figH)
+ # Axis size on figure
+ _, _, w, h = ax.get_position().bounds
+ # Ratio of display units
+ # print(w, h)
+ disp_ratio = (figH * h) / (figW * w)
+ # Ratio of data units
+ # Negative over negative because of the order of subtraction
+ data_ratio = sub(*ax.get_ylim()) / sub(*ax.get_xlim())
+ # print(data_ratio, disp_ratio)
+ return disp_ratio / data_ratio
+
+ if node_aspect is None:
+ node_aspect = get_aspect(ax)
# start drawing the outer ring first...
for ring in list(node_rings)[::-1]:
# print ring
# dictionary of rings: {0:{'sizes':(N,)-array, 'color_array':(N,)-array
# or None, 'cmap':string, 'vmin':float or None, 'vmax':float or None}}
- if node_rings[ring]['color_array'] is not None:
- color_data = node_rings[ring]['color_array']
- if node_rings[ring]['vmin'] is not None:
- vmin = node_rings[ring]['vmin']
+ if node_rings[ring]["color_array"] is not None:
+ color_data = node_rings[ring]["color_array"]
+ if node_rings[ring]["vmin"] is not None:
+ vmin = node_rings[ring]["vmin"]
else:
- vmin = node_rings[ring]['color_array'].min()
- if node_rings[ring]['vmax'] is not None:
- vmax = node_rings[ring]['vmax']
+ vmin = node_rings[ring]["color_array"].min()
+ if node_rings[ring]["vmax"] is not None:
+ vmax = node_rings[ring]["vmax"]
else:
- vmax = node_rings[ring]['color_array'].max()
- if node_rings[ring]['cmap'] is not None:
- cmap = node_rings[ring]['cmap']
+ vmax = node_rings[ring]["color_array"].max()
+ if node_rings[ring]["cmap"] is not None:
+ cmap = node_rings[ring]["cmap"]
else:
cmap = standard_cmap
data_to_rgb = pyplot.cm.ScalarMappable(
- norm=None, cmap=pyplot.get_cmap(cmap))
+ norm=None, cmap=pyplot.get_cmap(cmap)
+ )
data_to_rgb.set_array(color_data)
data_to_rgb.set_clim(vmin=vmin, vmax=vmax)
colors = [data_to_rgb.to_rgba(color_data[n]) for n in G]
- if node_rings[ring]['colorbar']:
+ if node_rings[ring]["colorbar"]:
# Create colorbars for nodes
# cax_n = pyplot.axes([.8 + ring*0.11,
# ax.figbox.bounds[1]+0.05, 0.025, 0.35], frameon=False) #
# setup colorbar axes.
# setup colorbar axes.
- cax_n = pyplot.axes([0.05, ax.figbox.bounds[1] + 0.02 +
- ring * 0.11,
- 0.4, 0.025 +
- (len(node_rings) == 1) * 0.035],
- frameon=False)
- cb_n = pyplot.colorbar(
- data_to_rgb, cax=cax_n, orientation='horizontal')
- try:
- cb_n.set_ticks(np.arange(_myround(vmin,
- node_rings[ring]['ticks'], 'down'), _myround(
- vmax, node_rings[ring]['ticks'], 'up') +
- node_rings[ring]['ticks'], node_rings[ring]['ticks']))
- except:
- print ('no ticks given')
+ cax_n = pyplot.axes(
+ [
+ 0.05,
+ ax.figbox.bounds[1] + 0.02 + ring * 0.11,
+ 0.4,
+ 0.025 + (len(node_rings) == 1) * 0.035,
+ ],
+ frameon=False,
+ )
+ cb_n = pyplot.colorbar(data_to_rgb, cax=cax_n, orientation="horizontal")
+ # try:
+ cb_n.set_ticks(
+ np.arange(
+ _myround(vmin, node_rings[ring]["ticks"], "down"),
+ _myround(vmax, node_rings[ring]["ticks"], "up")
+ + node_rings[ring]["ticks"],
+ node_rings[ring]["ticks"],
+ )
+ )
+ # except:
+ # print ('no ticks given')
cb_n.outline.remove()
# cb_n.set_ticks()
cax_n.set_xlabel(
- node_rings[ring]['label'], labelpad=1,
- fontsize=label_fontsize)
+ node_rings[ring]["label"], labelpad=1, fontsize=label_fontsize
+ )
else:
colors = None
vmin = None
vmax = None
for n in G:
- # if n==1: print node_sizes[:ring+1].sum(axis=0)[n]
-
if type(node_alpha) == dict:
alpha = node_alpha[n]
else:
- alpha = 1.
+ alpha = 1.0
if colors is None:
- ax.scatter(pos[n][0], pos[n][1],
- s=node_sizes[:ring + 1].sum(axis=0)[n] ** 2,
- facecolors=standard_color,
- edgecolors=standard_color, alpha=alpha,
- clip_on=False, linewidth=.1, zorder=-ring)
- else:
- ax.scatter(pos[n][0], pos[n][1],
- s=node_sizes[:ring + 1].sum(axis=0)[n] ** 2,
- facecolors=colors[n], edgecolors='white',
- alpha=alpha,
- clip_on=False, linewidth=.1, zorder=-ring)
+ c = Ellipse(
+ pos[n],
+ width=node_sizes[: ring + 1].sum(axis=0)[n] * node_aspect,
+ height=node_sizes[: ring + 1].sum(axis=0)[n],
+ clip_on=False,
+ facecolor=standard_color,
+ edgecolor=standard_color,
+ zorder=-ring - 1,
+ )
- if ring == 0:
- ax.text(pos[n][0], pos[n][1], node_labels[n],
- fontsize=node_label_size,
- horizontalalignment='center',
- verticalalignment='center', alpha=alpha)
-
- if node_rings[ring]['sizes'] is not None:
- # Draw reference node as legend
- ax.scatter(0., 0., s=node_sizes[:ring + 1].sum(axis=0).max() ** 2,
- alpha=1., facecolors='none', edgecolors='grey',
- clip_on=False, linewidth=.1, zorder=-ring)
-
- if log_sizes:
- ax.text(0., 0., ' ' * ring + '%.2f' %
- (np.exp(max_sizes[ring]) - 1.),
- fontsize=node_label_size,
- horizontalalignment='left', verticalalignment='center')
else:
- ax.text(0., 0., ' ' * ring + '%.2f' % max_sizes[ring],
- fontsize=node_label_size,
- horizontalalignment='left', verticalalignment='center')
-
- ##
- # Draw edges of different types
- ##
- # First draw small circles as anchorpoints of the curved edges
- for n in G:
- # , transform = ax.transAxes)
- size = standard_size*.3
- c = Circle(pos[n], radius=size, alpha=0., fill=False, linewidth=0., zorder=1)
- ax.add_patch(c)
-
- # avoiding attribute error raised by changes in networkx
- if hasattr(G, 'node'):
- # works with networkx 1.10
- G.node[n]['patch'] = c
- else:
- # works with networkx 2.4
- G.nodes[n]['patch'] = c
-
- # Collect all edge weights to get color scale
- all_links_weights = []
- all_links_edge_weights = []
- for (u, v, d) in G.edges(data=True):
- if u != v:
- if d['outer_edge'] and d['outer_edge_color'] is not None:
- all_links_weights.append(d['outer_edge_color'])
- if d['inner_edge'] and d['inner_edge_color'] is not None:
- all_links_weights.append(d['inner_edge_color'])
- # if d['outer_edge_edge'] and d['outer_edge_edgecolor'] is not None:
- # all_links_edge_weights.append(d['outer_edge_edgecolor'])
- # if d['inner_edge_edge'] and d['inner_edge_edgecolor'] is not None:
- # all_links_edge_weights.append(d['inner_edge_edgecolor'])
-
- if cmap_links is not None and len(all_links_weights) > 0:
- if links_vmin is None:
- links_vmin = np.array(all_links_weights).min()
- if links_vmax is None:
- links_vmax = np.array(all_links_weights).max()
- data_to_rgb_links = pyplot.cm.ScalarMappable(
- norm=None, cmap=pyplot.get_cmap(cmap_links))
- data_to_rgb_links.set_array(np.array(all_links_weights))
- data_to_rgb_links.set_clim(vmin=links_vmin, vmax=links_vmax)
- # Create colorbars for links
-
- # setup colorbar axes.
- if show_colorbar:
- cax_e = pyplot.axes([0.55, ax.figbox.bounds[1] + 0.02, 0.4, 0.025 +
- (len(all_links_edge_weights) == 0) * 0.035],
- frameon=False)
-
- cb_e = pyplot.colorbar(
- data_to_rgb_links, cax=cax_e, orientation='horizontal')
- try:
- cb_e.set_ticks(np.arange(_myround(links_vmin, links_ticks, 'down'),
- _myround(links_vmax, links_ticks, 'up') +
- links_ticks, links_ticks))
- except:
- print ('no ticks given')
+ c = Ellipse(
+ pos[n],
+ width=node_sizes[: ring + 1].sum(axis=0)[n] * node_aspect,
+ height=node_sizes[: ring + 1].sum(axis=0)[n],
+ clip_on=False,
+ facecolor=colors[n],
+ edgecolor=colors[n],
+ zorder=-ring - 1,
+ )
+
+ ax.add_patch(c)
+
+ # avoiding attribute error raised by changes in networkx
+ if hasattr(G, "node"):
+ # works with networkx 1.10
+ G.node[n]["patch"] = c
+ else:
+ # works with networkx 2.4
+ G.nodes[n]["patch"] = c
- cb_e.outline.remove()
- # cb_n.set_ticks()
- cax_e.set_xlabel(
- link_colorbar_label, labelpad=1, fontsize=label_fontsize)
+ if ring == 0:
+ ax.text(
+ pos[n][0],
+ pos[n][1],
+ node_labels[n],
+ fontsize=node_label_size,
+ horizontalalignment="center",
+ verticalalignment="center",
+ alpha=1.0,
+ )
# Draw edges
seen = {}
for (u, v, d) in G.edges(data=True):
+ if d.get("no_links"):
+ d["inner_edge_alpha"] = 1e-8
+ d["outer_edge_alpha"] = 1e-8
if u != v:
- if d['outer_edge']:
+ if d["outer_edge"]:
seen[(u, v)] = draw_edge(ax, u, v, d, seen, arrowstyle, outer_edge=True)
- if d['inner_edge']:
- # if ('oriented' not in d or d['oriented'] == False) and (v, u) not in seen:
- # seen[(u, v)] = draw_edge(ax, u, v, d, seen, outer_edge=False)
- # elif 'oriented' in d and d['oriented'] == (u,v):
- seen[(u, v)] = draw_edge(ax, u, v, d, seen, outer_edge=False)
+ if d["inner_edge"]:
+ seen[(u, v)] = draw_edge(ax, u, v, d, seen, outer_edge=False)
- #pyplot.tight_layout()
pyplot.subplots_adjust(bottom=network_lower_bound)
-[docs]def plot_graph(val_matrix=None,
- var_names=None,
- fig_ax=None,
- figsize=None,
- sig_thres=None,
- link_matrix=None,
- save_name=None,
- link_colorbar_label='MCI',
- node_colorbar_label='auto-MCI',
- link_width=None,
- link_attribute=None,
- node_pos=None,
- arrow_linewidth=30.,
- vmin_edges=-1,
- vmax_edges=1.,
- edge_ticks=.4,
- cmap_edges='RdBu_r',
- vmin_nodes=0,
- vmax_nodes=1.,
- node_ticks=.4,
- cmap_nodes='OrRd',
- node_size=20,
- arrowhead_size=20,
- curved_radius=.2,
- label_fontsize=10,
- alpha=1.,
- node_label_size=10,
- link_label_fontsize=6,
- lag_array=None,
- network_lower_bound=0.2,
- show_colorbar=True,
- ):
- """Creates a network plot.
+[docs]def plot_graph(
+ val_matrix=None,
+ var_names=None,
+ fig_ax=None,
+ figsize=None,
+ sig_thres=None,
+ link_matrix=None,
+ save_name=None,
+ link_colorbar_label="MCI",
+ node_colorbar_label="auto-MCI",
+ link_width=None,
+ link_attribute=None,
+ node_pos=None,
+ arrow_linewidth=10.0,
+ vmin_edges=-1,
+ vmax_edges=1.0,
+ edge_ticks=0.4,
+ cmap_edges="RdBu_r",
+ vmin_nodes=0,
+ vmax_nodes=1.0,
+ node_ticks=0.4,
+ cmap_nodes="OrRd",
+ node_size=0.3,
+ node_aspect=None,
+ arrowhead_size=20,
+ curved_radius=0.2,
+ label_fontsize=10,
+ alpha=1.0,
+ node_label_size=10,
+ link_label_fontsize=10,
+ lag_array=None,
+ network_lower_bound=0.2,
+ show_colorbar=True,
+ inner_edge_style="dashed",
+):
+ """Creates a network plot.
This is still in beta. The network is defined either from True values in
link_matrix, or from thresholding the val_matrix with sig_thres. Nodes
denote variables, straight links contemporaneous dependencies and curved
@@ -1192,7 +1587,6 @@ Source code for tigramite.plotting
dependency in order of absolute magnitude. The network can also be plotted
over a map drawn before on the same axis. Then the node positions can be
supplied in appropriate axis coordinates via node_pos.
-
Parameters
----------
val_matrix : array_like
@@ -1242,11 +1636,13 @@ Source code for tigramite.plotting
Node tick mark interval.
cmap_nodes : str, optional (default: 'OrRd')
Colormap for links.
- node_size : int, optional (default: 20)
+ node_size : int, optional (default: 0.3)
Node size.
+ node_aspect : float, optional (default: None)
+ Ratio between the heigth and width of the varible nodes.
arrowhead_size : int, optional (default: 20)
Size of link arrow head. Passed on to FancyArrowPatch object.
- curved_radius : float, optional (default: 0.2)
+ curved_radius, float, optional (default: 0.2)
Curvature of links. Passed on to FancyArrowPatch object.
label_fontsize : int, optional (default: 10)
Fontsize of colorbar labels.
@@ -1270,12 +1666,26 @@ Source code for tigramite.plotting
else:
fig, ax = fig_ax
- (link_matrix, val_matrix, link_width, link_attribute) = \
- _check_matrices(link_matrix, val_matrix, link_width, link_attribute)
+ (link_matrix, val_matrix, link_width, link_attribute) = _check_matrices(
+ link_matrix, val_matrix, link_width, link_attribute
+ )
N, N, dummy = val_matrix.shape
tau_max = dummy - 1
+ if np.count_nonzero(link_matrix != "") == np.count_nonzero(
+ np.diagonal(link_matrix) != ""
+ ):
+ diagonal = True
+ else:
+ diagonal = False
+
+ if np.count_nonzero(link_matrix == "") == link_matrix.size or diagonal:
+ link_matrix[0, 1, 0] = "---"
+ no_links = True
+ else:
+ no_links = False
+
if var_names is None:
var_names = range(N)
@@ -1286,17 +1696,21 @@ Source code for tigramite.plotting
# Only draw link in one direction among contemp
# Remove lower triangle
link_matrix_upper = np.copy(link_matrix)
- link_matrix_upper[:,:,0] = np.triu(link_matrix_upper[:,:,0])
+ link_matrix_upper[:, :, 0] = np.triu(link_matrix_upper[:, :, 0])
# net = _get_absmax(link_matrix != "")
net = np.any(link_matrix_upper != "", axis=2)
G = nx.DiGraph(net)
+ # This handels Graphs with no links.
+ # nx.draw(G, alpha=0, zorder=-10)
+
node_color = np.zeros(N)
# list of all strengths for color map
all_strengths = []
# Add attributes, contemporaneous and lagged links are handled separately
for (u, v, dic) in G.edges(data=True):
+ dic["no_links"] = no_links
# average lagfunc for link u --> v ANDOR u -- v
if tau_max > 0:
# argmax of absolute maximum
@@ -1314,14 +1728,10 @@ Source code for tigramite.plotting
# sig_thres[u, v][0]) or
# (np.abs(val_matrix[v, u][0]) >=
# sig_thres[v, u][0]))
-
-
- dic['inner_edge'] = link_matrix_upper[u,v,0]
-
- dic['inner_edge_type'] = link_matrix_upper[u,v, 0]
-
- dic['inner_edge_alpha'] = alpha
- dic['inner_edge_color'] = val_matrix[u, v, 0]
+ dic["inner_edge"] = link_matrix_upper[u, v, 0]
+ dic["inner_edge_type"] = link_matrix_upper[u, v, 0]
+ dic["inner_edge_alpha"] = alpha
+ dic["inner_edge_color"] = val_matrix[u, v, 0]
# # value at argmax of average
# if np.abs(val_matrix[u, v][0] - val_matrix[v, u][0]) > .0001:
# print("Contemporaneous I(%d; %d)=%.3f != I(%d; %d)=%.3f" % (
@@ -1334,72 +1744,70 @@ Source code for tigramite.plotting
# val_matrix[v, u][0]]]])).squeeze()
if link_width is None:
- dic['inner_edge_width'] = arrow_linewidth
+ dic["inner_edge_width"] = arrow_linewidth
else:
- dic['inner_edge_width'] = link_width[
- u, v, 0] / link_width.max() * arrow_linewidth
+ dic["inner_edge_width"] = (
+ link_width[u, v, 0] / link_width.max() * arrow_linewidth
+ )
if link_attribute is None:
- dic['inner_edge_attribute'] = None
+ dic["inner_edge_attribute"] = None
else:
- dic['inner_edge_attribute'] = link_attribute[
- u, v, 0]
+ dic["inner_edge_attribute"] = link_attribute[u, v, 0]
# # fraction of nonzero values
- dic['inner_edge_style'] = 'solid'
+ dic["inner_edge_style"] = "solid"
# else:
# dic['inner_edge_style'] = link_style[
# u, v, 0]
- all_strengths.append(dic['inner_edge_color'])
+ all_strengths.append(dic["inner_edge_color"])
if tau_max > 0:
# True if ensemble mean at lags > 0 is nonzero
# dic['outer_edge'] = np.any(
# np.abs(val_matrix[u, v][1:]) >= sig_thres[u, v][1:])
- dic['outer_edge'] = np.any(link_matrix_upper[u,v,1:] != "")
+ dic["outer_edge"] = np.any(link_matrix_upper[u, v, 1:] != "")
else:
- dic['outer_edge'] = False
-
- dic['outer_edge_type'] = link_matrix_upper[u,v, argmax]
+ dic["outer_edge"] = False
+ dic["outer_edge_type"] = link_matrix_upper[u, v, argmax]
- dic['outer_edge_alpha'] = alpha
+ dic["outer_edge_alpha"] = alpha
if link_width is None:
# fraction of nonzero values
- dic['outer_edge_width'] = arrow_linewidth
+ dic["outer_edge_width"] = arrow_linewidth
else:
- dic['outer_edge_width'] = link_width[
- u, v, argmax] / link_width.max() * arrow_linewidth
+ dic["outer_edge_width"] = (
+ link_width[u, v, argmax] / link_width.max() * arrow_linewidth
+ )
if link_attribute is None:
# fraction of nonzero values
- dic['outer_edge_attribute'] = None
+ dic["outer_edge_attribute"] = None
else:
- dic['outer_edge_attribute'] = link_attribute[
- u, v, argmax]
+ dic["outer_edge_attribute"] = link_attribute[u, v, argmax]
# value at argmax of average
- dic['outer_edge_color'] = val_matrix[u, v][argmax]
- all_strengths.append(dic['outer_edge_color'])
+ dic["outer_edge_color"] = val_matrix[u, v][argmax]
+ all_strengths.append(dic["outer_edge_color"])
# Sorted list of significant lags (only if robust wrt
# d['min_ensemble_frac'])
if tau_max > 0:
lags = np.abs(val_matrix[u, v][1:]).argsort()[::-1] + 1
- sig_lags = (np.where(link_matrix_upper[u, v,1:]!="")[0] + 1).tolist()
+ sig_lags = (np.where(link_matrix_upper[u, v, 1:] != "")[0] + 1).tolist()
else:
lags, sig_lags = [], []
if lag_array is not None:
- dic['label'] = str([lag_array[l] for l in lags if l in sig_lags])[1:-1]
+ dic["label"] = str([lag_array[l] for l in lags if l in sig_lags])[1:-1]
else:
- dic['label'] = str([l for l in lags if l in sig_lags])[1:-1]
+ dic["label"] = str([l for l in lags if l in sig_lags])[1:-1]
else:
# Node color is max of average autodependency
node_color[u] = val_matrix[u, v][argmax]
- dic['inner_edge_attribute'] = None
- dic['outer_edge_attribute'] = None
-
+ dic["inner_edge_attribute"] = None
+ dic["outer_edge_attribute"] = None
# dic['outer_edge_edge'] = False
# dic['outer_edge_edgecolor'] = None
@@ -1408,73 +1816,84 @@ Source code for tigramite.plotting
# If no links are present, set value to zero
if len(all_strengths) == 0:
- all_strengths = [0.]
+ all_strengths = [0.0]
if node_pos is None:
pos = nx.circular_layout(deepcopy(G))
-# pos = nx.spring_layout(deepcopy(G))
else:
pos = {}
for i in range(N):
- pos[i] = (node_pos['x'][i], node_pos['y'][i])
+ pos[i] = (node_pos["x"][i], node_pos["y"][i])
if cmap_nodes is None:
node_color = None
- node_rings = {0: {'sizes': None, 'color_array': node_color,
- 'cmap': cmap_nodes, 'vmin': vmin_nodes,
- 'vmax': vmax_nodes, 'ticks': node_ticks,
- 'label': node_colorbar_label, 'colorbar': show_colorbar,
- }
- }
+ node_rings = {
+ 0: {
+ "sizes": None,
+ "color_array": node_color,
+ "cmap": cmap_nodes,
+ "vmin": vmin_nodes,
+ "vmax": vmax_nodes,
+ "ticks": node_ticks,
+ "label": node_colorbar_label,
+ "colorbar": show_colorbar,
+ }
+ }
_draw_network_with_curved_edges(
- fig=fig, ax=ax,
- G=deepcopy(G), pos=pos,
+ fig=fig,
+ ax=ax,
+ G=deepcopy(G),
+ pos=pos,
# dictionary of rings: {0:{'sizes':(N,)-array, 'color_array':(N,)-array
# or None, 'cmap':string,
node_rings=node_rings,
# 'vmin':float or None, 'vmax':float or None, 'label':string or None}}
- node_labels=var_names, node_label_size=node_label_size,
- node_alpha=alpha, standard_size=node_size,
- standard_cmap='OrRd', standard_color='orange',
+ node_labels=var_names,
+ node_label_size=node_label_size,
+ node_alpha=alpha,
+ standard_size=node_size,
+ node_aspect=node_aspect,
+ standard_cmap="OrRd",
+ standard_color="orange",
log_sizes=False,
- cmap_links=cmap_edges, links_vmin=vmin_edges,
- links_vmax=vmax_edges, links_ticks=edge_ticks,
-
+ cmap_links=cmap_edges,
+ links_vmin=vmin_edges,
+ links_vmax=vmax_edges,
+ links_ticks=edge_ticks,
# cmap_links_edges='YlOrRd', links_edges_vmin=-1., links_edges_vmax=1.,
# links_edges_ticks=.2, link_edge_colorbar_label='link_edge',
-
- arrowstyle='simple', arrowhead_size=arrowhead_size,
- curved_radius=curved_radius, label_fontsize=label_fontsize,
+ arrowstyle="simple",
+ arrowhead_size=arrowhead_size,
+ curved_radius=curved_radius,
+ label_fontsize=label_fontsize,
link_label_fontsize=link_label_fontsize,
link_colorbar_label=link_colorbar_label,
network_lower_bound=network_lower_bound,
show_colorbar=show_colorbar,
# label_fraction=label_fraction,
- # inner_edge_style=inner_edge_style
- )
+ )
- # fig.subplots_adjust(left=0.1, right=.9, bottom=.25, top=.95)
- # savestring = os.path.expanduser(save_name)
if save_name is not None:
- pyplot.savefig(save_name)
+ pyplot.savefig(save_name, dpi=300)
else:
return fig, ax
+
def _reverse_patt(patt):
"""Inverts a link pattern"""
- if patt == '':
- return ''
+ if patt == "":
+ return ""
left_mark, middle_mark, right_mark = patt[0], patt[1], patt[2]
- if left_mark == '<':
- new_right_mark = '>'
+ if left_mark == "<":
+ new_right_mark = ">"
else:
new_right_mark = left_mark
- if right_mark == '>':
- new_left_mark = '<'
+ if right_mark == ">":
+ new_left_mark = "<"
else:
new_left_mark = right_mark
@@ -1493,92 +1912,126 @@ Source code for tigramite.plotting
# elif patt == '<--':
# return '-->'
-def _check_matrices(link_matrix, val_matrix, link_width, link_attribute):
+def _check_matrices(link_matrix, val_matrix, link_width, link_attribute):
if link_matrix is None and (val_matrix is None or sig_thres is None):
- raise ValueError("Need to specify either val_matrix together with sig_thres, or link_matrix")
+ raise ValueError(
+ "Need to specify either val_matrix together with sig_thres, or link_matrix"
+ )
if link_matrix is not None:
pass
elif link_matrix is None and sig_thres is not None and val_matrix is not None:
link_matrix = np.abs(val_matrix) >= sig_thres
else:
- raise ValueError("Need to specify either val_matrix together with sig_thres, or link_matrix")
+ raise ValueError(
+ "Need to specify either val_matrix together with sig_thres, or link_matrix"
+ )
- if link_matrix.dtype != '<U3':
+ if link_matrix.dtype != "<U3":
# Transform to new link_matrix data type U3
old_matrix = np.copy(link_matrix)
- link_matrix = np.zeros(old_matrix.shape, dtype='<U3')
+ link_matrix = np.zeros(old_matrix.shape, dtype="<U3")
link_matrix[:] = ""
for i, j, tau in zip(*np.where(old_matrix)):
if tau == 0:
- if old_matrix[j,i,0] == 0:
- link_matrix[i,j,0] = '-->'
- link_matrix[j,i,0] = '<--'
+ if old_matrix[j, i, 0] == 0:
+ link_matrix[i, j, 0] = "-->"
+ link_matrix[j, i, 0] = "<--"
else:
- link_matrix[i,j,0] = 'o-o'
- link_matrix[j,i,0] = 'o-o'
+ link_matrix[i, j, 0] = "o-o"
+ link_matrix[j, i, 0] = "o-o"
else:
- link_matrix[i,j,tau] = '-->'
+ link_matrix[i, j, tau] = "-->"
else:
# print(link_matrix[:,:,0])
- # Assert that link_matrix has valid and consistent lag-zero entries
+ # Assert that link_matrix has valid and consistent lag-zero entries
for i, j, tau in zip(*np.where(link_matrix)):
- if tau == 0:
- if link_matrix[i,j,0] != _reverse_patt(link_matrix[j,i,0]):
- raise ValueError("link_matrix needs to have consistent lag-zero patterns"
- " (eg link_matrix[i,j,0]='-->' requires link_matrix[j,i,0]='<--')")
- if val_matrix is not None and val_matrix[i,j,0] != val_matrix[j,i,0]:
+ if tau == 0:
+ if link_matrix[i, j, 0] != _reverse_patt(link_matrix[j, i, 0]):
+ raise ValueError(
+ "link_matrix needs to have consistent lag-zero patterns (eg"
+ " link_matrix[i,j,0]='-->' requires link_matrix[j,i,0]='<--')"
+ )
+ if (
+ val_matrix is not None
+ and val_matrix[i, j, 0] != val_matrix[j, i, 0]
+ ):
raise ValueError("val_matrix needs to be symmetric for lag-zero")
- if link_width is not None and link_width[i,j,0] != link_width[j,i,0]:
+ if (
+ link_width is not None
+ and link_width[i, j, 0] != link_width[j, i, 0]
+ ):
raise ValueError("link_width needs to be symmetric for lag-zero")
- if link_attribute is not None and link_attribute[i,j,0] != link_attribute[j,i,0]:
- raise ValueError("link_attribute needs to be symmetric for lag-zero")
-
- if link_matrix[i, j, tau] not in ['---', 'o--', '--o', 'o-o', 'o->', '<-o', '-->', '<--', '<->']:
+ if (
+ link_attribute is not None
+ and link_attribute[i, j, 0] != link_attribute[j, i, 0]
+ ):
+ raise ValueError(
+ "link_attribute needs to be symmetric for lag-zero"
+ )
+
+ if link_matrix[i, j, tau] not in [
+ "---",
+ "o--",
+ "--o",
+ "o-o",
+ "o->",
+ "<-o",
+ "-->",
+ "<--",
+ "<->",
+ "x-o",
+ "o-x",
+ "x--",
+ "--x",
+ "x->",
+ "<-x",
+ "x-x",
+ ]:
raise ValueError("Invalid link_matrix entry.")
if val_matrix is None:
- val_matrix = (link_matrix != "").astype('int')
+ val_matrix = (link_matrix != "").astype("int")
- if link_width is not None and not np.all(link_width >= 0.):
+ if link_width is not None and not np.all(link_width >= 0.0):
raise ValueError("link_width must be non-negative")
return link_matrix, val_matrix, link_width, link_attribute
+
[docs]def plot_time_series_graph(
- link_matrix=None,
- val_matrix=None,
- var_names=None,
- fig_ax=None,
- figsize=None,
- sig_thres=None,
- link_colorbar_label='MCI',
- save_name=None,
- link_width=None,
- link_attribute=None,
- arrow_linewidth=20.,
- vmin_edges=-1,
- vmax_edges=1.,
- edge_ticks=.4,
- cmap_edges='RdBu_r',
- order=None,
- node_size=10,
- arrowhead_size=20,
- curved_radius=.2,
- label_fontsize=10,
- alpha=1.,
- node_label_size=10,
- label_space_left=0.1,
- label_space_top=0.,
- network_lower_bound=0.2,
- inner_edge_style='dashed'
- ):
+ link_matrix=None,
+ val_matrix=None,
+ var_names=None,
+ fig_ax=None,
+ figsize=None,
+ sig_thres=None,
+ link_colorbar_label="MCI",
+ save_name=None,
+ link_width=None,
+ link_attribute=None,
+ arrow_linewidth=8,
+ vmin_edges=-1,
+ vmax_edges=1.0,
+ edge_ticks=0.4,
+ cmap_edges="RdBu_r",
+ order=None,
+ node_size=0.1,
+ node_aspect=None,
+ arrowhead_size=20,
+ curved_radius=0.2,
+ label_fontsize=12,
+ alpha=1.0,
+ node_label_size=12,
+ label_space_left=0.1,
+ label_space_top=0.0,
+ network_lower_bound=0.2,
+ inner_edge_style="dashed",
+):
"""Creates a time series graph.
-
This is still in beta. The time series graph's links are colored by
val_matrix.
-
Parameters
----------
val_matrix : array_like
@@ -1614,11 +2067,13 @@ Source code for tigramite.plotting
Link tick mark interval.
cmap_edges : str, optional (default: 'RdBu_r')
Colormap for links.
- node_size : int, optional (default: 20)
+ node_size : int, optional (default: 0.1)
Node size.
+ node_aspect : float, optional (default: None)
+ Ratio between the heigth and width of the varible nodes.
arrowhead_size : int, optional (default: 20)
Size of link arrow head. Passed on to FancyArrowPatch object.
- curved_radius : float, optional (default: 0.2)
+ curved_radius, float, optional (default: 0.2)
Curvature of links. Passed on to FancyArrowPatch object.
label_fontsize : int, optional (default: 10)
Fontsize of colorbar labels.
@@ -1644,13 +2099,20 @@ Source code for tigramite.plotting
else:
fig, ax = fig_ax
- (link_matrix, val_matrix, link_width, link_attribute) = \
- _check_matrices(link_matrix, val_matrix, link_width, link_attribute)
+ (link_matrix, val_matrix, link_width, link_attribute) = _check_matrices(
+ link_matrix, val_matrix, link_width, link_attribute
+ )
N, N, dummy = link_matrix.shape
tau_max = dummy - 1
max_lag = tau_max + 1
+ if np.count_nonzero(link_matrix == "") == link_matrix.size:
+ link_matrix[0, 1, 0] = "---"
+ no_links = True
+ else:
+ no_links = False
+
if var_names is None:
var_names = range(N)
@@ -1675,21 +2137,31 @@ Source code for tigramite.plotting
# Only draw link in one direction among contemp
# Remove lower triangle
link_matrix_tsg = np.copy(link_matrix)
- link_matrix_tsg[:,:,0] = np.triu(link_matrix[:,:,0])
+ link_matrix_tsg[:, :, 0] = np.triu(link_matrix[:, :, 0])
- for i, j, tau in np.column_stack(np.where(link_matrix_tsg)):
+ for i, j, tau in np.column_stack(np.where(link_matrix_tsg)):
for t in range(max_lag):
- if (0 <= translate(i, t - tau) and translate(i, t - tau) % max_lag <= translate(j, t) % max_lag):
-
- tsg[translate(i, t - tau), translate(j, t)] = 1. #val_matrix[i, j, tau]
+ if (
+ 0 <= translate(i, t - tau)
+ and translate(i, t - tau) % max_lag <= translate(j, t) % max_lag
+ ):
+
+ tsg[
+ translate(i, t - tau), translate(j, t)
+ ] = 1.0 # val_matrix[i, j, tau]
tsg_val[translate(i, t - tau), translate(j, t)] = val_matrix[i, j, tau]
- tsg_style[translate(i, t - tau), translate(j, t)] = link_matrix[i, j, tau]
+ tsg_style[translate(i, t - tau), translate(j, t)] = link_matrix[
+ i, j, tau
+ ]
if link_width is not None:
- tsg_width[translate(i, t - tau), translate(j, t)] = link_width[i, j, tau] / link_width.max() * arrow_linewidth
+ tsg_width[translate(i, t - tau), translate(j, t)] = (
+ link_width[i, j, tau] / link_width.max() * arrow_linewidth
+ )
if link_attribute is not None:
- tsg_attr[translate(i, t - tau), translate(j, t)] = link_attribute[i, j, tau]
+ tsg_attr[translate(i, t - tau), translate(j, t)] = link_attribute[
+ i, j, tau
+ ]
- # print(tsg.round(1))
G = nx.DiGraph(tsg)
# node_color = np.zeros(N)
@@ -1697,152 +2169,170 @@ Source code for tigramite.plotting
all_strengths = []
# Add attributes, contemporaneous and lagged links are handled separately
for (u, v, dic) in G.edges(data=True):
-
+ dic["no_links"] = no_links
if u != v:
+ dic["inner_edge"] = False
+ dic["outer_edge"] = True
- dic['inner_edge'] = False
- dic['outer_edge'] = True
+ dic["outer_edge_type"] = tsg_style[u, v]
- dic['outer_edge_type'] = tsg_style[u,v]
-
- dic['outer_edge_alpha'] = alpha
+ dic["outer_edge_alpha"] = alpha
if link_width is None:
# fraction of nonzero values
- dic['outer_edge_width'] = dic['inner_edge_width'] = arrow_linewidth
+ dic["outer_edge_width"] = dic["inner_edge_width"] = arrow_linewidth
else:
- dic['outer_edge_width'] = dic['inner_edge_width'] = tsg_width[u,v]
+ dic["outer_edge_width"] = dic["inner_edge_width"] = tsg_width[u, v]
if link_attribute is None:
- dic['outer_edge_attribute'] = None
+ dic["outer_edge_attribute"] = None
else:
- dic['outer_edge_attribute'] = tsg_attr[u,v]
-
+ dic["outer_edge_attribute"] = tsg_attr[u, v]
+
# value at argmax of average
- dic['outer_edge_color'] = tsg_val[u, v]
+ dic["outer_edge_color"] = tsg_val[u, v]
- all_strengths.append(dic['outer_edge_color'])
- dic['label'] = None
+ all_strengths.append(dic["outer_edge_color"])
+ dic["label"] = None
# If no links are present, set value to zero
if len(all_strengths) == 0:
- all_strengths = [0.]
+ all_strengths = [0.0]
posarray = np.zeros((N * max_lag, 2))
for i in range(N * max_lag):
-
- posarray[i] = np.array([(i % max_lag), (1. - i // max_lag)])
+ posarray[i] = np.array([(i % max_lag), (1.0 - i // max_lag)])
pos_tmp = {}
for i in range(N * max_lag):
# for n in range(N):
# for tau in range(max_lag):
# i = n*N + tau
- pos_tmp[i] = np.array([((i % max_lag) - posarray.min(axis=0)[0]) /
- (posarray.max(axis=0)[0] -
- posarray.min(axis=0)[0]),
- ((1. - i // max_lag) -
- posarray.min(axis=0)[1]) /
- (posarray.max(axis=0)[1] -
- posarray.min(axis=0)[1])])
- pos_tmp[i][np.isnan(pos_tmp[i])] = 0.
+ pos_tmp[i] = np.array(
+ [
+ ((i % max_lag) - posarray.min(axis=0)[0])
+ / (posarray.max(axis=0)[0] - posarray.min(axis=0)[0]),
+ ((1.0 - i // max_lag) - posarray.min(axis=0)[1])
+ / (posarray.max(axis=0)[1] - posarray.min(axis=0)[1]),
+ ]
+ )
+ pos_tmp[i][np.isnan(pos_tmp[i])] = 0.0
pos = {}
for n in range(N):
for tau in range(max_lag):
pos[n * max_lag + tau] = pos_tmp[order[n] * max_lag + tau]
- node_rings = {0: {'sizes': None, 'color_array': None,
- 'label': '', 'colorbar': False,
- }
- }
+ node_rings = {
+ 0: {"sizes": None, "color_array": None, "label": "", "colorbar": False,}
+ }
- # ] for v in range(max_lag)]
- node_labels = ['' for i in range(N * max_lag)]
+ node_labels = ["" for i in range(N * max_lag)]
_draw_network_with_curved_edges(
- fig=fig, ax=ax,
- G=deepcopy(G), pos=pos,
+ fig=fig,
+ ax=ax,
+ G=deepcopy(G),
+ pos=pos,
node_rings=node_rings,
- node_labels=node_labels, node_label_size=node_label_size,
- node_alpha=alpha, standard_size=node_size,
- standard_cmap='OrRd', standard_color='lightgrey',
+ node_labels=node_labels,
+ node_label_size=node_label_size,
+ node_alpha=alpha,
+ standard_size=node_size,
+ node_aspect=node_aspect,
+ standard_cmap="OrRd",
+ standard_color="lightgrey",
log_sizes=False,
- cmap_links=cmap_edges, links_vmin=vmin_edges,
- links_vmax=vmax_edges, links_ticks=edge_ticks,
- arrowstyle='simple', arrowhead_size=arrowhead_size,
- curved_radius=curved_radius, label_fontsize=label_fontsize,
- label_fraction=.5,
- link_colorbar_label=link_colorbar_label, inner_edge_curved=True,
+ cmap_links=cmap_edges,
+ links_vmin=vmin_edges,
+ links_vmax=vmax_edges,
+ links_ticks=edge_ticks,
+ arrowstyle="simple",
+ arrowhead_size=arrowhead_size,
+ curved_radius=curved_radius,
+ label_fontsize=label_fontsize,
+ label_fraction=0.5,
+ link_colorbar_label=link_colorbar_label,
+ inner_edge_curved=True,
network_lower_bound=network_lower_bound,
- inner_edge_style=inner_edge_style
- )
+ inner_edge_style=inner_edge_style,
+ )
for i in range(N):
- trans = transforms.blended_transform_factory(
- fig.transFigure, ax.transData)
- ax.text(label_space_left, pos[order[i] * max_lag][1],
- '%s' % str(var_names[order[i]]), fontsize=label_fontsize,
- horizontalalignment='left', verticalalignment='center',
- transform=trans)
+ trans = transforms.blended_transform_factory(fig.transFigure, ax.transData)
+ ax.text(
+ label_space_left,
+ pos[order[i] * max_lag][1],
+ f"{var_names[order[i]]}",
+ fontsize=label_fontsize,
+ horizontalalignment="left",
+ verticalalignment="center",
+ transform=trans,
+ )
for tau in np.arange(max_lag - 1, -1, -1):
- trans = transforms.blended_transform_factory(
- ax.transData, fig.transFigure)
+ trans = transforms.blended_transform_factory(ax.transData, fig.transFigure)
if tau == max_lag - 1:
- ax.text(pos[tau][0], 1.-label_space_top, r'$t$',
- fontsize=int(label_fontsize*0.7),
- horizontalalignment='center',
- verticalalignment='top', transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t$",
+ fontsize=int(label_fontsize * 0.8),
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
else:
- ax.text(pos[tau][0], 1.-label_space_top,
- r'$t-%s$' % str(max_lag - tau - 1),
- fontsize=int(label_fontsize*0.7),
- horizontalalignment='center', verticalalignment='top',
- transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t-%s$" % str(max_lag - tau - 1),
+ fontsize=int(label_fontsize * 0.8),
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
- # fig.subplots_adjust(left=0.1, right=.98, bottom=.25, top=.9)
- # savestring = os.path.expanduser(save_name)
if save_name is not None:
pyplot.savefig(save_name, dpi=300)
else:
return fig, ax
+
[docs]def plot_mediation_time_series_graph(
- path_node_array,
- tsg_path_val_matrix,
- var_names=None,
- fig_ax=None,
- figsize=None,
- link_colorbar_label='link coeff. (edge color)',
- node_colorbar_label='MCE (node color)',
- save_name=None,
- link_width=None,
- arrow_linewidth=20.,
- vmin_edges=-1,
- vmax_edges=1.,
- edge_ticks=.4,
- cmap_edges='RdBu_r',
- order=None,
- vmin_nodes=-1.,
- vmax_nodes=1.,
- node_ticks=.4,
- cmap_nodes='RdBu_r',
- node_size=10,
- arrowhead_size=20,
- curved_radius=.2,
- label_fontsize=10,
- alpha=1.,
- node_label_size=10,
- label_space_left=0.1,
- label_space_top=0.,
- network_lower_bound=0.2
- ):
+ path_node_array,
+ tsg_path_val_matrix,
+ var_names=None,
+ fig_ax=None,
+ figsize=None,
+ link_colorbar_label="link coeff. (edge color)",
+ node_colorbar_label="MCE (node color)",
+ save_name=None,
+ link_width=None,
+ arrow_linewidth=8,
+ vmin_edges=-1,
+ vmax_edges=1.0,
+ edge_ticks=0.4,
+ cmap_edges="RdBu_r",
+ order=None,
+ vmin_nodes=-1.0,
+ vmax_nodes=1.0,
+ node_ticks=0.4,
+ cmap_nodes="RdBu_r",
+ node_size=0.1,
+ node_aspect=None,
+ arrowhead_size=20,
+ curved_radius=0.2,
+ label_fontsize=12,
+ alpha=1.0,
+ node_label_size=12,
+ label_space_left=0.1,
+ label_space_top=0.0,
+ network_lower_bound=0.2,
+):
"""Creates a mediation time series graph plot.
-
This is still in beta. The time series graph's links are colored by
val_matrix.
-
Parameters
----------
tsg_path_val_matrix : array_like
@@ -1884,11 +2374,13 @@ Source code for tigramite.plotting
Node tick mark interval.
cmap_nodes : str, optional (default: 'OrRd')
Colormap for links.
- node_size : int, optional (default: 20)
+ node_size : int, optional (default: 0.1)
Node size.
+ node_aspect : float, optional (default: None)
+ Ratio between the heigth and width of the varible nodes.
arrowhead_size : int, optional (default: 20)
Size of link arrow head. Passed on to FancyArrowPatch object.
- curved_radius : float, optional (default: 0.2)
+ curved_radius, float, optional (default: 0.2)
Curvature of links. Passed on to FancyArrowPatch object.
label_fontsize : int, optional (default: 10)
Fontsize of colorbar labels.
@@ -1918,7 +2410,7 @@ Source code for tigramite.plotting
else:
fig, ax = fig_ax
- if link_width is not None and not np.all(link_width >= 0.):
+ if link_width is not None and not np.all(link_width >= 0.0):
raise ValueError("link_width must be non-negative")
if order is None:
@@ -1930,6 +2422,19 @@ Source code for tigramite.plotting
def translate(row, lag):
return row * max_lag + lag
+ if np.count_nonzero(tsg_path_val_matrix) == np.count_nonzero(
+ np.diagonal(tsg_path_val_matrix)
+ ):
+ diagonal = True
+ else:
+ diagonal = False
+
+ if np.count_nonzero(tsg_path_val_matrix) == tsg_path_val_matrix.size or diagonal:
+ tsg_path_val_matrix[0, 1] = 1
+ no_links = True
+ else:
+ no_links = False
+
# Define graph links by absolute maximum (positive or negative like for
# partial correlation)
tsg = tsg_path_val_matrix
@@ -1942,34 +2447,33 @@ Source code for tigramite.plotting
all_strengths = []
# Add attributes, contemporaneous and lagged links are handled separately
for (u, v, dic) in G.edges(data=True):
-
- dic['outer_edge_attribute'] = None
+ dic["no_links"] = no_links
+ dic["outer_edge_attribute"] = None
if u != v:
if u % max_lag == v % max_lag:
- dic['inner_edge'] = True
- dic['outer_edge'] = False
+ dic["inner_edge"] = True
+ dic["outer_edge"] = False
else:
- dic['inner_edge'] = False
- dic['outer_edge'] = True
+ dic["inner_edge"] = False
+ dic["outer_edge"] = True
- dic['inner_edge_alpha'] = alpha
- dic['inner_edge_color'] = _get_absmax(
- np.array([[[tsg[u, v],
- tsg[v, u]]]])
+ dic["inner_edge_alpha"] = alpha
+ dic["inner_edge_color"] = _get_absmax(
+ np.array([[[tsg[u, v], tsg[v, u]]]])
).squeeze()
- dic['inner_edge_width'] = arrow_linewidth
- all_strengths.append(dic['inner_edge_color'])
+ dic["inner_edge_width"] = arrow_linewidth
+ all_strengths.append(dic["inner_edge_color"])
- dic['outer_edge_alpha'] = alpha
+ dic["outer_edge_alpha"] = alpha
- dic['outer_edge_width'] = arrow_linewidth
+ dic["outer_edge_width"] = arrow_linewidth
# value at argmax of average
- dic['outer_edge_color'] = tsg[u, v]
- all_strengths.append(dic['outer_edge_color'])
- dic['label'] = None
+ dic["outer_edge_color"] = tsg[u, v]
+ all_strengths.append(dic["outer_edge_color"])
+ dic["label"] = None
# dic['outer_edge_edge'] = False
# dic['outer_edge_edgecolor'] = None
@@ -1978,26 +2482,26 @@ Source code for tigramite.plotting
# If no links are present, set value to zero
if len(all_strengths) == 0:
- all_strengths = [0.]
+ all_strengths = [0.0]
posarray = np.zeros((N * max_lag, 2))
for i in range(N * max_lag):
-
- posarray[i] = np.array([(i % max_lag), (1. - i // max_lag)])
+ posarray[i] = np.array([(i % max_lag), (1.0 - i // max_lag)])
pos_tmp = {}
for i in range(N * max_lag):
# for n in range(N):
# for tau in range(max_lag):
# i = n*N + tau
- pos_tmp[i] = np.array([((i % max_lag) - posarray.min(axis=0)[0]) /
- (posarray.max(axis=0)[0] -
- posarray.min(axis=0)[0]),
- ((1. - i // max_lag) -
- posarray.min(axis=0)[1]) /
- (posarray.max(axis=0)[1] -
- posarray.min(axis=0)[1])])
- pos_tmp[i][np.isnan(pos_tmp[i])] = 0.
+ pos_tmp[i] = np.array(
+ [
+ ((i % max_lag) - posarray.min(axis=0)[0])
+ / (posarray.max(axis=0)[0] - posarray.min(axis=0)[0]),
+ ((1.0 - i // max_lag) - posarray.min(axis=0)[1])
+ / (posarray.max(axis=0)[1] - posarray.min(axis=0)[1]),
+ ]
+ )
+ pos_tmp[i][np.isnan(pos_tmp[i])] = 0.0
pos = {}
for n in range(N):
@@ -2006,70 +2510,96 @@ Source code for tigramite.plotting
node_color = np.zeros(N * max_lag)
for inet, n in enumerate(range(0, N * max_lag, max_lag)):
- node_color[n:n+max_lag] = path_node_array[inet]
+ node_color[n : n + max_lag] = path_node_array[inet]
# node_rings = {0: {'sizes': None, 'color_array': color_array,
# 'label': '', 'colorbar': False,
# }
# }
- node_rings = {0: {'sizes': None, 'color_array': node_color,
- 'cmap': cmap_nodes, 'vmin': vmin_nodes,
- 'vmax': vmax_nodes, 'ticks': node_ticks,
- 'label': node_colorbar_label, 'colorbar': True,
- }
- }
+ node_rings = {
+ 0: {
+ "sizes": None,
+ "color_array": node_color,
+ "cmap": cmap_nodes,
+ "vmin": vmin_nodes,
+ "vmax": vmax_nodes,
+ "ticks": node_ticks,
+ "label": node_colorbar_label,
+ "colorbar": True,
+ }
+ }
# ] for v in range(max_lag)]
- node_labels = ['' for i in range(N * max_lag)]
+ node_labels = ["" for i in range(N * max_lag)]
_draw_network_with_curved_edges(
- fig=fig, ax=ax,
- G=deepcopy(G), pos=pos,
+ fig=fig,
+ ax=ax,
+ G=deepcopy(G),
+ pos=pos,
# dictionary of rings: {0:{'sizes':(N,)-array, 'color_array':(N,)-array
# or None, 'cmap':string,
node_rings=node_rings,
# 'vmin':float or None, 'vmax':float or None, 'label':string or None}}
- node_labels=node_labels, node_label_size=node_label_size,
- node_alpha=alpha, standard_size=node_size,
- standard_cmap='OrRd', standard_color='grey',
+ node_labels=node_labels,
+ node_label_size=node_label_size,
+ node_alpha=alpha,
+ standard_size=node_size,
+ node_aspect=node_aspect,
+ standard_cmap="OrRd",
+ standard_color="grey",
log_sizes=False,
- cmap_links=cmap_edges, links_vmin=vmin_edges,
- links_vmax=vmax_edges, links_ticks=edge_ticks,
-
+ cmap_links=cmap_edges,
+ links_vmin=vmin_edges,
+ links_vmax=vmax_edges,
+ links_ticks=edge_ticks,
# cmap_links_edges='YlOrRd', links_edges_vmin=-1., links_edges_vmax=1.,
# links_edges_ticks=.2, link_edge_colorbar_label='link_edge',
-
- arrowstyle='simple', arrowhead_size=arrowhead_size,
- curved_radius=curved_radius, label_fontsize=label_fontsize,
- label_fraction=.5,
- link_colorbar_label=link_colorbar_label, inner_edge_curved=True,
+ arrowhead_size=arrowhead_size,
+ curved_radius=curved_radius,
+ label_fontsize=label_fontsize,
+ label_fraction=0.5,
+ link_colorbar_label=link_colorbar_label,
+ inner_edge_curved=True,
network_lower_bound=network_lower_bound
# inner_edge_style=inner_edge_style
- )
+ )
for i in range(N):
- trans = transforms.blended_transform_factory(
- fig.transFigure, ax.transData)
- ax.text(label_space_left, pos[order[i] * max_lag][1],
- '%s' % str(var_names[order[i]]), fontsize=label_fontsize,
- horizontalalignment='left', verticalalignment='center',
- transform=trans)
+ trans = transforms.blended_transform_factory(fig.transFigure, ax.transData)
+ ax.text(
+ label_space_left,
+ pos[order[i] * max_lag][1],
+ "%s" % str(var_names[order[i]]),
+ fontsize=label_fontsize,
+ horizontalalignment="left",
+ verticalalignment="center",
+ transform=trans,
+ )
for tau in np.arange(max_lag - 1, -1, -1):
- trans = transforms.blended_transform_factory(
- ax.transData, fig.transFigure)
+ trans = transforms.blended_transform_factory(ax.transData, fig.transFigure)
if tau == max_lag - 1:
- ax.text(pos[tau][0], 1.-label_space_top, r'$t$',
- fontsize=label_fontsize,
- horizontalalignment='center',
- verticalalignment='top', transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t$",
+ fontsize=label_fontsize,
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
else:
- ax.text(pos[tau][0], 1.-label_space_top,
- r'$t-%s$' % str(max_lag - tau - 1),
- fontsize=label_fontsize,
- horizontalalignment='center', verticalalignment='top',
- transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t-%s$" % str(max_lag - tau - 1),
+ fontsize=label_fontsize,
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
# fig.subplots_adjust(left=0.1, right=.98, bottom=.25, top=.9)
# savestring = os.path.expanduser(save_name)
@@ -2078,38 +2608,39 @@ Source code for tigramite.plotting
else:
pyplot.show()
+
[docs]def plot_mediation_graph(
- path_val_matrix,
- path_node_array=None,
- var_names=None,
- fig_ax=None,
- figsize=None,
- save_name=None,
- link_colorbar_label='link coeff. (edge color)',
- node_colorbar_label='MCE (node color)',
- link_width=None,
- node_pos=None,
- arrow_linewidth=30.,
- vmin_edges=-1,
- vmax_edges=1.,
- edge_ticks=.4,
- cmap_edges='RdBu_r',
- vmin_nodes=-1.,
- vmax_nodes=1.,
- node_ticks=.4,
- cmap_nodes='RdBu_r',
- node_size=20,
- arrowhead_size=20,
- curved_radius=.2,
- label_fontsize=10,
- lag_array=None,
- alpha=1.,
- node_label_size=10,
- link_label_fontsize=6,
- network_lower_bound=0.2,
- ):
+ path_val_matrix,
+ path_node_array=None,
+ var_names=None,
+ fig_ax=None,
+ figsize=None,
+ save_name=None,
+ link_colorbar_label="link coeff. (edge color)",
+ node_colorbar_label="MCE (node color)",
+ link_width=None,
+ node_pos=None,
+ arrow_linewidth=10.0,
+ vmin_edges=-1,
+ vmax_edges=1.0,
+ edge_ticks=0.4,
+ cmap_edges="RdBu_r",
+ vmin_nodes=-1.0,
+ vmax_nodes=1.0,
+ node_ticks=0.4,
+ cmap_nodes="RdBu_r",
+ node_size=0.3,
+ node_aspect=None,
+ arrowhead_size=20,
+ curved_radius=0.2,
+ label_fontsize=10,
+ lag_array=None,
+ alpha=1.0,
+ node_label_size=10,
+ link_label_fontsize=10,
+ network_lower_bound=0.2,
+):
"""Creates a network plot visualizing the pathways of a mediation analysis.
-
This is still in beta. The network is defined from non-zero entries in
``path_val_matrix``. Nodes denote variables, straight links contemporaneous
dependencies and curved arrows lagged dependencies. The node color denotes
@@ -2118,7 +2649,6 @@ Source code for tigramite.plotting
significant dependency in order of absolute magnitude. The network can also
be plotted over a map drawn before on the same axis. Then the node positions
can be supplied in appropriate axis coordinates via node_pos.
-
Parameters
----------
path_val_matrix : array_like
@@ -2162,11 +2692,13 @@ Source code for tigramite.plotting
Node tick mark interval.
cmap_nodes : str, optional (default: 'OrRd')
Colormap for links.
- node_size : int, optional (default: 20)
+ node_size : int, optional (default: 0.3)
Node size.
+ node_aspect : float, optional (default: None)
+ Ratio between the heigth and width of the varible nodes.
arrowhead_size : int, optional (default: 20)
Size of link arrow head. Passed on to FancyArrowPatch object.
- curved_radius : float, optional (default: 0.2)
+ curved_radius, float, optional (default: 0.2)
Curvature of links. Passed on to FancyArrowPatch object.
label_fontsize : int, optional (default: 10)
Fontsize of colorbar labels.
@@ -2189,19 +2721,30 @@ Source code for tigramite.plotting
else:
fig, ax = fig_ax
- if link_width is not None and not np.all(link_width >= 0.):
+ if link_width is not None and not np.all(link_width >= 0.0):
raise ValueError("link_width must be non-negative")
N, N, dummy = val_matrix.shape
tau_max = dummy - 1
+ if np.count_nonzero(val_matrix) == np.count_nonzero(np.diagonal(val_matrix)):
+ diagonal = True
+ else:
+ diagonal = False
+
+ if np.count_nonzero(val_matrix) == val_matrix.size or diagonal:
+ val_matrix[0, 1, 0] = 1
+ no_links = True
+ else:
+ no_links = False
+
if var_names is None:
var_names = range(N)
# Define graph links by absolute maximum (positive or negative like for
# partial correlation)
# val_matrix[np.abs(val_matrix) < sig_thres] = 0.
- link_matrix = val_matrix != 0.
+ link_matrix = val_matrix != 0.0
net = _get_absmax(val_matrix)
G = nx.DiGraph(net)
@@ -2210,8 +2753,8 @@ Source code for tigramite.plotting
all_strengths = []
# Add attributes, contemporaneous and lagged links are handled separately
for (u, v, dic) in G.edges(data=True):
- dic['outer_edge_attribute'] = None
-
+ dic["outer_edge_attribute"] = None
+ dic["no_links"] = no_links
# average lagfunc for link u --> v ANDOR u -- v
if tau_max > 0:
# argmax of absolute maximum
@@ -2228,56 +2771,60 @@ Source code for tigramite.plotting
# sig_thres[u, v][0]) or
# (np.abs(val_matrix[v, u][0]) >=
# sig_thres[v, u][0]))
- dic['inner_edge'] = (link_matrix[u,v,0] or link_matrix[v,u,0])
- dic['inner_edge_alpha'] = alpha
+ dic["inner_edge"] = link_matrix[u, v, 0] or link_matrix[v, u, 0]
+ dic["inner_edge_alpha"] = alpha
# value at argmax of average
- if np.abs(val_matrix[u, v][0] - val_matrix[v, u][0]) > .0001:
- print("Contemporaneous I(%d; %d)=%.3f != I(%d; %d)=%.3f" % (
- u, v, val_matrix[u, v][0], v, u, val_matrix[v, u][0]) +
- " due to conditions, finite sample effects or "
- "masking, here edge color = "
- "larger (absolute) value.")
- dic['inner_edge_color'] = _get_absmax(
- np.array([[[val_matrix[u, v][0],
- val_matrix[v, u][0]]]])).squeeze()
+ if np.abs(val_matrix[u, v][0] - val_matrix[v, u][0]) > 0.0001:
+ print(
+ "Contemporaneous I(%d; %d)=%.3f != I(%d; %d)=%.3f"
+ % (u, v, val_matrix[u, v][0], v, u, val_matrix[v, u][0])
+ + " due to conditions, finite sample effects or "
+ "masking, here edge color = "
+ "larger (absolute) value."
+ )
+ dic["inner_edge_color"] = _get_absmax(
+ np.array([[[val_matrix[u, v][0], val_matrix[v, u][0]]]])
+ ).squeeze()
if link_width is None:
- dic['inner_edge_width'] = arrow_linewidth
+ dic["inner_edge_width"] = arrow_linewidth
else:
- dic['inner_edge_width'] = link_width[
- u, v, 0] / link_width.max() * arrow_linewidth
+ dic["inner_edge_width"] = (
+ link_width[u, v, 0] / link_width.max() * arrow_linewidth
+ )
- all_strengths.append(dic['inner_edge_color'])
+ all_strengths.append(dic["inner_edge_color"])
if tau_max > 0:
# True if ensemble mean at lags > 0 is nonzero
# dic['outer_edge'] = np.any(
# np.abs(val_matrix[u, v][1:]) >= sig_thres[u, v][1:])
- dic['outer_edge'] = np.any(link_matrix[u,v,1:])
+ dic["outer_edge"] = np.any(link_matrix[u, v, 1:])
else:
- dic['outer_edge'] = False
- dic['outer_edge_alpha'] = alpha
+ dic["outer_edge"] = False
+ dic["outer_edge_alpha"] = alpha
if link_width is None:
# fraction of nonzero values
- dic['outer_edge_width'] = arrow_linewidth
+ dic["outer_edge_width"] = arrow_linewidth
else:
- dic['outer_edge_width'] = link_width[
- u, v, argmax] / link_width.max() * arrow_linewidth
+ dic["outer_edge_width"] = (
+ link_width[u, v, argmax] / link_width.max() * arrow_linewidth
+ )
# value at argmax of average
- dic['outer_edge_color'] = val_matrix[u, v][argmax]
- all_strengths.append(dic['outer_edge_color'])
+ dic["outer_edge_color"] = val_matrix[u, v][argmax]
+ all_strengths.append(dic["outer_edge_color"])
# Sorted list of significant lags (only if robust wrt
# d['min_ensemble_frac'])
if tau_max > 0:
lags = np.abs(val_matrix[u, v][1:]).argsort()[::-1] + 1
- sig_lags = (np.where(link_matrix[u, v,1:])[0] + 1).tolist()
+ sig_lags = (np.where(link_matrix[u, v, 1:])[0] + 1).tolist()
else:
lags, sig_lags = [], []
if lag_array is not None:
- dic['label'] = str([lag_array[l] for l in lags if l in sig_lags])[1:-1]
+ dic["label"] = str([lag_array[l] for l in lags if l in sig_lags])[1:-1]
else:
- dic['label'] = str([l for l in lags if l in sig_lags])[1:-1]
+ dic["label"] = str([l for l in lags if l in sig_lags])[1:-1]
else:
# Node color is max of average autodependency
node_color[u] = val_matrix[u, v][argmax]
@@ -2291,48 +2838,61 @@ Source code for tigramite.plotting
# print node_color
# If no links are present, set value to zero
if len(all_strengths) == 0:
- all_strengths = [0.]
+ all_strengths = [0.0]
if node_pos is None:
pos = nx.circular_layout(deepcopy(G))
-# pos = nx.spring_layout(deepcopy(G))
+ # pos = nx.spring_layout(deepcopy(G))
else:
pos = {}
for i in range(N):
- pos[i] = (node_pos['x'][i], node_pos['y'][i])
-
- node_rings = {0: {'sizes': None, 'color_array': node_color,
- 'cmap': cmap_nodes, 'vmin': vmin_nodes,
- 'vmax': vmax_nodes, 'ticks': node_ticks,
- 'label': node_colorbar_label, 'colorbar': True,
- }
- }
+ pos[i] = (node_pos["x"][i], node_pos["y"][i])
+
+ node_rings = {
+ 0: {
+ "sizes": None,
+ "color_array": node_color,
+ "cmap": cmap_nodes,
+ "vmin": vmin_nodes,
+ "vmax": vmax_nodes,
+ "ticks": node_ticks,
+ "label": node_colorbar_label,
+ "colorbar": True,
+ }
+ }
_draw_network_with_curved_edges(
- fig=fig, ax=ax,
- G=deepcopy(G), pos=pos,
+ fig=fig,
+ ax=ax,
+ G=deepcopy(G),
+ pos=pos,
# dictionary of rings: {0:{'sizes':(N,)-array, 'color_array':(N,)-array
# or None, 'cmap':string,
node_rings=node_rings,
# 'vmin':float or None, 'vmax':float or None, 'label':string or None}}
- node_labels=var_names, node_label_size=node_label_size,
- node_alpha=alpha, standard_size=node_size,
- standard_cmap='OrRd', standard_color='orange',
+ node_labels=var_names,
+ node_label_size=node_label_size,
+ node_alpha=alpha,
+ standard_size=node_size,
+ node_aspect=node_aspect,
+ standard_cmap="OrRd",
+ standard_color="orange",
log_sizes=False,
- cmap_links=cmap_edges, links_vmin=vmin_edges,
- links_vmax=vmax_edges, links_ticks=edge_ticks,
-
+ cmap_links=cmap_edges,
+ links_vmin=vmin_edges,
+ links_vmax=vmax_edges,
+ links_ticks=edge_ticks,
# cmap_links_edges='YlOrRd', links_edges_vmin=-1., links_edges_vmax=1.,
# links_edges_ticks=.2, link_edge_colorbar_label='link_edge',
-
- arrowstyle='simple', arrowhead_size=arrowhead_size,
- curved_radius=curved_radius, label_fontsize=label_fontsize,
+ arrowhead_size=arrowhead_size,
+ curved_radius=curved_radius,
+ label_fontsize=label_fontsize,
link_label_fontsize=link_label_fontsize,
link_colorbar_label=link_colorbar_label,
network_lower_bound=network_lower_bound,
# label_fraction=label_fraction,
# inner_edge_style=inner_edge_style
- )
+ )
# fig.subplots_adjust(left=0.1, right=.9, bottom=.25, top=.95)
# savestring = os.path.expanduser(save_name)
@@ -2341,27 +2901,25 @@ Source code for tigramite.plotting
else:
pyplot.show()
+
#
# Functions to plot time series graphs from links including ancestors
#
[docs]def plot_tsg(links, X, Y, Z=None, anc_x=None, anc_y=None, anc_xy=None):
"""Plots TSG that is input in format (N*max_lag, N*max_lag).
-
- Compared to the tigramite plotting function here links
- X^i_{t-tau} --> X^j_t can be missing for different t'. Helpful to
- visualize the conditioned TSG.
+ Compared to the tigramite plotting function here links
+ X^i_{t-tau} --> X^j_t can be missing for different t'. Helpful to
+ visualize the conditioned TSG.
"""
def varlag2node(var, lag):
"""Translate from (var, lag) notation to node in TSG.
-
lag must be <= 0.
"""
return var * max_lag + lag
def node2varlag(node):
"""Translate from node in TSG to (var, -tau) notation.
-
Here tau is <= 0.
"""
var = node // max_lag
@@ -2370,7 +2928,6 @@ Source code for tigramite.plotting
def _links_to_tsg(link_coeffs, max_lag=None):
"""Transform link_coeffs to time series graph.
-
TSG is of shape (N*max_lag, N*max_lag).
"""
N = len(link_coeffs)
@@ -2390,22 +2947,22 @@ Source code for tigramite.plotting
tau = abs(lag)
coeff = link_props[1]
# func = link_props[2]
- if coeff != 0.:
+ if coeff != 0.0:
for t in range(max_lag):
- if (0 <= varlag2node(i, t - tau) and
- varlag2node(i, t - tau) % max_lag
- <= varlag2node(j, t) % max_lag):
- tsg[varlag2node(i, t - tau),
- varlag2node(j, t)] = 1.
+ if (
+ 0 <= varlag2node(i, t - tau)
+ and varlag2node(i, t - tau) % max_lag
+ <= varlag2node(j, t) % max_lag
+ ):
+ tsg[varlag2node(i, t - tau), varlag2node(j, t)] = 1.0
return tsg
- color_list = ['lightgrey', 'grey', 'black', 'red', 'blue', 'orange']
+ color_list = ["lightgrey", "grey", "black", "red", "blue", "orange"]
listcmap = ListedColormap(color_list)
N = len(links)
-
min_lag_links, max_lag_links = pp._get_minmax_lag(links)
max_lag = max_lag_links
@@ -2415,8 +2972,7 @@ Source code for tigramite.plotting
max_lag = max(max_lag, abs(anc[1]))
if Z is not None:
for anc in Z:
- max_lag = max(max_lag, abs(anc[1]))
-
+ max_lag = max(max_lag, abs(anc[1]))
if anc_x is not None:
for anc in anc_x:
@@ -2434,46 +2990,45 @@ Source code for tigramite.plotting
G = nx.DiGraph(tsg)
- figsize=(3, 3)
- link_colorbar_label='MCI'
- arrow_linewidth=20.
- vmin_edges=-1
- vmax_edges=1.
- edge_ticks=.4
- cmap_edges='RdBu_r'
- order=None
- node_size=10
- arrowhead_size=20
- curved_radius=.2
- label_fontsize=10
- alpha=1.
- node_label_size=10
- label_space_left=0.1
- label_space_top=0.
- network_lower_bound=0.2
- inner_edge_style='dashed'
-
-
- node_color = np.ones(N * max_lag) #, dtype = 'object')
+ figsize = (3, 3)
+ link_colorbar_label = "MCI"
+ arrow_linewidth = 20.0
+ vmin_edges = -1
+ vmax_edges = 1.0
+ edge_ticks = 0.4
+ cmap_edges = "RdBu_r"
+ order = None
+ node_size = 10
+ arrowhead_size = 20
+ curved_radius = 0.2
+ label_fontsize = 10
+ alpha = 1.0
+ node_label_size = 10
+ label_space_left = 0.1
+ label_space_top = 0.0
+ network_lower_bound = 0.2
+ inner_edge_style = "dashed"
+
+ node_color = np.ones(N * max_lag) # , dtype = 'object')
node_color[:] = 0
if anc_x is not None:
- for n in [varlag2node(itau[0], max_lag-1 + itau[1]) for itau in anc_x]:
+ for n in [varlag2node(itau[0], max_lag - 1 + itau[1]) for itau in anc_x]:
node_color[n] = 3
if anc_y is not None:
- for n in [varlag2node(itau[0], max_lag-1 + itau[1]) for itau in anc_y]:
+ for n in [varlag2node(itau[0], max_lag - 1 + itau[1]) for itau in anc_y]:
node_color[n] = 4
if anc_xy is not None:
- for n in [varlag2node(itau[0], max_lag-1 + itau[1]) for itau in anc_xy]:
+ for n in [varlag2node(itau[0], max_lag - 1 + itau[1]) for itau in anc_xy]:
node_color[n] = 5
for x in X:
- node_color[varlag2node(x[0], max_lag-1 + x[1])] = 2
+ node_color[varlag2node(x[0], max_lag - 1 + x[1])] = 2
for y in Y:
- node_color[varlag2node(y[0], max_lag-1 + y[1])] = 2
+ node_color[varlag2node(y[0], max_lag - 1 + y[1])] = 2
if Z is not None:
for z in Z:
- node_color[varlag2node(z[0], max_lag-1 + z[1])] = 1
+ node_color[varlag2node(z[0], max_lag - 1 + z[1])] = 1
fig = pyplot.figure(figsize=figsize)
ax = fig.add_subplot(111, frame_on=False)
@@ -2486,247 +3041,155 @@ Source code for tigramite.plotting
for (u, v, dic) in G.edges(data=True):
if u != v:
if tsg[u, v] and tsg[v, u]:
- dic['inner_edge'] = True
- dic['outer_edge'] = False
+ dic["inner_edge"] = True
+ dic["outer_edge"] = False
else:
- dic['inner_edge'] = False
- dic['outer_edge'] = True
+ dic["inner_edge"] = False
+ dic["outer_edge"] = True
- dic['inner_edge_alpha'] = alpha
- dic['inner_edge_color'] = tsg[u, v]
+ dic["inner_edge_alpha"] = alpha
+ dic["inner_edge_color"] = tsg[u, v]
- dic['inner_edge_width'] = arrow_linewidth
- dic['inner_edge_attribute'] = dic['outer_edge_attribute'] = None
+ dic["inner_edge_width"] = arrow_linewidth
+ dic["inner_edge_attribute"] = dic["outer_edge_attribute"] = None
- all_strengths.append(dic['inner_edge_color'])
- dic['outer_edge_alpha'] = alpha
- dic['outer_edge_width'] = dic['inner_edge_width'] = arrow_linewidth
+ all_strengths.append(dic["inner_edge_color"])
+ dic["outer_edge_alpha"] = alpha
+ dic["outer_edge_width"] = dic["inner_edge_width"] = arrow_linewidth
# value at argmax of average
- dic['outer_edge_color'] = tsg[u, v]
+ dic["outer_edge_color"] = tsg[u, v]
- all_strengths.append(dic['outer_edge_color'])
- dic['label'] = None
-
- # dic['outer_edge_edge'] = False
- # dic['outer_edge_edgecolor'] = None
- # dic['inner_edge_edge'] = False
- # dic['inner_edge_edgecolor'] = None
+ all_strengths.append(dic["outer_edge_color"])
+ dic["label"] = None
# If no links are present, set value to zero
if len(all_strengths) == 0:
- all_strengths = [0.]
+ all_strengths = [0.0]
posarray = np.zeros((N * max_lag, 2))
for i in range(N * max_lag):
- posarray[i] = np.array([(i % max_lag), (1. - i // max_lag)])
+ posarray[i] = np.array([(i % max_lag), (1.0 - i // max_lag)])
pos_tmp = {}
for i in range(N * max_lag):
- pos_tmp[i] = np.array([((i % max_lag) - posarray.min(axis=0)[0]) /
- (posarray.max(axis=0)[0] -
- posarray.min(axis=0)[0]),
- ((1. - i // max_lag) -
- posarray.min(axis=0)[1]) /
- (posarray.max(axis=0)[1] -
- posarray.min(axis=0)[1])])
- pos_tmp[i][np.isnan(pos_tmp[i])] = 0.
+ pos_tmp[i] = np.array(
+ [
+ ((i % max_lag) - posarray.min(axis=0)[0])
+ / (posarray.max(axis=0)[0] - posarray.min(axis=0)[0]),
+ ((1.0 - i // max_lag) - posarray.min(axis=0)[1])
+ / (posarray.max(axis=0)[1] - posarray.min(axis=0)[1]),
+ ]
+ )
+ pos_tmp[i][np.isnan(pos_tmp[i])] = 0.0
pos = {}
for n in range(N):
for tau in range(max_lag):
pos[n * max_lag + tau] = pos_tmp[order[n] * max_lag + tau]
- node_rings = {0: {'sizes': None, 'color_array': node_color,
- 'label': '', 'colorbar': False,
- 'cmap': listcmap, 'vmin': 0,
- 'vmax': len(color_list),
- }
- }
+ node_rings = {
+ 0: {
+ "sizes": None,
+ "color_array": node_color,
+ "label": "",
+ "colorbar": False,
+ "cmap": listcmap,
+ "vmin": 0,
+ "vmax": len(color_list),
+ }
+ }
- # ] for v in range(max_lag)]
- node_labels = ['' for i in range(N * max_lag)]
+ node_labels = ["" for i in range(N * max_lag)]
_draw_network_with_curved_edges(
- fig=fig, ax=ax,
- G=deepcopy(G), pos=pos,
+ fig=fig,
+ ax=ax,
+ G=deepcopy(G),
+ pos=pos,
# dictionary of rings: {0:{'sizes':(N,)-array, 'color_array':(N,)-array
# or None, 'cmap':string,
node_rings=node_rings,
# 'vmin':float or None, 'vmax':float or None, 'label':string or None}}
- node_labels=node_labels, node_label_size=node_label_size,
- node_alpha=alpha, standard_size=node_size,
- standard_cmap='OrRd', standard_color='lightgrey',
+ node_labels=node_labels,
+ node_label_size=ode_label_size,
+ node_alpha=alpha,
+ standard_size=node_size,
+ node_aspect=node_aspect,
+ standard_cmap="OrRd",
+ standard_color="lightgrey",
log_sizes=False,
- cmap_links=cmap_edges, links_vmin=vmin_edges,
- links_vmax=vmax_edges, links_ticks=edge_ticks,
-
- # cmap_links_edges='YlOrRd', links_edges_vmin=-1., links_edges_vmax=1.,
- # links_edges_ticks=.2, link_edge_colorbar_label='link_edge',
-
- arrowstyle='simple', arrowhead_size=arrowhead_size,
- curved_radius=curved_radius, label_fontsize=label_fontsize,
- label_fraction=.5,
- link_colorbar_label=link_colorbar_label, inner_edge_curved=True,
+ cmap_links=cmap_edges,
+ links_vmin=vmin_edges,
+ links_vmax=vmax_edges,
+ links_ticks=edge_ticks,
+ arrowstyle="simple",
+ arrowhead_size=arrowhead_size,
+ curved_radius=curved_radius,
+ label_fontsize=label_fontsize,
+ label_fraction=0.5,
+ link_colorbar_label=link_colorbar_label,
+ inner_edge_curved=True,
network_lower_bound=network_lower_bound,
- inner_edge_style=inner_edge_style, show_colorbar=False,
- )
+ inner_edge_style=inner_edge_style,
+ show_colorbar=False,
+ )
for i in range(N):
- trans = transforms.blended_transform_factory(
- fig.transFigure, ax.transData)
- ax.text(label_space_left, pos[order[i] * max_lag][1],
- '%s' % str(var_names[order[i]]), fontsize=label_fontsize,
- horizontalalignment='left', verticalalignment='center',
- transform=trans)
+ trans = transforms.blended_transform_factory(fig.transFigure, ax.transData)
+ ax.text(
+ label_space_left,
+ pos[order[i] * max_lag][1],
+ "%s" % str(var_names[order[i]]),
+ fontsize=label_fontsize,
+ horizontalalignment="left",
+ verticalalignment="center",
+ transform=trans,
+ )
for tau in np.arange(max_lag - 1, -1, -1):
- trans = transforms.blended_transform_factory(
- ax.transData, fig.transFigure)
+ trans = transforms.blended_transform_factory(ax.transData, fig.transFigure)
if tau == max_lag - 1:
- ax.text(pos[tau][0], 1.-label_space_top, r'$t$',
- fontsize=int(label_fontsize*0.7),
- horizontalalignment='center',
- verticalalignment='top', transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t$",
+ fontsize=int(label_fontsize * 0.7),
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
else:
- ax.text(pos[tau][0], 1.-label_space_top,
- r'$t-%s$' % str(max_lag - tau - 1),
- fontsize=int(label_fontsize*0.7),
- horizontalalignment='center', verticalalignment='top',
- transform=trans)
+ ax.text(
+ pos[tau][0],
+ 1.0 - label_space_top,
+ r"$t-%s$" % str(max_lag - tau - 1),
+ fontsize=int(label_fontsize * 0.7),
+ horizontalalignment="center",
+ verticalalignment="top",
+ transform=trans,
+ )
- # fig.subplots_adjust(left=0.1, right=.98, bottom=.25, top=.9)
- # savestring = os.path.expanduser(save_name)
-# plt.show()
return fig, ax
-if __name__ == '__main__':
+if __name__ == "__main__":
- import os
- from tigramite.independence_tests import ParCorr
- import tigramite.data_processing as pp
- # np.random.seed(42)
+ val_matrix = np.zeros((4, 4, 3))
+ # Complete test case
+ link_matrix = np.zeros(val_matrix.shape)
- val_matrix = 2.+np.random.rand(4, 4, 2)
+ link_matrix[0, 1, 0] = 0
+ link_matrix[1, 0, 0] = 1
- # Complete test case
- link_matrix = np.zeros(val_matrix.shape, dtype='U3')
-
- link_matrix[0,1,0] = 'o->'
- link_matrix[1,0,0] = '<-o'
- link_matrix[1,2,0] = 'o-o'
- link_matrix[2,1,0] = 'o-o'
- link_matrix[0,2,0] = 'o--'
- link_matrix[2,0,0] = '--o'
- link_matrix[2,3,0] = '---'
- link_matrix[3,2,0] = '---'
- link_matrix[1,3,0] = '-->'
- link_matrix[3,1,0] = '<--'
-
- link_matrix[0,2,1] = '<->'
- link_matrix[0,0,1] = 'o->'
- link_matrix[0,1,1] = '-->'
- link_matrix[1,0,1] = 'o->'
-
- link_width = np.ones(val_matrix.shape)
- link_attribute = np.zeros(val_matrix.shape, dtype = 'object')
- link_attribute[:] = ''
- link_attribute[0,1,0] = 'spurious'
- link_attribute[1,0,0] = 'spurious'
-
- # link_attribute[0,2,1] = 'spurious'
-
- # link_matrix = np.random.randint(0, 2, size=val_matrix.shape)
-
- # print(link_matrix[:,:,1])
- print(link_matrix[:,:,0])
- plot_time_series_graph(
- # val_matrix=val_matrix,
- sig_thres=None,
- link_matrix=link_matrix,
- link_width=link_width,
- link_attribute=link_attribute,
- var_names=range(len(val_matrix)),
- inner_edge_style='dashed',
- save_name='tsg_test.pdf',
- )
- plot_graph(
- # val_matrix=val_matrix,
- sig_thres=None,
- link_matrix=link_matrix,
- link_width=link_width,
- link_attribute=link_attribute,
- var_names=range(len(val_matrix)),
- # inner_edge_style='dashed',
- save_name='graph_test.pdf',
- )
- # pyplot.show()
-
- # print link_matrix
- # data = np.random.randn(100,3)
- # mask = np.random.randint(0, 2, size=(100,3))
- # dataframe = pp.DataFrame(data, mask=mask)
-
-
- # data = np.random.randn(100, 3)
- # datatime = np.arange(100)
- # mask = np.zeros(data.shape)
-
- # mask[:int(len(data)/2)]=True
-
- # data[:,0] = -99.
- # plot_lagfuncs(val_matrix=val_matrix,
- # setup_args={'figsize':(10,10),
- # 'label_space_top':0.05,
- # 'label_space_left':0.1,
- # 'x_base':1, 'y_base':5,
- # 'var_names':range(3),
- # 'lag_array':np.array(['a%d' % i for i in range(4)])},
- # name='test.pdf',
- # )
-
-
- # plot_timeseries(
- # dataframe=dataframe,
- # save_name='/home/rung_ja/Downloads/test.pdf',
- # fig_axes=None,
- # var_units=None,
- # time_label='years',
- # use_mask=True,
- # grey_masked_samples='data',
- # data_linewidth=1.,
- # skip_ticks_data_x=1,
- # skip_ticks_data_y=1,
- # label_fontsize=8,
- # figsize=(3.375, 3.),
- # )
-
- # lagmat = setup_matrix(3, 3, range(3), lag_units = 'months')
-
- # lagmat.add_lagfuncs(
- # val_matrix=val_matrix,
- # # sig_thres=None,
- # # link_matrix=link_matrix
- # )
- # lagmat.savefig()
-
- # fig = pyplot.figure(figsize=(4, 3), frameon=False)
- # ax = fig.add_subplot(111, frame_on=False)
-
- """
- plot_graph(
- figsize=(3, 3),
- val_matrix=val_matrix,
- sig_thres=None,
- link_matrix=link_matrix,
- link_width=link_width,
- link_attribute=link_attribute,
- var_names=range(len(val_matrix)),
- save_name='/home/rung_ja/Downloads/test.pdf',
- )
- """
+ nolinks = np.zeros(link_matrix.shape)
+ # nolinks[range(4), range(4), 1] = 1
+
+ plot_time_series_graph(link_matrix=nolinks)
+ plot_graph(link_matrix=nolinks, save_name=None)
+
+ pyplot.show()
diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt
index 60d44a8e..be82a31d 100644
--- a/docs/_build/html/_sources/index.rst.txt
+++ b/docs/_build/html/_sources/index.rst.txt
@@ -27,9 +27,12 @@ Detecting and quantifying causal associations in large nonlinear time series
datasets. Sci. Adv. 5, eaau4996.
https://advances.sciencemag.org/content/5/11/eaau4996
-2. J. Runge (2020): Discovering contemporaneous and lagged causal relations
-in autocorrelated nonlinear time series datasets
-https://arxiv.org/abs/2003.03685
+2. J. Runge (2020):
+Discovering contemporaneous and lagged causal relations in autocorrelated
+nonlinear time series datasets. Proceedings of the 36th Conference on
+Uncertainty in Artificial Intelligence, UAI 2020,Toronto, Canada, 2019,
+AUAI Press, 2020.
+http://auai.org/uai2020/proceedings/579_main_paper.pdf
3. J. Runge et al. (2015): Identifying causal gateways and mediators in
complex spatio-temporal systems. Nature Communications, 6, 8502.
diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html
index cd842ff3..48222689 100644
--- a/docs/_build/html/index.html
+++ b/docs/_build/html/index.html
@@ -83,9 +83,12 @@ TIGRAMITEhttps://advances.sciencemag.org/content/5/11/eaau4996
-
2. J. Runge (2020): Discovering contemporaneous and lagged causal relations
-in autocorrelated nonlinear time series datasets
-https://arxiv.org/abs/2003.03685
+2. J. Runge (2020):
+Discovering contemporaneous and lagged causal relations in autocorrelated
+nonlinear time series datasets. Proceedings of the 36th Conference on
+Uncertainty in Artificial Intelligence, UAI 2020,Toronto, Canada, 2019,
+AUAI Press, 2020.
+http://auai.org/uai2020/proceedings/579_main_paper.pdf
3. J. Runge et al. (2015): Identifying causal gateways and mediators in
complex spatio-temporal systems. Nature Communications, 6, 8502.
http://doi.org/10.1038/ncomms9502
@@ -177,7 +180,7 @@
different times and a link indicates a conditional dependency that can be
interpreted as a causal dependency under certain assumptions (see paper).
Assuming stationarity, the links are repeated in time. The parents
- of a variable are defined as the set of all nodes
+ of a variable are defined as the set of all nodes
with a link towards it (blue and red boxes in Figure).
The different PCMCI methods estimate causal links by iterative
conditional independence testing. PCMCI can be flexibly combined with
@@ -196,7 +199,7 @@
J. Runge,
Discovering contemporaneous and lagged causal relations in
autocorrelated nonlinear time series datasets
-https://arxiv.org/abs/2003.03685
+http://www.auai.org/~w-auai/uai2020/proceedings/579_main_paper.pdf
@@ -726,8 +729,8 @@
Further optional parameters are discussed in 1.
Examples
>>> import numpy
->>> from tigramite.pcmci import PCMCI
->>> from tigramite.independence_tests import ParCorr
+>>> from tigramite.pcmci import PCMCI
+>>> from tigramite.independence_tests import ParCorr
>>> import tigramite.data_processing as pp
>>> numpy.random.seed(7)
>>> # Example process to play around with
@@ -738,7 +741,7 @@
2: [((2, -1), 0.8), ((1, -2), -0.6)]}
>>> data, _ = pp.var_process(links_coeffs, T=1000)
>>> # Data must be array of shape (time, variables)
->>> print data.shape
+>>> print (data.shape)
(1000, 3)
>>> dataframe = pp.DataFrame(data)
>>> cond_ind_test = ParCorr()
@@ -751,14 +754,14 @@
-
-- Variable 0 has 1 link(s):
(0 -1): pval = 0.00000 | val = 0.632
+
+- Variable 0 has 1 link(s):
(0 -1): pval = 0.00000 | val = 0.588
-- Variable 1 has 2 link(s):
(1 -1): pval = 0.00000 | val = 0.653
-(0 -1): pval = 0.00000 | val = 0.444
+- Variable 1 has 2 link(s):
(1 -1): pval = 0.00000 | val = 0.606
+(0 -1): pval = 0.00000 | val = 0.447
-- Variable 2 has 2 link(s):
(2 -1): pval = 0.00000 | val = 0.623
-(1 -2): pval = 0.00000 | val = -0.533
+- Variable 2 has 2 link(s):
(2 -1): pval = 0.00000 | val = 0.618
+(1 -2): pval = 0.00000 | val = -0.499
@@ -803,7 +806,8 @@
run_pcmciplus
(selected_links=None, tau_min=0, tau_max=1, pc_alpha=0.01, contemp_collider_rule='majority', conflict_resolution=True, reset_lagged_links=False, max_conds_dim=None, max_conds_py=None, max_conds_px=None, max_conds_px_lagged=None, fdr_method='none')[source]¶
Runs PCMCIplus time-lagged and contemporaneous causal discovery for
time series.
-Method described in 5: https://arxiv.org/abs/2003.03685
+Method described in 5:
+http://www.auai.org/~w-auai/uai2020/proceedings/579_main_paper.pdf
Notes
The PCMCIplus causal discovery method is described in 5, where
also analytical and numerical results are presented. In contrast to
@@ -836,17 +840,17 @@
4. PC rule orientation phase: Orient remaining contemporaneous
links based on PC rules.
In contrast to PCMCI, the relevant output of PCMCIplus is the
-array graph
. Its entries are interpreted as follows:
+array graph
. Its string entries are interpreted as follows:
-graph[i,j,tau]=1
for denotes a directed, lagged
+
graph[i,j,tau]=-->
for denotes a directed, lagged
causal link from to at lag
-graph[i,j,0]=1
and graph[j,i,0]=0
denotes a directed,
+
graph[i,j,0]=-->
(and graph[j,i,0]=<--
) denotes a directed,
contemporaneous causal link from to
-graph[i,j,0]=1
and graph[j,i,0]=1
denotes an unoriented,
+
graph[i,j,0]=o-o
(and graph[j,i,0]=o-o
) denotes an unoriented,
contemporaneous adjacency between and indicating
that the collider and orientation rules could not be applied (Markov
equivalence)
-graph[i,j,0]=2
and graph[j,i,0]=2
denotes a conflicting,
+
graph[i,j,0]=x-x
and (graph[j,i,0]=x-x
) denotes a conflicting,
contemporaneous adjacency between and indicating
that the directionality is undecided due to conflicting orientation
rules
@@ -887,9 +891,9 @@
larger runtimes.
Further optional parameters are discussed in 5.
Examples
->>> import numpy
->>> from tigramite.pcmci import PCMCI
->>> from tigramite.independence_tests import ParCorr
+>>> import numpy as np
+>>> from tigramite.pcmci import PCMCI
+>>> from tigramite.independence_tests import ParCorr
>>> import tigramite.data_processing as pp
>>> # Example process to play around with
>>> # Each key refers to a variable and the incoming links are supplied
@@ -900,12 +904,10 @@
2: [((2, -1), 0.7, lin_f), ((1, 0), 0.6, lin_f)],
3: [((3, -1), 0.7, lin_f), ((2, 0), -0.5, lin_f)],
}
->>> # Specify dynamical noise term distributions
->>> noises = [np.random.randn for j in links.keys()]
>>> data, nonstat = pp.structural_causal_process(links,
- T=1000, noises=noises, seed=7)
+ T=1000, seed=7)
>>> # Data must be array of shape (time, variables)
->>> print data.shape
+>>> print (data.shape)
(1000, 4)
>>> dataframe = pp.DataFrame(data)
>>> cond_ind_test = ParCorr()
@@ -916,17 +918,17 @@
-
-- Variable 0 has 1 link(s):
(0 -1): pval = 0.00000 | val = 0.676
+
+- Variable 0 has 1 link(s):
(0 -1): pval = 0.00000 | val = 0.676
-- Variable 1 has 2 link(s):
(1 -1): pval = 0.00000 | val = 0.602
-(0 -1): pval = 0.00000 | val = 0.599
+- Variable 1 has 2 link(s):
(1 -1): pval = 0.00000 | val = 0.602
+(0 -1): pval = 0.00000 | val = 0.599
-- Variable 2 has 2 link(s):
(1 0): pval = 0.00000 | val = 0.486
-(2 -1): pval = 0.00000 | val = 0.466
+- Variable 2 has 2 link(s):
(1 0): pval = 0.00000 | val = 0.486
+(2 -1): pval = 0.00000 | val = 0.466
-- Variable 3 has 2 link(s):
(3 -1): pval = 0.00000 | val = 0.524
-(2 0): pval = 0.00000 | val = -0.449
+- Variable 3 has 2 link(s):
(3 -1): pval = 0.00000 | val = 0.524
+(2 0): pval = 0.00000 | val = -0.449
@@ -1540,7 +1542,7 @@
- Returns
-pval – P-value.
+pval – p-value.
- Return type
float or numpy.nan
@@ -2997,9 +2999,9 @@
Tigramite plotting package.
-
-
tigramite.plotting.
plot_graph
(val_matrix=None, var_names=None, fig_ax=None, figsize=None, sig_thres=None, link_matrix=None, save_name=None, link_colorbar_label='MCI', node_colorbar_label='auto-MCI', link_width=None, link_attribute=None, node_pos=None, arrow_linewidth=30.0, vmin_edges=-1, vmax_edges=1.0, edge_ticks=0.4, cmap_edges='RdBu_r', vmin_nodes=0, vmax_nodes=1.0, node_ticks=0.4, cmap_nodes='OrRd', node_size=20, arrowhead_size=20, curved_radius=0.2, label_fontsize=10, alpha=1.0, node_label_size=10, link_label_fontsize=6, lag_array=None, network_lower_bound=0.2, show_colorbar=True)[source]¶
-Creates a network plot.
-This is still in beta. The network is defined either from True values in
+tigramite.plotting.
plot_graph
(val_matrix=None, var_names=None, fig_ax=None, figsize=None, sig_thres=None, link_matrix=None, save_name=None, link_colorbar_label='MCI', node_colorbar_label='auto-MCI', link_width=None, link_attribute=None, node_pos=None, arrow_linewidth=10.0, vmin_edges=-1, vmax_edges=1.0, edge_ticks=0.4, cmap_edges='RdBu_r', vmin_nodes=0, vmax_nodes=1.0, node_ticks=0.4, cmap_nodes='OrRd', node_size=0.3, node_aspect=None, arrowhead_size=20, curved_radius=0.2, label_fontsize=10, alpha=1.0, node_label_size=10, link_label_fontsize=10, lag_array=None, network_lower_bound=0.2, show_colorbar=True, inner_edge_style='dashed')[source]¶
+
Creates a network plot.
+This is still in beta. The network is defined either from True values in
link_matrix, or from thresholding the val_matrix with sig_thres. Nodes
denote variables, straight links contemporaneous dependencies and curved
arrows lagged dependencies. The node color denotes the maximal absolute
@@ -3007,16 +3009,22 @@
absolute cross-dependency. The link label lists the lags with significant
dependency in order of absolute magnitude. The network can also be plotted
over a map drawn before on the same axis. Then the node positions can be
-supplied in appropriate axis coordinates via node_pos.
+supplied in appropriate axis coordinates via node_pos.
+:param val_matrix: Matrix of shape (N, N, tau_max+1) containing test statistic values.
+:type val_matrix: array_like
+:param var_names: List of variable names. If None, range(N) is used.
+:type var_names: list, optional (default: None)
+:param fig_ax: Figure and axes instance. If None they are created.
+:type fig_ax: tuple of figure and axis object, optional (default: None)
+:param figsize: Size of figure.
+:type figsize: tuple
+:param sig_thres: Matrix of significance thresholds. Must be of same shape as val_matrix.
+
+Either sig_thres or link_matrix has to be provided.
+
- Parameters
-val_matrix (array_like) – Matrix of shape (N, N, tau_max+1) containing test statistic values.
-var_names (list, optional (default: None)) – List of variable names. If None, range(N) is used.
-fig_ax (tuple of figure and axis object, optional (default: None)) – Figure and axes instance. If None they are created.
-figsize (tuple) – Size of figure.
-sig_thres (array-like, optional (default: None)) – Matrix of significance thresholds. Must be of same shape as val_matrix.
-Either sig_thres or link_matrix has to be provided.
link_matrix (bool array-like, optional (default: None)) – Matrix of significant links. Must be of same shape as val_matrix. Either
sig_thres or link_matrix has to be provided.
save_name (str, optional (default: None)) – Name of figure file to save figure. If None, figure is shown in window.
@@ -3037,9 +3045,10 @@
vmax_nodes (float, optional (default: 1)) – Node colorbar scale upper bound.
node_ticks (float, optional (default: 0.4)) – Node tick mark interval.
cmap_nodes (str, optional (default: 'OrRd')) – Colormap for links.
-node_size (int, optional (default: 20)) – Node size.
+node_size (int, optional (default: 0.3)) – Node size.
+node_aspect (float, optional (default: None)) – Ratio between the heigth and width of the varible nodes.
arrowhead_size (int, optional (default: 20)) – Size of link arrow head. Passed on to FancyArrowPatch object.
-curved_radius (float, optional (default: 0.2)) – Curvature of links. Passed on to FancyArrowPatch object.
+float, optional (default (curved_radius,) – Curvature of links. Passed on to FancyArrowPatch object.
label_fontsize (int, optional (default: 10)) – Fontsize of colorbar labels.
alpha (float, optional (default: 1.)) – Opacity.
node_label_size (int, optional (default: 10)) – Fontsize of node labels.
@@ -3055,18 +3064,20 @@
-