pulse-code 1.0.1__py3-none-any.whl

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 (82) hide show
  1. pulse/__init__.py +1 -0
  2. pulse/__main__.py +4 -0
  3. pulse/catalog.py +102 -0
  4. pulse/cli.py +984 -0
  5. pulse/data/catalog.json +1599 -0
  6. pulse/data/queries_index.json +328 -0
  7. pulse/data/variable_labels.json +1338 -0
  8. pulse/llm_builder.py +732 -0
  9. pulse/matcher.py +180 -0
  10. pulse/queries/aids-cases-by-year-1981-1999-req.xml +178 -0
  11. pulse/queries/births-by-year-1995-2002-req.xml +226 -0
  12. pulse/queries/births-by-year-2003-2006-req.xml +306 -0
  13. pulse/queries/births-by-year-2007-2024-req.xml +334 -0
  14. pulse/queries/cancer-incidence-by-site-by-year-1999-2022-req.xml +174 -0
  15. pulse/queries/cancer-mortality-by-site-by-year-2018-2023-req.xml +166 -0
  16. pulse/queries/covid-deaths-by-race-2020-2023-req.xml +529 -0
  17. pulse/queries/drug-deaths-by-month-1999-2020-req.xml +436 -0
  18. pulse/queries/drug-deaths-by-month-2018-2024-req.xml +544 -0
  19. pulse/queries/drug-deaths-by-year-1999-2020-req.xml +436 -0
  20. pulse/queries/drug-deaths-by-year-2018-2024-req.xml +536 -0
  21. pulse/queries/fentanyl-deaths-by-month-1999-2020-req.xml +430 -0
  22. pulse/queries/fentanyl-deaths-by-month-2018-2024-req.xml +530 -0
  23. pulse/queries/fetal-deaths-by-cause-by-year-2014-2024-req.xml +530 -0
  24. pulse/queries/fetal-deaths-by-year-2005-2024-req.xml +322 -0
  25. pulse/queries/heart-vs-cancer-by-sex-2018-2023-req.xml +532 -0
  26. pulse/queries/heat-wave-days-by-county-req.xml +154 -0
  27. pulse/queries/infant-mortality-2018-2023-req.xml +531 -0
  28. pulse/queries/infant-mortality-by-cause-by-year-2007-2023-req.xml +290 -0
  29. pulse/queries/maternal-mortality-by-year-1999-2020-req.xml +351 -0
  30. pulse/queries/maternal-mortality-by-year-2018-2024-req.xml +413 -0
  31. pulse/queries/mortality-by-race-sex-2018-2023-req.xml +490 -0
  32. pulse/queries/mortality-by-year-cause-1979-1998-req.xml +222 -0
  33. pulse/queries/mortality-by-year-cause-1999-2020-req.xml +434 -0
  34. pulse/queries/mortality-by-year-cause-2021-2024-req.xml +529 -0
  35. pulse/queries/opioid-overdose-deaths-2018-2024-req.xml +544 -0
  36. pulse/queries/pm25-by-year-2003-2011-req.xml +194 -0
  37. pulse/queries/provisional-births-by-month-2023-req.xml +854 -0
  38. pulse/queries/racial-mortality-gap-2018-2023-req.xml +531 -0
  39. pulse/queries/std-cases-by-disease-by-year-1984-2014-req.xml +178 -0
  40. pulse/queries/suicide-by-sex-1999-2020-req.xml +411 -0
  41. pulse/queries/suicide-by-sex-2021-2024-req.xml +551 -0
  42. pulse/queries/tb-cases-by-year-1993-2023-req.xml +206 -0
  43. pulse/queries/tick-borne-diseases-by-year-2016-2023-req.xml +125 -0
  44. pulse/queries/underlying-cause-mortality-by-year-1999-2020-req.xml +350 -0
  45. pulse/queries/unintentional-injuries-by-age-2018-2023-req.xml +531 -0
  46. pulse/templates/D10-base.xml +226 -0
  47. pulse/templates/D104-base.xml +142 -0
  48. pulse/templates/D117-base.xml +110 -0
  49. pulse/templates/D128-base.xml +182 -0
  50. pulse/templates/D140-base.xml +318 -0
  51. pulse/templates/D141-base.xml +454 -0
  52. pulse/templates/D149-base.xml +878 -0
  53. pulse/templates/D157-base.xml +490 -0
  54. pulse/templates/D158-base.xml +406 -0
  55. pulse/templates/D159-base.xml +774 -0
  56. pulse/templates/D16-base.xml +266 -0
  57. pulse/templates/D176-base.xml +526 -0
  58. pulse/templates/D178-base.xml +158 -0
  59. pulse/templates/D18-base.xml +262 -0
  60. pulse/templates/D192-base.xml +854 -0
  61. pulse/templates/D204-base.xml +142 -0
  62. pulse/templates/D23-base.xml +258 -0
  63. pulse/templates/D27-base.xml +342 -0
  64. pulse/templates/D31-base.xml +262 -0
  65. pulse/templates/D60-base.xml +274 -0
  66. pulse/templates/D61-base.xml +250 -0
  67. pulse/templates/D66-base.xml +378 -0
  68. pulse/templates/D69-base.xml +278 -0
  69. pulse/templates/D73-base.xml +182 -0
  70. pulse/templates/D74-base.xml +254 -0
  71. pulse/templates/D76-base.xml +350 -0
  72. pulse/templates/D77-base.xml +434 -0
  73. pulse/templates/D8-base.xml +314 -0
  74. pulse/templates/D80-base.xml +174 -0
  75. pulse/templates/D81-base.xml +178 -0
  76. pulse/wonder_client.py +161 -0
  77. pulse_code-1.0.1.dist-info/METADATA +249 -0
  78. pulse_code-1.0.1.dist-info/RECORD +82 -0
  79. pulse_code-1.0.1.dist-info/WHEEL +5 -0
  80. pulse_code-1.0.1.dist-info/entry_points.txt +2 -0
  81. pulse_code-1.0.1.dist-info/licenses/LICENSE +121 -0
  82. pulse_code-1.0.1.dist-info/top_level.txt +1 -0
pulse/wonder_client.py ADDED
@@ -0,0 +1,161 @@
1
+ """CDC WONDER HTTP client and response parser."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ import xml.etree.ElementTree as ET
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+ from typing import Any, Optional
10
+
11
+ import requests
12
+
13
+
14
+ @dataclass
15
+ class ResponseCell:
16
+ label: Optional[str] = None
17
+ value: Optional[str] = None
18
+ data_total: Optional[str] = None
19
+
20
+ def numeric(self) -> Optional[float]:
21
+ raw = self.value or self.data_total
22
+ if raw is None:
23
+ return None
24
+ try:
25
+ return float(raw.replace(",", ""))
26
+ except ValueError, AttributeError:
27
+ return None
28
+
29
+
30
+ @dataclass
31
+ class ResponseRow:
32
+ cells: list[ResponseCell]
33
+ is_total: bool = False
34
+
35
+
36
+ class WonderClient:
37
+ BASE_URL = "https://wonder.cdc.gov/controller/datarequest"
38
+
39
+ def __init__(self, timeout: int = 120) -> None:
40
+ self.timeout = timeout
41
+ self.session = requests.Session()
42
+
43
+ def query_from_xml(self, dataset_id: str, xml: str) -> str:
44
+ data = {"request_xml": xml, "accept_datause_restrictions": "true"}
45
+ resp = self.session.post(
46
+ f"{self.BASE_URL}/{dataset_id}", data=data, timeout=self.timeout
47
+ )
48
+ if resp.status_code != 200:
49
+ raise RuntimeError(
50
+ f"CDC WONDER returned HTTP {resp.status_code}: {resp.text[:400]}"
51
+ )
52
+ return resp.text
53
+
54
+ def execute_file(self, path: str | Path) -> str:
55
+ xml = Path(path).read_text()
56
+ dataset_id = self._extract_dataset_id(xml)
57
+ if not dataset_id:
58
+ raise ValueError(f"Could not find dataset_code in {path}")
59
+ return self.query_from_xml(dataset_id, xml)
60
+
61
+ @staticmethod
62
+ def _extract_dataset_id(xml: str) -> Optional[str]:
63
+ try:
64
+ root = ET.fromstring(xml)
65
+ el = root.find(".//parameter[name='dataset_code']/value")
66
+ return el.text if el is not None else None
67
+ except ET.ParseError:
68
+ return None
69
+
70
+ def parse_rows(self, xml: str) -> list[ResponseRow]:
71
+ root = ET.fromstring(xml)
72
+ table = root.find(".//data-table")
73
+ if table is None:
74
+ raise ValueError("No <data-table> found in CDC WONDER response")
75
+
76
+ rows: list[ResponseRow] = []
77
+ for r in table.findall("r"):
78
+ cells = []
79
+ is_total = False
80
+ for c in r.findall("c"):
81
+ dt = c.get("dt")
82
+ if dt is not None:
83
+ is_total = True
84
+ cells.append(
85
+ ResponseCell(label=c.get("l"), value=c.get("v"), data_total=dt)
86
+ )
87
+ rows.append(ResponseRow(cells=cells, is_total=is_total))
88
+ return rows
89
+
90
+ def get_headers(self, xml: str) -> list[str]:
91
+ root = ET.fromstring(xml)
92
+ var_labels: dict[str, str] = {}
93
+ for var in root.findall(".//*[@code]"):
94
+ code = var.get("code")
95
+ label = var.get("label")
96
+ if code and label:
97
+ var_labels[code] = label
98
+ for hier in var.findall("hier-level"):
99
+ h_code = hier.get("code")
100
+ h_label = hier.get("label")
101
+ if h_code and h_label:
102
+ var_labels[h_code] = h_label
103
+
104
+ headers: list[str] = []
105
+ byvars = root.find(".//byvariables")
106
+ if byvars is not None:
107
+ for bv in byvars.findall("variable"):
108
+ code = bv.get("code")
109
+ headers.append(var_labels.get(code, code or ""))
110
+
111
+ measure_labels: dict[str, str] = {}
112
+ for m in root.findall(".//measure[@code]"):
113
+ c = m.get("code")
114
+ label = m.get("label")
115
+ if c and label:
116
+ measure_labels[c] = label
117
+
118
+ ms = root.find(".//response//measure-selections")
119
+ if ms is not None:
120
+ for m in ms.findall("measure"):
121
+ c = m.get("code")
122
+ if c and not re.search(r"\.M\d{2,}$", c):
123
+ headers.append(measure_labels.get(c, c or ""))
124
+
125
+ return headers or [f"Col {i + 1}" for i in range(6)]
126
+
127
+ def to_records(self, xml: str) -> list[dict[str, Any]]:
128
+ headers = self.get_headers(xml)
129
+ rows = self.parse_rows(xml)
130
+ records = []
131
+ for row in rows:
132
+ record: dict[str, Any] = {}
133
+ for i, cell in enumerate(row.cells):
134
+ key = headers[i] if i < len(headers) else f"col_{i}"
135
+ if cell.label:
136
+ record[key] = cell.label
137
+ else:
138
+ num = cell.numeric()
139
+ record[key] = (
140
+ num if num is not None else (cell.value or cell.data_total)
141
+ )
142
+ if record:
143
+ records.append(record)
144
+ return records
145
+
146
+ def to_arrays(self, xml: str) -> tuple[list[str], list[list[Any]]]:
147
+ headers = self.get_headers(xml)
148
+ rows = self.parse_rows(xml)
149
+ data: list[list[Any]] = []
150
+ for row in rows:
151
+ r: list[Any] = []
152
+ for cell in row.cells:
153
+ if cell.label:
154
+ r.append(cell.label)
155
+ else:
156
+ num = cell.numeric()
157
+ r.append(
158
+ num if num is not None else (cell.value or cell.data_total)
159
+ )
160
+ data.append(r)
161
+ return headers, data
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: pulse-code
3
+ Version: 1.0.1
4
+ Summary: CDC WONDER query CLI — explore, build, and refine public health data queries
5
+ Requires-Python: >=3.14
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: anthropic==0.115.1
9
+ Requires-Dist: openai==2.44.0
10
+ Requires-Dist: pydantic==2.13.4
11
+ Requires-Dist: python-dotenv==1.2.2
12
+ Requires-Dist: requests==2.34.2
13
+ Requires-Dist: rich==15.0.0
14
+ Requires-Dist: socksio==1.0.0
15
+ Requires-Dist: typer==0.26.8
16
+ Dynamic: license-file
17
+
18
+ # pulse
19
+
20
+ CDC WONDER public health query CLI — explore datasets, run bundled queries, and use Claude to build and refine custom XML queries for public health data that Americans should care about.
21
+
22
+ ## What is this?
23
+
24
+ [CDC WONDER](https://wonder.cdc.gov/) (Wide-ranging ONline Data for Epidemiologic Research) is the government's primary interface for public health statistics: drug overdose deaths, maternal mortality, birth rates, COVID deaths by race, suicide trends, vaccine adverse events, and much more. Its XML API is powerful but opaque.
25
+
26
+ `pulse` makes it usable:
27
+
28
+ - **Explore** all datasets with clear descriptions of what they cover and when
29
+ - **Search** by topic to find the right dataset or a working example query
30
+ - **Run** bundled, validated XML queries directly against the CDC API
31
+ - **Build** new queries from natural language using Claude
32
+ - **Refine** existing queries with conversational feedback
33
+
34
+ ## Setup
35
+
36
+ ```bash
37
+ # Install (requires Python 3.12+)
38
+ uv sync
39
+
40
+ # For build/query/refine/compare/chat commands, set your Anthropic API key:
41
+ export ANTHROPIC_API_KEY=sk-ant-...
42
+ # or put it in a .env file:
43
+ echo "ANTHROPIC_API_KEY=sk-ant-..." > .env
44
+ ```
45
+
46
+ ### LLM provider
47
+
48
+ `pulse` defaults to Anthropic Claude but can also run against an Azure
49
+ OpenAI Foundry deployment (e.g. GPT-5.4). Select the provider with
50
+ `LLM_PROVIDER` (defaults to `anthropic`):
51
+
52
+ ```bash
53
+ # Anthropic (default) — needs ANTHROPIC_API_KEY as above
54
+
55
+ # Azure OpenAI Foundry
56
+ export LLM_PROVIDER=azure_openai
57
+ export AZURE_OPENAI_API_KEY=...
58
+ export AZURE_OPENAI_ENDPOINT=https://<your-resource>.openai.azure.com
59
+ export AZURE_OPENAI_DEPLOYMENT=<your-gpt-5.4-deployment-name>
60
+ export AZURE_OPENAI_API_VERSION=<api-version-your-resource-supports>
61
+ ```
62
+
63
+ All four `AZURE_OPENAI_*` variables are required when `LLM_PROVIDER=azure_openai`;
64
+ `pulse` will tell you which ones are missing. These can also go in a `.env`
65
+ file alongside `ANTHROPIC_API_KEY`.
66
+
67
+ If the LLM endpoint isn't directly reachable — e.g. an Azure OpenAI resource
68
+ with public network access disabled, requiring a private endpoint — bridge
69
+ the connection through a proxy with `LLM_HTTP_PROXY`. Applies to both
70
+ providers, and supports `http://`, `https://`, `socks5://`, and `socks5h://`
71
+ (DNS resolved through the proxy):
72
+
73
+ ```bash
74
+ export LLM_HTTP_PROXY=socks5h://user:pass@host:port
75
+ ```
76
+
77
+ ## Commands
78
+
79
+ ### `pulse datasets` — what's available
80
+
81
+ ```bash
82
+ pulse datasets # all datasets
83
+ pulse datasets --topic Mortality # filter by topic
84
+ pulse datasets --json # JSON output
85
+ ```
86
+
87
+ Shows all 26+ CDC WONDER datasets with: topic, year range, what the data covers, number of bundled example queries, and whether age-adjusted rates are available.
88
+
89
+ **Topics:** Mortality · Infant Mortality · Natality · Environment · Vaccine Safety · Infectious Disease
90
+
91
+ ### `pulse info <ID>` — deep dive on a dataset
92
+
93
+ ```bash
94
+ pulse info D176 # Provisional Mortality (2018–present)
95
+ pulse info D66 # Natality / birth data
96
+ pulse info D8 # VAERS vaccine adverse events
97
+ ```
98
+
99
+ Shows: subject description, available measures, key grouping dimensions, and all bundled example queries for that dataset.
100
+
101
+ ### `pulse search "<topic>"` — find what you need
102
+
103
+ ```bash
104
+ pulse search "opioid overdose deaths by state"
105
+ pulse search "maternal mortality by race"
106
+ pulse search "birth rates 2010 to 2020"
107
+ pulse search "tick-borne disease cases" --queries # queries only
108
+ pulse search "recent COVID deaths" --datasets # datasets only
109
+ ```
110
+
111
+ ### `pulse list-queries` — all bundled example queries
112
+
113
+ ```bash
114
+ pulse list-queries
115
+ pulse list-queries --dataset D176 # filter by dataset
116
+ ```
117
+
118
+ 23 working XML queries covering: drug/opioid/fentanyl deaths, maternal mortality, births, COVID deaths by race, suicide, tick-borne diseases, racial mortality gap, infant mortality, heart disease vs. cancer, and more.
119
+
120
+ ### `pulse run <query>` — execute a query
121
+
122
+ ```bash
123
+ # Run a bundled query by filename (no path needed)
124
+ pulse run drug-deaths-by-year-2018-2024-req.xml
125
+
126
+ # Output formats
127
+ pulse run opioid-overdose-deaths-2018-2024-req.xml -f csv
128
+ pulse run mortality-by-year-cause-2021-2024-req.xml -f json
129
+ pulse run births-by-year-2007-2024-req.xml -f table -o births.csv
130
+
131
+ # Run your own query file
132
+ pulse run /path/to/my-query.xml
133
+ ```
134
+
135
+ Hits the live CDC WONDER API. No login required; CDC requires a ~2-minute cooldown between queries.
136
+
137
+ ### `pulse build "<description>"` — build a query with Claude
138
+
139
+ ```bash
140
+ # Requires ANTHROPIC_API_KEY
141
+ pulse build "drug overdose deaths by state and year 2018-2023"
142
+ pulse build "maternal mortality by race, 2018-2023" -o maternal-race.xml
143
+ pulse build "birth rates by age of mother 2010 to 2024" --no-suggest
144
+ ```
145
+
146
+ Suggests closest existing queries first, then calls Claude to build a new XML query. The LLM selects the right dataset and generates overrides merged onto a validated base template.
147
+
148
+ ### `pulse query "<description>"` — build and run in one step
149
+
150
+ ```bash
151
+ pulse query "fentanyl deaths by state 2020-2024" -f csv
152
+ pulse query "infant mortality by race 2018-2023" --save-xml infant-race.xml
153
+ ```
154
+
155
+ ### `pulse refine <file> "<feedback>"` — iterate on a query
156
+
157
+ ```bash
158
+ pulse refine opioid-overdose-deaths-2018-2024-req.xml "break it down by state"
159
+ pulse refine drug-deaths-by-year-2018-2024-req.xml "add sex breakdown" -o drug-sex.xml
160
+ pulse refine drug-deaths-by-year-2018-2024-req.xml "show monthly not yearly" --run -f csv
161
+ ```
162
+
163
+ ## Testing
164
+
165
+ ```bash
166
+ uv run pytest # unit tests only — fast, no network (default)
167
+ uv run pytest -m integration # + integration tests (see below)
168
+ ```
169
+
170
+ Unit tests cover catalog/matcher lookups, XML template merging (including
171
+ the CDC WONDER radio-button-trap regression), AAR constraints, provider
172
+ selection, and the offline-network-free CLI commands.
173
+
174
+ Integration tests (`tests/integration/`) are excluded by default and split
175
+ into two kinds:
176
+
177
+ - **`test_socks_proxy_integration.py`** — always runs. Spins up a local
178
+ SOCKS5 relay and a local mock LLM HTTP server, so it genuinely exercises
179
+ `LLM_HTTP_PROXY` end-to-end (real SOCKS handshake, real HTTP
180
+ request/response) without needing real Azure/Anthropic credentials.
181
+ - **`test_llm_provider_live.py`** — hits whatever `ANTHROPIC_API_KEY` /
182
+ `LLM_PROVIDER=azure_openai` + `AZURE_OPENAI_*` / `LLM_HTTP_PROXY` you
183
+ actually have configured. Skips if credentials aren't set; also skips
184
+ (rather than fails) if the provider is reachable but blocked at the
185
+ network layer (e.g. an Azure OpenAI resource with public access disabled
186
+ and no working proxy) — that's an environment gap, not a code defect.
187
+
188
+ ## Bundled Datasets (with base templates)
189
+
190
+ | ID | Subject | Years |
191
+ |----|---------|-------|
192
+ | D176 | Provisional mortality — opioids, COVID, suicide, heart disease | 2018–present |
193
+ | D157 | Final mortality, single race (MCD+UCD) | 2018–2023 |
194
+ | D158 | Underlying cause of death, single race — maternal mortality | 2018–2023 |
195
+ | D77 | Multiple cause of death — drug deaths (historical) | 1999–2020 |
196
+ | D76 | Underlying cause of death — suicide, cancer (historical) | 1999–2020 |
197
+ | D141 | MCD with US-Mexico border regions | 1999–2020 |
198
+ | D140 | Compressed mortality ICD-10 | 1999–2016 |
199
+ | D16 | Compressed mortality ICD-9 | 1979–1998 |
200
+ | D74 | Compressed mortality ICD-8 | 1968–1978 |
201
+ | D69 | Linked birth/infant death records | 2007–2023 |
202
+ | D159 | Linked birth/infant death, expanded race | 2017–2023 |
203
+ | D31/D18/D23 | Linked birth/infant death (historical) | 1995–2006 |
204
+ | D66 | Natality — birth rates, birth outcomes | 2007–2024 |
205
+ | D149 | Natality, expanded race detail | 2016–2024 |
206
+ | D192 | Provisional natality (monthly) | 2023–present |
207
+ | D27/D10 | Natality (historical) | 1995–2006 |
208
+ | D8 | VAERS vaccine adverse events | 1990–present |
209
+ | D104 | Heat wave days by county | 1981–2010 |
210
+ | D60/D80/D81 | NLDAS temperature, sunlight, precipitation | 1979–2011 |
211
+ | D73 | PM2.5 fine particulate matter | 2003–2011 |
212
+ | D61 | MODIS land surface temperature | 2003–2008 |
213
+
214
+ ## Public Health Questions You Can Answer
215
+
216
+ - How did opioid overdose deaths trend from 1999 to today, broken down by drug type?
217
+ - What is the racial gap in COVID-19 mortality?
218
+ - How does maternal mortality differ by race and state?
219
+ - Which states have the highest suicide rates by sex?
220
+ - How have birth rates changed by age of mother since 1995?
221
+ - Are tick-borne disease cases increasing?
222
+ - How do PM2.5 air quality levels correlate with where people live?
223
+ - What are the most common adverse events reported after COVID vaccines?
224
+
225
+ ## Releasing
226
+
227
+ Releases are cut by pushing a tag. `publish.yml` (single workflow, one run
228
+ per tag) handles the rest as three sequential jobs:
229
+
230
+ 1. Bump `version` in `pyproject.toml`, commit it.
231
+ 2. `git tag vX.Y.Z && git push origin vX.Y.Z`
232
+ 3. **`build`** builds the sdist/wheel, failing fast if the tag doesn't match
233
+ `pyproject.toml`'s version.
234
+ 4. **`release`** (needs `build`) creates the GitHub Release with the built
235
+ artifacts attached — the source of truth for what shipped.
236
+ 5. **`publish`** (needs `release`) publishes those same artifacts to PyPI
237
+ (`pulse-code`) via trusted publishing (OIDC) against the `prod`
238
+ environment — no API tokens stored in the repo.
239
+
240
+ The `needs:` chain means a failure at any step blocks everything after it —
241
+ e.g. a PyPI hiccup can't leave a GitHub Release around for a package that
242
+ isn't actually installable. If the `publish` job fails after `release`
243
+ succeeds, use "Re-run failed jobs" on that workflow run rather than
244
+ re-tagging. PyPI publishing is immutable: once a version is published it
245
+ can't be re-uploaded, so a bad release means bumping to a new version.
246
+
247
+ ## Based On
248
+
249
+ Built using [fartbagxp/health](https://github.com/fartbagxp/health) as reference — a comprehensive collection of CDC data pipelines and the CDC WONDER XML API client and LLM query builder this tool builds on.
@@ -0,0 +1,82 @@
1
+ pulse/__init__.py,sha256=xI4qey-ZxVJZMsX988bo8Oz-DxhdCoFwRoqzgd3fdUw,84
2
+ pulse/__main__.py,sha256=atmJJ_NZbVf8svKlDGJZdvdENC-a8YWs6kd8kvlvh6Q,64
3
+ pulse/catalog.py,sha256=K6hkYxe5I4GDs1JJJjChbG8NKrWptdCesilk0GStaGM,2765
4
+ pulse/cli.py,sha256=ju_yIl_-6H3WwCsPgkMlO5BglSioW-MplbWZu08JMZA,34207
5
+ pulse/llm_builder.py,sha256=FQwevCiyGRHA61ii9GGY-zofPT31eKv19I6WOLWCxHg,26594
6
+ pulse/matcher.py,sha256=ir7uorJY1Tz5eyGsIIevINo4edJ1ZHqPjcdYRdRwHLw,5856
7
+ pulse/wonder_client.py,sha256=JgBDeUThwack3W2C-0Oa-6bVI2RUrt7vVzda3xYalVY,5406
8
+ pulse/data/catalog.json,sha256=Cdx4oTXFapI9_RBKnAfrlseDt7D7TUJ1IRkReF0cJ1w,45383
9
+ pulse/data/queries_index.json,sha256=H-rGCV69PWzVQ8epCWpRupH0u6Qe8DHh4lxVF9wQvBM,14728
10
+ pulse/data/variable_labels.json,sha256=I8oiKrMAJaqdeWM_tE-tqQs5NF4kAh-h-MsEONOd854,51073
11
+ pulse/queries/aids-cases-by-year-1981-1999-req.xml,sha256=L0xGgnJlsUDy2lXTKulMuSAhxkez4CpHvVY2eg8_bRA,3437
12
+ pulse/queries/births-by-year-1995-2002-req.xml,sha256=kfo4busCtmol3zyQaRMRIhZ-073YT4KQPxoOiHmAqQw,4330
13
+ pulse/queries/births-by-year-2003-2006-req.xml,sha256=69UqfY0UhAkQR9fBhaopWOTeL7yjlYIVWgmbqJE64cw,5853
14
+ pulse/queries/births-by-year-2007-2024-req.xml,sha256=k7_4JzUnqyovI8rxicxRVNCFScPWrpk1AY44SXlSacg,6392
15
+ pulse/queries/cancer-incidence-by-site-by-year-1999-2022-req.xml,sha256=VPCuYpjy-qJp0ujxs2yM_ZfBkor87EBw5Y-Hyi8XaqI,3420
16
+ pulse/queries/cancer-mortality-by-site-by-year-2018-2023-req.xml,sha256=_978FpII4iE47dT4HVtbsSRLDmP-HiYlzAiKMCa7X9Q,3277
17
+ pulse/queries/covid-deaths-by-race-2020-2023-req.xml,sha256=vA2-3fO698NdKVyoP6saRasUqiWI-2BMClsFAd3rxWE,10006
18
+ pulse/queries/drug-deaths-by-month-1999-2020-req.xml,sha256=2BL4723jhoLxcRhMNPgi8MLmM50Xy9aqn7BeBXE4uP8,8068
19
+ pulse/queries/drug-deaths-by-month-2018-2024-req.xml,sha256=PZyg2H7eyj5S3oMH2kStahA0Po2r60-gn5VsrEiTiVE,10167
20
+ pulse/queries/drug-deaths-by-year-1999-2020-req.xml,sha256=2GSmP17FExLkWLKdQRxp4YhEkoRmLyX5-0aLiix2_zA,8061
21
+ pulse/queries/drug-deaths-by-year-2018-2024-req.xml,sha256=IeGCHcOR4ZOSBcnkfuuRGj8_OSFpAbq761OVO6gq4JA,9993
22
+ pulse/queries/fentanyl-deaths-by-month-1999-2020-req.xml,sha256=HlCHncdAGa7wAC-zwn_kzM3JqCt6eu_AcwwLJFZuaLc,8024
23
+ pulse/queries/fentanyl-deaths-by-month-2018-2024-req.xml,sha256=yNDJ8lIVB1oEgbCSptIX5AtTSJ1TXYc3Q4VcKvmK_FA,9956
24
+ pulse/queries/fetal-deaths-by-cause-by-year-2014-2024-req.xml,sha256=GNhw47kqontko1r4MZ2gbNQcM8TfQJOb9Q7JL8vnyyI,10192
25
+ pulse/queries/fetal-deaths-by-year-2005-2024-req.xml,sha256=RpP8jYNGFSulqgohoueIQ0MLjz4hDM0Eh3PIc9AS3GI,6182
26
+ pulse/queries/heart-vs-cancer-by-sex-2018-2023-req.xml,sha256=MSO7eYD7cf-rH3fvx339QDpCHUaAryPe7S4YcD7voE0,10082
27
+ pulse/queries/heat-wave-days-by-county-req.xml,sha256=hx4WWhXCsqYZ7obyuerYHaoO8nZTSIb5OrWsiel5aOU,2989
28
+ pulse/queries/infant-mortality-2018-2023-req.xml,sha256=pvFA5GS7fTEmNBtUQdI1BSg7GNlXwKvBdyskqEY-92U,10046
29
+ pulse/queries/infant-mortality-by-cause-by-year-2007-2023-req.xml,sha256=SRNVyOdRIaahb9yA707N6DOy0XYcw_X1Z6e57hbVNYM,5572
30
+ pulse/queries/maternal-mortality-by-year-1999-2020-req.xml,sha256=v67tjLV_n3PK9BOPSYeSa4THAXvGecCSJUecTSXb9Eo,6723
31
+ pulse/queries/maternal-mortality-by-year-2018-2024-req.xml,sha256=mfeNg7zF2ZHbi_TCJ-h635iOx_5kgM2DFTnEBNLSO1c,7998
32
+ pulse/queries/mortality-by-race-sex-2018-2023-req.xml,sha256=U0kNBsfY3OOQhQaj7HylK2erUSDgOkpXM_zplVF7drk,9249
33
+ pulse/queries/mortality-by-year-cause-1979-1998-req.xml,sha256=j2RRjN2PdbMOJRC_IuWOJNcPDdQO0XftVTJwGDP2Wok,4272
34
+ pulse/queries/mortality-by-year-cause-1999-2020-req.xml,sha256=CFkxldz4ZPkVLXraLyvPxcnaBIN3-qORxLXn9lkPaRw,8121
35
+ pulse/queries/mortality-by-year-cause-2021-2024-req.xml,sha256=wjY9YbAaedQP8nxeg4nC2gSKSXkIjWACcGn1CQIHodk,9949
36
+ pulse/queries/opioid-overdose-deaths-2018-2024-req.xml,sha256=NQEEiYhkIGe_YlghN9vbOpUEpVi9SDtB3wngi-fHCHA,10335
37
+ pulse/queries/pm25-by-year-2003-2011-req.xml,sha256=74M1EiJLj1htgwDy9oHrQ0zbKcazE0gXIHAlhSX20vw,3748
38
+ pulse/queries/provisional-births-by-month-2023-req.xml,sha256=bafhV59EXeBKsnclDSPg-Cg_lQFXlJZnldRnjCftPKg,16426
39
+ pulse/queries/racial-mortality-gap-2018-2023-req.xml,sha256=FptCuyXX9hBkJp7D943HORZ92J5FADB4lDXI6JVttiM,10049
40
+ pulse/queries/std-cases-by-disease-by-year-1984-2014-req.xml,sha256=T2laPTXhu7z38rNMUhHnYSUTrkCaiq7jwEXUi29L6Pc,3462
41
+ pulse/queries/suicide-by-sex-1999-2020-req.xml,sha256=PXzNSlOHBIzLVPeHfGFnX_MteCHcLjaRxiE7JAJ6AZk,7647
42
+ pulse/queries/suicide-by-sex-2021-2024-req.xml,sha256=sXOcMjOXjxe29D6B9qfjOqVWn66VqadTsdSntb70oqI,10501
43
+ pulse/queries/tb-cases-by-year-1993-2023-req.xml,sha256=KxTqgcYWvjf7Cvo0kPyzmNul1u3urnLmGFEzBl9PBxQ,3927
44
+ pulse/queries/tick-borne-diseases-by-year-2016-2023-req.xml,sha256=3Tc9qTwISXxRehPMo-u8G1L0CVuEc8pkETwZK-9rwzU,2465
45
+ pulse/queries/underlying-cause-mortality-by-year-1999-2020-req.xml,sha256=66SiAoC8TXIicJbG0VZWjd6C0ay_cNz0ULY-sbsN0sk,6705
46
+ pulse/queries/unintentional-injuries-by-age-2018-2023-req.xml,sha256=kFGwke_gYQtVTKm3kRuEErnxAGozAa_exPa6woraTdc,10052
47
+ pulse/templates/D10-base.xml,sha256=-Iq3xCCG6WJlxWHgGbrJD7DfMV3xREhPbO87t9C61uU,4326
48
+ pulse/templates/D104-base.xml,sha256=Eqr5A1xkkIz_XnXWOPizGx9lF7FTRHudbB_HuzJs10I,2778
49
+ pulse/templates/D117-base.xml,sha256=T1LfkS0DQcQY6U9XMQg5d39ERTuTIBhBlXW3KJ1IjiY,2205
50
+ pulse/templates/D128-base.xml,sha256=1j0Laql6j05NzH6X-KTib0ng--EdM2DF4klLJ7pcwY8,3571
51
+ pulse/templates/D140-base.xml,sha256=YWL2VT6baHb_kI6nOX0Cm_IAXtgZlg-mg3lrJ4k6f5k,6135
52
+ pulse/templates/D141-base.xml,sha256=wrRnKVlNaGyEmckkbaZBpVf23iXY73V25IqlzHoSOG8,8752
53
+ pulse/templates/D149-base.xml,sha256=T_d5mDyjHeapfTudAKCBQz8SQKhhBBi-ObLSJ3ohC7I,16865
54
+ pulse/templates/D157-base.xml,sha256=VdJSu8W7I9meB7Q_SdS2ESLnSloHBb7FK7hUerFii0s,9239
55
+ pulse/templates/D158-base.xml,sha256=3ZC5hJzkHZ9y8E-zzGLlKxXnrvlu29R9ra2KqCX3qEk,7834
56
+ pulse/templates/D159-base.xml,sha256=3-jrwiMgTCeglJIk-qUV9E827GSXlkPDe5X5pWuxmLE,14881
57
+ pulse/templates/D16-base.xml,sha256=cT5b-Mm_C7WV1oGDjMYdRwEbheUNxKOBhxaRFCSk6qU,5093
58
+ pulse/templates/D176-base.xml,sha256=VZMLUZBRfXFDA5zQcYELcsKMduTkkMbtYAkz1UcPVqE,9868
59
+ pulse/templates/D178-base.xml,sha256=ZrHE9fCODYA0ZRTgc52wCgQaRtuJs9RdVuLUHf-NF58,3093
60
+ pulse/templates/D18-base.xml,sha256=1Ur7SJortL39qhDaecf7NaSqv0z2MpCe4A3HPTd58g0,5030
61
+ pulse/templates/D192-base.xml,sha256=TJWymMvJFv08cI_Qk6MP1Xp4_9IiPVRr-BpYDvIVnLI,16419
62
+ pulse/templates/D204-base.xml,sha256=F4O4K96vjLPsXXk1ruoYHyhecO0VhLjBmrcb3MMY3MQ,2785
63
+ pulse/templates/D23-base.xml,sha256=ouIeZwORaUjmLkxgYsHAV73uTOBunBXpWaoyCtzyAzs,4959
64
+ pulse/templates/D27-base.xml,sha256=7qnD4caqBfBUy7XbX_pkd3nELVk1UIfkzUiyPWZZSXE,6493
65
+ pulse/templates/D31-base.xml,sha256=f2dV45cO1xaAEz_or_9KLEGx9EZjPi-Rap74-1H0BEk,5030
66
+ pulse/templates/D60-base.xml,sha256=pMSIKNMdCYI_N6iEodaLzZB-vM3B8lX7PABH6fP4hBc,5230
67
+ pulse/templates/D61-base.xml,sha256=PNh6R14S3AecB5jVVee3u4weNHWi3yAlTJIjZEGIUmU,4791
68
+ pulse/templates/D66-base.xml,sha256=gonZO0uvS-iNCvFV9CJH8w1SzxHOBitVPwMKeoqplLM,7176
69
+ pulse/templates/D69-base.xml,sha256=BH7cCtzgbXfonHdNEWwseY3N0Ft3LnlfD4oMxqqmAHo,5330
70
+ pulse/templates/D73-base.xml,sha256=-s2se0voJu9hGRoN1-GM34wc0CTafA1KUoLIDuwBAOQ,3519
71
+ pulse/templates/D74-base.xml,sha256=fTAMPtnlR9rWHNWd14D5s2O3Jd6lesYx0RLAtYCn7gM,4871
72
+ pulse/templates/D76-base.xml,sha256=QU7MZ4uZk54uTbdwMOPX7_k89HQgZl_wGnhSaeAEZgs,6691
73
+ pulse/templates/D77-base.xml,sha256=5iBRy9Jk9VDNG830w7MlDbbQROd6odCCZ-mx7AV0JSs,8107
74
+ pulse/templates/D8-base.xml,sha256=-72s4bB0BQBRVfN-O5CPQgJE4TgtLNFFwQUnfJv5Ykg,5814
75
+ pulse/templates/D80-base.xml,sha256=22oeW7UmjHw7_ca_yPY5IdA9r-9wyhar8GZ-kGeAXnc,3406
76
+ pulse/templates/D81-base.xml,sha256=_NyeAFVT1NVZWiiIYg0RFtOIyOz2a1WjbUi7wnS1Wlc,3482
77
+ pulse_code-1.0.1.dist-info/licenses/LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
78
+ pulse_code-1.0.1.dist-info/METADATA,sha256=-0l2XjjcWEWdIJqo-jJuBFtgx1bSbCLtuZ5qSHr4Jtk,10388
79
+ pulse_code-1.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
80
+ pulse_code-1.0.1.dist-info/entry_points.txt,sha256=8JmklTqLTsHiCLSeKJx-55gnt1mYNFfKuE2rwz3efyo,40
81
+ pulse_code-1.0.1.dist-info/top_level.txt,sha256=gQdwpJBbAgjgx7qW49yUgv8h89nOedqh1oGgfnxmR_g,6
82
+ pulse_code-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pulse = pulse.cli:app
@@ -0,0 +1,121 @@
1
+ Creative Commons Legal Code
2
+
3
+ CC0 1.0 Universal
4
+
5
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12
+ HEREUNDER.
13
+
14
+ Statement of Purpose
15
+
16
+ The laws of most jurisdictions throughout the world automatically confer
17
+ exclusive Copyright and Related Rights (defined below) upon the creator
18
+ and subsequent owner(s) (each and all, an "owner") of an original work of
19
+ authorship and/or a database (each, a "Work").
20
+
21
+ Certain owners wish to permanently relinquish those rights to a Work for
22
+ the purpose of contributing to a commons of creative, cultural and
23
+ scientific works ("Commons") that the public can reliably and without fear
24
+ of later claims of infringement build upon, modify, incorporate in other
25
+ works, reuse and redistribute as freely as possible in any form whatsoever
26
+ and for any purposes, including without limitation commercial purposes.
27
+ These owners may contribute to the Commons to promote the ideal of a free
28
+ culture and the further production of creative, cultural and scientific
29
+ works, or to gain reputation or greater distribution for their Work in
30
+ part through the use and efforts of others.
31
+
32
+ For these and/or other purposes and motivations, and without any
33
+ expectation of additional consideration or compensation, the person
34
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35
+ is an owner of Copyright and Related Rights in the Work, voluntarily
36
+ elects to apply CC0 to the Work and publicly distribute the Work under its
37
+ terms, with knowledge of his or her Copyright and Related Rights in the
38
+ Work and the meaning and intended legal effect of CC0 on those rights.
39
+
40
+ 1. Copyright and Related Rights. A Work made available under CC0 may be
41
+ protected by copyright and related or neighboring rights ("Copyright and
42
+ Related Rights"). Copyright and Related Rights include, but are not
43
+ limited to, the following:
44
+
45
+ i. the right to reproduce, adapt, distribute, perform, display,
46
+ communicate, and translate a Work;
47
+ ii. moral rights retained by the original author(s) and/or performer(s);
48
+ iii. publicity and privacy rights pertaining to a person's image or
49
+ likeness depicted in a Work;
50
+ iv. rights protecting against unfair competition in regards to a Work,
51
+ subject to the limitations in paragraph 4(a), below;
52
+ v. rights protecting the extraction, dissemination, use and reuse of data
53
+ in a Work;
54
+ vi. database rights (such as those arising under Directive 96/9/EC of the
55
+ European Parliament and of the Council of 11 March 1996 on the legal
56
+ protection of databases, and under any national implementation
57
+ thereof, including any amended or successor version of such
58
+ directive); and
59
+ vii. other similar, equivalent or corresponding rights throughout the
60
+ world based on applicable law or treaty, and any national
61
+ implementations thereof.
62
+
63
+ 2. Waiver. To the greatest extent permitted by, but not in contravention
64
+ of, applicable law, Affirmer hereby overtly, fully, permanently,
65
+ irrevocably and unconditionally waives, abandons, and surrenders all of
66
+ Affirmer's Copyright and Related Rights and associated claims and causes
67
+ of action, whether now known or unknown (including existing as well as
68
+ future claims and causes of action), in the Work (i) in all territories
69
+ worldwide, (ii) for the maximum duration provided by applicable law or
70
+ treaty (including future time extensions), (iii) in any current or future
71
+ medium and for any number of copies, and (iv) for any purpose whatsoever,
72
+ including without limitation commercial, advertising or promotional
73
+ purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74
+ member of the public at large and to the detriment of Affirmer's heirs and
75
+ successors, fully intending that such Waiver shall not be subject to
76
+ revocation, rescission, cancellation, termination, or any other legal or
77
+ equitable action to disrupt the quiet enjoyment of the Work by the public
78
+ as contemplated by Affirmer's express Statement of Purpose.
79
+
80
+ 3. Public License Fallback. Should any part of the Waiver for any reason
81
+ be judged legally invalid or ineffective under applicable law, then the
82
+ Waiver shall be preserved to the maximum extent permitted taking into
83
+ account Affirmer's express Statement of Purpose. In addition, to the
84
+ extent the Waiver is so judged Affirmer hereby grants to each affected
85
+ person a royalty-free, non transferable, non sublicensable, non exclusive,
86
+ irrevocable and unconditional license to exercise Affirmer's Copyright and
87
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
88
+ maximum duration provided by applicable law or treaty (including future
89
+ time extensions), (iii) in any current or future medium and for any number
90
+ of copies, and (iv) for any purpose whatsoever, including without
91
+ limitation commercial, advertising or promotional purposes (the
92
+ "License"). The License shall be deemed effective as of the date CC0 was
93
+ applied by Affirmer to the Work. Should any part of the License for any
94
+ reason be judged legally invalid or ineffective under applicable law, such
95
+ partial invalidity or ineffectiveness shall not invalidate the remainder
96
+ of the License, and in such case Affirmer hereby affirms that he or she
97
+ will not (i) exercise any of his or her remaining Copyright and Related
98
+ Rights in the Work or (ii) assert any associated claims and causes of
99
+ action with respect to the Work, in either case contrary to Affirmer's
100
+ express Statement of Purpose.
101
+
102
+ 4. Limitations and Disclaimers.
103
+
104
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
105
+ surrendered, licensed or otherwise affected by this document.
106
+ b. Affirmer offers the Work as-is and makes no representations or
107
+ warranties of any kind concerning the Work, express, implied,
108
+ statutory or otherwise, including without limitation warranties of
109
+ title, merchantability, fitness for a particular purpose, non
110
+ infringement, or the absence of latent or other defects, accuracy, or
111
+ the present or absence of errors, whether or not discoverable, all to
112
+ the greatest extent permissible under applicable law.
113
+ c. Affirmer disclaims responsibility for clearing rights of other persons
114
+ that may apply to the Work or any use thereof, including without
115
+ limitation any person's Copyright and Related Rights in the Work.
116
+ Further, Affirmer disclaims responsibility for obtaining any necessary
117
+ consents, permissions or other rights required for any use of the
118
+ Work.
119
+ d. Affirmer understands and acknowledges that Creative Commons is not a
120
+ party to this document and has no duty or obligation with respect to
121
+ this CC0 or use of the Work.
@@ -0,0 +1 @@
1
+ pulse