# MBVL-Granger: MultiBand Variable-Lag Granger Causality Analysis
A Python framework to infer causality between time series using MultiBand Variable-Lag Granger causality with frequency-band decomposition.
Traditional Granger causality assumes fixed time delays between cause and effect. However, for non-stationary time series, this assumption often fails. For example, in neural signals, the delay between brain regions can vary over time due to changing network dynamics.
We propose MBVL-Granger that allows variable-lags and analyzes causality within specific frequency bands to handle complex, non-stationary time series relationships.
## Installation
You can install our package from PyPI:
```bash
pip install mbvlgranger
```
For the newest version from GitHub:
```bash
git clone https://github.com/Teddy50060/mbvlgranger.git
cd mbvlgranger
pip install -e .
```
## Example: Gas Furnace Data Analysis
First, we load time series data where gas input rate (X) potentially causes CO2 concentration (Y) with variable delays.
```python
import numpy as np
import scipy.io
from mbvlgranger import quick_mbvlgranger
# Load gas furnace data
mat_data = scipy.io.loadmat('data/gasfurnace.mat')
x = np.array(mat_data['gasfurnace'][0]).flatten() # Gas input rate
y = np.array(mat_data['gasfurnace'][1]).flatten() # CO2 concentration
```
We use the following function to infer whether X causes Y across different frequency bands:
```python
# Run MBVL-Granger analysis
results = quick_mbvlgranger(
x=x, y=y,
fs=250, # sampling frequency
max_lag=50,
bands={
'slow': (1, 10), # Slow thermal dynamics
'medium': (11, 25), # Medium process dynamics
'fast': (26, 50), # Fast control responses
'rapid': (51, 100) # Rapid fluctuations
}
)
```
The result of MBVL-Granger causality analysis:
```python
print(f"Overall Causality: {results['overall_causality']}")
print(f"Combined p-value: {results['combined_p_value']:.6f}")
# Actual output:
# Overall Causality: True
# Combined p-value: 0.000000
```
If `results['overall_causality']` is True, then X MBVL-Granger-causes Y. The `combined_p_value` indicates statistical significance across all frequency bands.
For individual frequency band results:
```python
from mbvlgranger import print_mbvlgranger_results
# Print detailed results for each frequency band
print_mbvlgranger_results(results)
# Actual output:
# VL-Granger Frequency Causality Analysis Results
# ==================================================
# Overall Causality: True
# Combined P-value: 0.000000
# Method: fisher
# Valid Bands: 4
#
# Individual Band Results:
# --------------------------------------------------
# 1-10Hz | F=32.014 | p=0.000000 | BIC= 0.746 | Lag= 3 | Sig=YES
# 11-25Hz | F= 0.000 | p=1.000000 | BIC=-27.633 | Lag= 4 | Sig=NO
# 26-50Hz | F= 0.996 | p=0.492149 | BIC= -1.279 | Lag= 4 | Sig=NO
# 51-100Hz | F= 0.663 | p=0.952331 | BIC= -1.492 | Lag=12 | Sig=NO
```
## Core Analysis
For more control over the analysis:
```python
from mbvlgranger import VLGrangerCausality
# Single time series analysis with core algorithm
analyzer = VLGrangerCausality()
result = analyzer.analyze_causality(Y=y, X=x, max_lag=25, gamma=0.5)
print(f"Causality detected: {result['XgCsY']}")
print(f"Detected lag: {result['following_result']['opt_delay']}")
print(f"BIC ratio: {result['BIC_diff_ratio']:.3f}")
```
Raw data
{
"_id": null,
"home_page": "https://github.com/Teddy50060/MBVLgranger",
"name": "mbvlgranger",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "granger-causality, time-series, neuroscience, causality, frequency-analysis",
"author": "Chakattrai Sookkongwaree",
"author_email": "Chakattrai Sookkongwaree <6632033821@student.chula.ac.th>",
"download_url": "https://files.pythonhosted.org/packages/51/b7/e542c78e2aac32240479a4deea06ab5d1ecd7a1b5b85f6c65df9e9a014d7/mbvlgranger-0.1.3.tar.gz",
"platform": null,
"description": "# MBVL-Granger: MultiBand Variable-Lag Granger Causality Analysis\n\nA Python framework to infer causality between time series using MultiBand Variable-Lag Granger causality with frequency-band decomposition.\n\nTraditional Granger causality assumes fixed time delays between cause and effect. However, for non-stationary time series, this assumption often fails. For example, in neural signals, the delay between brain regions can vary over time due to changing network dynamics. \n\nWe propose MBVL-Granger that allows variable-lags and analyzes causality within specific frequency bands to handle complex, non-stationary time series relationships.\n\n## Installation\n\nYou can install our package from PyPI:\n\n```bash\npip install mbvlgranger\n```\n\nFor the newest version from GitHub:\n\n```bash\ngit clone https://github.com/Teddy50060/mbvlgranger.git\ncd mbvlgranger\npip install -e .\n```\n\n## Example: Gas Furnace Data Analysis\n\nFirst, we load time series data where gas input rate (X) potentially causes CO2 concentration (Y) with variable delays.\n\n```python\nimport numpy as np\nimport scipy.io\nfrom mbvlgranger import quick_mbvlgranger\n\n# Load gas furnace data\nmat_data = scipy.io.loadmat('data/gasfurnace.mat')\nx = np.array(mat_data['gasfurnace'][0]).flatten() # Gas input rate\ny = np.array(mat_data['gasfurnace'][1]).flatten() # CO2 concentration\n```\n\nWe use the following function to infer whether X causes Y across different frequency bands:\n\n```python\n# Run MBVL-Granger analysis\nresults = quick_mbvlgranger(\n x=x, y=y,\n fs=250, # sampling frequency\n max_lag=50,\n bands={\n 'slow': (1, 10), # Slow thermal dynamics\n 'medium': (11, 25), # Medium process dynamics\n 'fast': (26, 50), # Fast control responses\n 'rapid': (51, 100) # Rapid fluctuations\n }\n)\n```\n\nThe result of MBVL-Granger causality analysis:\n\n```python\nprint(f\"Overall Causality: {results['overall_causality']}\")\nprint(f\"Combined p-value: {results['combined_p_value']:.6f}\")\n\n# Actual output:\n# Overall Causality: True\n# Combined p-value: 0.000000\n```\n\nIf `results['overall_causality']` is True, then X MBVL-Granger-causes Y. The `combined_p_value` indicates statistical significance across all frequency bands.\n\nFor individual frequency band results:\n\n```python\nfrom mbvlgranger import print_mbvlgranger_results\n\n# Print detailed results for each frequency band\nprint_mbvlgranger_results(results)\n\n# Actual output:\n# VL-Granger Frequency Causality Analysis Results\n# ==================================================\n# Overall Causality: True\n# Combined P-value: 0.000000\n# Method: fisher\n# Valid Bands: 4\n# \n# Individual Band Results:\n# --------------------------------------------------\n# 1-10Hz | F=32.014 | p=0.000000 | BIC= 0.746 | Lag= 3 | Sig=YES\n# 11-25Hz | F= 0.000 | p=1.000000 | BIC=-27.633 | Lag= 4 | Sig=NO\n# 26-50Hz | F= 0.996 | p=0.492149 | BIC= -1.279 | Lag= 4 | Sig=NO\n# 51-100Hz | F= 0.663 | p=0.952331 | BIC= -1.492 | Lag=12 | Sig=NO\n```\n\n## Core Analysis\n\nFor more control over the analysis:\n\n```python\nfrom mbvlgranger import VLGrangerCausality\n\n# Single time series analysis with core algorithm\nanalyzer = VLGrangerCausality()\nresult = analyzer.analyze_causality(Y=y, X=x, max_lag=25, gamma=0.5)\n\nprint(f\"Causality detected: {result['XgCsY']}\")\nprint(f\"Detected lag: {result['following_result']['opt_delay']}\")\nprint(f\"BIC ratio: {result['BIC_diff_ratio']:.3f}\")\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Multi-Band Variable-Lag Granger Causality: A Unified Framework for Causal Time Series Inference across Frequencies",
"version": "0.1.3",
"project_urls": {
"Bug Tracker": "https://github.com/Teddy50060/mbvlgranger/issues",
"Documentation": "https://github.com/Teddy50060/mbvlgranger/docs",
"Homepage": "https://github.com/Teddy50060/mbvlgranger",
"Repository": "https://github.com/Teddy50060/mbvlgranger.git"
},
"split_keywords": [
"granger-causality",
" time-series",
" neuroscience",
" causality",
" frequency-analysis"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ae32698de608dc42ebd76d08671fcfef683627ad68623acbebf9aab0166aa309",
"md5": "3476eebb97157fe455460ac15cde8b43",
"sha256": "e07a2ec8816347d83de86fb6024fc5be87ce2a8666f6b00541ff76c8c6c8fa42"
},
"downloads": -1,
"filename": "mbvlgranger-0.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3476eebb97157fe455460ac15cde8b43",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 28434,
"upload_time": "2025-07-31T11:44:22",
"upload_time_iso_8601": "2025-07-31T11:44:22.191004Z",
"url": "https://files.pythonhosted.org/packages/ae/32/698de608dc42ebd76d08671fcfef683627ad68623acbebf9aab0166aa309/mbvlgranger-0.1.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "51b7e542c78e2aac32240479a4deea06ab5d1ecd7a1b5b85f6c65df9e9a014d7",
"md5": "9a47faf87a0daa0a3b2956dd5a6cd1a7",
"sha256": "055f08f97e0ea0a2724ab68f3c4b5dfc6e380e03c850bbaf4263940f2156626c"
},
"downloads": -1,
"filename": "mbvlgranger-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "9a47faf87a0daa0a3b2956dd5a6cd1a7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 28656,
"upload_time": "2025-07-31T11:44:23",
"upload_time_iso_8601": "2025-07-31T11:44:23.544387Z",
"url": "https://files.pythonhosted.org/packages/51/b7/e542c78e2aac32240479a4deea06ab5d1ecd7a1b5b85f6c65df9e9a014d7/mbvlgranger-0.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-31 11:44:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Teddy50060",
"github_project": "MBVLgranger",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "numpy",
"specs": [
[
">=",
"1.20.0"
]
]
},
{
"name": "pandas",
"specs": [
[
">=",
"1.3.0"
]
]
},
{
"name": "scipy",
"specs": [
[
">=",
"1.7.0"
]
]
},
{
"name": "matplotlib",
"specs": [
[
">=",
"3.3.0"
]
]
},
{
"name": "statsmodels",
"specs": [
[
">=",
"0.12.0"
]
]
},
{
"name": "scikit-learn",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "dtaidistance",
"specs": [
[
">=",
"2.3.0"
]
]
}
],
"lcname": "mbvlgranger"
}