intensify 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. intensify-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
  2. intensify-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +22 -0
  3. intensify-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  4. intensify-0.2.0/.github/workflows/ci.yml +129 -0
  5. intensify-0.2.0/.github/workflows/publish.yml +37 -0
  6. intensify-0.2.0/.gitignore +47 -0
  7. intensify-0.2.0/.pre-commit-config.yaml +24 -0
  8. intensify-0.2.0/CHANGELOG.md +177 -0
  9. intensify-0.2.0/CITATION.cff +38 -0
  10. intensify-0.2.0/CODE_OF_CONDUCT.md +43 -0
  11. intensify-0.2.0/CONTRIBUTING.md +68 -0
  12. intensify-0.2.0/ISSUES.md +465 -0
  13. intensify-0.2.0/LICENSE +21 -0
  14. intensify-0.2.0/PKG-INFO +170 -0
  15. intensify-0.2.0/README.md +123 -0
  16. intensify-0.2.0/SECURITY.md +27 -0
  17. intensify-0.2.0/benchmarks/README.md +48 -0
  18. intensify-0.2.0/benchmarks/reference_dataset.py +147 -0
  19. intensify-0.2.0/benchmarks/run_intensify.py +186 -0
  20. intensify-0.2.0/benchmarks/run_scaling.py +143 -0
  21. intensify-0.2.0/benchmarks/run_tick.py +128 -0
  22. intensify-0.2.0/devdoc.md +995 -0
  23. intensify-0.2.0/docs/_static/.gitkeep +1 -0
  24. intensify-0.2.0/docs/api_reference.rst +50 -0
  25. intensify-0.2.0/docs/benchmarks.md +168 -0
  26. intensify-0.2.0/docs/conf.py +28 -0
  27. intensify-0.2.0/docs/getting_started.md +157 -0
  28. intensify-0.2.0/docs/index.rst +14 -0
  29. intensify-0.2.0/docs/scaling.md +68 -0
  30. intensify-0.2.0/docs/user_guide/diagnostics.md +80 -0
  31. intensify-0.2.0/docs/user_guide/index.rst +10 -0
  32. intensify-0.2.0/docs/user_guide/inference.md +149 -0
  33. intensify-0.2.0/docs/user_guide/kernels.md +110 -0
  34. intensify-0.2.0/docs/user_guide/simulation.md +63 -0
  35. intensify-0.2.0/examples/biology_epidemiology_ecology.ipynb +1219 -0
  36. intensify-0.2.0/examples/neuroscience_spike_analysis.ipynb +1052 -0
  37. intensify-0.2.0/examples/seismology_aftershocks.ipynb +1018 -0
  38. intensify-0.2.0/intensify/__init__.py +96 -0
  39. intensify-0.2.0/intensify/_config.py +41 -0
  40. intensify-0.2.0/intensify/backends/__init__.py +10 -0
  41. intensify-0.2.0/intensify/backends/_backend.py +90 -0
  42. intensify-0.2.0/intensify/backends/jax_backend.py +132 -0
  43. intensify-0.2.0/intensify/backends/numpy_backend.py +144 -0
  44. intensify-0.2.0/intensify/core/__init__.py +57 -0
  45. intensify-0.2.0/intensify/core/base.py +122 -0
  46. intensify-0.2.0/intensify/core/diagnostics/__init__.py +34 -0
  47. intensify-0.2.0/intensify/core/diagnostics/goodness_of_fit.py +197 -0
  48. intensify-0.2.0/intensify/core/diagnostics/metrics.py +39 -0
  49. intensify-0.2.0/intensify/core/diagnostics/residuals.py +79 -0
  50. intensify-0.2.0/intensify/core/inference/__init__.py +317 -0
  51. intensify-0.2.0/intensify/core/inference/bayesian.py +162 -0
  52. intensify-0.2.0/intensify/core/inference/em.py +176 -0
  53. intensify-0.2.0/intensify/core/inference/mle.py +1300 -0
  54. intensify-0.2.0/intensify/core/inference/multivariate_hawkes_mle_params.py +76 -0
  55. intensify-0.2.0/intensify/core/inference/online.py +131 -0
  56. intensify-0.2.0/intensify/core/inference/univariate_hawkes_mle_params.py +154 -0
  57. intensify-0.2.0/intensify/core/kernels/__init__.py +34 -0
  58. intensify-0.2.0/intensify/core/kernels/approx_power_law.py +135 -0
  59. intensify-0.2.0/intensify/core/kernels/base.py +197 -0
  60. intensify-0.2.0/intensify/core/kernels/exponential.py +100 -0
  61. intensify-0.2.0/intensify/core/kernels/nonparametric.py +191 -0
  62. intensify-0.2.0/intensify/core/kernels/power_law.py +79 -0
  63. intensify-0.2.0/intensify/core/kernels/sum_exponential.py +122 -0
  64. intensify-0.2.0/intensify/core/processes/__init__.py +31 -0
  65. intensify-0.2.0/intensify/core/processes/cox.py +304 -0
  66. intensify-0.2.0/intensify/core/processes/hawkes.py +372 -0
  67. intensify-0.2.0/intensify/core/processes/marked_hawkes.py +233 -0
  68. intensify-0.2.0/intensify/core/processes/nonlinear_hawkes.py +279 -0
  69. intensify-0.2.0/intensify/core/processes/poisson.py +373 -0
  70. intensify-0.2.0/intensify/core/regularizers.py +55 -0
  71. intensify-0.2.0/intensify/core/simulation/__init__.py +17 -0
  72. intensify-0.2.0/intensify/core/simulation/cluster.py +142 -0
  73. intensify-0.2.0/intensify/core/simulation/thinning.py +249 -0
  74. intensify-0.2.0/intensify/py.typed +0 -0
  75. intensify-0.2.0/intensify/visualization/__init__.py +14 -0
  76. intensify-0.2.0/intensify/visualization/connectivity.py +84 -0
  77. intensify-0.2.0/intensify/visualization/event_histograms.py +106 -0
  78. intensify-0.2.0/intensify/visualization/intensity.py +102 -0
  79. intensify-0.2.0/intensify/visualization/kernels.py +70 -0
  80. intensify-0.2.0/pyproject.toml +114 -0
  81. intensify-0.2.0/tests/__init__.py +1 -0
  82. intensify-0.2.0/tests/conftest.py +28 -0
  83. intensify-0.2.0/tests/test_backends.py +35 -0
  84. intensify-0.2.0/tests/test_cluster.py +28 -0
  85. intensify-0.2.0/tests/test_cox.py +57 -0
  86. intensify-0.2.0/tests/test_diagnostics.py +76 -0
  87. intensify-0.2.0/tests/test_edge_cases.py +111 -0
  88. intensify-0.2.0/tests/test_em.py +31 -0
  89. intensify-0.2.0/tests/test_hawkes.py +95 -0
  90. intensify-0.2.0/tests/test_inhomogeneous_poisson.py +37 -0
  91. intensify-0.2.0/tests/test_jit.py +430 -0
  92. intensify-0.2.0/tests/test_jit_integration.py +637 -0
  93. intensify-0.2.0/tests/test_kernels.py +71 -0
  94. intensify-0.2.0/tests/test_mle_kernel_expansion.py +106 -0
  95. intensify-0.2.0/tests/test_multivariate_hawkes.py +93 -0
  96. intensify-0.2.0/tests/test_plan_phases.py +346 -0
  97. intensify-0.2.0/tests/test_poisson.py +57 -0
  98. intensify-0.2.0/tests/test_real_data_stress.py +1052 -0
  99. intensify-0.2.0/tests/test_remaining_kernels.py +139 -0
  100. intensify-0.2.0/tests/test_simulation.py +33 -0
  101. intensify-0.2.0/tests/test_textbook_cases.py +112 -0
  102. intensify-0.2.0/tests/test_visualization.py +51 -0
  103. intensify-0.2.0/tutorials/01_basic_hawkes.ipynb +32 -0
  104. intensify-0.2.0/tutorials/02_multivariate.ipynb +44 -0
  105. intensify-0.2.0/tutorials/03_marked_and_online.ipynb +38 -0
  106. intensify-0.2.0/tutorials/04_connectivity_and_nonlinear.ipynb +36 -0
@@ -0,0 +1,62 @@
1
+ name: Bug report
2
+ description: Something doesn't work as documented.
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to file a bug report. A minimal,
9
+ reproducible example is the fastest path to a fix.
10
+
11
+ - type: textarea
12
+ id: reproducer
13
+ attributes:
14
+ label: Minimal reproducer
15
+ description: Self-contained Python snippet that demonstrates the bug.
16
+ render: python
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: expected
22
+ attributes:
23
+ label: Expected vs observed
24
+ description: What you expected to happen, and what actually happened.
25
+ validations:
26
+ required: true
27
+
28
+ - type: textarea
29
+ id: traceback
30
+ attributes:
31
+ label: Full traceback (if any)
32
+ render: text
33
+
34
+ - type: input
35
+ id: version
36
+ attributes:
37
+ label: intensify version
38
+ placeholder: "`python -c 'import intensify; print(intensify.__version__)'`"
39
+ validations:
40
+ required: true
41
+
42
+ - type: input
43
+ id: python
44
+ attributes:
45
+ label: Python version
46
+ placeholder: "3.12.2"
47
+ validations:
48
+ required: true
49
+
50
+ - type: dropdown
51
+ id: backend
52
+ attributes:
53
+ label: Active backend
54
+ options: [jax, numpy]
55
+ validations:
56
+ required: true
57
+
58
+ - type: input
59
+ id: os
60
+ attributes:
61
+ label: OS
62
+ placeholder: "Ubuntu 22.04 / macOS 14 / Windows 11"
@@ -0,0 +1,22 @@
1
+ name: Feature request
2
+ description: Suggest a new feature or capability.
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: What problem does this solve?
9
+ description: Describe the use case, not just the desired API.
10
+ validations:
11
+ required: true
12
+
13
+ - type: textarea
14
+ id: proposal
15
+ attributes:
16
+ label: Proposed solution
17
+ description: A sketch of the API or implementation.
18
+
19
+ - type: textarea
20
+ id: alternatives
21
+ attributes:
22
+ label: Alternatives considered
@@ -0,0 +1,19 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR do and why? 1-3 sentences. -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Bulleted list of the concrete changes. -->
8
+
9
+ ## Checklist
10
+
11
+ - [ ] Tests added or updated (and pass locally)
12
+ - [ ] `ruff check intensify tests` clean
13
+ - [ ] Public API changes documented in `CHANGELOG.md` under `## [Unreleased]`
14
+ - [ ] Math changes cite a paper or textbook in docstrings / comments
15
+ - [ ] Breaking change? Call it out clearly above
16
+
17
+ ## Related issues
18
+
19
+ Closes #
@@ -0,0 +1,129 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu-latest, macos-latest, windows-latest]
16
+ python-version: ["3.10", "3.11", "3.12"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+ cache: 'pip'
26
+
27
+ - name: Install dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ pip install hatch
31
+ hatch env create
32
+
33
+ - name: Lint with ruff
34
+ run: hatch run lint:check
35
+
36
+ - name: Test with pytest
37
+ run: hatch run pytest:test
38
+
39
+ typecheck:
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+
44
+ - name: Set up Python
45
+ uses: actions/setup-python@v5
46
+ with:
47
+ python-version: "3.12"
48
+
49
+ - name: Install dependencies
50
+ run: |
51
+ python -m pip install --upgrade pip
52
+ pip install -e ".[dev]" mypy
53
+
54
+ - name: mypy
55
+ run: mypy intensify --ignore-missing-imports --no-strict-optional || true
56
+
57
+ docs:
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+
62
+ - name: Set up Python
63
+ uses: actions/setup-python@v5
64
+ with:
65
+ python-version: "3.12"
66
+
67
+ - name: Install dependencies
68
+ run: |
69
+ python -m pip install --upgrade pip
70
+ pip install hatch
71
+ pip install -e ".[docs]"
72
+
73
+ - name: Build docs
74
+ run: sphinx-build -W -b html docs docs/_build/html
75
+
76
+ - uses: actions/upload-artifact@v4
77
+ with:
78
+ name: docs-html
79
+ path: docs/_build/html
80
+
81
+ readme-doctest:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@v4
85
+ - uses: actions/setup-python@v5
86
+ with:
87
+ python-version: "3.12"
88
+ - name: Install
89
+ run: |
90
+ python -m pip install --upgrade pip
91
+ pip install -e ".[dev]"
92
+ - name: Doctest README
93
+ env:
94
+ MPLBACKEND: Agg
95
+ run: |
96
+ python -c "
97
+ import os, re, sys, subprocess
98
+ src = open('README.md').read()
99
+ blocks = re.findall(r'\`\`\`python\n(.*?)\n\`\`\`', src, flags=re.S)
100
+ if not blocks:
101
+ print('No python blocks found in README'); sys.exit(0)
102
+ code = blocks[0]
103
+ print('Running README quickstart block...')
104
+ env = dict(os.environ, MPLBACKEND='Agg')
105
+ subprocess.check_call([sys.executable, '-c', code], env=env)
106
+ "
107
+
108
+ build:
109
+ runs-on: ubuntu-latest
110
+ needs: [test, typecheck, docs]
111
+ if: github.ref == 'refs/heads/main'
112
+
113
+ steps:
114
+ - uses: actions/checkout@v4
115
+
116
+ - name: Set up Python
117
+ uses: actions/setup-python@v5
118
+ with:
119
+ python-version: "3.12"
120
+
121
+ - name: Build distribution
122
+ run: |
123
+ pip install hatch
124
+ hatch build
125
+
126
+ - uses: actions/upload-artifact@v4
127
+ with:
128
+ name: dist
129
+ path: dist/*
@@ -0,0 +1,37 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*.*.*"]
6
+
7
+ jobs:
8
+ build-and-publish:
9
+ runs-on: ubuntu-latest
10
+ environment:
11
+ name: pypi
12
+ url: https://pypi.org/project/intensify/
13
+ permissions:
14
+ id-token: write # OIDC trusted publishing
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Build sdist + wheel
24
+ run: |
25
+ python -m pip install --upgrade pip hatch
26
+ hatch build
27
+
28
+ - name: Sanity-check artifacts
29
+ run: |
30
+ ls -la dist/
31
+ python -m pip install twine
32
+ python -m twine check dist/*
33
+
34
+ - name: Publish to PyPI
35
+ uses: pypa/gh-action-pypi-publish@release/v1
36
+ with:
37
+ packages-dir: dist/
@@ -0,0 +1,47 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ env/
8
+ venv/
9
+ .venv/
10
+ env.bak/
11
+ venv.bak/
12
+
13
+ # IDEs
14
+ .vscode/
15
+ .idea/
16
+ *.swp
17
+ *.swo
18
+ *~
19
+
20
+ # Distribution / packaging
21
+ dist/
22
+ build/
23
+ *.egg-info/
24
+ *.egg
25
+ manifest.in
26
+ wheels/
27
+
28
+ # Testing
29
+ .pytest_cache/
30
+ .coverage
31
+ htmlcov/
32
+ nosetests.xml
33
+ coverage.xml
34
+ *.cover
35
+
36
+ # Project-specific
37
+ *.db
38
+ *.sqlite
39
+ data/
40
+ results/
41
+ .DS_Store
42
+
43
+ # JAX
44
+ .jax/
45
+
46
+ # Sphinx build output
47
+ docs/_build/
@@ -0,0 +1,24 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.11.2
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/pre-commit/pre-commit-hooks
10
+ rev: v4.6.0
11
+ hooks:
12
+ - id: check-yaml
13
+ - id: check-toml
14
+ - id: check-added-large-files
15
+ args: ["--maxkb=1000"]
16
+ - id: end-of-file-fixer
17
+ - id: trailing-whitespace
18
+ - id: mixed-line-ending
19
+
20
+ - repo: https://github.com/codespell-project/codespell
21
+ rev: v2.3.0
22
+ hooks:
23
+ - id: codespell
24
+ args: ["--skip=*.ipynb,coverage.xml,.venv,docs/_build"]
@@ -0,0 +1,177 @@
1
+ # Changelog
2
+
3
+ All notable changes to `intensify` are documented here.
4
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
+ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Added
10
+ - `MLEInference.fit(..., fit_decay=False)` — locks every β slot in the
11
+ flat parameter vector to its initial value via a zero-width L-BFGS-B
12
+ bound. Reduces the active parameter count, speeds up the fit, and
13
+ matches the problem `tick.HawkesExpKern` solves (β supplied as
14
+ input). Supported for `ExponentialKernel` and `SumExponentialKernel`
15
+ in univariate, marked, nonlinear, and multivariate paths. Raises
16
+ `TypeError` for kernels without an identifiable decay-rate axis
17
+ (`PowerLawKernel.beta` is a tail exponent, not a decay rate).
18
+ - **Scaling-study benchmarks** in `docs/scaling.md` showing
19
+ `mv_exp_5d` fit time vs N from 501 to 91,249 total events. Both
20
+ intensify and tick scale linearly; the ~10× wall-clock ratio is
21
+ stable across the whole range (it does not grow at scale);
22
+ parameter-recovery RMSE is statistically indistinguishable by
23
+ N≈10k. Reproducible via `benchmarks/run_scaling.py`.
24
+ - **O(N·M) recursive multivariate neg-log-likelihood** for the
25
+ shared-β exp-Hawkes case (every β_{m,k} the same scalar), cached
26
+ per `M`. Auto-selected by `_fit_multivariate_numpy` when
27
+ `fit_decay=False` and the kernel matrix has a shared β. Replaces the
28
+ dense O(N²) lag matrix with a `jax.lax.scan` carrying an M-vector
29
+ state per source dim. For `mv_exp_5d` (N=1099, M=5): ~220× fewer
30
+ compute steps, **17 ms fits vs 200 ms** on the same problem.
31
+ Per-cell β still falls back to the dense path.
32
+
33
+ ### Fixed
34
+ - **Correctness (critical, multivariate Hawkes likelihood)**:
35
+ `MultivariateHawkes._log_likelihood_dim` summed `log λ_m(t)` over
36
+ every event in the system, then summed across `m` — an `M`-fold
37
+ overcounting of the log-intensity term. The textbook likelihood is
38
+ `Σ_n log λ_{k_n}(t_n) − Σ_m Λ_m(T)`, i.e. each event contributes
39
+ `log` of its own *source* dim's intensity exactly once. Verified
40
+ against a hand-computed reference on a 2-d sim (current −63.0 vs
41
+ correct −44.4 on an identical data set). Fix causes multivariate MLE
42
+ parameter RMSE on the `mv_exp_5d` benchmark to drop from 0.167 → ~0.1,
43
+ now within 2× of tick on the same data. This bug was silently
44
+ affecting every multivariate Hawkes fit since the library's
45
+ inception.
46
+ - **Performance (univariate JAX MLE)**: each fit was paying ~370 ms on
47
+ fresh JIT compilation because `_make_jit_neg_loglik_*` returned a new
48
+ `@jax.jit`-decorated closure per call (closing over `events_jax` /
49
+ `T_jax`). JAX caches by function identity, so the trace was
50
+ recompiled every fit. The neg-log-likelihood functions are now lifted
51
+ to module scope and the `value+grad` / Hessian closures are cached by
52
+ `(kernel kind, n_components, r)`. Result: `uni_exp_small` fit dropped
53
+ from **376 ms → 5 ms** steady-state (~75× faster), bringing univariate
54
+ intensify within ~5× of `tick.HawkesExpKern` on the same data while
55
+ still fitting the decay rate jointly.
56
+ - **Performance (multivariate JAX MLE)**: `_fit_multivariate_numpy` now
57
+ has a JAX-JIT fast path for the all-`ExponentialKernel` case
58
+ (indirectly required by the flat-vector parameter layout already).
59
+ Uses a dense N×N causal lag matrix with gathered per-pair
60
+ `(α_mk, β_mk)` from `(source_i, source_j)` indexing, and caches the
61
+ compiled `value+grad` per `M`. Multivariate `mv_exp_5d` fit dropped
62
+ **77 s → 1.1 s** (~70× faster). Mixed-kernel multivariate matrices
63
+ still take the numpy fallback path (unchanged).
64
+ - Pre-0.2.0 callers of `_make_jit_neg_loglik_exp` /
65
+ `_make_jit_neg_loglik_sum_exp` / `_make_jit_neg_loglik_power_law` /
66
+ `_make_jit_neg_loglik_approx_pl` and the old
67
+ `_jax_hessian_std_errors(neg_ll_fn, x_opt, names)` signature still
68
+ work — they're shimmed to the cached implementation.
69
+
70
+ ## [0.2.0] - 2026-04-20
71
+
72
+ Public launch release. Consolidates correctness, API polish, and the
73
+ full documentation, CI, and scientific-credibility scaffolding needed
74
+ for lab adoption. Includes verified head-to-head benchmarks vs
75
+ [tick](https://github.com/X-DataInitiative/tick).
76
+
77
+ ### Fixed
78
+ - **Correctness (critical)**: `_recursive_compensators` in the time-rescaling
79
+ diagnostic had incorrect math for `ExponentialKernel` /
80
+ `SumExponentialKernel` — the computed cumulative intensities were off by a
81
+ factor of β, causing KS p-values to be catastrophically small under
82
+ well-specified models. Replaced with the correct recursion (equivalent
83
+ to the verified general pairwise-integral path, but O(N) instead of
84
+ O(N²)). Unknown recursive kernels now fall back to the general path
85
+ rather than applying the buggy formula. Before this fix the fast path of
86
+ `time_rescaling_test` and `qq_plot` produced wrong p-values for every
87
+ exponential-family Hawkes fit.
88
+
89
+ ### Added
90
+ - `benchmarks/` with README, `reference_dataset.py`, `run_intensify.py`,
91
+ `run_tick.py`, and verified head-to-head results in
92
+ `docs/benchmarks.md`. Datasets use portable `.npy`+`.json` pairs so the
93
+ same files work across NumPy 1.x and 2.x environments. pyhawkes was
94
+ evaluated and dropped (transitive deps reference
95
+ `scipy.misc.logsumexp`, removed in SciPy 1.0).
96
+ - `tests/test_textbook_cases.py`: parameter-recovery on seeded simulations,
97
+ log-likelihood scaling, well-specified-vs-misspecified KS sanity check.
98
+ - Community infrastructure: `CITATION.cff`, `CONTRIBUTING.md`,
99
+ `CODE_OF_CONDUCT.md`, `SECURITY.md`, GitHub issue + PR templates.
100
+ - Documentation: expanded `docs/getting_started.md` with regularization
101
+ shorthand, backend-switching, and input-validation notes; new
102
+ `docs/user_guide/diagnostics.md` covering the (corrected) time-rescaling
103
+ theorem; new `docs/user_guide/simulation.md`; kernel-coverage table in
104
+ `docs/user_guide/inference.md`.
105
+ - README rewrite: PyPI / Python / license / CI badges, "Why intensify?"
106
+ comparison vs `tick` and `pyhawkes`, citation block, doc links.
107
+ - CI: multi-OS matrix (ubuntu / macOS / windows), mypy job, Sphinx
108
+ docs-build job with `-W` treat-warnings-as-errors, README-quickstart
109
+ doctest job (`MPLBACKEND=Agg`), PyPI publish workflow on tags using
110
+ OIDC trusted publishing.
111
+ - Pre-commit: `codespell`, `check-yaml`, `check-toml`,
112
+ `check-added-large-files`, `end-of-file-fixer`, `trailing-whitespace`,
113
+ `mixed-line-ending`.
114
+
115
+ ## [0.1.1] - 2026-04-19
116
+
117
+ API-consistency release. No correctness changes; surface-area polish.
118
+
119
+ ### Added
120
+ - `MarkedHawkes` and `NonlinearHawkes` MLE now support every kernel type
121
+ the univariate helpers understand: `ExponentialKernel` (signed and
122
+ unsigned), `SumExponentialKernel`, `PowerLawKernel`, `ApproxPowerLawKernel`,
123
+ `NonparametricKernel`. Previously both processes raised
124
+ `NotImplementedError` for anything other than unsigned `ExponentialKernel`.
125
+ - `regularization="l1"` / `"elasticnet"` string shorthand accepted by
126
+ `MLEInference.fit`, resolving to default `L1()` / `ElasticNet()`.
127
+ Instances still pass through unchanged.
128
+ - Backend proxy: `get_backend()` returns a lazy proxy that delegates every
129
+ attribute to the currently active backend. Module-level
130
+ `bt = get_backend()` captures now pick up runtime `set_backend()` switches.
131
+ - `tests/test_mle_kernel_expansion.py`: parametric regression suite for the
132
+ expanded MLE kernel surface + regularization shorthand + backend proxy.
133
+
134
+ ### Changed
135
+ - `hawkes_mle_bounds` and `hawkes_mle_apply_vector` now preserve
136
+ `ExponentialKernel.allow_signed` so signed kernels round-trip through MLE
137
+ correctly when reused by `NonlinearHawkes`.
138
+
139
+ ### Fixed
140
+ - Pre-existing test/spec mismatches aligned with documented behavior:
141
+ `endogeneity_index` saturates at 1.0 at critical branching (per docstring);
142
+ `FitResult.connectivity_matrix()` raises `TypeError` (not `ValueError`)
143
+ when called on a non-multivariate process — test expectations updated.
144
+
145
+ ## [0.1.0] - 2026-04-19
146
+
147
+ First versioned release. Focus: correctness on real data, stable packaging.
148
+
149
+ ### Added
150
+ - `__version__` attribute on the top-level package.
151
+ - `py.typed` marker for PEP 561 type-checker support.
152
+ - `Kernel.scale(factor)` method on all built-in kernels so
153
+ `project_params` can enforce stationarity uniformly across kernel types
154
+ (`ExponentialKernel`, `SumExponentialKernel`, `PowerLawKernel`,
155
+ `ApproxPowerLawKernel`, `NonparametricKernel`).
156
+ - `RuntimeWarning` emitted from every MLE fit path when the SciPy optimizer
157
+ does not converge — previously only the multivariate path warned.
158
+ - `RuntimeWarning` when the fitted multivariate Hawkes spectral radius
159
+ remains ≥ 1 after projection (non-stationary fit).
160
+ - Minimum-version pins on all runtime dependencies (`numpy>=1.24`,
161
+ `jax>=0.4.20`, `scipy>=1.11`, `optax>=0.1.7`, `matplotlib>=3.7`).
162
+ - Project URLs: Documentation, Issues, Changelog.
163
+ - Classifiers: `Operating System :: OS Independent`,
164
+ `Topic :: Scientific/Engineering :: Mathematics`, `Typing :: Typed`.
165
+
166
+ ### Changed
167
+ - `UnivariateHawkes.project_params` and `MultivariateHawkes.project_params`
168
+ now use `Kernel.scale()`, so non-`alpha` kernels (e.g. `SumExponentialKernel`,
169
+ `NonparametricKernel`) are actually projected instead of silently skipped.
170
+ - Version bumped from `0.1.0-alpha` to `0.1.0`.
171
+
172
+ ### Fixed
173
+ - Replaced runtime-validation `assert` statements in
174
+ `intensify/core/kernels/nonparametric.py` and
175
+ `intensify/core/processes/marked_hawkes.py` with explicit `ValueError` /
176
+ `RuntimeError` raises. Asserts are stripped under `python -O` and previously
177
+ hid real errors.
@@ -0,0 +1,38 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use intensify in your research, please cite it as below."
3
+ title: "intensify: A modern Python point process library with deep Hawkes specialization"
4
+ abstract: >-
5
+ intensify is an open-source Python library for simulating, fitting, and
6
+ diagnosing point process models — with emphasis on Hawkes processes for
7
+ quantitative finance and computational neuroscience. It provides
8
+ univariate, multivariate, marked, and nonlinear Hawkes variants; a
9
+ pluggable kernel family (exponential, sum-of-exponentials, power-law,
10
+ approximate power-law, nonparametric); MLE inference with JAX autodiff
11
+ and a NumPy fallback; and goodness-of-fit tooling based on the
12
+ time-rescaling theorem.
13
+ type: software
14
+ authors:
15
+ - family-names: Hill
16
+ given-names: Matthew
17
+ license: MIT
18
+ repository-code: "https://github.com/hillmatt7/intensify"
19
+ url: "https://hillmatt7.github.io/intensify"
20
+ version: 0.2.0
21
+ date-released: "2026-04-19"
22
+ keywords:
23
+ - point-process
24
+ - hawkes-process
25
+ - self-exciting
26
+ - maximum-likelihood
27
+ - jax
28
+ - quantitative-finance
29
+ - computational-neuroscience
30
+ - time-rescaling
31
+ preferred-citation:
32
+ type: software
33
+ authors:
34
+ - family-names: Hill
35
+ given-names: Matthew
36
+ title: "intensify: A modern Python point process library with deep Hawkes specialization"
37
+ year: 2026
38
+ url: "https://github.com/hillmatt7/intensify"
@@ -0,0 +1,43 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in
6
+ the `intensify` community a harassment-free experience for everyone,
7
+ regardless of age, body size, visible or invisible disability, ethnicity,
8
+ sex characteristics, gender identity and expression, level of experience,
9
+ education, socio-economic status, nationality, personal appearance, race,
10
+ caste, color, religion, or sexual identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our standards
16
+
17
+ Examples of behavior that contributes to a positive environment:
18
+
19
+ - Demonstrating empathy and kindness toward other people.
20
+ - Being respectful of differing opinions, viewpoints, and experiences.
21
+ - Giving and gracefully accepting constructive feedback.
22
+ - Taking responsibility and apologizing to those affected by our mistakes.
23
+ - Focusing on what is best not just for us as individuals but for the
24
+ overall community.
25
+
26
+ Examples of unacceptable behavior:
27
+
28
+ - Sexualized language or imagery; sexual attention or advances of any kind.
29
+ - Trolling, insulting or derogatory comments, personal or political attacks.
30
+ - Public or private harassment.
31
+ - Publishing others' private information without explicit permission.
32
+ - Other conduct that could reasonably be considered inappropriate in a
33
+ professional setting.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported to the maintainers via GitHub's private security advisory channel
39
+ or by email. All complaints will be reviewed and investigated promptly and
40
+ fairly.
41
+
42
+ This Code of Conduct is adapted from the
43
+ [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
@@ -0,0 +1,68 @@
1
+ # Contributing to intensify
2
+
3
+ Thank you for considering a contribution. This project aims to be a reliable,
4
+ well-tested building block for point-process research in labs and industry.
5
+
6
+ ## Ground rules
7
+
8
+ - **Correctness first.** Every numerical change should ship with a test that
9
+ asserts the quantity it affects, not just that the code runs.
10
+ - **No silent fallbacks.** If a code path can produce a wrong answer under
11
+ certain conditions (non-stationary fit, degenerate data, optimizer stall),
12
+ surface it as a `warning` or `raise`, never as a silent sentinel.
13
+ - **Backend-agnostic.** Anything under `intensify/core/` must work with
14
+ both the JAX and NumPy backends. Use `from ...backends import get_backend`
15
+ and call backend methods through the returned proxy.
16
+
17
+ ## Development setup
18
+
19
+ ```bash
20
+ git clone https://github.com/hillmatt7/intensify
21
+ cd intensify
22
+
23
+ # Create a virtualenv and install with dev extras
24
+ python -m venv .venv
25
+ source .venv/bin/activate
26
+ pip install -e ".[dev,docs]"
27
+
28
+ pre-commit install
29
+ ```
30
+
31
+ ## Running checks
32
+
33
+ ```bash
34
+ # Lint + format
35
+ hatch run lint:check
36
+
37
+ # Tests (with coverage)
38
+ pytest tests/
39
+
40
+ # Docs
41
+ hatch run docs:build
42
+ ```
43
+
44
+ ## Pull request checklist
45
+
46
+ - [ ] Tests cover the new or changed behavior.
47
+ - [ ] `pytest tests/` passes locally (no new warnings unless intentional).
48
+ - [ ] `ruff check intensify tests` is clean.
49
+ - [ ] Public API changes are documented in `CHANGELOG.md` under `## [Unreleased]`.
50
+ - [ ] If you changed math, a citation (paper or textbook chapter) appears in
51
+ the docstring or in-line comment.
52
+
53
+ ## Reporting bugs
54
+
55
+ Open an issue at
56
+ <https://github.com/hillmatt7/intensify/issues/new/choose>.
57
+ Please include a minimal reproducer, the observed vs expected behavior,
58
+ your Python version, `intensify.__version__`, and the active backend
59
+ (`intensify.get_backend_name()`).
60
+
61
+ ## Security
62
+
63
+ See [`SECURITY.md`](SECURITY.md) for reporting security issues privately.
64
+
65
+ ## Community
66
+
67
+ This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By
68
+ participating you agree to uphold it.