psdl-lang 0.2.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.
- psdl_lang-0.2.0/LICENSE +190 -0
- psdl_lang-0.2.0/PKG-INFO +398 -0
- psdl_lang-0.2.0/README.md +336 -0
- psdl_lang-0.2.0/pyproject.toml +176 -0
- psdl_lang-0.2.0/setup.cfg +28 -0
- psdl_lang-0.2.0/src/psdl/__init__.py +84 -0
- psdl_lang-0.2.0/src/psdl/adapters/__init__.py +19 -0
- psdl_lang-0.2.0/src/psdl/adapters/fhir.py +522 -0
- psdl_lang-0.2.0/src/psdl/adapters/omop.py +683 -0
- psdl_lang-0.2.0/src/psdl/cli.py +178 -0
- psdl_lang-0.2.0/src/psdl/examples/__init__.py +137 -0
- psdl_lang-0.2.0/src/psdl/execution/__init__.py +96 -0
- psdl_lang-0.2.0/src/psdl/execution/batch.py +937 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/__init__.py +73 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/compiler.py +543 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/config.py +283 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/flink_runtime.py +573 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/models.py +274 -0
- psdl_lang-0.2.0/src/psdl/execution/streaming/operators.py +489 -0
- psdl_lang-0.2.0/src/psdl/expression_parser.py +431 -0
- psdl_lang-0.2.0/src/psdl/mapping.py +359 -0
- psdl_lang-0.2.0/src/psdl/operators.py +441 -0
- psdl_lang-0.2.0/src/psdl/parser.py +424 -0
- psdl_lang-0.2.0/src/psdl/py.typed +1 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/PKG-INFO +398 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/SOURCES.txt +43 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/dependency_links.txt +1 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/entry_points.txt +6 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/requires.txt +38 -0
- psdl_lang-0.2.0/src/psdl_lang.egg-info/top_level.txt +1 -0
- psdl_lang-0.2.0/tests/test_all_scenarios_e2e.py +556 -0
- psdl_lang-0.2.0/tests/test_clinical_validation.py +610 -0
- psdl_lang-0.2.0/tests/test_conformance.py +505 -0
- psdl_lang-0.2.0/tests/test_end_to_end.py +525 -0
- psdl_lang-0.2.0/tests/test_evaluator.py +455 -0
- psdl_lang-0.2.0/tests/test_fhir_backend.py +586 -0
- psdl_lang-0.2.0/tests/test_fhir_local.py +442 -0
- psdl_lang-0.2.0/tests/test_formal_spec.py +243 -0
- psdl_lang-0.2.0/tests/test_independent_verification.py +499 -0
- psdl_lang-0.2.0/tests/test_omop_backend.py +363 -0
- psdl_lang-0.2.0/tests/test_parser.py +468 -0
- psdl_lang-0.2.0/tests/test_psdl_vs_sql.py +561 -0
- psdl_lang-0.2.0/tests/test_scenarios_comprehensive.py +594 -0
- psdl_lang-0.2.0/tests/test_streaming.py +607 -0
psdl_lang-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
Copyright 2024 PSDL Contributors
|
|
179
|
+
|
|
180
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
|
+
you may not use this file except in compliance with the License.
|
|
182
|
+
You may obtain a copy of the License at
|
|
183
|
+
|
|
184
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
185
|
+
|
|
186
|
+
Unless required by applicable law or agreed to in writing, software
|
|
187
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
188
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
189
|
+
See the License for the specific language governing permissions and
|
|
190
|
+
limitations under the License.
|
psdl_lang-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: psdl-lang
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Patient Scenario Definition Language - Reference Implementation
|
|
5
|
+
Author-email: Ziyuan Guan <ziyuan.guan@ufl.edu>
|
|
6
|
+
Maintainer-email: Ziyuan Guan <ziyuan.guan@ufl.edu>
|
|
7
|
+
License: Apache-2.0
|
|
8
|
+
Project-URL: Homepage, https://github.com/Chesterguan/PSDL
|
|
9
|
+
Project-URL: Documentation, https://github.com/Chesterguan/PSDL#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/Chesterguan/PSDL
|
|
11
|
+
Project-URL: Issues, https://github.com/Chesterguan/PSDL/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/Chesterguan/PSDL/blob/main/CHANGELOG.md
|
|
13
|
+
Keywords: healthcare,clinical,patient,scenario,DSL,OMOP,FHIR,EHR,temporal,medical
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Typing :: Typed
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pyyaml>=6.0
|
|
32
|
+
Provides-Extra: full
|
|
33
|
+
Requires-Dist: requests>=2.28; extra == "full"
|
|
34
|
+
Requires-Dist: sqlalchemy>=2.0; extra == "full"
|
|
35
|
+
Provides-Extra: omop
|
|
36
|
+
Requires-Dist: sqlalchemy>=2.0; extra == "omop"
|
|
37
|
+
Provides-Extra: fhir
|
|
38
|
+
Requires-Dist: requests>=2.28; extra == "fhir"
|
|
39
|
+
Provides-Extra: streaming
|
|
40
|
+
Requires-Dist: apache-flink>=1.17; extra == "streaming"
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
44
|
+
Requires-Dist: jsonschema>=4.0; extra == "dev"
|
|
45
|
+
Requires-Dist: lark>=1.1; extra == "dev"
|
|
46
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
47
|
+
Requires-Dist: isort>=5.12; extra == "dev"
|
|
48
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
49
|
+
Requires-Dist: requests>=2.28; extra == "dev"
|
|
50
|
+
Provides-Extra: docs
|
|
51
|
+
Requires-Dist: sphinx>=6.0; extra == "docs"
|
|
52
|
+
Requires-Dist: sphinx-rtd-theme>=1.3; extra == "docs"
|
|
53
|
+
Requires-Dist: myst-parser>=2.0; extra == "docs"
|
|
54
|
+
Provides-Extra: notebook
|
|
55
|
+
Requires-Dist: jupyter>=1.0; extra == "notebook"
|
|
56
|
+
Requires-Dist: ipywidgets>=8.0; extra == "notebook"
|
|
57
|
+
Requires-Dist: pandas>=2.0; extra == "notebook"
|
|
58
|
+
Requires-Dist: matplotlib>=3.7; extra == "notebook"
|
|
59
|
+
Provides-Extra: all
|
|
60
|
+
Requires-Dist: psdl-lang[dev,docs,full,notebook,streaming]; extra == "all"
|
|
61
|
+
Dynamic: license-file
|
|
62
|
+
|
|
63
|
+
<p align="center">
|
|
64
|
+
<img src="docs/assets/logo.jpeg" alt="PSDL Logo" width="400"/>
|
|
65
|
+
</p>
|
|
66
|
+
|
|
67
|
+
<h1 align="center">PSDL</h1>
|
|
68
|
+
<h3 align="center">Patient Scenario Definition Language</h3>
|
|
69
|
+
|
|
70
|
+
<p align="center">
|
|
71
|
+
<em>An Open Standard for Clinical Logic, Real-Time Monitoring & AI Integration</em>
|
|
72
|
+
</p>
|
|
73
|
+
|
|
74
|
+
<p align="center">
|
|
75
|
+
<a href="https://github.com/Chesterguan/PSDL/actions/workflows/ci.yml"><img src="https://github.com/Chesterguan/PSDL/actions/workflows/ci.yml/badge.svg" alt="Tests"></a>
|
|
76
|
+
<a href="#specification"><img src="https://img.shields.io/badge/Spec-0.1.0-blue?style=flat-square" alt="Spec Version"></a>
|
|
77
|
+
<a href="#license"><img src="https://img.shields.io/badge/License-Apache%202.0-green?style=flat-square" alt="License"></a>
|
|
78
|
+
<a href="#contributing"><img src="https://img.shields.io/badge/PRs-Welcome-brightgreen?style=flat-square" alt="PRs Welcome"></a>
|
|
79
|
+
<img src="https://img.shields.io/badge/Python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue?style=flat-square&logo=python&logoColor=white" alt="Python 3.8-3.12">
|
|
80
|
+
</p>
|
|
81
|
+
|
|
82
|
+
<p align="center">
|
|
83
|
+
<strong>What SQL became for data queries, ONNX for ML models, and GraphQL for APIs —<br/>
|
|
84
|
+
PSDL is becoming the <em>semantic layer</em> for clinical AI.</strong>
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
<p align="center">
|
|
88
|
+
📄 <strong>Read the Whitepaper:</strong>
|
|
89
|
+
<a href="docs/WHITEPAPER_EN.md">English</a> ·
|
|
90
|
+
<a href="docs/WHITEPAPER_ZH.md">简体中文</a> ·
|
|
91
|
+
<a href="docs/WHITEPAPER_ES.md">Español</a> ·
|
|
92
|
+
<a href="docs/WHITEPAPER_FR.md">Français</a> ·
|
|
93
|
+
<a href="docs/WHITEPAPER_JA.md">日本語</a>
|
|
94
|
+
</p>
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Try It Now (No Setup Required)
|
|
99
|
+
|
|
100
|
+
Run PSDL in your browser with Google Colab - zero installation, real clinical data:
|
|
101
|
+
|
|
102
|
+
| Notebook | Data | Description |
|
|
103
|
+
|----------|------|-------------|
|
|
104
|
+
| [](https://colab.research.google.com/github/Chesterguan/PSDL/blob/main/notebooks/PSDL_Colab_Synthea.ipynb) | **Synthetic** | Quick demo with generated patient data (2 min) |
|
|
105
|
+
| [](https://colab.research.google.com/github/Chesterguan/PSDL/blob/main/notebooks/PSDL_Colab_MIMIC_Demo.ipynb) | **MIMIC-IV Demo** | 100 real ICU patients, ICD diagnoses |
|
|
106
|
+
| [](https://colab.research.google.com/github/Chesterguan/PSDL/blob/main/notebooks/PSDL_Colab_Sepsis_Challenge.ipynb) | **PhysioNet Sepsis** | 40,000+ patients with labeled sepsis |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## The Problem
|
|
111
|
+
|
|
112
|
+
Despite significant advances in clinical AI and machine learning, **real-time decision support in healthcare remains fragmented, non-portable, non-reproducible, and exceptionally difficult to audit or regulate**.
|
|
113
|
+
|
|
114
|
+
<p align="center">
|
|
115
|
+
<img src="docs/assets/layers.jpeg" alt="Healthcare AI Semantic Stack" width="800"/>
|
|
116
|
+
<br/>
|
|
117
|
+
<em>PSDL fills the missing semantic layer in the healthcare AI stack</em>
|
|
118
|
+
</p>
|
|
119
|
+
|
|
120
|
+
## What is PSDL?
|
|
121
|
+
|
|
122
|
+
PSDL (Patient Scenario Definition Language) is a declarative, vendor-neutral language for expressing clinical scenarios. It provides a structured way to define:
|
|
123
|
+
|
|
124
|
+
| Component | Description |
|
|
125
|
+
|-----------|-------------|
|
|
126
|
+
| **Signals** | Time-series clinical data bindings (labs, vitals, etc.) |
|
|
127
|
+
| **Trends** | Temporal computations over signals (deltas, slopes, averages) |
|
|
128
|
+
| **Logic** | Boolean algebra combining trends into clinical states |
|
|
129
|
+
| **Population** | Criteria for which patients a scenario applies to |
|
|
130
|
+
| **Triggers** | Event-condition-action rules (v0.2) |
|
|
131
|
+
|
|
132
|
+
<p align="center">
|
|
133
|
+
<img src="docs/assets/semantic langauge.jpeg" alt="How PSDL Works" width="800"/>
|
|
134
|
+
<br/>
|
|
135
|
+
<em>Syntax vs Semantics vs Runtime - How PSDL Works</em>
|
|
136
|
+
</p>
|
|
137
|
+
|
|
138
|
+
## Quick Example
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
# Detect early kidney injury
|
|
142
|
+
scenario: AKI_Early_Detection
|
|
143
|
+
version: "0.1.0"
|
|
144
|
+
|
|
145
|
+
signals:
|
|
146
|
+
Cr:
|
|
147
|
+
source: creatinine
|
|
148
|
+
concept_id: 3016723 # OMOP concept
|
|
149
|
+
unit: mg/dL
|
|
150
|
+
|
|
151
|
+
trends:
|
|
152
|
+
cr_rising:
|
|
153
|
+
expr: delta(Cr, 6h) > 0.3
|
|
154
|
+
description: "Creatinine rise > 0.3 mg/dL in 6 hours"
|
|
155
|
+
|
|
156
|
+
cr_high:
|
|
157
|
+
expr: last(Cr) > 1.5
|
|
158
|
+
description: "Current creatinine elevated"
|
|
159
|
+
|
|
160
|
+
logic:
|
|
161
|
+
aki_risk:
|
|
162
|
+
expr: cr_rising AND cr_high
|
|
163
|
+
severity: high
|
|
164
|
+
description: "Early AKI - rising and elevated creatinine"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Why PSDL?
|
|
168
|
+
|
|
169
|
+
| Challenge | Without PSDL | With PSDL |
|
|
170
|
+
|-----------|--------------|-----------|
|
|
171
|
+
| **Portability** | Logic tied to specific hospital systems | Same scenario runs anywhere with mapping |
|
|
172
|
+
| **Auditability** | Scattered across Python, SQL, configs | Single structured, version-controlled file |
|
|
173
|
+
| **Reproducibility** | Hidden state, implicit dependencies | Deterministic execution, explicit semantics |
|
|
174
|
+
| **Regulatory Compliance** | Manual documentation | Built-in audit primitives |
|
|
175
|
+
| **Research Sharing** | Cannot validate published scenarios | Portable, executable definitions |
|
|
176
|
+
|
|
177
|
+
## Installation
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Clone the repository
|
|
181
|
+
git clone https://github.com/Chesterguan/PSDL.git
|
|
182
|
+
cd psdl
|
|
183
|
+
|
|
184
|
+
# Install dependencies
|
|
185
|
+
pip install -r requirements.txt
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Usage
|
|
189
|
+
|
|
190
|
+
### Parse a Scenario
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from psdl import PSDLParser
|
|
194
|
+
|
|
195
|
+
parser = PSDLParser()
|
|
196
|
+
scenario = parser.parse_file("examples/aki_detection.yaml")
|
|
197
|
+
|
|
198
|
+
print(f"Scenario: {scenario.name}")
|
|
199
|
+
print(f"Signals: {list(scenario.signals.keys())}")
|
|
200
|
+
print(f"Logic rules: {list(scenario.logic.keys())}")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Evaluate Against Patient Data
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from psdl import PSDLParser, PSDLEvaluator, InMemoryBackend
|
|
207
|
+
from psdl.operators import DataPoint
|
|
208
|
+
from datetime import datetime, timedelta
|
|
209
|
+
|
|
210
|
+
# Parse scenario
|
|
211
|
+
parser = PSDLParser()
|
|
212
|
+
scenario = parser.parse_file("examples/aki_detection.yaml")
|
|
213
|
+
|
|
214
|
+
# Set up data backend
|
|
215
|
+
backend = InMemoryBackend()
|
|
216
|
+
now = datetime.now()
|
|
217
|
+
|
|
218
|
+
# Add patient data
|
|
219
|
+
backend.add_data(
|
|
220
|
+
patient_id=123,
|
|
221
|
+
signal_name="Cr",
|
|
222
|
+
data=[
|
|
223
|
+
DataPoint(now - timedelta(hours=6), 1.0),
|
|
224
|
+
DataPoint(now - timedelta(hours=3), 1.3),
|
|
225
|
+
DataPoint(now, 1.8),
|
|
226
|
+
]
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Evaluate
|
|
230
|
+
evaluator = PSDLEvaluator(scenario, backend)
|
|
231
|
+
result = evaluator.evaluate_patient(patient_id=123, reference_time=now)
|
|
232
|
+
|
|
233
|
+
if result.is_triggered:
|
|
234
|
+
print(f"Patient triggered: {result.triggered_logic}")
|
|
235
|
+
print(f"Trend values: {result.trend_values}")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Temporal Operators
|
|
239
|
+
|
|
240
|
+
| Operator | Syntax | Description |
|
|
241
|
+
|----------|--------|-------------|
|
|
242
|
+
| `delta` | `delta(signal, window)` | Absolute change over window |
|
|
243
|
+
| `slope` | `slope(signal, window)` | Linear regression slope |
|
|
244
|
+
| `ema` | `ema(signal, window)` | Exponential moving average |
|
|
245
|
+
| `sma` | `sma(signal, window)` | Simple moving average |
|
|
246
|
+
| `min` | `min(signal, window)` | Minimum value in window |
|
|
247
|
+
| `max` | `max(signal, window)` | Maximum value in window |
|
|
248
|
+
| `count` | `count(signal, window)` | Observation count |
|
|
249
|
+
| `last` | `last(signal)` | Most recent value |
|
|
250
|
+
|
|
251
|
+
### Window Formats
|
|
252
|
+
|
|
253
|
+
- `30s` - 30 seconds
|
|
254
|
+
- `5m` - 5 minutes
|
|
255
|
+
- `6h` - 6 hours
|
|
256
|
+
- `1d` - 1 day
|
|
257
|
+
- `7d` - 7 days
|
|
258
|
+
|
|
259
|
+
## Project Structure
|
|
260
|
+
|
|
261
|
+
PSDL follows industry-standard patterns (like GraphQL, CQL, ONNX):
|
|
262
|
+
- **Specification** defines WHAT
|
|
263
|
+
- **Reference Implementation** shows HOW.
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
psdl/
|
|
267
|
+
├── README.md # This file
|
|
268
|
+
├── spec/ # SPECIFICATION
|
|
269
|
+
│ └── schema-v0.1.yaml # YAML schema + operator semantics
|
|
270
|
+
├── src/psdl/ # REFERENCE IMPLEMENTATION (Python)
|
|
271
|
+
│ ├── __init__.py
|
|
272
|
+
│ ├── parser.py # YAML parser
|
|
273
|
+
│ ├── evaluator.py # Batch execution mode
|
|
274
|
+
│ ├── operators.py # Temporal operators
|
|
275
|
+
│ ├── execution/ # Execution Modes
|
|
276
|
+
│ │ ├── batch.py # Batch mode + SQL compiler
|
|
277
|
+
│ │ └── streaming/ # Streaming mode (Flink)
|
|
278
|
+
│ └── adapters/ # Data Adapters
|
|
279
|
+
│ ├── omop.py # OMOP CDM adapter (SQL)
|
|
280
|
+
│ └── fhir.py # FHIR R4 adapter (REST)
|
|
281
|
+
├── examples/ # Example scenarios
|
|
282
|
+
│ ├── icu_deterioration.yaml
|
|
283
|
+
│ ├── aki_detection.yaml
|
|
284
|
+
│ └── sepsis_screening.yaml
|
|
285
|
+
├── docs/
|
|
286
|
+
│ ├── getting-started.md
|
|
287
|
+
│ ├── WHITEPAPER.md # Full specification document
|
|
288
|
+
│ └── assets/ # Images and diagrams
|
|
289
|
+
└── tests/
|
|
290
|
+
├── test_parser.py
|
|
291
|
+
└── test_evaluator.py
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
| Component | Description |
|
|
295
|
+
|-----------|-------------|
|
|
296
|
+
| **Specification** | PSDL language definition (YAML schema + operator semantics) |
|
|
297
|
+
| **Reference Implementation** | Python implementation demonstrating the spec |
|
|
298
|
+
| **Parser** | Parses PSDL YAML into internal representation |
|
|
299
|
+
| **Evaluator** | Executes parsed scenarios (batch mode) |
|
|
300
|
+
| **Data Adapter** | Interface to clinical data sources (OMOP, FHIR) |
|
|
301
|
+
|
|
302
|
+
## Running Tests
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Run all tests
|
|
306
|
+
pytest tests/ -v
|
|
307
|
+
|
|
308
|
+
# Run with verbose output
|
|
309
|
+
pytest tests/ -v -s
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Test Coverage: 234 Tests (All Passing)
|
|
313
|
+
|
|
314
|
+
- **Unit Tests**: Parser, evaluator, operators, scenarios
|
|
315
|
+
- **Integration Tests**: FHIR adapter, OMOP backend with population filtering
|
|
316
|
+
- **Validation**: SQL equivalence (100% match), KDIGO clinical guidelines
|
|
317
|
+
- **Streaming Tests**: Window functions, logic evaluation, Flink compiler
|
|
318
|
+
|
|
319
|
+
See [tests/TEST_VALIDATION.md](tests/TEST_VALIDATION.md) for detailed methodology.
|
|
320
|
+
|
|
321
|
+
## Example Scenarios
|
|
322
|
+
|
|
323
|
+
| Scenario | Description | Clinical Use |
|
|
324
|
+
|----------|-------------|--------------|
|
|
325
|
+
| **ICU Deterioration** | Monitors for early signs of clinical deterioration | Kidney function, lactate trends, hemodynamics |
|
|
326
|
+
| **AKI Detection** | KDIGO criteria for Acute Kidney Injury staging | Creatinine-based staging |
|
|
327
|
+
| **Sepsis Screening** | qSOFA + lactate-based sepsis screening | Early sepsis identification |
|
|
328
|
+
|
|
329
|
+
## Design Principles
|
|
330
|
+
|
|
331
|
+
| Principle | Description |
|
|
332
|
+
|-----------|-------------|
|
|
333
|
+
| **Declarative** | Define *what* to detect, not *how* to compute it |
|
|
334
|
+
| **Portable** | Same scenario runs on any OMOP/FHIR backend with mapping |
|
|
335
|
+
| **Auditable** | Structured format enables static analysis and version control |
|
|
336
|
+
| **Deterministic** | Predictable execution with no hidden state |
|
|
337
|
+
| **Open** | Vendor-neutral, community-governed |
|
|
338
|
+
|
|
339
|
+
## Roadmap
|
|
340
|
+
|
|
341
|
+
| Phase | Status | Focus |
|
|
342
|
+
|-------|--------|-------|
|
|
343
|
+
| **Phase 1: Semantic Foundation** | ✅ Complete | Spec, parser, operators, OMOP/FHIR adapters, 234 tests |
|
|
344
|
+
| **Phase 2: Enhanced Runtime** | 🚧 Current | ✅ Streaming, ✅ SQL generation, triggers, packaging |
|
|
345
|
+
| **Phase 3: Community** | 📋 Planned | Blog series, conferences, tooling ecosystem |
|
|
346
|
+
| **Phase 4: Adoption** | 🔮 Future | Hospital pilots, standards engagement |
|
|
347
|
+
|
|
348
|
+
📍 **[View Full Roadmap →](docs/ROADMAP.md)**
|
|
349
|
+
|
|
350
|
+
## Related Standards
|
|
351
|
+
|
|
352
|
+
| Standard | Relationship |
|
|
353
|
+
|----------|--------------|
|
|
354
|
+
| **OMOP CDM** | Data model for signals (concept_id references) |
|
|
355
|
+
| **FHIR** | Planned runtime target |
|
|
356
|
+
| **CQL** | Similar domain, different scope (quality measures) |
|
|
357
|
+
| **ONNX** | Inspiration for portable format approach |
|
|
358
|
+
|
|
359
|
+
## Documentation
|
|
360
|
+
|
|
361
|
+
| Document | Description |
|
|
362
|
+
|----------|-------------|
|
|
363
|
+
| [Whitepaper](docs/WHITEPAPER.md) | Full project vision and specification (5 languages) |
|
|
364
|
+
| [Getting Started](docs/getting-started.md) | Quick start guide |
|
|
365
|
+
| [Roadmap](docs/ROADMAP.md) | Development phases and timeline |
|
|
366
|
+
| [Schema](spec/schema-v0.1.yaml) | YAML schema definition |
|
|
367
|
+
| [Changelog](CHANGELOG.md) | Version history |
|
|
368
|
+
|
|
369
|
+
## Contributing
|
|
370
|
+
|
|
371
|
+
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
372
|
+
|
|
373
|
+
### Ways to Contribute
|
|
374
|
+
|
|
375
|
+
- **Specification**: Propose language features, operators, semantics
|
|
376
|
+
- **Implementation**: Build runtimes, backends, tooling
|
|
377
|
+
- **Documentation**: Improve guides, tutorials, examples
|
|
378
|
+
- **Testing**: Add conformance tests, find edge cases
|
|
379
|
+
- **Adoption**: Share use cases, pilot experiences
|
|
380
|
+
|
|
381
|
+
## License
|
|
382
|
+
|
|
383
|
+
Apache 2.0 - See [LICENSE](LICENSE) for details.
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
<p align="center">
|
|
388
|
+
<strong>Clinical AI doesn't fail because models are weak.<br/>
|
|
389
|
+
It fails because there's no semantic layer to express clinical logic portably.</strong>
|
|
390
|
+
</p>
|
|
391
|
+
|
|
392
|
+
<p align="center">
|
|
393
|
+
<em>PSDL is the semantic layer for clinical AI — like SQL for databases.</em>
|
|
394
|
+
</p>
|
|
395
|
+
|
|
396
|
+
<p align="center">
|
|
397
|
+
<sub>An open standard built by the community, for the community.</sub>
|
|
398
|
+
</p>
|