pylantir 0.1.3__tar.gz → 0.2.1__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.
- pylantir-0.2.1/PKG-INFO +584 -0
- pylantir-0.2.1/README.md +527 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/pyproject.toml +13 -2
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/__init__.py +1 -1
- pylantir-0.2.1/src/pylantir/api_server.py +769 -0
- pylantir-0.2.1/src/pylantir/auth_db_setup.py +188 -0
- pylantir-0.2.1/src/pylantir/auth_models.py +80 -0
- pylantir-0.2.1/src/pylantir/auth_utils.py +210 -0
- pylantir-0.2.1/src/pylantir/cli/run.py +597 -0
- pylantir-0.2.1/src/pylantir/config/config_example_with_cors.json +108 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/config/mwl_config.json +18 -0
- pylantir-0.2.1/src/pylantir/db_concurrency.py +180 -0
- pylantir-0.2.1/src/pylantir/db_setup.py +121 -0
- pylantir-0.2.1/src/pylantir/redcap_to_db.py +458 -0
- pylantir-0.1.3/.devcontainer/Dockerfile +0 -12
- pylantir-0.1.3/.devcontainer/devcontainer.json +0 -44
- pylantir-0.1.3/.github/dependabot.yml +0 -22
- pylantir-0.1.3/.github/template-sync.yml +0 -21
- pylantir-0.1.3/.github/workflows/CI.yml +0 -21
- pylantir-0.1.3/.github/workflows/publish.yml +0 -33
- pylantir-0.1.3/.github/workflows/schedule-update-actions.yml +0 -25
- pylantir-0.1.3/.github/workflows/semantic-pr-check.yml +0 -17
- pylantir-0.1.3/.github/workflows/sphinx.yml +0 -18
- pylantir-0.1.3/.github/workflows/template-sync.yml +0 -12
- pylantir-0.1.3/.gitignore +0 -129
- pylantir-0.1.3/.pre-commit-config.yaml +0 -60
- pylantir-0.1.3/.pypirc +0 -10
- pylantir-0.1.3/.vscode/launch.json +0 -19
- pylantir-0.1.3/.vscode/settings.json +0 -29
- pylantir-0.1.3/CODE_OF_CONDUCT.md +0 -9
- pylantir-0.1.3/PKG-INFO +0 -193
- pylantir-0.1.3/README.md +0 -145
- pylantir-0.1.3/SECURITY.md +0 -41
- pylantir-0.1.3/SUPPORT.md +0 -25
- pylantir-0.1.3/docs/Makefile +0 -20
- pylantir-0.1.3/docs/conf.py +0 -67
- pylantir-0.1.3/docs/devcontainer.md +0 -16
- pylantir-0.1.3/docs/developer.md +0 -3
- pylantir-0.1.3/docs/index.rst +0 -20
- pylantir-0.1.3/docs/make.bat +0 -35
- pylantir-0.1.3/docs/modules.rst +0 -7
- pylantir-0.1.3/docs/pre-commit-config.md +0 -6
- pylantir-0.1.3/docs/pylint.md +0 -507
- pylantir-0.1.3/docs/pyproject.md +0 -9
- pylantir-0.1.3/docs/python_package.hello_world.rst +0 -21
- pylantir-0.1.3/docs/python_package.rst +0 -29
- pylantir-0.1.3/docs/requirements.txt +0 -3
- pylantir-0.1.3/docs/vscode.md +0 -1
- pylantir-0.1.3/docs/workflows.md +0 -4
- pylantir-0.1.3/pylantir.png +0 -0
- pylantir-0.1.3/src/README.md +0 -1
- pylantir-0.1.3/src/pylantir/cli/run.py +0 -291
- pylantir-0.1.3/src/pylantir/db_setup.py +0 -46
- pylantir-0.1.3/src/pylantir/redcap_to_db.py +0 -324
- pylantir-0.1.3/tests/client.py +0 -63
- pylantir-0.1.3/tests/client2.py +0 -46
- pylantir-0.1.3/tests/conftest.py +0 -30
- pylantir-0.1.3/tests/mpps_tester.py +0 -147
- pylantir-0.1.3/tests/query_db.py +0 -44
- pylantir-0.1.3/tests/test_methods.py +0 -32
- {pylantir-0.1.3 → pylantir-0.2.1}/LICENSE +0 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/cli/__init__.py +0 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/models.py +0 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/mwl_server.py +0 -0
- {pylantir-0.1.3 → pylantir-0.2.1}/src/pylantir/populate_db.py +0 -0
pylantir-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pylantir
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Python - DICOM Modality WorkList with Optional API
|
|
5
|
+
Author-email: Milton Camacho <miltoncamachoicc@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11.1
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pynetdicom
|
|
18
|
+
Requires-Dist: sqlalchemy
|
|
19
|
+
Requires-Dist: PyCap
|
|
20
|
+
Requires-Dist: uuid
|
|
21
|
+
Requires-Dist: coloredlogs
|
|
22
|
+
Requires-Dist: python-dotenv
|
|
23
|
+
Requires-Dist: pandas
|
|
24
|
+
Requires-Dist: fastapi>=0.104.1 ; extra == "api"
|
|
25
|
+
Requires-Dist: uvicorn[standard]>=0.24.0 ; extra == "api"
|
|
26
|
+
Requires-Dist: passlib[bcrypt]==1.7.4 ; extra == "api"
|
|
27
|
+
Requires-Dist: bcrypt==4.0.1 ; extra == "api"
|
|
28
|
+
Requires-Dist: python-jose[cryptography]==3.5.0 ; extra == "api"
|
|
29
|
+
Requires-Dist: python-multipart>=0.0.6 ; extra == "api"
|
|
30
|
+
Requires-Dist: psutil>=5.9.0 ; extra == "monitoring"
|
|
31
|
+
Requires-Dist: pyspark>=3.0.0 ; extra == "spark"
|
|
32
|
+
Requires-Dist: bandit[toml]==1.7.5 ; extra == "test"
|
|
33
|
+
Requires-Dist: black==23.3.0 ; extra == "test"
|
|
34
|
+
Requires-Dist: check-manifest==0.49 ; extra == "test"
|
|
35
|
+
Requires-Dist: flake8-bugbear==23.5.9 ; extra == "test"
|
|
36
|
+
Requires-Dist: flake8-docstrings ; extra == "test"
|
|
37
|
+
Requires-Dist: flake8-formatter_junit_xml ; extra == "test"
|
|
38
|
+
Requires-Dist: flake8 ; extra == "test"
|
|
39
|
+
Requires-Dist: flake8-pyproject ; extra == "test"
|
|
40
|
+
Requires-Dist: pre-commit==3.3.1 ; extra == "test"
|
|
41
|
+
Requires-Dist: pylint==3.3.6 ; extra == "test"
|
|
42
|
+
Requires-Dist: pylint_junit ; extra == "test"
|
|
43
|
+
Requires-Dist: pytest-cov==4.0.0 ; extra == "test"
|
|
44
|
+
Requires-Dist: pytest-mock<3.10.1 ; extra == "test"
|
|
45
|
+
Requires-Dist: pytest-runner ; extra == "test"
|
|
46
|
+
Requires-Dist: pytest==7.3.1 ; extra == "test"
|
|
47
|
+
Requires-Dist: pytest-github-actions-annotate-failures ; extra == "test"
|
|
48
|
+
Requires-Dist: shellcheck-py==0.9.0.2 ; extra == "test"
|
|
49
|
+
Project-URL: Documentation, https://github.com/miltoncamacho/pylantir/tree/main#readme
|
|
50
|
+
Project-URL: Source, https://github.com/miltoncamacho/pylantir
|
|
51
|
+
Project-URL: Tracker, https://github.com/miltoncamacho/pylantir/issues
|
|
52
|
+
Provides-Extra: api
|
|
53
|
+
Provides-Extra: monitoring
|
|
54
|
+
Provides-Extra: spark
|
|
55
|
+
Provides-Extra: test
|
|
56
|
+
|
|
57
|
+
<div style="text-align: center;">
|
|
58
|
+
<h1>Pylantir</h1>
|
|
59
|
+
</div>
|
|
60
|
+
<div style="text-align: center;">
|
|
61
|
+
<img src="pylantir.png" alt="Pylantir" width="50%">
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
This project's goal is to significantly reduce the number of human-related errors when manualy registering participants for medical imaging procedures.
|
|
65
|
+
|
|
66
|
+
It effectively provides a python based DICOM Modality Worklist Server (SCP) and Modality Performed Procedure Step (SCP) able to receive requests from medical imaging equipemnt based on DICOM network comunication (e.g., a C-FIND, N-CREATE, N-SET requests).
|
|
67
|
+
|
|
68
|
+
It will build/update a database based on the information entered in the study-related REDCap database using a REDCap API (You will require to have API access to the study).
|
|
69
|
+
|
|
70
|
+
## Getting Started
|
|
71
|
+
|
|
72
|
+
To get started simply install using:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install pylantir
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Optional Dependencies
|
|
79
|
+
|
|
80
|
+
Pylantir offers several optional dependency groups for enhanced functionality:
|
|
81
|
+
|
|
82
|
+
#### API Support
|
|
83
|
+
For REST API and web interface capabilities:
|
|
84
|
+
```bash
|
|
85
|
+
pip install pylantir[api]
|
|
86
|
+
```
|
|
87
|
+
Includes: FastAPI, Uvicorn, JWT authentication, password hashing
|
|
88
|
+
|
|
89
|
+
#### Memory Monitoring
|
|
90
|
+
For enhanced memory usage monitoring and cleanup during REDCap synchronization:
|
|
91
|
+
```bash
|
|
92
|
+
pip install pylantir[monitoring]
|
|
93
|
+
```
|
|
94
|
+
Includes: psutil for system resource monitoring
|
|
95
|
+
|
|
96
|
+
#### Big Data Processing
|
|
97
|
+
For Spark-based data processing capabilities:
|
|
98
|
+
```bash
|
|
99
|
+
pip install pylantir[spark]
|
|
100
|
+
```
|
|
101
|
+
Includes: PySpark for large-scale data processing
|
|
102
|
+
|
|
103
|
+
#### Multiple Options
|
|
104
|
+
Install multiple optional dependency groups:
|
|
105
|
+
```bash
|
|
106
|
+
# API + Memory Monitoring
|
|
107
|
+
pip install pylantir[api,monitoring]
|
|
108
|
+
|
|
109
|
+
# All optional dependencies
|
|
110
|
+
pip install pylantir[api,monitoring,spark]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Development and Testing
|
|
114
|
+
For running tests and development:
|
|
115
|
+
```bash
|
|
116
|
+
pip install pylantir[test]
|
|
117
|
+
```
|
|
118
|
+
Includes: pytest, coverage tools, and testing utilities
|
|
119
|
+
|
|
120
|
+
You need to provide your REDCap API URL and API token before starting the server.
|
|
121
|
+
Set up environmental variables before starting the server:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
export REDCAP_API_URL=<your API url>
|
|
125
|
+
export REDCAP_API_TOKEN=<your API token>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Start a server called with AEtitle MWL_SERVER.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pylantir start --ip 127.0.0.1 --port 4242 --AEtitle MWL_SERVER --pylantir_config Path/to/your/config.json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Tests
|
|
135
|
+
|
|
136
|
+
If you want to run the tests make sure to clone the repository and run them from there.
|
|
137
|
+
|
|
138
|
+
Git clone the repository:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git clone https://github.com/miltoncamacho/pylantir
|
|
142
|
+
cd pylantir/tests
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Query the worklist database to check that you have some entries using:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
python query-db.py
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Then, you can get a StudyUID from one of the entries to test the MPPS workflow. For example: 1.2.840.10008.3.1.2.3.4.55635351412689303463019139483773956632
|
|
152
|
+
|
|
153
|
+
Take this and run a create action to mark the worklist Procedure Step Status as IN_PROGRESS
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python test-mpps.py --AEtitle MWL_SERVER --mpps_action create --callingAEtitle MWL_TESTER --ip 127.0.0.1 --port 4242 --study_uid 1.2.840.10008.3.1.2.3.4.55635351412689303463019139483773956632
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
You can verify that this in fact modified your database re-running:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
python query-db.py
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Finally, you can also simulate the pocedure completion efectively updating the Procedure Step Status to COMPLETED or DISCONTINUED:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
python test-mpps.py --AEtitle MWL_SERVER --mpps_action set --mpps_status COMPLETED --callingAEtitle MWL_TESTER --ip 127.0.0.1 --port 4242 --study_uid 1.2.840.10008.3.1.2.3.4.55635351412689303463019139483773956632 --sop_uid 1.2.840.10008.3.1.2.3.4.187176383255263644225774937658729238426
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Usage
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
usage: pylantir [-h] [--AEtitle AETITLE] [--ip IP] [--port PORT] [--pylantir_config PYLANTIR_CONFIG] [--mpps_action {create,set}] [--mpps_status {COMPLETED,DISCONTINUED}] [--callingAEtitle CALLINGAETITLE] [--study_uid STUDY_UID] [--sop_uid SOP_UID] {start,query-db,test-client,test-mpps}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**pylantir** - Python DICOM Modality WorkList and Modality Performed Procedure Step compliance
|
|
178
|
+
|
|
179
|
+
### Positional Arguments:
|
|
180
|
+
|
|
181
|
+
- **{start,query-db,test-client,test-mpps,start-api,admin-password,create-user,list-users}**: Command to run:
|
|
182
|
+
- **start**: Start the MWL server
|
|
183
|
+
- **query-db**: Query the MWL database
|
|
184
|
+
- **test-client**: Run tests for MWL
|
|
185
|
+
- **test-mpps**: Run tests for MPPS
|
|
186
|
+
- **start-api**: Start the FastAPI server (requires [api] dependencies)
|
|
187
|
+
- **admin-password**: Change admin password
|
|
188
|
+
- **create-user**: Create a new user (admin only)
|
|
189
|
+
- **list-users**: List all users (admin only)
|
|
190
|
+
|
|
191
|
+
### Options:
|
|
192
|
+
|
|
193
|
+
- **-h, --help**: Show this help message and exit
|
|
194
|
+
- **--AEtitle AETITLE**: AE Title for the server
|
|
195
|
+
- **--ip IP**: IP/host address for the server
|
|
196
|
+
- **--port PORT**: Port for the server
|
|
197
|
+
- **--pylantir_config PYLANTIR_CONFIG**: Path to the configuration JSON file containing pylantir configs:
|
|
198
|
+
- **allowed_aet**: List of allowed AE titles e.g. `["MRI_SCANNER", "MRI_SCANNER_2"]`
|
|
199
|
+
- **site**: Site ID:string
|
|
200
|
+
- **protocol**: `{"site": "protocol_name", "mapping": "HIS/RIS mapping"}`
|
|
201
|
+
- **redcap2wl**: Dictionary of REDCap fields to worklist fields mapping e.g., `{"redcap_field": "worklist_field"}`
|
|
202
|
+
- **db_path**: Path to main worklist database e.g., `"/path/to/worklist.db"`
|
|
203
|
+
- **users_db_path**: Optional path to users authentication database e.g., `"/path/to/users.db"`
|
|
204
|
+
- **db_update_interval**: How often to reload the database e
|
|
205
|
+
- **operation_interval**: What is the time range in a day in which the database will be updated e.g., `{"start_time":[hours,minutes],"end_time":[hours,minutes]}`
|
|
206
|
+
- **--mpps_action {create,set}**: Action to perform for MPPS either create or set
|
|
207
|
+
- **--mpps_status {COMPLETED,DISCONTINUED}**: Status to set for MPPS either COMPLETED or DISCONTINUED
|
|
208
|
+
- **--callingAEtitle CALLINGAETITLE**: Calling AE Title for MPPS, it helps when the MWL is limited to only accept certain AE titles
|
|
209
|
+
- **--study_uid STUDY_UID**: StudyInstanceUID to test MPPS
|
|
210
|
+
- **--sop_uid SOP_UID**: SOPInstanceUID to test MPPS
|
|
211
|
+
|
|
212
|
+
## Configuration JSON file
|
|
213
|
+
|
|
214
|
+
As a default pylantir will try to read a JSON structured file with the following structure:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"db_path": "/path/to/worklist.db",
|
|
219
|
+
"users_db_path": "/path/to/users.db",
|
|
220
|
+
"db_echo": "False",
|
|
221
|
+
"db_update_interval": 60,
|
|
222
|
+
"operation_interval": {"start_time": [0,0],"end_time": [23,59]},
|
|
223
|
+
"allowed_aet": [],
|
|
224
|
+
"site": "792",
|
|
225
|
+
"redcap2wl": {
|
|
226
|
+
"study_id": "study_id",
|
|
227
|
+
"instrument": "redcap_repeat_instrument",
|
|
228
|
+
"session_id" : "mri_instance",
|
|
229
|
+
"family_id": "family_id",
|
|
230
|
+
"youth_dob_y": "youth_dob_y",
|
|
231
|
+
"t1_date": "t1_date",
|
|
232
|
+
"demo_sex": "demo_sex",
|
|
233
|
+
"scheduled_date": "mri_date",
|
|
234
|
+
"scheduled_time": "mri_time",
|
|
235
|
+
"mri_wt_lbs": "patient_weight_lb",
|
|
236
|
+
"referring_physician": "referring_physician_name",
|
|
237
|
+
"performing_physician": "performing_physician",
|
|
238
|
+
"station_name": "station_name",
|
|
239
|
+
"status": "performed_procedure_step_status"
|
|
240
|
+
},
|
|
241
|
+
"protocol": {
|
|
242
|
+
"792": "BRAIN_MRI_3T",
|
|
243
|
+
"mapping": "GEHC"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Memory Management (Optional)
|
|
249
|
+
|
|
250
|
+
When you install the `monitoring` optional dependency (`pip install pylantir[monitoring]`), Pylantir gains enhanced memory monitoring capabilities during REDCap synchronization:
|
|
251
|
+
|
|
252
|
+
- **Automatic Memory Cleanup**: Performs garbage collection after each sync cycle
|
|
253
|
+
- **Memory Usage Reporting**: Logs current memory usage before and after cleanup
|
|
254
|
+
- **Connection Management**: Properly closes database connections and clears session caches
|
|
255
|
+
- **Resource Monitoring**: Tracks system resource usage during long-running operations
|
|
256
|
+
|
|
257
|
+
This is particularly useful for production deployments with frequent synchronization intervals or large datasets, helping prevent memory leaks during continuous operation.
|
|
258
|
+
|
|
259
|
+
**Memory monitoring works automatically** - no additional configuration required. The system will use enhanced monitoring when `psutil` is available, and fall back to basic garbage collection when it's not installed.
|
|
260
|
+
|
|
261
|
+
## FastAPI REST API (Optional)
|
|
262
|
+
|
|
263
|
+
**New in v0.2.0**: Pylantir now includes an optional REST API for programmatic access to worklist data and user management.
|
|
264
|
+
|
|
265
|
+
### Installation with API Support
|
|
266
|
+
|
|
267
|
+
To use the API features, install with optional API dependencies:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
pip install pylantir[api]
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This installs additional dependencies:
|
|
274
|
+
- `fastapi>=0.104.1`: Modern web framework for building APIs
|
|
275
|
+
- `uvicorn[standard]>=0.24.0`: ASGI server for running FastAPI
|
|
276
|
+
- `passlib[bcrypt]==1.7.4`: Password hashing library
|
|
277
|
+
- `bcrypt==4.0.1`: Bcrypt hashing algorithm
|
|
278
|
+
- `python-jose[cryptography]==3.5.0`: JWT token handling
|
|
279
|
+
- `python-multipart>=0.0.6`: Form data parsing
|
|
280
|
+
|
|
281
|
+
### Starting the API Server
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Start API server on default port (8000)
|
|
285
|
+
pylantir start-api --api-host 0.0.0.0 --api-port 8000
|
|
286
|
+
|
|
287
|
+
# With custom configuration
|
|
288
|
+
pylantir start-api --pylantir_config /path/to/config.json --api-port 8080
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The API server will be available at:
|
|
292
|
+
- **API Endpoints**: `http://localhost:8000`
|
|
293
|
+
- **Interactive Documentation**: `http://localhost:8000/docs` (Swagger UI)
|
|
294
|
+
- **Alternative Documentation**: `http://localhost:8000/redoc` (ReDoc)
|
|
295
|
+
|
|
296
|
+
### Authentication & Authorization
|
|
297
|
+
|
|
298
|
+
The API uses JWT (JSON Web Token) authentication with role-based access control:
|
|
299
|
+
|
|
300
|
+
#### User Roles:
|
|
301
|
+
- **admin**: Full access to users and worklist data (CRUD operations)
|
|
302
|
+
- **write**: Read and write access to worklist data only
|
|
303
|
+
- **read**: Read-only access to worklist data only
|
|
304
|
+
|
|
305
|
+
#### Initial Setup:
|
|
306
|
+
On first run, a default admin user is created:
|
|
307
|
+
- **Username**: `admin`
|
|
308
|
+
- **Password**: `admin123`
|
|
309
|
+
|
|
310
|
+
⚠️ **Change the default password immediately:**
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
pylantir admin-password --username admin
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### API Endpoints
|
|
317
|
+
|
|
318
|
+
#### Authentication
|
|
319
|
+
- `POST /auth/login`: Authenticate and receive JWT token
|
|
320
|
+
|
|
321
|
+
#### Worklist Management
|
|
322
|
+
- `GET /worklist`: Retrieve worklist items with filtering
|
|
323
|
+
- `POST /worklist`: Create new worklist items (write/admin)
|
|
324
|
+
- `PUT /worklist/{id}`: Update worklist items (write/admin)
|
|
325
|
+
- `DELETE /worklist/{id}`: Delete worklist items (write/admin)
|
|
326
|
+
|
|
327
|
+
#### User Management (Admin Only)
|
|
328
|
+
- `GET /users`: List all users
|
|
329
|
+
- `POST /users`: Create new users
|
|
330
|
+
- `PUT /users/{id}`: Update users
|
|
331
|
+
- `DELETE /users/{id}`: Delete users
|
|
332
|
+
|
|
333
|
+
#### Health Check
|
|
334
|
+
- `GET /health`: API health status
|
|
335
|
+
|
|
336
|
+
### API Usage Examples
|
|
337
|
+
|
|
338
|
+
#### 1. Login and Get Token
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
curl -X POST "http://localhost:8000/auth/login" \
|
|
342
|
+
-H "Content-Type: application/json" \
|
|
343
|
+
-d '{
|
|
344
|
+
"username": "admin",
|
|
345
|
+
"password": "your_new_password",
|
|
346
|
+
"access_token_expire_minutes": 60
|
|
347
|
+
}'
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
You can optionally send `access_token_expire_minutes` in the login payload to override the default TTL that is applied to newly minted tokens.
|
|
351
|
+
|
|
352
|
+
Response:
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
356
|
+
"token_type": "bearer"
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### 2. Get Worklist Items
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Get all scheduled and in-progress items (default)
|
|
364
|
+
curl -X GET "http://localhost:8000/worklist" \
|
|
365
|
+
-H "Authorization: Bearer YOUR_TOKEN"
|
|
366
|
+
|
|
367
|
+
# Filter by specific status
|
|
368
|
+
curl -X GET "http://localhost:8000/worklist?status=SCHEDULED&status=COMPLETED" \
|
|
369
|
+
-H "Authorization: Bearer YOUR_TOKEN"
|
|
370
|
+
|
|
371
|
+
# Filter by patient ID
|
|
372
|
+
curl -X GET "http://localhost:8000/worklist?patient_id=PATIENT001" \
|
|
373
|
+
-H "Authorization: Bearer YOUR_TOKEN"
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### 3. Create Worklist Item
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
curl -X POST "http://localhost:8000/worklist" \
|
|
380
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
381
|
+
-H "Content-Type: application/json" \
|
|
382
|
+
-d '{
|
|
383
|
+
"patient_name": "Doe^John",
|
|
384
|
+
"patient_id": "PATIENT001",
|
|
385
|
+
"patient_birth_date": "19900101",
|
|
386
|
+
"patient_sex": "M",
|
|
387
|
+
"modality": "MR",
|
|
388
|
+
"performed_procedure_step_status": "SCHEDULED"
|
|
389
|
+
}'
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
#### 4. Update Procedure Status
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
curl -X PUT "http://localhost:8000/worklist/1" \
|
|
396
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
397
|
+
-H "Content-Type: application/json" \
|
|
398
|
+
-d '{"performed_procedure_step_status": "IN_PROGRESS"}'
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### CLI User Management
|
|
402
|
+
|
|
403
|
+
#### Change Admin Password
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
pylantir admin-password --username admin
|
|
407
|
+
# Prompts for current and new password
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### Create New User
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
pylantir create-user --username newuser --role write --email user@example.com
|
|
414
|
+
# Prompts for admin credentials and new user password
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### List Users
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
pylantir list-users
|
|
421
|
+
# Prompts for admin credentials, then displays user table
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Python Client Example
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
import requests
|
|
428
|
+
|
|
429
|
+
# Login
|
|
430
|
+
response = requests.post("http://localhost:8000/auth/login", json={
|
|
431
|
+
"username": "admin",
|
|
432
|
+
"password": "your_password",
|
|
433
|
+
"access_token_expire_minutes": 120
|
|
434
|
+
})
|
|
435
|
+
token = response.json()["access_token"]
|
|
436
|
+
|
|
437
|
+
# Set headers for authenticated requests
|
|
438
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
439
|
+
|
|
440
|
+
# Get worklist items
|
|
441
|
+
response = requests.get("http://localhost:8000/worklist", headers=headers)
|
|
442
|
+
worklist_items = response.json()
|
|
443
|
+
|
|
444
|
+
# Create new item
|
|
445
|
+
new_item = {
|
|
446
|
+
"patient_name": "Smith^Jane",
|
|
447
|
+
"patient_id": "PATIENT002",
|
|
448
|
+
"modality": "CT",
|
|
449
|
+
"performed_procedure_step_status": "SCHEDULED"
|
|
450
|
+
}
|
|
451
|
+
response = requests.post("http://localhost:8000/worklist",
|
|
452
|
+
json=new_item, headers=headers)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### API Configuration
|
|
456
|
+
|
|
457
|
+
The API server uses the same configuration file as the main DICOM server for database settings. You can configure both the main worklist database and the users authentication database paths.
|
|
458
|
+
|
|
459
|
+
#### Database Configuration Options:
|
|
460
|
+
|
|
461
|
+
1. **Automatic Location (Default)**:
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"db_path": "/path/to/worklist.db"
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
- Users database will be created as `users.db` in the same directory
|
|
468
|
+
- Result: `/path/to/users.db`
|
|
469
|
+
|
|
470
|
+
2. **Custom Users Database Path**:
|
|
471
|
+
```json
|
|
472
|
+
{
|
|
473
|
+
"db_path": "/path/to/worklist.db",
|
|
474
|
+
"users_db_path": "/different/path/to/authentication.db"
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
- Users database will be created at the specified location
|
|
478
|
+
- Allows separation of databases for security or organizational reasons
|
|
479
|
+
|
|
480
|
+
3. **Environment Variable Override**:
|
|
481
|
+
```bash
|
|
482
|
+
export USERS_DB_PATH="/custom/path/to/users.db"
|
|
483
|
+
```
|
|
484
|
+
- Takes precedence over configuration file setting
|
|
485
|
+
- Useful for deployment-specific configurations
|
|
486
|
+
|
|
487
|
+
#### Configuration Precedence:
|
|
488
|
+
1. `users_db_path` in configuration JSON file
|
|
489
|
+
2. `USERS_DB_PATH` environment variable
|
|
490
|
+
3. Default: `users.db` in same directory as main database
|
|
491
|
+
|
|
492
|
+
Example directory structures:
|
|
493
|
+
|
|
494
|
+
**Default Setup:**
|
|
495
|
+
```
|
|
496
|
+
/path/to/databases/
|
|
497
|
+
├── worklist.db # Main DICOM worklist database
|
|
498
|
+
└── users.db # API authentication database (auto-created)
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**Custom Setup:**
|
|
502
|
+
```
|
|
503
|
+
/path/to/databases/
|
|
504
|
+
├── worklist.db # Main DICOM worklist database
|
|
505
|
+
|
|
506
|
+
/secure/auth/
|
|
507
|
+
└── authentication.db # API authentication database (custom path)
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### CORS Configuration
|
|
511
|
+
|
|
512
|
+
Control Cross-Origin Resource Sharing (CORS) for web frontend integration:
|
|
513
|
+
|
|
514
|
+
```json
|
|
515
|
+
{
|
|
516
|
+
"db_path": "/path/to/worklist.db",
|
|
517
|
+
"api": {
|
|
518
|
+
"cors_allowed_origins": [
|
|
519
|
+
"http://localhost:3000",
|
|
520
|
+
"http://localhost:8080",
|
|
521
|
+
"https://radiology-dashboard.hospital.local",
|
|
522
|
+
"https://your-frontend-domain.com"
|
|
523
|
+
],
|
|
524
|
+
"cors_allow_credentials": true,
|
|
525
|
+
"cors_allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
526
|
+
"cors_allow_headers": ["*"]
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
**CORS Configuration Options:**
|
|
532
|
+
|
|
533
|
+
- **`cors_allowed_origins`**: Array of allowed origin URLs for browser requests
|
|
534
|
+
- Use specific domains for security (avoid `["*"]` in production)
|
|
535
|
+
- Include all frontend application URLs that will access the API
|
|
536
|
+
- Supports both HTTP (development) and HTTPS (production) origins
|
|
537
|
+
|
|
538
|
+
- **`cors_allow_credentials`**: Boolean, allows cookies/auth headers in CORS requests
|
|
539
|
+
- Set to `true` for JWT token authentication (recommended)
|
|
540
|
+
- Required for browser-based authentication
|
|
541
|
+
|
|
542
|
+
- **`cors_allow_methods`**: Array of allowed HTTP methods
|
|
543
|
+
- Default: `["GET", "POST", "PUT", "DELETE", "OPTIONS"]`
|
|
544
|
+
- Include `"OPTIONS"` for preflight requests
|
|
545
|
+
|
|
546
|
+
- **`cors_allow_headers`**: Array of allowed request headers
|
|
547
|
+
- Default: `["*"]` allows all headers
|
|
548
|
+
- Can specify specific headers like `["Authorization", "Content-Type"]`
|
|
549
|
+
|
|
550
|
+
**CORS Security Best Practices:**
|
|
551
|
+
- Never use `["*"]` for origins in production environments
|
|
552
|
+
- Specify only the exact domains that need API access
|
|
553
|
+
- Use HTTPS origins for production deployments
|
|
554
|
+
- Regularly audit and update allowed origins list
|
|
555
|
+
|
|
556
|
+
**Example Production CORS Setup:**
|
|
557
|
+
```json
|
|
558
|
+
{
|
|
559
|
+
"api": {
|
|
560
|
+
"cors_allowed_origins": [
|
|
561
|
+
"https://radiology.hospital.com",
|
|
562
|
+
"https://dashboard.hospital.com"
|
|
563
|
+
],
|
|
564
|
+
"cors_allow_credentials": true,
|
|
565
|
+
"cors_allow_methods": ["GET", "POST", "PUT", "DELETE"],
|
|
566
|
+
"cors_allow_headers": ["Authorization", "Content-Type"]
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Security Considerations
|
|
572
|
+
|
|
573
|
+
- **Change Default Password**: Always change the default admin password
|
|
574
|
+
- **Use HTTPS**: In production, use HTTPS with proper SSL certificates
|
|
575
|
+
- **Network Security**: Restrict API access using firewalls/network policies
|
|
576
|
+
- **Token Management**: JWT tokens expire after 30 minutes by default
|
|
577
|
+
- **Database Permissions**: Ensure database files have appropriate file permissions
|
|
578
|
+
|
|
579
|
+
## Clean Stop of the MWL and Database Sync
|
|
580
|
+
|
|
581
|
+
To cleanly stop the MWL server and ensure the database syncronization properly, press `Ctrl + C` (you might need to press it twice).
|
|
582
|
+
|
|
583
|
+
To stop the API server, use `Ctrl + C` in the terminal where it's running.
|
|
584
|
+
|