@@ -69,6 +69,150 @@ why the activity occurred.
6969This is a heuristic first pass. Weekly data cannot uniquely identify an IANA
7070timezone without dates, and yearly data is sensitive to the meaning of the
7171activity 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