tpattern 0.1.12__tar.gz → 0.1.13__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 (41) hide show
  1. {tpattern-0.1.12/tpattern.egg-info → tpattern-0.1.13}/PKG-INFO +71 -7
  2. {tpattern-0.1.12 → tpattern-0.1.13}/README.md +70 -6
  3. {tpattern-0.1.12 → tpattern-0.1.13}/pyproject.toml +1 -1
  4. tpattern-0.1.13/tests/test_starter.py +34 -0
  5. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/__init__.py +3 -2
  6. tpattern-0.1.13/tpattern/starter.py +147 -0
  7. {tpattern-0.1.12 → tpattern-0.1.13/tpattern.egg-info}/PKG-INFO +71 -7
  8. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern.egg-info/SOURCES.txt +2 -0
  9. {tpattern-0.1.12 → tpattern-0.1.13}/LICENSE +0 -0
  10. {tpattern-0.1.12 → tpattern-0.1.13}/setup.cfg +0 -0
  11. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_calibrated_pins.py +0 -0
  12. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_contrast.py +0 -0
  13. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_dedup.py +0 -0
  14. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_guided.py +0 -0
  15. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_null_compare.py +0 -0
  16. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_outputs.py +0 -0
  17. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_read_table_validation.py +0 -0
  18. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_reference.py +0 -0
  19. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_report_dendrogram.py +0 -0
  20. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_reproduction.py +0 -0
  21. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_sofcoder.py +0 -0
  22. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_support_reporting.py +0 -0
  23. {tpattern-0.1.12 → tpattern-0.1.13}/tests/test_synthetic.py +0 -0
  24. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/advisor.py +0 -0
  25. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/ci.py +0 -0
  26. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/contrast.py +0 -0
  27. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/detect.py +0 -0
  28. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/diagnostics.py +0 -0
  29. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/guided.py +0 -0
  30. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/io.py +0 -0
  31. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/methods.py +0 -0
  32. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/pattern.py +0 -0
  33. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/randomise.py +0 -0
  34. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/reference.py +0 -0
  35. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/report.py +0 -0
  36. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/significance.py +0 -0
  37. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/synthetic.py +0 -0
  38. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern/viz.py +0 -0
  39. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern.egg-info/dependency_links.txt +0 -0
  40. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern.egg-info/requires.txt +0 -0
  41. {tpattern-0.1.12 → tpattern-0.1.13}/tpattern.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tpattern
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Open, auditable temporal & sequential pattern analysis (T-patterns) for sport and behaviour
5
5
  Author-email: Andrew Callaway <acallaway@bournemouth.ac.uk>
6
6
  License-Expression: MIT
@@ -54,6 +54,60 @@ analysis companion to the [OpenTag.Studio](https://opentag.studio) tagging tool.
54
54
  Bring your own data (one row per event — see [`SCHEMA.md`](SCHEMA.md)) or try the
55
55
  included [`data/`](data/) example.
56
56
 
57
+ ## Getting started in a minute
58
+
59
+ Install, generate a starter script, point it at your data, run it:
60
+
61
+ ```bash
62
+ pip install tpattern
63
+ python -c "import tpattern; tpattern.new_analysis()" # writes my_analysis.py
64
+ ```
65
+
66
+ Open `my_analysis.py`, change the two lines marked `# <-- EDIT` (your file and its time
67
+ unit), and run `python my_analysis.py`. It loads your events, **checks the file and tells
68
+ you in plain language about any problem**, recommends the analysis settings with reasons,
69
+ calibrates every pattern against a chance model, and writes a folder of results with a
70
+ plain-English verdict for each pattern.
71
+
72
+ Doing something more specific? Generate a template for it:
73
+
74
+ ```python
75
+ from tpattern import new_analysis
76
+ new_analysis() # one group: detect, calibrate, report
77
+ new_analysis(template="two_groups") # compare two groups (odds ratios + forest plot)
78
+ new_analysis(template="null_choice") # core vs shell: which null a pattern survives
79
+ ```
80
+
81
+ Not sure what a setting means? Ask the code — every setting and output column is documented:
82
+
83
+ ```python
84
+ from tpattern import explain
85
+ print(explain("min_lag")) # what it does, its range, the recommended value, higher vs lower
86
+ print(explain("fdr_q")) # what an output column means
87
+ ```
88
+
89
+ ## What you get
90
+
91
+ - **Forgiving data import.** `read_table` checks your file as it reads it and reports, in
92
+ plain language, any problem, how much of the file it affects, and how to fix it — instead
93
+ of silently dropping rows. Each check has a stable code (Appendix A of the tutorial; also
94
+ [`PARAMETERS.md`](PARAMETERS.md)).
95
+ - **A proper chance model.** Every pattern is tested against a surrogate null, with p-values
96
+ corrected for repeated testing (Benjamini–Hochberg FDR for screening, Holm family-wise for
97
+ confirmatory claims), stratified by hierarchy level.
98
+ - **Temporal reporting.** Beyond *which* patterns are real, the output says *when*: each
99
+ pattern's occurrence timing (median lag and spread) is reported by default — on the
100
+ dendrogram, in the table, and in the plain-English verdict — for every pattern.
101
+ - **Readable output.** Results-table columns are named for what they are (`monte_carlo_p`,
102
+ `fdr_q`, `survives_fwer_holm`, `bout_support`, `duration_median_ms`), and each pattern
103
+ carries a plain-English `interpretation`. `explain()` documents every setting and column;
104
+ the full reference is in [`PARAMETERS.md`](PARAMETERS.md).
105
+ - **One reference, everywhere.** Settings and columns live in one registry that generates the
106
+ code's `explain()`, `PARAMETERS.md`, the Colab form labels, and the tutorial's tables — so
107
+ the software, the paper and the notebook can't drift apart.
108
+ - **Clean figures** — dendrograms, temporal signatures, forest plots — that share one
109
+ customisable style (`tpattern.viz.STYLE`).
110
+
57
111
  ## Why it exists
58
112
 
59
113
  T-pattern analysis finds behaviourally meaningful structure that event counts and
@@ -62,7 +116,7 @@ software, the reference implementation. `tpattern` is an open, complementary
62
116
  implementation that reproduces THEME's detection and adds a reproducible chance
63
117
  model and clear reporting:
64
118
 
65
- - **reproduces** THEME's core detection (critical intervals, Nx/T baseline,
119
+ - **reproduces** THEME's core detection (critical intervals, NX/T baseline,
66
120
  completeness competition) — validated to the pattern for published datasets;
67
121
  - **adds a chance model** — every pattern is tested against a surrogate null, with
68
122
  p-values **corrected for repeated testing** (false-discovery rate and
@@ -109,12 +163,18 @@ print(recommend(observations))
109
163
  result = calibrate(observations, Config(), null="profile", B=200, q_target=0.05)
110
164
  survivors = result.kept("fdr") # patterns that survive false-discovery control
111
165
 
112
- # 4. Report: a tidy table (with q-values), pattern dendrograms and a summary —
113
- # plus a paste-ready Methods paragraph stating every setting and what it does.
114
- report(result, "report_out", title="My analysis")
166
+ # 4. Report: a tidy results table (monte_carlo_p, fdr_q, survives_fwer_holm, the observed
167
+ # timing, and a plain-English `interpretation` per pattern), pattern dendrograms, the
168
+ # temporal-signature and occurrence plots, the event-type roles/connections tables, and a
169
+ # paste-ready Methods paragraph stating every setting and what it does.
170
+ report(result, "report_out", observations=observations, title="My analysis")
115
171
  print(methods_text(Config(), observations=observations, calibration=result))
116
172
  ```
117
173
 
174
+ Prefer not to write the pipeline yourself? `python -c "import tpattern;
175
+ tpattern.new_analysis()"` writes a commented [`my_analysis.py`](examples/my_analysis.py)
176
+ you edit and run (see [Getting started](#getting-started-in-a-minute)).
177
+
118
178
  Two runnable examples:
119
179
 
120
180
  ```bash
@@ -128,7 +188,8 @@ Config()).detect()` returns them directly.
128
188
 
129
189
  **Comparing two groups** (winner vs loser, goal vs non-goal, condition A vs B)?
130
190
  `group_contrast(observations, group_of)` tests each pattern's occurrence between
131
- the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot`.
191
+ the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot` — or run
192
+ `new_analysis(template="two_groups")` for a ready-made script.
132
193
 
133
194
  ## The workflow
134
195
 
@@ -179,7 +240,10 @@ survive the surrogate null. All seeded and deterministic. See
179
240
  - [`SCHEMA.md`](SCHEMA.md) — the input data structure (what your export must contain).
180
241
  - [`CODING_GUIDE.md`](CODING_GUIDE.md) — how to set up a coding window to produce it.
181
242
  - [`data/`](data/) — the derived World Cup sequences, in the canonical format.
182
- - [`examples/`](examples/) — a runnable quickstart and the reproduction script.
243
+ - [`examples/`](examples/) — a runnable quickstart, the reproduction script, and the
244
+ `my_analysis.py` / `my_group_comparison.py` / `my_null_choice.py` starter templates.
245
+ - [`PARAMETERS.md`](PARAMETERS.md) — every setting and output column, with range, recommended
246
+ value, and what higher/lower does (generated from the code, so it never drifts).
183
247
 
184
248
  ## Tests
185
249
 
@@ -19,6 +19,60 @@ analysis companion to the [OpenTag.Studio](https://opentag.studio) tagging tool.
19
19
  Bring your own data (one row per event — see [`SCHEMA.md`](SCHEMA.md)) or try the
20
20
  included [`data/`](data/) example.
21
21
 
22
+ ## Getting started in a minute
23
+
24
+ Install, generate a starter script, point it at your data, run it:
25
+
26
+ ```bash
27
+ pip install tpattern
28
+ python -c "import tpattern; tpattern.new_analysis()" # writes my_analysis.py
29
+ ```
30
+
31
+ Open `my_analysis.py`, change the two lines marked `# <-- EDIT` (your file and its time
32
+ unit), and run `python my_analysis.py`. It loads your events, **checks the file and tells
33
+ you in plain language about any problem**, recommends the analysis settings with reasons,
34
+ calibrates every pattern against a chance model, and writes a folder of results with a
35
+ plain-English verdict for each pattern.
36
+
37
+ Doing something more specific? Generate a template for it:
38
+
39
+ ```python
40
+ from tpattern import new_analysis
41
+ new_analysis() # one group: detect, calibrate, report
42
+ new_analysis(template="two_groups") # compare two groups (odds ratios + forest plot)
43
+ new_analysis(template="null_choice") # core vs shell: which null a pattern survives
44
+ ```
45
+
46
+ Not sure what a setting means? Ask the code — every setting and output column is documented:
47
+
48
+ ```python
49
+ from tpattern import explain
50
+ print(explain("min_lag")) # what it does, its range, the recommended value, higher vs lower
51
+ print(explain("fdr_q")) # what an output column means
52
+ ```
53
+
54
+ ## What you get
55
+
56
+ - **Forgiving data import.** `read_table` checks your file as it reads it and reports, in
57
+ plain language, any problem, how much of the file it affects, and how to fix it — instead
58
+ of silently dropping rows. Each check has a stable code (Appendix A of the tutorial; also
59
+ [`PARAMETERS.md`](PARAMETERS.md)).
60
+ - **A proper chance model.** Every pattern is tested against a surrogate null, with p-values
61
+ corrected for repeated testing (Benjamini–Hochberg FDR for screening, Holm family-wise for
62
+ confirmatory claims), stratified by hierarchy level.
63
+ - **Temporal reporting.** Beyond *which* patterns are real, the output says *when*: each
64
+ pattern's occurrence timing (median lag and spread) is reported by default — on the
65
+ dendrogram, in the table, and in the plain-English verdict — for every pattern.
66
+ - **Readable output.** Results-table columns are named for what they are (`monte_carlo_p`,
67
+ `fdr_q`, `survives_fwer_holm`, `bout_support`, `duration_median_ms`), and each pattern
68
+ carries a plain-English `interpretation`. `explain()` documents every setting and column;
69
+ the full reference is in [`PARAMETERS.md`](PARAMETERS.md).
70
+ - **One reference, everywhere.** Settings and columns live in one registry that generates the
71
+ code's `explain()`, `PARAMETERS.md`, the Colab form labels, and the tutorial's tables — so
72
+ the software, the paper and the notebook can't drift apart.
73
+ - **Clean figures** — dendrograms, temporal signatures, forest plots — that share one
74
+ customisable style (`tpattern.viz.STYLE`).
75
+
22
76
  ## Why it exists
23
77
 
24
78
  T-pattern analysis finds behaviourally meaningful structure that event counts and
@@ -27,7 +81,7 @@ software, the reference implementation. `tpattern` is an open, complementary
27
81
  implementation that reproduces THEME's detection and adds a reproducible chance
28
82
  model and clear reporting:
29
83
 
30
- - **reproduces** THEME's core detection (critical intervals, Nx/T baseline,
84
+ - **reproduces** THEME's core detection (critical intervals, NX/T baseline,
31
85
  completeness competition) — validated to the pattern for published datasets;
32
86
  - **adds a chance model** — every pattern is tested against a surrogate null, with
33
87
  p-values **corrected for repeated testing** (false-discovery rate and
@@ -74,12 +128,18 @@ print(recommend(observations))
74
128
  result = calibrate(observations, Config(), null="profile", B=200, q_target=0.05)
75
129
  survivors = result.kept("fdr") # patterns that survive false-discovery control
76
130
 
77
- # 4. Report: a tidy table (with q-values), pattern dendrograms and a summary —
78
- # plus a paste-ready Methods paragraph stating every setting and what it does.
79
- report(result, "report_out", title="My analysis")
131
+ # 4. Report: a tidy results table (monte_carlo_p, fdr_q, survives_fwer_holm, the observed
132
+ # timing, and a plain-English `interpretation` per pattern), pattern dendrograms, the
133
+ # temporal-signature and occurrence plots, the event-type roles/connections tables, and a
134
+ # paste-ready Methods paragraph stating every setting and what it does.
135
+ report(result, "report_out", observations=observations, title="My analysis")
80
136
  print(methods_text(Config(), observations=observations, calibration=result))
81
137
  ```
82
138
 
139
+ Prefer not to write the pipeline yourself? `python -c "import tpattern;
140
+ tpattern.new_analysis()"` writes a commented [`my_analysis.py`](examples/my_analysis.py)
141
+ you edit and run (see [Getting started](#getting-started-in-a-minute)).
142
+
83
143
  Two runnable examples:
84
144
 
85
145
  ```bash
@@ -93,7 +153,8 @@ Config()).detect()` returns them directly.
93
153
 
94
154
  **Comparing two groups** (winner vs loser, goal vs non-goal, condition A vs B)?
95
155
  `group_contrast(observations, group_of)` tests each pattern's occurrence between
96
- the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot`.
156
+ the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot` — or run
157
+ `new_analysis(template="two_groups")` for a ready-made script.
97
158
 
98
159
  ## The workflow
99
160
 
@@ -144,7 +205,10 @@ survive the surrogate null. All seeded and deterministic. See
144
205
  - [`SCHEMA.md`](SCHEMA.md) — the input data structure (what your export must contain).
145
206
  - [`CODING_GUIDE.md`](CODING_GUIDE.md) — how to set up a coding window to produce it.
146
207
  - [`data/`](data/) — the derived World Cup sequences, in the canonical format.
147
- - [`examples/`](examples/) — a runnable quickstart and the reproduction script.
208
+ - [`examples/`](examples/) — a runnable quickstart, the reproduction script, and the
209
+ `my_analysis.py` / `my_group_comparison.py` / `my_null_choice.py` starter templates.
210
+ - [`PARAMETERS.md`](PARAMETERS.md) — every setting and output column, with range, recommended
211
+ value, and what higher/lower does (generated from the code, so it never drifts).
148
212
 
149
213
  ## Tests
150
214
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tpattern"
7
- version = "0.1.12"
7
+ version = "0.1.13"
8
8
  description = "Open, auditable temporal & sequential pattern analysis (T-patterns) for sport and behaviour"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,34 @@
1
+ """The copy-and-adapt analysis template generator and its variants."""
2
+ import ast, pytest
3
+ from tpattern import new_analysis
4
+ from tpattern.starter import TEMPLATES
5
+
6
+
7
+ def test_all_templates_are_valid_python():
8
+ assert set(TEMPLATES) == {"basic", "two_groups", "null_choice"}
9
+ for name, src in TEMPLATES.items():
10
+ ast.parse(src) # each generated script is valid Python
11
+ assert "# <-- EDIT" in src and "read_table" in src
12
+
13
+
14
+ def test_new_analysis_default_and_named(tmp_path):
15
+ p = new_analysis(tmp_path / "a.py")
16
+ assert "recommend" in open(p).read() and "calibrate" in open(p).read()
17
+ g = new_analysis(tmp_path / "g.py", template="two_groups")
18
+ assert "group_contrast" in open(g).read() and "forest_plot" in open(g).read()
19
+ n = new_analysis(tmp_path / "n.py", template="null_choice")
20
+ assert "compare_nulls" in open(n).read()
21
+
22
+
23
+ def test_overwrite_guard_and_bad_name(tmp_path):
24
+ f = tmp_path / "a.py"
25
+ new_analysis(f)
26
+ with pytest.raises(FileExistsError):
27
+ new_analysis(f)
28
+ new_analysis(f, overwrite=True)
29
+ with pytest.raises(ValueError):
30
+ new_analysis(tmp_path / "x.py", template="nope")
31
+
32
+
33
+ def test_basic_template_uses_readable_columns():
34
+ assert "monte_carlo_p" in TEMPLATES["basic"] and "survives_fwer_holm" in TEMPLATES["basic"]
@@ -6,7 +6,7 @@ behavior: T-patterns and their detection. Behavior Research Methods,
6
6
  Instruments, & Computers, 32(1), 93-110.
7
7
  """
8
8
 
9
- __version__ = "0.1.12" # defined before submodule imports (methods.py reads it)
9
+ __version__ = "0.1.13" # defined before submodule imports (methods.py reads it)
10
10
 
11
11
  from .io import (Observation, read_observation, read_sample, read_table,
12
12
  read_sofcoder, DataFormatError, check_reference, CHECKS)
@@ -26,6 +26,7 @@ from .guided import run_analysis, launch
26
26
  from .contrast import group_contrast, contrast_items
27
27
  from .reference import (explain, explain_settings, explain_columns,
28
28
  parameters_markdown, SETTINGS, COLUMNS)
29
+ from .starter import new_analysis, TEMPLATE
29
30
 
30
31
  __all__ = [
31
32
  "Observation", "read_observation", "read_sample", "read_table", "read_sofcoder",
@@ -43,5 +44,5 @@ __all__ = [
43
44
  "run_analysis", "launch",
44
45
  "group_contrast", "contrast_items",
45
46
  "explain", "explain_settings", "explain_columns", "parameters_markdown",
46
- "SETTINGS", "COLUMNS",
47
+ "SETTINGS", "COLUMNS", "new_analysis",
47
48
  ]
@@ -0,0 +1,147 @@
1
+ """
2
+ Starting points students can copy and adapt.
3
+ =============================================
4
+
5
+ The tutorial teaches the method on the worked example; this gives a learner a clean
6
+ template for their *own* data. `new_analysis()` writes a heavily commented starter
7
+ script, with every line to change marked and pointers to `explain()` for each setting.
8
+ Three flavours cover the common designs:
9
+
10
+ new_analysis() # one group: detect, calibrate, report
11
+ new_analysis(template="two_groups") # compare two groups (odds ratios + forest plot)
12
+ new_analysis(template="null_choice") # core vs shell: which null a pattern survives
13
+
14
+ It is the "now do it on your own research" bridge.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from pathlib import Path
20
+
21
+ _BASIC = '''\
22
+ """
23
+ My T-pattern analysis. (tpattern.new_analysis — copy and adapt.)
24
+
25
+ Point this at your own event table and run it. Every line to change is marked # <-- EDIT.
26
+ For any setting, see what it does, its range and the recommended value with:
27
+ from tpattern import explain; print(explain("min_lag"))
28
+ Your data: one row per event, with columns observation, event, start
29
+ (which session/rally/bout the event belongs to, what happened, and when). See SCHEMA.md
30
+ and the tutorial paper for the full walk-through.
31
+ """
32
+ from tpattern import read_table, recommend, Config, calibrate, report, explain
33
+
34
+ # 1. LOAD -----------------------------------------------------------------------
35
+ DATA_FILE = "my_events.csv" # <-- EDIT: your event table (CSV)
36
+ TIME_UNIT = "ms" # <-- EDIT: "s" or "ms", the unit of your start column
37
+ observations = read_table(DATA_FILE, time_unit=TIME_UNIT, report="all")
38
+ # read_table checks the file as it reads it and prints any problems by code (Appendix A).
39
+
40
+ # 2. INSPECT + RECOMMEND --------------------------------------------------------
41
+ # The advisor inspects your data and recommends the null, the minimum lag and the error
42
+ # control, each with its reason. Read it, then decide (you are not obliged to follow it).
43
+ print(recommend(observations))
44
+
45
+ # 3. CONFIGURE ------------------------------------------------------------------
46
+ # Start from the advisor's recommendation. To understand any setting, print its help:
47
+ # print(explain("min_lag")) print(explain("surrogate_null")) print(explain("frequent_event_exclusion"))
48
+ cfg = Config(
49
+ min_lag=1, # <-- 1 requires a genuine time gap (recommended for frame-coded data); 0 = THEME-style
50
+ freq_exclude=1.5, # <-- set a very common event aside from pattern-building (kept in the counts)
51
+ # everything else is left at sensible defaults; run explain() to see them
52
+ )
53
+ NULL = "profile" # <-- "profile" tests coupling beyond each type's own timing (the usual choice)
54
+ B = 2000 # <-- surrogates: 200 to screen many patterns, 2000+ for a confirmatory claim
55
+
56
+ # 4. CALIBRATE + REPORT ---------------------------------------------------------
57
+ result = calibrate(observations, cfg, null=NULL, B=B, q_target=0.05)
58
+ report(result, "my_output", observations=observations, title="My analysis")
59
+
60
+ # my_output/ now holds the results table (patterns_table.csv, with monte_carlo_p, fdr_q and
61
+ # survives_fwer_holm), the pattern dendrograms, the temporal-signature plot, the event-type
62
+ # roles and connections tables, and a plain-text SUMMARY. Each pattern's "interpretation"
63
+ # column reads it in plain English. To understand a column: print(explain("fdr_q"))
64
+ print("\\nDone. Open the my_output/ folder.")
65
+ '''
66
+
67
+ _TWO_GROUPS = '''\
68
+ """
69
+ My T-pattern group comparison. (tpattern.new_analysis(template="two_groups"))
70
+
71
+ Do patterns occur differently between two groups (winners vs losers, condition A vs B,
72
+ goals vs non-goals)? For each pattern this tests its occurrence between the groups
73
+ (Fisher's exact test, odds ratio with a 95% confidence interval) and draws a forest plot.
74
+ Lines to change are marked # <-- EDIT. Run explain("min_lag") etc. for any setting.
75
+ """
76
+ import csv
77
+ from tpattern import read_table, Config, group_contrast, forest_plot
78
+
79
+ # 1. LOAD your events (one row per event: observation, event, start).
80
+ DATA_FILE = "my_events.csv" # <-- EDIT
81
+ TIME_UNIT = "ms" # <-- EDIT: "s" or "ms"
82
+ observations = read_table(DATA_FILE, time_unit=TIME_UNIT, report="all")
83
+
84
+ # 2. GROUP each observation. group_of maps an observation's name to its group label.
85
+ # Easiest: a two-column CSV (observation,group). <-- EDIT the path and column names.
86
+ group_of = {row["observation"]: row["group"]
87
+ for row in csv.DictReader(open("my_groups.csv"))}
88
+
89
+ # 3. CONTRAST: detect patterns and compare their occurrence between the two groups.
90
+ # min_count drops patterns too rare to compare; raise it to be more conservative.
91
+ items = group_contrast(observations, group_of, Config(min_lag=1), min_count=5)
92
+
93
+ # 4. PLOT the odds ratios with 95% CIs (a point whose CI excludes 1 differs between groups).
94
+ forest_plot(items, "group_contrast.png", title="Pattern occurrence: group comparison")
95
+ print("wrote group_contrast.png (odds ratios with 95% confidence intervals)")
96
+ '''
97
+
98
+ _NULL_CHOICE = '''\
99
+ """
100
+ My null-choice comparison. (tpattern.new_analysis(template="null_choice"))
101
+
102
+ Which patterns are genuine coupling, and which are just shared timing? This calibrates
103
+ your data under two nulls and splits the survivors into the CORE (survives both nulls =
104
+ coupling beyond each event's own timing) and the SHELL (survives the rotation null only =
105
+ co-occurrence driven by shared timing). Lines to change are marked # <-- EDIT.
106
+ """
107
+ from tpattern import read_table, Config, compare_nulls, null_comparison_plot
108
+
109
+ DATA_FILE = "my_events.csv" # <-- EDIT
110
+ TIME_UNIT = "ms" # <-- EDIT: "s" or "ms"
111
+ observations = read_table(DATA_FILE, time_unit=TIME_UNIT, report="all")
112
+
113
+ # Compare the profile-preserving null (coupling) against the rotation null (any structure).
114
+ # B = 2000 gives a fine Monte-Carlo p; use 200 to explore quickly first.
115
+ cmp = compare_nulls(observations, Config(min_lag=1), nulls=("profile", "rotation"), B=2000)
116
+ print(cmp) # lists the core and the shell, with each pattern's q under each null
117
+
118
+ null_comparison_plot(cmp, "null_comparison.png")
119
+ print("\\nwrote null_comparison.png (core = survives both nulls; shell = rotation only)")
120
+ '''
121
+
122
+ TEMPLATES = {"basic": _BASIC, "two_groups": _TWO_GROUPS, "null_choice": _NULL_CHOICE}
123
+ _DEFAULT_NAME = {"basic": "my_analysis.py", "two_groups": "my_group_comparison.py",
124
+ "null_choice": "my_null_choice.py"}
125
+
126
+ # kept for backward compatibility (0.1.12 exported TEMPLATE)
127
+ TEMPLATE = _BASIC
128
+
129
+
130
+ def new_analysis(path: str | Path | None = None, *, template: str = "basic",
131
+ overwrite: bool = False) -> str:
132
+ """Write a copy-and-adapt analysis template to `path`. Returns the path written.
133
+
134
+ `template` is one of ``"basic"`` (one group), ``"two_groups"`` (compare two groups),
135
+ or ``"null_choice"`` (core vs shell). If `path` is omitted a sensible filename is used.
136
+
137
+ >>> from tpattern import new_analysis
138
+ >>> new_analysis() # writes ./my_analysis.py
139
+ >>> new_analysis(template="two_groups") # writes ./my_group_comparison.py
140
+ """
141
+ if template not in TEMPLATES:
142
+ raise ValueError(f"template must be one of {sorted(TEMPLATES)}, got {template!r}")
143
+ p = Path(path) if path is not None else Path(_DEFAULT_NAME[template])
144
+ if p.exists() and not overwrite:
145
+ raise FileExistsError(f"{p} already exists; pass overwrite=True to replace it.")
146
+ p.write_text(TEMPLATES[template])
147
+ return str(p)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tpattern
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Open, auditable temporal & sequential pattern analysis (T-patterns) for sport and behaviour
5
5
  Author-email: Andrew Callaway <acallaway@bournemouth.ac.uk>
6
6
  License-Expression: MIT
@@ -54,6 +54,60 @@ analysis companion to the [OpenTag.Studio](https://opentag.studio) tagging tool.
54
54
  Bring your own data (one row per event — see [`SCHEMA.md`](SCHEMA.md)) or try the
55
55
  included [`data/`](data/) example.
56
56
 
57
+ ## Getting started in a minute
58
+
59
+ Install, generate a starter script, point it at your data, run it:
60
+
61
+ ```bash
62
+ pip install tpattern
63
+ python -c "import tpattern; tpattern.new_analysis()" # writes my_analysis.py
64
+ ```
65
+
66
+ Open `my_analysis.py`, change the two lines marked `# <-- EDIT` (your file and its time
67
+ unit), and run `python my_analysis.py`. It loads your events, **checks the file and tells
68
+ you in plain language about any problem**, recommends the analysis settings with reasons,
69
+ calibrates every pattern against a chance model, and writes a folder of results with a
70
+ plain-English verdict for each pattern.
71
+
72
+ Doing something more specific? Generate a template for it:
73
+
74
+ ```python
75
+ from tpattern import new_analysis
76
+ new_analysis() # one group: detect, calibrate, report
77
+ new_analysis(template="two_groups") # compare two groups (odds ratios + forest plot)
78
+ new_analysis(template="null_choice") # core vs shell: which null a pattern survives
79
+ ```
80
+
81
+ Not sure what a setting means? Ask the code — every setting and output column is documented:
82
+
83
+ ```python
84
+ from tpattern import explain
85
+ print(explain("min_lag")) # what it does, its range, the recommended value, higher vs lower
86
+ print(explain("fdr_q")) # what an output column means
87
+ ```
88
+
89
+ ## What you get
90
+
91
+ - **Forgiving data import.** `read_table` checks your file as it reads it and reports, in
92
+ plain language, any problem, how much of the file it affects, and how to fix it — instead
93
+ of silently dropping rows. Each check has a stable code (Appendix A of the tutorial; also
94
+ [`PARAMETERS.md`](PARAMETERS.md)).
95
+ - **A proper chance model.** Every pattern is tested against a surrogate null, with p-values
96
+ corrected for repeated testing (Benjamini–Hochberg FDR for screening, Holm family-wise for
97
+ confirmatory claims), stratified by hierarchy level.
98
+ - **Temporal reporting.** Beyond *which* patterns are real, the output says *when*: each
99
+ pattern's occurrence timing (median lag and spread) is reported by default — on the
100
+ dendrogram, in the table, and in the plain-English verdict — for every pattern.
101
+ - **Readable output.** Results-table columns are named for what they are (`monte_carlo_p`,
102
+ `fdr_q`, `survives_fwer_holm`, `bout_support`, `duration_median_ms`), and each pattern
103
+ carries a plain-English `interpretation`. `explain()` documents every setting and column;
104
+ the full reference is in [`PARAMETERS.md`](PARAMETERS.md).
105
+ - **One reference, everywhere.** Settings and columns live in one registry that generates the
106
+ code's `explain()`, `PARAMETERS.md`, the Colab form labels, and the tutorial's tables — so
107
+ the software, the paper and the notebook can't drift apart.
108
+ - **Clean figures** — dendrograms, temporal signatures, forest plots — that share one
109
+ customisable style (`tpattern.viz.STYLE`).
110
+
57
111
  ## Why it exists
58
112
 
59
113
  T-pattern analysis finds behaviourally meaningful structure that event counts and
@@ -62,7 +116,7 @@ software, the reference implementation. `tpattern` is an open, complementary
62
116
  implementation that reproduces THEME's detection and adds a reproducible chance
63
117
  model and clear reporting:
64
118
 
65
- - **reproduces** THEME's core detection (critical intervals, Nx/T baseline,
119
+ - **reproduces** THEME's core detection (critical intervals, NX/T baseline,
66
120
  completeness competition) — validated to the pattern for published datasets;
67
121
  - **adds a chance model** — every pattern is tested against a surrogate null, with
68
122
  p-values **corrected for repeated testing** (false-discovery rate and
@@ -109,12 +163,18 @@ print(recommend(observations))
109
163
  result = calibrate(observations, Config(), null="profile", B=200, q_target=0.05)
110
164
  survivors = result.kept("fdr") # patterns that survive false-discovery control
111
165
 
112
- # 4. Report: a tidy table (with q-values), pattern dendrograms and a summary —
113
- # plus a paste-ready Methods paragraph stating every setting and what it does.
114
- report(result, "report_out", title="My analysis")
166
+ # 4. Report: a tidy results table (monte_carlo_p, fdr_q, survives_fwer_holm, the observed
167
+ # timing, and a plain-English `interpretation` per pattern), pattern dendrograms, the
168
+ # temporal-signature and occurrence plots, the event-type roles/connections tables, and a
169
+ # paste-ready Methods paragraph stating every setting and what it does.
170
+ report(result, "report_out", observations=observations, title="My analysis")
115
171
  print(methods_text(Config(), observations=observations, calibration=result))
116
172
  ```
117
173
 
174
+ Prefer not to write the pipeline yourself? `python -c "import tpattern;
175
+ tpattern.new_analysis()"` writes a commented [`my_analysis.py`](examples/my_analysis.py)
176
+ you edit and run (see [Getting started](#getting-started-in-a-minute)).
177
+
118
178
  Two runnable examples:
119
179
 
120
180
  ```bash
@@ -128,7 +188,8 @@ Config()).detect()` returns them directly.
128
188
 
129
189
  **Comparing two groups** (winner vs loser, goal vs non-goal, condition A vs B)?
130
190
  `group_contrast(observations, group_of)` tests each pattern's occurrence between
131
- the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot`.
191
+ the groups (Fisher's exact test, odds ratio + 95% CI) and feeds `forest_plot` — or run
192
+ `new_analysis(template="two_groups")` for a ready-made script.
132
193
 
133
194
  ## The workflow
134
195
 
@@ -179,7 +240,10 @@ survive the surrogate null. All seeded and deterministic. See
179
240
  - [`SCHEMA.md`](SCHEMA.md) — the input data structure (what your export must contain).
180
241
  - [`CODING_GUIDE.md`](CODING_GUIDE.md) — how to set up a coding window to produce it.
181
242
  - [`data/`](data/) — the derived World Cup sequences, in the canonical format.
182
- - [`examples/`](examples/) — a runnable quickstart and the reproduction script.
243
+ - [`examples/`](examples/) — a runnable quickstart, the reproduction script, and the
244
+ `my_analysis.py` / `my_group_comparison.py` / `my_null_choice.py` starter templates.
245
+ - [`PARAMETERS.md`](PARAMETERS.md) — every setting and output column, with range, recommended
246
+ value, and what higher/lower does (generated from the code, so it never drifts).
183
247
 
184
248
  ## Tests
185
249
 
@@ -12,6 +12,7 @@ tests/test_reference.py
12
12
  tests/test_report_dendrogram.py
13
13
  tests/test_reproduction.py
14
14
  tests/test_sofcoder.py
15
+ tests/test_starter.py
15
16
  tests/test_support_reporting.py
16
17
  tests/test_synthetic.py
17
18
  tpattern/__init__.py
@@ -28,6 +29,7 @@ tpattern/randomise.py
28
29
  tpattern/reference.py
29
30
  tpattern/report.py
30
31
  tpattern/significance.py
32
+ tpattern/starter.py
31
33
  tpattern/synthetic.py
32
34
  tpattern/viz.py
33
35
  tpattern.egg-info/PKG-INFO
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes