Skip to content

Commit 0a34812

Browse files
committed
tutorials
1 parent 14ed85e commit 0a34812

File tree

3 files changed

+777
-0
lines changed

3 files changed

+777
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "c4fa3cdf-d540-4add-8a31-a1fd6b126ba3",
6+
"metadata": {},
7+
"source": [
8+
"# ArithmeticPhenotype Tutorial\n",
9+
"\n",
10+
"The ArithmeticPhenotype allows us to perform simple mathematical operations such as addition, subtraction, division and multiplication with the output of other phenotypes.\n",
11+
"\n",
12+
"There are two obvious use cases for this in RWD :\n",
13+
"1. calculating medical scores, such as the CHADSVASC score or the Charlson Comorbidity Index\n",
14+
"2. calculating a derived measurement value, such as Body Mass Index, which is calculated using height and weight.\n",
15+
"\n",
16+
"\n",
17+
"In this tutorial, we will see how to calculate CHASVASC and how to calculate BMI.\n",
18+
"\n",
19+
"\n",
20+
"## Calculating scores\n",
21+
"Like the LogicPhenotype, the Arithmetic phenotype operates on other phenotypes; we refer to the phenotypes that an ArithmeticPhenotype operates on the 'component phenotypes'. \n",
22+
"\n",
23+
"In order to perform arithmetic, we need to associate a value to patients fulfilling criteria of a component phenotype. By default, this is done by associating the value of '1' with all patients that fulfill the criteria of a component phenotype. Patients that do not fulfill the component phenotype criteria are associated with a value of '0'. \n",
24+
"\n",
25+
"Let's see how this works on a simple example of the CHADSVASC score. We will assume that Codelists already exist for each component phenotype.\n",
26+
"### Step 1 : Create all component phenotypes"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": null,
32+
"id": "16f7c761-32d8-4a8f-a844-2022b302ddeb",
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"# Step 1 : First create all component phenotypes\n",
37+
"c = CodelistPhenotype(\n",
38+
" codelist=Codelist(\"heart_failure\"), \n",
39+
" domain=\"condition_occurrence\",\n",
40+
" relative_time_range = ONEYEAR_PREINDEX\n",
41+
")\n",
42+
"\n",
43+
"h = CodelistPhenotype(\n",
44+
" codelist=Codelist(\"hypertension\"), \n",
45+
" domain=\"condition_occurrence\",\n",
46+
" relative_time_range = ONEYEAR_PREINDEX\n",
47+
")\n",
48+
"\n",
49+
"a75 = AgePhenotype(\n",
50+
" min_age=GreaterThanOrEqualTo(75),\n",
51+
" relative_time_range = ONEYEAR_PREINDEX\n",
52+
")\n",
53+
"\n",
54+
"d = CodelistPhenotype(\n",
55+
" codelist=Codelist(\"diabetes_and_impaired_glucose_tolerance\"),\n",
56+
" domain=\"condition_occurrence\",\n",
57+
" relative_time_range = ONEYEAR_PREINDEX\n",
58+
")\n",
59+
"\n",
60+
"s = CodelistPhenotype(\n",
61+
" codelist=Codelist(\"stroke\"), \n",
62+
" domain=\"condition_occurrence\",\n",
63+
" relative_time_range = ONEYEAR_PREINDEX\n",
64+
")\n",
65+
"\n",
66+
"v = CodelistPhenotype(\n",
67+
" codelist=Codelist(\"peripheral_artery_disease\"), \n",
68+
" domain=\"condition_occurrence\",\n",
69+
" relative_time_range = ONEYEAR_PREINDEX\n",
70+
")\n",
71+
"\n",
72+
"a65to74 = AgePhenotype(\n",
73+
" min_age=GreaterThanOrEqualTo(65),\n",
74+
" max_age=LessThanOrEqualTo(74),\n",
75+
" relative_time_range = ONEYEAR_PREINDEX\n",
76+
")\n",
77+
"\n",
78+
"sc = SexPhenotype(allowed_values=[2]) # female is defined as a value of 2 in our optum data base"
79+
]
80+
},
81+
{
82+
"cell_type": "markdown",
83+
"id": "8aecd389-46d7-4a77-88d1-1ede2a881daa",
84+
"metadata": {},
85+
"source": [
86+
"### Step 2 : Create ArithmeticPhenotype\n",
87+
"We can then create our arithmetic phenotype by combining our phenotypes with mathematical operations. We do this for chadsvasc by adding up all the component phenotype values. Recall that the default value for a component phenotype is 1; if we want another value associated with the component phenotype, we perform multiplication with that value (see that age>75 and sex category a75,s respectively are associated with the value of 2)"
88+
]
89+
},
90+
{
91+
"cell_type": "code",
92+
"execution_count": null,
93+
"id": "602d4982-ddd1-457c-a9bd-8fcdd504a003",
94+
"metadata": {},
95+
"outputs": [],
96+
"source": [
97+
"chadsvasc = ScorePhenotype(\n",
98+
" name = \"chadsvasc\",\n",
99+
" expression = c + h + a75 * 2 + d + s * 2 + v + a65to74 + sc,\n",
100+
")"
101+
]
102+
},
103+
{
104+
"cell_type": "markdown",
105+
"id": "2cb1da51-c544-4dfa-83c7-5e189cdfeb38",
106+
"metadata": {},
107+
"source": [
108+
"## Calculating derived measurement values\n",
109+
"MeasurementPhenotypes are unique in that, if the return_value keyword argument is set, they are associated with a value. ArithmeticPhenotype will operate on the returned value of MeasurementPhenotypes, allowing us to calculate derived values from measurement values.\n",
110+
"\n",
111+
"This is useful for the example of body mass index, which is defined as weight divided by height in meters to the power of 2. \n",
112+
"\n",
113+
"As seen in the above example, the steps are to (1) define our component phenotypes and (2) create the arithmetic phenotype that combines them with our mathematical operations\n",
114+
"### Step 1 : Create all component phenotypes"
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": null,
120+
"id": "dcf77a03-b191-4443-a4f8-822829fd1fb0",
121+
"metadata": {},
122+
"outputs": [],
123+
"source": [
124+
"# define our component phenotypes\n",
125+
"h = MeasurementPhenotype(\n",
126+
" name=\"height\",\n",
127+
" codelist=Codelist(\"HEIGHT\"),\n",
128+
" domain=\"measurement\",\n",
129+
" relative_time_range = ONEYEAR_PREINDEX,\n",
130+
" value_aggregation=\"mean\",\n",
131+
" return_value=\"all\"\n",
132+
")\n",
133+
"\n",
134+
"w = MeasurementPhenotype(\n",
135+
" name=\"weight\",\n",
136+
" codelist=Codelist(\"WEIGHT\"),\n",
137+
" domain=\"measurement\",\n",
138+
" relative_time_range = ONEYEAR_PREINDEX,\n",
139+
" value_aggregation=\"mean\",\n",
140+
" return_value=\"all\"\n",
141+
")"
142+
]
143+
},
144+
{
145+
"cell_type": "markdown",
146+
"id": "23f9e24f-8519-4fcc-995c-4dec89754210",
147+
"metadata": {},
148+
"source": [
149+
"### Step 2: Create ArithmeticPhenotype"
150+
]
151+
},
152+
{
153+
"cell_type": "code",
154+
"execution_count": null,
155+
"id": "cfcc64fc-c6ce-4e4b-bb8e-1ffea5c21ec5",
156+
"metadata": {},
157+
"outputs": [],
158+
"source": [
159+
"\n",
160+
"# calculate the bmi\n",
161+
"bmi = ArithmeticPhenotype(\n",
162+
" name=\"bmi\",\n",
163+
" expression = w / (h / 100) ** 2, \n",
164+
")\n"
165+
]
166+
},
167+
{
168+
"cell_type": "markdown",
169+
"id": "786165f4-7d08-4a16-a5f4-1d5c900eecd7",
170+
"metadata": {},
171+
"source": [
172+
"## Setting value filters\n",
173+
"With ArithmeticPhenotype, like MeasurementPhenotype, we can define value_filters that allow us to subset patients that fulfill some filtering criteria.\n",
174+
"\n",
175+
"For example, I may be interested only in patients with a BMI greater or equal to 30. "
176+
]
177+
},
178+
{
179+
"cell_type": "code",
180+
"execution_count": null,
181+
"id": "f5f6379b-9cfe-425d-adbb-aedee80185e0",
182+
"metadata": {},
183+
"outputs": [],
184+
"source": [
185+
"# calculate the bmi\n",
186+
"bmi = ArithmeticPhenotype(\n",
187+
" name=\"bmi\",\n",
188+
" logic=w / (h / 100) ** 2, \n",
189+
" value_filter=ValueFilter(\">=\", 30, \"value\"),\n",
190+
")"
191+
]
192+
}
193+
],
194+
"metadata": {
195+
"kernelspec": {
196+
"display_name": "Python 3 (ipykernel)",
197+
"language": "python",
198+
"name": "python3"
199+
},
200+
"language_info": {
201+
"codemirror_mode": {
202+
"name": "ipython",
203+
"version": 3
204+
},
205+
"file_extension": ".py",
206+
"mimetype": "text/x-python",
207+
"name": "python",
208+
"nbconvert_exporter": "python",
209+
"pygments_lexer": "ipython3",
210+
"version": "3.12.7"
211+
}
212+
},
213+
"nbformat": 4,
214+
"nbformat_minor": 5
215+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "ce4eeb71-b2ff-4803-b9c1-8e0e35998feb",
6+
"metadata": {},
7+
"source": [
8+
"# LogicPhenotype Tutorial\n",
9+
"\n",
10+
"The LogicPhenotype allows us to combine phenotypes with logical operations AND, OR and NOT\n",
11+
"\n",
12+
"There are obvious use cases for this in RWD :\n",
13+
"1. We want to combine information from multiple domains, for example \"procedures\" and \"diagnoses\". An example is : Which patients have a diagnosis for heart transplant OR a procedure for heart transplant?\n",
14+
"2. We want to calculate complicated logical definitions : It is common to generate algorithms to correctly classify patients has having a condition. This means we want patients to fulfill some lab value criteria, diagnosis criteria and so on. We can create arbitraily complex definitions using Complex Phenotype\n",
15+
"\n"
16+
]
17+
},
18+
{
19+
"cell_type": "markdown",
20+
"id": "f24b9966-9f11-4f00-ab68-bcdfae180f98",
21+
"metadata": {},
22+
"source": [
23+
"## Combining information from multiple domains\n",
24+
"We often want to ask 'which patients have a diagnosis of condition_x OR a procedure treating condition_x'. Diagnoses and procedures are often found in separate domains, the condition_occurrence and procedure_occurence table\n",
25+
"\n",
26+
"LogicPhenotype allows us to combine information from multiple domains\n",
27+
"\n",
28+
"### Step 1 : Create component phenotypes"
29+
]
30+
},
31+
{
32+
"cell_type": "code",
33+
"execution_count": null,
34+
"id": "6761f436-d192-43c0-a1d8-3d214524f98a",
35+
"metadata": {},
36+
"outputs": [],
37+
"source": [
38+
"ht_procedure_codes = Codelist(\"heart_transplant\")\n",
39+
"ht_diagnosis_codes = Codelist(\"heart_transplant\")\n",
40+
"\n",
41+
"\n",
42+
"ht_procedures = CodelistPhenotype(\n",
43+
" name_phenotype=\"ht_procedures\",\n",
44+
" codelist=ht_procedure_codes,\n",
45+
" domain=\"procedure_occurrence\",\n",
46+
" time_range_filter=ONEYEAR_PREINDEX,\n",
47+
")\n",
48+
"\n",
49+
"ht_diagnoses = CodelistPhenotype(\n",
50+
" name_phenotype=\"ht_diagnoses\",\n",
51+
" codelist= ht_diagnosis_codes,\n",
52+
" domain=\"condition_occurrence\",\n",
53+
" time_range_filter=ONEYEAR_PREINDEX,\n",
54+
")\n"
55+
]
56+
},
57+
{
58+
"cell_type": "markdown",
59+
"id": "1e156f2b-a4ff-486d-b3cb-9fa7a7d1788c",
60+
"metadata": {},
61+
"source": [
62+
"### Step 2 : Create LogicPhenotype\n",
63+
"We are now ready to create our LogicPhenotype using our component phenotypes. Here we can use the logical operations and, or (&,|). \n",
64+
"\n",
65+
"Here we will show two logic phenotypes, one using OR and one using AND.\n",
66+
"\n"
67+
]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": null,
72+
"id": "1d9df98c-2556-48eb-ae4e-6379815fe4bc",
73+
"metadata": {},
74+
"outputs": [],
75+
"source": [
76+
"\n",
77+
"# use logical OR\n",
78+
"ht_or = LogicPhenotype(\n",
79+
" name_phenotype=\"ht_procedure_OR_diagnosis\", \n",
80+
" logic = ht_procedures | ht_diagnoses\n",
81+
")\n",
82+
"\n",
83+
"# use logical AND\n",
84+
"ht_and = LogicPhenotype(\n",
85+
" name_phenotype=\"ht_procedure_AND_diagnosis\", \n",
86+
" logic = ht_procedures & ht_diagnoses\n",
87+
")"
88+
]
89+
},
90+
{
91+
"cell_type": "markdown",
92+
"id": "1365771d-637c-4b26-99c5-30bdd51436a6",
93+
"metadata": {},
94+
"source": [
95+
"## Complicated logical phenotypes\n",
96+
"We can add arbitraily complex logic to our operations. Lets add two more component phenotypes, death and an 'end of coverage' phenotype. We will use these to create a censoring event phenotype, which is ht"
97+
]
98+
},
99+
{
100+
"cell_type": "code",
101+
"execution_count": null,
102+
"id": "94ba769a-2127-45bb-8009-790a35f3a5d4",
103+
"metadata": {},
104+
"outputs": [],
105+
"source": [
106+
"# create two new component phenotypes\n",
107+
"death = DeathPhenotype()\n",
108+
"late_date_active = ContinuousCoveragePhenotype(return_date=\"last\")\n",
109+
"\n",
110+
"# create a logic phenotype combining all components\n",
111+
"censoring_event = LogicPhenotype(\n",
112+
" name_phenotype=\"any_censoring\",\n",
113+
" logic= ht_or | death | late_date_active,\n",
114+
" return_date=\"first\",\n",
115+
")\n"
116+
]
117+
}
118+
],
119+
"metadata": {
120+
"kernelspec": {
121+
"display_name": "Python 3 (ipykernel)",
122+
"language": "python",
123+
"name": "python3"
124+
},
125+
"language_info": {
126+
"codemirror_mode": {
127+
"name": "ipython",
128+
"version": 3
129+
},
130+
"file_extension": ".py",
131+
"mimetype": "text/x-python",
132+
"name": "python",
133+
"nbconvert_exporter": "python",
134+
"pygments_lexer": "ipython3",
135+
"version": "3.9.19"
136+
}
137+
},
138+
"nbformat": 4,
139+
"nbformat_minor": 5
140+
}

0 commit comments

Comments
 (0)