fyron 0.1.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.
- fyron-0.1.0/LICENSE +21 -0
- fyron-0.1.0/PKG-INFO +576 -0
- fyron-0.1.0/README.md +545 -0
- fyron-0.1.0/pyproject.toml +40 -0
- fyron-0.1.0/src/fyron/__init__.py +65 -0
- fyron-0.1.0/src/fyron/core/__init__.py +14 -0
- fyron-0.1.0/src/fyron/core/env.py +37 -0
- fyron-0.1.0/src/fyron/core/io.py +394 -0
- fyron-0.1.0/src/fyron/dicom/__init__.py +5 -0
- fyron-0.1.0/src/fyron/dicom/client.py +523 -0
- fyron-0.1.0/src/fyron/documents/__init__.py +5 -0
- fyron-0.1.0/src/fyron/documents/client.py +278 -0
- fyron-0.1.0/src/fyron/fhir/__init__.py +49 -0
- fyron-0.1.0/src/fyron/fhir/auth.py +282 -0
- fyron-0.1.0/src/fyron/fhir/rest.py +987 -0
- fyron-0.1.0/src/fyron/fhir/sql.py +478 -0
- fyron-0.1.0/src/fyron/fhir/types.py +40 -0
- fyron-0.1.0/src/fyron/fhir/utils.py +309 -0
- fyron-0.1.0/src/fyron/llm/__init__.py +5 -0
- fyron-0.1.0/src/fyron/llm/agent.py +649 -0
fyron-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bits & Flames
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fyron-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fyron
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Fyron is an open-source Python toolkit for interoperable healthcare data and AI workflows. It provides unified access to FHIR data via REST APIs and relational (SQL-backed) FHIR servers, integrates DICOM imaging sources, and enables semantic exploration of clinical narratives using modern language models.
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: FHIR,DICOM,healthcare,clinical,NLP,LLM
|
|
8
|
+
Author: Bits & Flames
|
|
9
|
+
Author-email: hello@bitsandflames.ai
|
|
10
|
+
Requires-Python: >=3.10,<4.0
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Requires-Dist: SimpleITK (>=2.3.1,<3.0.0)
|
|
19
|
+
Requires-Dist: dicomweb-client (>=0.59.1,<0.60.0)
|
|
20
|
+
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
21
|
+
Requires-Dist: psycopg (>=3.1.19,<4.0.0)
|
|
22
|
+
Requires-Dist: pydicom (>=2.4.4,<3.0.0)
|
|
23
|
+
Requires-Dist: pyjwt (>=2.9.0,<3.0.0)
|
|
24
|
+
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
25
|
+
Requires-Dist: requests (>=2.32.0,<3.0.0)
|
|
26
|
+
Requires-Dist: tqdm (>=4.66.0,<5.0.0)
|
|
27
|
+
Project-URL: Homepage, https://github.com/bitsandflames/fyron
|
|
28
|
+
Project-URL: Repository, https://github.com/bitsandflames/fyron
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Fyron
|
|
32
|
+

|
|
33
|
+
<div align="center">
|
|
34
|
+
<img alt="Python" src="https://img.shields.io/badge/python-3.10%2B-blue" />
|
|
35
|
+
<img alt="License" src="https://img.shields.io/badge/license-MIT-green" />
|
|
36
|
+
<img alt="FHIR" src="https://img.shields.io/badge/FHIR-enabled-0b7dda" />
|
|
37
|
+
<img alt="DICOM" src="https://img.shields.io/badge/DICOM-supported-2e7d32" />
|
|
38
|
+
<img alt="Documents" src="https://img.shields.io/badge/Documents-supported-6a1b9a" />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
Fyron is a pragmatic Python toolkit for interoperable healthcare data and AI workflows. It gives developers clean, testable primitives for FHIR (REST + SQL), DICOM imaging, document downloads, Teable integration, and LLM-assisted analysis without hiding the underlying protocols.
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
Install and run a first FHIR query in minutes.
|
|
45
|
+
|
|
46
|
+
This installs the package from PyPI.
|
|
47
|
+
```bash
|
|
48
|
+
pip install fyron
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Requires Python 3.10+.
|
|
52
|
+
|
|
53
|
+
This copies the sample environment file so you can fill in your credentials.
|
|
54
|
+
```bash
|
|
55
|
+
cp .example.env .env
|
|
56
|
+
# edit .env with your credentials
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This loads the .env explicitly (recommended in production or scripts).
|
|
60
|
+
```python
|
|
61
|
+
from fyron import load_env
|
|
62
|
+
|
|
63
|
+
load_env()
|
|
64
|
+
```
|
|
65
|
+
Options: `path` (explicit .env), `override` (replace existing env vars), `warn_if_missing`.
|
|
66
|
+
|
|
67
|
+
This runs a minimal REST query and returns a DataFrame.
|
|
68
|
+
```python
|
|
69
|
+
from fyron import FHIRRestClient
|
|
70
|
+
|
|
71
|
+
client = FHIRRestClient()
|
|
72
|
+
patients = client.query_df(
|
|
73
|
+
resource_type="Patient",
|
|
74
|
+
params={"_count": 25, "_sort": "_id"},
|
|
75
|
+
max_pages=1,
|
|
76
|
+
)
|
|
77
|
+
print(patients.head())
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Who It’s For
|
|
81
|
+
- Data scientists and ML engineers building clinical datasets and cohorts.
|
|
82
|
+
- Clinical informatics and analytics teams working across FHIR, SQL, and imaging.
|
|
83
|
+
- Researchers who need reproducible pipelines and methods-ready documentation.
|
|
84
|
+
- Engineers integrating healthcare data into apps, dashboards, or LLM workflows.
|
|
85
|
+
|
|
86
|
+
## Package Layout
|
|
87
|
+
```
|
|
88
|
+
fyron/
|
|
89
|
+
fhir/ # REST + SQL clients, auth, types, utilities
|
|
90
|
+
dicom/ # DICOM downloader
|
|
91
|
+
documents/ # Document downloader
|
|
92
|
+
llm/ # LLM agent
|
|
93
|
+
core/ # IO + integrations
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Supported Tabs
|
|
97
|
+
Use the tabs below to see what Fyron supports in each area.
|
|
98
|
+
|
|
99
|
+
<details open>
|
|
100
|
+
<summary><strong>FHIR</strong></summary>
|
|
101
|
+
REST client with pagination, caching, multiprocessing, and FHIRPath extraction. SQL client for Postgres-backed FHIR stores.
|
|
102
|
+
</details>
|
|
103
|
+
|
|
104
|
+
<details>
|
|
105
|
+
<summary><strong>DICOM</strong></summary>
|
|
106
|
+
DICOMweb downloads with optional NIfTI conversion and per-series/study manifests.
|
|
107
|
+
</details>
|
|
108
|
+
|
|
109
|
+
<details>
|
|
110
|
+
<summary><strong>Documents</strong></summary>
|
|
111
|
+
Deterministic URL downloads with metadata, hashes, and DataFrame helpers.
|
|
112
|
+
</details>
|
|
113
|
+
|
|
114
|
+
<details>
|
|
115
|
+
<summary><strong>Teable</strong></summary>
|
|
116
|
+
Read/write DataFrames to Teable tables with pagination, overwrite support, and base/table creation.
|
|
117
|
+
</details>
|
|
118
|
+
|
|
119
|
+
<details>
|
|
120
|
+
<summary><strong>LLM</strong></summary>
|
|
121
|
+
Prompting utilities for text, documents, images, and PDFs via configurable providers.
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
## Setup
|
|
125
|
+
Fyron reads environment variables (see `.example.env`). Minimal examples:
|
|
126
|
+
|
|
127
|
+
This shows the smallest set of environment variables for the main features.
|
|
128
|
+
```bash
|
|
129
|
+
# FHIR REST
|
|
130
|
+
export FHIR_BASE_URL="https://example.org/fhir"
|
|
131
|
+
export FHIR_AUTH_URL="https://example.org/auth/token"
|
|
132
|
+
export FHIR_REFRESH_URL="https://example.org/auth/refresh"
|
|
133
|
+
export FHIR_USER="alice"
|
|
134
|
+
export FHIR_PASSWORD="secret"
|
|
135
|
+
|
|
136
|
+
# DICOMweb
|
|
137
|
+
export DICOM_WEB_URL="https://pacs.example.org/dicomweb"
|
|
138
|
+
export DICOM_USER="alice"
|
|
139
|
+
export DICOM_PASSWORD="secret"
|
|
140
|
+
|
|
141
|
+
# FHIR SQL
|
|
142
|
+
export FHIR_DB_HOST="localhost"
|
|
143
|
+
export FHIR_DB_PORT="5432"
|
|
144
|
+
export FHIR_DB_NAME="fhir"
|
|
145
|
+
export FHIR_DB_USER="postgres"
|
|
146
|
+
export FHIR_DB_PASSWORD="secret"
|
|
147
|
+
|
|
148
|
+
# LLM
|
|
149
|
+
export LLM_PROVIDER="openai"
|
|
150
|
+
export LLM_BASE_URL="https://api.openai.com"
|
|
151
|
+
export LLM_API_KEY="your_api_key"
|
|
152
|
+
export LLM_MODEL="gpt-4.1-mini"
|
|
153
|
+
|
|
154
|
+
# Teable
|
|
155
|
+
export TEABLE_BASE_URL="https://app.teable.ai"
|
|
156
|
+
export TEABLE_TOKEN="your_teable_token"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Notes:
|
|
160
|
+
- FHIR token auth uses `FHIR_USER`/`FHIR_PASSWORD` plus `FHIR_AUTH_URL`.
|
|
161
|
+
- Use `Auth.token_env(...)` for the simplest token-based auth flow.
|
|
162
|
+
- FHIRPath extraction requires `fhirpathpy` (`pip install fhirpathpy`).
|
|
163
|
+
- Use `load_env()` to load a `.env` from the current working directory.
|
|
164
|
+
## Core Workflows
|
|
165
|
+
|
|
166
|
+
### FHIR REST
|
|
167
|
+
This queries a single FHIR resource type and returns rows as a DataFrame.
|
|
168
|
+
```python
|
|
169
|
+
from fyron import FHIRRestClient
|
|
170
|
+
|
|
171
|
+
client = FHIRRestClient()
|
|
172
|
+
patients = client.query_df(
|
|
173
|
+
resource_type="Patient",
|
|
174
|
+
params={"_count": 25, "_sort": "_id"},
|
|
175
|
+
max_pages=1,
|
|
176
|
+
)
|
|
177
|
+
print(patients.head())
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`FHIRRestClient` arguments:
|
|
181
|
+
|
|
182
|
+
| Argument | Description | Values/Defaults |
|
|
183
|
+
| --- | --- | --- |
|
|
184
|
+
| `base_url` | FHIR server base URL | Defaults to `FHIR_BASE_URL` |
|
|
185
|
+
| `auth` | Reuse `Auth` or `requests.Session` | Optional |
|
|
186
|
+
| `num_processes` | Parallel worker count | Default `4` |
|
|
187
|
+
| `request_timeout` | Per-request timeout in seconds | Default `30` |
|
|
188
|
+
| `log_requests` | Log timing and summaries | `True`/`False` |
|
|
189
|
+
| `return_fhir_obj` | Wrap bundles as `FHIRObj` | `True`/`False` |
|
|
190
|
+
|
|
191
|
+
This uses FHIRPath expressions to extract specific fields.
|
|
192
|
+
```python
|
|
193
|
+
from fyron import FHIRRestClient
|
|
194
|
+
|
|
195
|
+
client = FHIRRestClient()
|
|
196
|
+
|
|
197
|
+
df = client.query_df(
|
|
198
|
+
resource_type="Observation",
|
|
199
|
+
params={"_count": 25},
|
|
200
|
+
fhir_paths=[
|
|
201
|
+
("patient_id", "subject.reference.replace('Patient/', '')"),
|
|
202
|
+
("code", "code.coding.code"),
|
|
203
|
+
("value", "valueQuantity.value"),
|
|
204
|
+
],
|
|
205
|
+
max_pages=1,
|
|
206
|
+
)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
This applies a custom bundle processor with safe FHIR extraction.
|
|
210
|
+
`safe_get` supports dotted paths and list indexes (for example, `"code.coding[0].code"`).
|
|
211
|
+
```python
|
|
212
|
+
from fyron import FHIRObj, FHIRRestClient, safe_get
|
|
213
|
+
|
|
214
|
+
client = FHIRRestClient(return_fhir_obj=True)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def process_bundle(bundle):
|
|
218
|
+
bundle = FHIRObj(**bundle) if isinstance(bundle, dict) else bundle
|
|
219
|
+
rows = []
|
|
220
|
+
for entry in bundle.entry or []:
|
|
221
|
+
resource = entry.resource
|
|
222
|
+
rows.append({
|
|
223
|
+
"resourceType": safe_get(resource, "resourceType"),
|
|
224
|
+
"id": safe_get(resource, "id"),
|
|
225
|
+
"subject": safe_get(resource, "subject.reference"),
|
|
226
|
+
"code": safe_get(resource, "code.coding[0].code"),
|
|
227
|
+
})
|
|
228
|
+
return {"Resource": rows}
|
|
229
|
+
|
|
230
|
+
custom_df = client.query_df(
|
|
231
|
+
resource_type="Patient",
|
|
232
|
+
params={"_count": 10},
|
|
233
|
+
mode="custom",
|
|
234
|
+
process_function=process_bundle,
|
|
235
|
+
max_pages=1,
|
|
236
|
+
)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
This runs one query per row in a DataFrame and fetches in parallel.
|
|
240
|
+
```python
|
|
241
|
+
from fyron import Auth, FHIRRestClient
|
|
242
|
+
|
|
243
|
+
auth = Auth.token_env(
|
|
244
|
+
auth_url="https://example.org/auth/token",
|
|
245
|
+
refresh_url="https://example.org/auth/refresh",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
client = FHIRRestClient(auth=auth, num_processes=4)
|
|
249
|
+
|
|
250
|
+
result_df = client.query_df_from(
|
|
251
|
+
df=patients_df,
|
|
252
|
+
resource_type="Observation",
|
|
253
|
+
column_map={"subject": "patient_id"},
|
|
254
|
+
params={"_count": 50},
|
|
255
|
+
parallel_fetch=True,
|
|
256
|
+
)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`Auth.token_env` arguments:
|
|
260
|
+
|
|
261
|
+
| Argument | Description | Values/Defaults |
|
|
262
|
+
| --- | --- | --- |
|
|
263
|
+
| `auth_url` | Token endpoint URL | Required |
|
|
264
|
+
| `refresh_url` | Refresh endpoint | Optional |
|
|
265
|
+
| `token` | Pre-issued bearer token | Optional |
|
|
266
|
+
|
|
267
|
+
### FHIR SQL
|
|
268
|
+
This runs a SQL query and returns a DataFrame.
|
|
269
|
+
```python
|
|
270
|
+
from fyron import FHIRSQLClient
|
|
271
|
+
|
|
272
|
+
sql_client = FHIRSQLClient()
|
|
273
|
+
|
|
274
|
+
patients = sql_client.query_df(
|
|
275
|
+
"SELECT id, resource_type FROM fhir_resources WHERE resource_type = %s",
|
|
276
|
+
params=["Patient"],
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
sql = """
|
|
280
|
+
SELECT id, resource_type, subject_id
|
|
281
|
+
FROM observation
|
|
282
|
+
WHERE subject_id IN ({patient_ids})
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
obs = sql_client.query_df_from(
|
|
286
|
+
df=patients_df,
|
|
287
|
+
sql=sql,
|
|
288
|
+
column_map={"patient_ids": "patient_id"},
|
|
289
|
+
chunk_size=500,
|
|
290
|
+
parallel=True,
|
|
291
|
+
)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
`FHIRSQLClient` arguments:
|
|
295
|
+
|
|
296
|
+
| Argument | Description | Values/Defaults |
|
|
297
|
+
| --- | --- | --- |
|
|
298
|
+
| `dsn` | Full connection string | Optional |
|
|
299
|
+
| `host` | DB host | Optional |
|
|
300
|
+
| `port` | DB port | Optional |
|
|
301
|
+
| `dbname` | Database name | Optional |
|
|
302
|
+
| `user` | DB user | Optional |
|
|
303
|
+
| `password` | DB password | Optional |
|
|
304
|
+
| `connect_timeout` | Connect timeout (seconds) | Default `10` |
|
|
305
|
+
| `log_queries` | Log SQL queries | `True`/`False` |
|
|
306
|
+
|
|
307
|
+
### FHIR Utilities
|
|
308
|
+
This uses built-in bundle processors to standardize common resources.
|
|
309
|
+
```python
|
|
310
|
+
from fyron import (
|
|
311
|
+
FHIRRestClient,
|
|
312
|
+
process_patient_bundle,
|
|
313
|
+
process_encounter_bundle,
|
|
314
|
+
process_observation_bundle,
|
|
315
|
+
process_condition_bundle,
|
|
316
|
+
process_procedure_bundle,
|
|
317
|
+
process_imaging_study_bundle,
|
|
318
|
+
process_diagnostic_report_bundle,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
client = FHIRRestClient(return_fhir_obj=True)
|
|
322
|
+
|
|
323
|
+
patients = client.query_df(
|
|
324
|
+
resource_type="Patient",
|
|
325
|
+
params={"_count": 25},
|
|
326
|
+
mode="custom",
|
|
327
|
+
process_function=process_patient_bundle,
|
|
328
|
+
)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### DICOM
|
|
332
|
+
This downloads a single DICOM series and optionally converts to NIfTI.
|
|
333
|
+
```python
|
|
334
|
+
from fyron import DICOMDownloader
|
|
335
|
+
|
|
336
|
+
loader = DICOMDownloader(output_format="nifti", num_processes=2)
|
|
337
|
+
|
|
338
|
+
results = loader.download_series(
|
|
339
|
+
study_uid="1.2.3.4.5",
|
|
340
|
+
series_uid="1.2.3.4.5.6",
|
|
341
|
+
output_dir="dicom_out",
|
|
342
|
+
)
|
|
343
|
+
print(results)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
`DICOMDownloader` arguments:
|
|
347
|
+
|
|
348
|
+
| Argument | Description | Values/Defaults |
|
|
349
|
+
| --- | --- | --- |
|
|
350
|
+
| `dicom_web_url` | DICOMweb endpoint | Defaults to `DICOM_WEB_URL` |
|
|
351
|
+
| `output_format` | Output format | `"dicom"` or `"nifti"` |
|
|
352
|
+
| `num_processes` | Parallel workers for DataFrame downloads | Default `1` |
|
|
353
|
+
| `use_compression` | Compress NIfTI output | `True`/`False` |
|
|
354
|
+
|
|
355
|
+
This downloads studies or series listed in a DataFrame.
|
|
356
|
+
```python
|
|
357
|
+
from fyron import DICOMDownloader
|
|
358
|
+
|
|
359
|
+
loader = DICOMDownloader(output_format="nifti", num_processes=2)
|
|
360
|
+
|
|
361
|
+
downloads = loader.download_from_df(
|
|
362
|
+
df=imaging_df, # must include study_instance_uid and series_instance_uid
|
|
363
|
+
output_dir="dicom_out",
|
|
364
|
+
)
|
|
365
|
+
print(downloads.head())
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Documents
|
|
369
|
+
This downloads a list of document URLs to a deterministic folder structure.
|
|
370
|
+
```python
|
|
371
|
+
from fyron import DocumentDownloader
|
|
372
|
+
|
|
373
|
+
urls = [
|
|
374
|
+
"https://example.org/reports/report1.pdf",
|
|
375
|
+
"https://example.org/reports/report2.pdf",
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
loader = DocumentDownloader(output_dir="docs_out")
|
|
379
|
+
results = loader.download_urls(urls)
|
|
380
|
+
print(results.head())
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`DocumentDownloader` arguments:
|
|
384
|
+
|
|
385
|
+
| Argument | Description | Values/Defaults |
|
|
386
|
+
| --- | --- | --- |
|
|
387
|
+
| `base_url` | Prefix for relative URLs | Defaults to `FHIR_BASE_URL` |
|
|
388
|
+
| `output_dir` | Download folder | Default `documents_out` |
|
|
389
|
+
| `timeout` | Request timeout (seconds) | Default `30` |
|
|
390
|
+
| `skip_existing` | Skip if file exists | `True`/`False` |
|
|
391
|
+
| `max_workers` | Thread pool size | Default `4` |
|
|
392
|
+
| `save_mode` | File mode | `"auto"`, `"txt"`, `"pdf"` |
|
|
393
|
+
| `force_extension` | Force file extension | Optional |
|
|
394
|
+
|
|
395
|
+
This downloads documents referenced by a DataFrame column.
|
|
396
|
+
```python
|
|
397
|
+
from fyron import DocumentDownloader
|
|
398
|
+
|
|
399
|
+
loader = DocumentDownloader(output_dir="docs_out")
|
|
400
|
+
results = loader.download_from_df(df=docs_df, url_col="document_url")
|
|
401
|
+
print(results.head())
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### LLM Agent
|
|
405
|
+
This sends a single prompt and returns the model response.
|
|
406
|
+
```python
|
|
407
|
+
from fyron import LLMAgent
|
|
408
|
+
|
|
409
|
+
agent = LLMAgent(provider="openai")
|
|
410
|
+
response = agent.prompt("Summarize the key findings in this dataset")
|
|
411
|
+
print(response)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
`LLMAgent` arguments:
|
|
415
|
+
|
|
416
|
+
| Argument | Description | Values/Defaults |
|
|
417
|
+
| --- | --- | --- |
|
|
418
|
+
| `provider` | Provider type | `"openai"`, `"anyllm"`, `"custom"` |
|
|
419
|
+
| `base_url` | API base or custom endpoint | Defaults to `LLM_BASE_URL` |
|
|
420
|
+
| `api_key` | API key | Optional (required by some providers) |
|
|
421
|
+
| `model` | Model name | Defaults to `LLM_MODEL` |
|
|
422
|
+
| `timeout` | Request timeout (seconds) | Default `30` |
|
|
423
|
+
| `verify_ssl` | Verify TLS | `True`/`False` |
|
|
424
|
+
|
|
425
|
+
This runs a prompt across a list of documents or file paths.
|
|
426
|
+
```python
|
|
427
|
+
from fyron import LLMAgent
|
|
428
|
+
|
|
429
|
+
agent = LLMAgent(provider="openai")
|
|
430
|
+
|
|
431
|
+
docs = ["doc1 text", "doc2 text", "/path/to/file.txt"]
|
|
432
|
+
summary_df = agent.prompt_documents(
|
|
433
|
+
documents=docs,
|
|
434
|
+
prompt="Summarize clinically relevant findings.",
|
|
435
|
+
output_csv="doc_summaries.csv",
|
|
436
|
+
)
|
|
437
|
+
print(summary_df.head())
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
This runs a prompt across a DataFrame column and appends results.
|
|
441
|
+
```python
|
|
442
|
+
from fyron import LLMAgent
|
|
443
|
+
|
|
444
|
+
agent = LLMAgent(provider="openai")
|
|
445
|
+
|
|
446
|
+
out = agent.prompt_dataframe(
|
|
447
|
+
df=notes_df,
|
|
448
|
+
text_col="note_text",
|
|
449
|
+
prompt="Extract key diagnoses.",
|
|
450
|
+
output_col="diagnoses",
|
|
451
|
+
output_csv="notes_with_diagnoses.csv",
|
|
452
|
+
)
|
|
453
|
+
print(out.head())
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
This generates a Methods-style description of a Python module.
|
|
457
|
+
```python
|
|
458
|
+
from fyron import LLMAgent
|
|
459
|
+
|
|
460
|
+
agent = LLMAgent(provider="openai")
|
|
461
|
+
md = agent.describe_python_file(
|
|
462
|
+
file_path="src/project/pipeline.py",
|
|
463
|
+
output_md="docs/methods_pipeline.md",
|
|
464
|
+
)
|
|
465
|
+
print(md[:400])
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Data IO
|
|
469
|
+
This provides shortcut CSV and Excel read/write helpers.
|
|
470
|
+
```python
|
|
471
|
+
from fyron import read_csv, write_excel
|
|
472
|
+
|
|
473
|
+
df = read_csv("patients.csv")
|
|
474
|
+
write_excel(df, "patients.xlsx")
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Teable
|
|
478
|
+
This reads and writes Teable tables as DataFrames.
|
|
479
|
+
```python
|
|
480
|
+
from fyron import TeableClient
|
|
481
|
+
|
|
482
|
+
teable = TeableClient(base_url="https://app.teable.ai", token="YOUR_TOKEN")
|
|
483
|
+
|
|
484
|
+
df = teable.read_table("tblXXXX")
|
|
485
|
+
record_ids = teable.write_dataframe("tblXXXX", df)
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`TeableClient` arguments:
|
|
489
|
+
|
|
490
|
+
| Argument | Description | Values/Defaults |
|
|
491
|
+
| --- | --- | --- |
|
|
492
|
+
| `base_url` | Teable API base | Defaults to `TEABLE_BASE_URL` |
|
|
493
|
+
| `token` | Teable API token | Required |
|
|
494
|
+
| `timeout` | Request timeout (seconds) | Default `30` |
|
|
495
|
+
|
|
496
|
+
This lists spaces, bases, and tables for discovery.
|
|
497
|
+
```python
|
|
498
|
+
from fyron import TeableClient
|
|
499
|
+
|
|
500
|
+
teable = TeableClient(base_url="https://app.teable.ai", token="YOUR_TOKEN")
|
|
501
|
+
|
|
502
|
+
spaces = teable.list_spaces()
|
|
503
|
+
space_id = spaces[0]["id"] if spaces else None
|
|
504
|
+
bases = teable.list_bases(space_id=space_id) if space_id else []
|
|
505
|
+
tables = teable.list_tables(bases[0]["id"]) if bases else []
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
This ensures a base and table exist (creating them if needed).
|
|
509
|
+
```python
|
|
510
|
+
from fyron import TeableClient
|
|
511
|
+
|
|
512
|
+
teable = TeableClient(base_url="https://app.teable.ai", token="YOUR_TOKEN")
|
|
513
|
+
|
|
514
|
+
base = teable.get_or_create_base(name="Clinical", space_name="My Workspace")
|
|
515
|
+
base_id = base["id"]
|
|
516
|
+
|
|
517
|
+
table = teable.get_or_create_table(
|
|
518
|
+
base_id=base_id,
|
|
519
|
+
name="Observations",
|
|
520
|
+
)
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
This fully replaces a table by deleting then inserting all rows.
|
|
524
|
+
```python
|
|
525
|
+
from fyron import TeableClient
|
|
526
|
+
|
|
527
|
+
teable = TeableClient(base_url="https://app.teable.ai", token="YOUR_TOKEN")
|
|
528
|
+
record_ids = teable.overwrite_table("tblXXXX", df)
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## Caching
|
|
532
|
+
This configures the in-memory cache for FHIR REST GET responses.
|
|
533
|
+
```python
|
|
534
|
+
from fyron import FHIRRestClient
|
|
535
|
+
|
|
536
|
+
client = FHIRRestClient(
|
|
537
|
+
cache_ttl_seconds=300, # default 5 minutes
|
|
538
|
+
cache_max_entries=1000, # default 1000 responses
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
# Disable caching
|
|
542
|
+
client = FHIRRestClient(cache_ttl_seconds=0, cache_max_entries=0)
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Logging
|
|
546
|
+
This enables request logging and summary output.
|
|
547
|
+
```python
|
|
548
|
+
import logging
|
|
549
|
+
from fyron import FHIRRestClient
|
|
550
|
+
|
|
551
|
+
logging.basicConfig(level=logging.INFO)
|
|
552
|
+
client = FHIRRestClient(log_requests=True)
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
## CLI
|
|
556
|
+
This runs a DICOM download from the command line.
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
fyron-dicom --dicom-web-url https://pacs.example.org/dicomweb \
|
|
560
|
+
--study-uid 1.2.3.4.5 --series-uid 1.2.3.4.5.6 --output-dir dicom_out
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
## Example Scripts
|
|
564
|
+
These examples connect to public or configured services for quick validation.
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
python examples/hapi_rest_example.py
|
|
568
|
+
python examples/sql_examples.py
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Contributing
|
|
572
|
+
See `CONTRIBUTING.md`.
|
|
573
|
+
|
|
574
|
+
## License
|
|
575
|
+
MIT
|
|
576
|
+
|