Skip to content

Commit a7d4ebe

Browse files
authored
Merge pull request #22 from ail-project/codex/add-documentation-for-tempolocus-library
Add documentation for using tempolocus as a Python library
2 parents 0c81e59 + fbb316c commit a7d4ebe

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,150 @@ why the activity occurred.
6969
This is a heuristic first pass. Weekly data cannot uniquely identify an IANA
7070
timezone without dates, and yearly data is sensitive to the meaning of the
7171
activity counter.
72+
73+
## Using tempolocus as a Python library
74+
75+
Install `tempolocus` in the Python environment that will import it:
76+
77+
```bash
78+
python -m pip install tempolocus
79+
```
80+
81+
For development against a local checkout, install it in editable mode instead:
82+
83+
```bash
84+
python -m pip install -e .
85+
```
86+
87+
The public package entry points are `detect`, `analyze_activity`, and
88+
`load_json`:
89+
90+
```python
91+
from tempolocus import analyze_activity, detect, load_json
92+
93+
data = load_json("samples/weekfull-chan1.json")
94+
result = detect(data, top=10)
95+
96+
print(result["input_type"])
97+
print(result["results"][0]["label"])
98+
print(result["analysis"]["activity_type"])
99+
100+
activity = analyze_activity(data)
101+
print(activity["activity_type"])
102+
```
103+
104+
### `detect(data, kind="auto", top=5, holiday_profile="standard", activity_signal="lack")`
105+
106+
Use `detect` when you want the full inference result. It accepts already-loaded
107+
Python data structures rather than file paths, which makes it suitable for web
108+
services, notebooks, pipelines, and tests. The return value is a dictionary with
109+
metadata, assumptions, signal summaries, and ranked `results`.
110+
111+
Parameters:
112+
113+
- `data`: one of the supported input shapes described below.
114+
- `kind`: `"auto"`, `"weekly"`, `"yearly"`, or `"timestamps"`. Use `"auto"`
115+
when the input shape is unambiguous; force a kind when your caller already
116+
knows what it provided.
117+
- `top`: number of ranked candidates to include. Must be at least `1`.
118+
- `holiday_profile`: for yearly inputs, `"standard"` or `"public-worker"`. The
119+
public-worker profile adds public-sector closure references where available.
120+
- `activity_signal`: for yearly inputs, `"lack"` to match low activity on
121+
holidays or `"peak"` to match unusually high activity on holidays.
122+
123+
Weekly hourly bucket example:
124+
125+
```python
126+
from tempolocus import detect
127+
128+
weekly_rows = [
129+
{"day": day, "hour": hour, "count": 10 if day <= 4 and 9 <= hour <= 17 else 1}
130+
for day in range(7)
131+
for hour in range(24)
132+
]
133+
134+
result = detect(weekly_rows, kind="weekly", top=3)
135+
for candidate in result["results"]:
136+
print(candidate["probability"], candidate["id"], candidate["label"])
137+
```
138+
139+
Timestamp list example:
140+
141+
```python
142+
from tempolocus import detect
143+
144+
timestamps = [
145+
"2026-01-05T09:15:00Z",
146+
"2026-01-06 10:30:00 UTC",
147+
1767605400, # Unix epoch seconds in UTC
148+
]
149+
150+
result = detect(timestamps, kind="timestamps")
151+
print(result["signals"]["timestamps_seen"])
152+
```
153+
154+
Yearly daily bucket example:
155+
156+
```python
157+
from tempolocus import detect
158+
159+
yearly = {
160+
"year": 2026,
161+
"max": 42,
162+
"nb": [
163+
["2026-01-01", 0],
164+
["2026-01-02", 18],
165+
["2026-01-03", 21],
166+
],
167+
}
168+
169+
result = detect(
170+
yearly,
171+
kind="yearly",
172+
top=5,
173+
holiday_profile="public-worker",
174+
activity_signal="lack",
175+
)
176+
print(result["results"][0]["id"], result["results"][0]["label"])
177+
```
178+
179+
### `analyze_activity(data, kind="auto")`
180+
181+
Use `analyze_activity` when you only need the generic activity classification
182+
without timezone or holiday-region rankings. It returns fields such as
183+
`activity_type`, `score`, and `shares`. Weekly inputs are classified from local
184+
business-hours versus weekend/off-hours activity; yearly inputs compare weekday
185+
and weekend activity.
186+
187+
```python
188+
from tempolocus import analyze_activity, load_json
189+
190+
activity = analyze_activity(load_json("samples/year.json"), kind="yearly")
191+
print(activity["activity_type"], activity["score"])
192+
```
193+
194+
### Input shape reference
195+
196+
| Kind | Python shape | Notes |
197+
| --- | --- | --- |
198+
| `weekly` | `list[dict]` with `day`, `hour`, and `count` | `day` is `0` through `6`; `hour` is `0` through `23`; buckets are interpreted as UTC. |
199+
| `yearly` | `dict` with `year`, `max`, and `nb` | `nb` is a list of `[YYYY-MM-DD, count]` pairs. Missing days inside the observed range are filled as zero activity. |
200+
| `timestamps` | `list[str | int | float]` | Strings are parsed as UTC timestamps; numbers are Unix epoch seconds in UTC. |
201+
202+
Invalid inputs raise `tempolocus.core.DetectionError`, a subclass of
203+
`ValueError`. Catch it around user-supplied data if you need to return a custom
204+
error response:
205+
206+
```python
207+
from tempolocus import detect
208+
from tempolocus.core import DetectionError
209+
210+
try:
211+
result = detect(user_supplied_data)
212+
except DetectionError as error:
213+
result = {"error": str(error)}
214+
```
215+
72216
## Example
73217

74218
~~~

0 commit comments

Comments
 (0)