diff --git a/OMOP_demo.ipynb b/OMOP_demo.ipynb new file mode 100644 index 0000000..fd738f6 --- /dev/null +++ b/OMOP_demo.ipynb @@ -0,0 +1,1065 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/anaconda3/envs/ehrapy_latents/lib/python3.9/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from ehrdata import OMOP\n", + "# Using MIMIC-IV demo data in the OMOP Common Data Model\n", + "# Download link: https://physionet.org/content/mimic-iv-demo-omop/0.9/" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "omop = OMOP(file_paths=\"/Users/xinyuezhang/mimic-iv-demo-data-in-the-omop-common-data-model-0.9/1_omop_data_csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m2024-01-04 13:38:37,971\u001b[0m - \u001b[1;34mroot\u001b[0m \u001b[1;30mINFO - Transformed passed dataframe into an AnnData object with n_obs x n_vars = `852` x `2`.\u001b[0m\n" + ] + } + ], + "source": [ + "# Load some tables\n", + "adata = omop.load(level='stay_level')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# think about where to store these statistics" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Couldn't find concept [0] in concept table!\n",
+       "
\n" + ], + "text/plain": [ + "Couldn't find concept \u001b[1m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1m]\u001b[0m in concept table!\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Explore most frequent n features in measurement table\n", + "feature_counts = omop.feature_statistics(source='measurement', number=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
feature_namemeasurement_concept_id_1measurement_concept_id_2count
0Respiratory Rate2000030002302417119776
1Heart Rate2000030001302701819319
2O2 saturation pulseoxymetry20000300034076249917683
3Heart Rhythm2000030004302231812441
4ART BP Mean200003009630275989738
5Arterial Blood Pressure systolic200003000930042499661
6Manual Blood Pressure Diastolic Right200003015730128889660
7Non Invasive Blood Pressure diastolic2000030006214922408373
8Non Invasive Blood Pressure systolic2000030005214922398371
9Non Invasive Blood Pressure mean2000030007214922418366
100006850
11Temperature Celsius200003009230208914057
12Potassium (serum)200003006230231033970
13Sodium (serum)200003006330195503954
14Chloride (serum)200003006430145763933
15Creatinine (serum)200003006830167233886
16Hemoglobin|Blood|Blood Gas200000100830009633778
17HCO3 (serum)200003006930162933763
18Glucose (serum)200003007230045013597
19GCS - Eye Opening200003001330163353268
\n", + "
" + ], + "text/plain": [ + " feature_name measurement_concept_id_1 \\\n", + "0 Respiratory Rate 2000030002 \n", + "1 Heart Rate 2000030001 \n", + "2 O2 saturation pulseoxymetry 2000030003 \n", + "3 Heart Rhythm 2000030004 \n", + "4 ART BP Mean 2000030096 \n", + "5 Arterial Blood Pressure systolic 2000030009 \n", + "6 Manual Blood Pressure Diastolic Right 2000030157 \n", + "7 Non Invasive Blood Pressure diastolic 2000030006 \n", + "8 Non Invasive Blood Pressure systolic 2000030005 \n", + "9 Non Invasive Blood Pressure mean 2000030007 \n", + "10 0 0 \n", + "11 Temperature Celsius 2000030092 \n", + "12 Potassium (serum) 2000030062 \n", + "13 Sodium (serum) 2000030063 \n", + "14 Chloride (serum) 2000030064 \n", + "15 Creatinine (serum) 2000030068 \n", + "16 Hemoglobin|Blood|Blood Gas 2000001008 \n", + "17 HCO3 (serum) 2000030069 \n", + "18 Glucose (serum) 2000030072 \n", + "19 GCS - Eye Opening 2000030013 \n", + "\n", + " measurement_concept_id_2 count \n", + "0 3024171 19776 \n", + "1 3027018 19319 \n", + "2 40762499 17683 \n", + "3 3022318 12441 \n", + "4 3027598 9738 \n", + "5 3004249 9661 \n", + "6 3012888 9660 \n", + "7 21492240 8373 \n", + "8 21492239 8371 \n", + "9 21492241 8366 \n", + "10 0 6850 \n", + "11 3020891 4057 \n", + "12 3023103 3970 \n", + "13 3019550 3954 \n", + "14 3014576 3933 \n", + "15 3016723 3886 \n", + "16 3000963 3778 \n", + "17 3016293 3763 \n", + "18 3004501 3597 \n", + "19 3016335 3268 " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_counts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata = omop.extract_features(adata, source='measurement', features=[2000030003, 'Respiratory Rate'], map_concept=True, add_aggregation_to_X=False, verbose=True, remove_empty_column=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AnnData object with n_obs × n_vars = 852 × 2\n", + " obs: 'preceding_visit_occurrence_id', 'race_source_concept_id', 'discharge_to_concept_id', 'discharge_to_source_value', 'death_datetime', 'visit_concept_id', 'race_source_value', 'gender_source_concept_id', 'cause_source_concept_id', 'cause_concept_id', 'death_type_concept_id', 'provider_id_y', 'care_site_id_y', 'provider_id_x', 'visit_end_date', 'month_of_birth', 'visit_type_concept_id', 'visit_source_concept_id', 'day_of_birth', 'cause_source_value', 'birth_datetime', 'visit_start_datetime', 'race_concept_id', 'care_site_id_x', 'visit_end_datetime', 'admitting_source_concept_id', 'location_id', 'ethnicity_source_value', 'visit_source_value', 'gender_concept_id', 'ethnicity_concept_id', 'visit_start_date', 'ethnicity_source_concept_id', 'person_source_value', 'death_date', 'admitting_source_value'\n", + " uns: 'numerical_columns', 'non_numerical_columns'\n", + " obsm: 'O2 saturation pulseoxymetry'\n", + " layers: 'original'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Detected: feature Pain Level Response, feature ID 3034263 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mPain Level Response\u001b[0m, feature ID \u001b[1;32m3034263\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Pain Level Acceptable, feature ID 4138763 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mPain Level Acceptable\u001b[0m, feature ID \u001b[1;32m4138763\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Pain Present, feature ID 40757693 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mPain Present\u001b[0m, feature ID \u001b[1;32m40757693\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Temperature Site, feature ID 3024265 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mTemperature Site\u001b[0m, feature ID \u001b[1;32m3024265\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Oral Care, feature ID 3039006 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mOral Care\u001b[0m, feature ID \u001b[1;32m3039006\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Bowel Sounds, feature ID 4337265 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mBowel Sounds\u001b[0m, feature ID \u001b[1;32m4337265\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Past medical history, feature ID 3001062 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mPast medical history\u001b[0m, feature ID \u001b[1;32m3001062\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Respiratory Effort, feature ID 21492835 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mRespiratory Effort\u001b[0m, feature ID \u001b[1;32m21492835\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Code Status, feature ID 4127294 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mCode Status\u001b[0m, feature ID \u001b[1;32m4127294\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Pain Management, feature ID 4192791 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mPain Management\u001b[0m, feature ID \u001b[1;32m4192791\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature O2 Delivery Device(s), feature ID 4036936 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mO2 Delivery \u001b[0m\u001b[1;32mDevice\u001b[0m\u001b[1;32m(\u001b[0m\u001b[32ms\u001b[0m\u001b[1;32m)\u001b[0m, feature ID \u001b[1;32m4036936\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Fall, feature ID 436583 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mFall\u001b[0m, feature ID \u001b[1;32m436583\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Ventilator Type, feature ID 3007397 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mVentilator Type\u001b[0m, feature ID \u001b[1;32m3007397\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Family updated by MD, feature ID 46273928 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mFamily updated by MD\u001b[0m, feature ID \u001b[1;32m46273928\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature SVV (Arterial), feature ID 37116693 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mSVV \u001b[0m\u001b[1;32m(\u001b[0m\u001b[32mArterial\u001b[0m\u001b[1;32m)\u001b[0m, feature ID \u001b[1;32m37116693\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Tobacco Use History, feature ID 3012697 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mTobacco Use History\u001b[0m, feature ID \u001b[1;32m3012697\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature Family meeting attempted, unable, feature ID 46272666 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mFamily meeting attempted, unable\u001b[0m, feature ID \u001b[1;32m46272666\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature OR Sent, feature ID 4162219 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mOR Sent\u001b[0m, feature ID \u001b[1;32m4162219\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature MRSA SCREEN, feature ID 37397888 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mMRSA SCREEN\u001b[0m, feature ID \u001b[1;32m37397888\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature OR Received, feature ID 4265599 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mOR Received\u001b[0m, feature ID \u001b[1;32m4265599\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature ICP Line Insertion Date, feature ID 4048955 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mICP Line Insertion Date\u001b[0m, feature ID \u001b[1;32m4048955\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Couldn't find concept [4215685, 440922, 44784283, 4296248, 2617452, 4214956, 4251171, 40766231, 40758030, 46235654,\n",
+       "435928, 443345, 4179084, 4310926, 4306655, 4207283, 46273937, 4119499, 4323360, 4311079, 4239756, 4203722, 433942, \n",
+       "4256640, 440279, 4324190, 4179963, 40479553, 46272451, 440927, 4060985, 439221, 4314870, 432789, 4233464, 433930, \n",
+       "46272450, 45766277, 4276526, 4135421, 437165, 4167217, 441764, 4180749, 46272734, 37016200, 4060705, 4168834, \n",
+       "4182335, 4179242, 441749, 4019967, 4143274, 4178782, 4014023, 4324321, 4323345, 439228, 441192, 439222, 439996, \n",
+       "46274064, 4059907, 36717001, 4095498, 43021271, 4005823, 46270032, 4148407, 46274011, 4315085, 441751, 436882, \n",
+       "441744, 4279614, 4144274, 438046, 4322482, 44782983, 443367, 4162908, 438950, 4022569, 42539646, 4140830, 4324181, \n",
+       "441207, 43020581, 4139934, 4168192, 40481022, 433658, 443370, 4096435, 4152408, 4147565, 4060084, 4305831, \n",
+       "43021273, 4059910, 437175, 36716245, 436315, 439371, 4310065, 42709971, 4058728, 4311077, 4190634, 4305297, \n",
+       "4325851, 437483, 4216727, 4334494, 441206, 40481819, 4312972, 443340, 4327107, 4144292, 4310928, 442165, 4330220, \n",
+       "443548, 4179214, 37016166, 437738, 4323344, 4175576, 436292] in concept table!\n",
+       "
\n" + ], + "text/plain": [ + "Couldn't find concept \u001b[1m[\u001b[0m\u001b[1;36m4215685\u001b[0m, \u001b[1;36m440922\u001b[0m, \u001b[1;36m44784283\u001b[0m, \u001b[1;36m4296248\u001b[0m, \u001b[1;36m2617452\u001b[0m, \u001b[1;36m4214956\u001b[0m, \u001b[1;36m4251171\u001b[0m, \u001b[1;36m40766231\u001b[0m, \u001b[1;36m40758030\u001b[0m, \u001b[1;36m46235654\u001b[0m,\n", + "\u001b[1;36m435928\u001b[0m, \u001b[1;36m443345\u001b[0m, \u001b[1;36m4179084\u001b[0m, \u001b[1;36m4310926\u001b[0m, \u001b[1;36m4306655\u001b[0m, \u001b[1;36m4207283\u001b[0m, \u001b[1;36m46273937\u001b[0m, \u001b[1;36m4119499\u001b[0m, \u001b[1;36m4323360\u001b[0m, \u001b[1;36m4311079\u001b[0m, \u001b[1;36m4239756\u001b[0m, \u001b[1;36m4203722\u001b[0m, \u001b[1;36m433942\u001b[0m, \n", + "\u001b[1;36m4256640\u001b[0m, \u001b[1;36m440279\u001b[0m, \u001b[1;36m4324190\u001b[0m, \u001b[1;36m4179963\u001b[0m, \u001b[1;36m40479553\u001b[0m, \u001b[1;36m46272451\u001b[0m, \u001b[1;36m440927\u001b[0m, \u001b[1;36m4060985\u001b[0m, \u001b[1;36m439221\u001b[0m, \u001b[1;36m4314870\u001b[0m, \u001b[1;36m432789\u001b[0m, \u001b[1;36m4233464\u001b[0m, \u001b[1;36m433930\u001b[0m, \n", + "\u001b[1;36m46272450\u001b[0m, \u001b[1;36m45766277\u001b[0m, \u001b[1;36m4276526\u001b[0m, \u001b[1;36m4135421\u001b[0m, \u001b[1;36m437165\u001b[0m, \u001b[1;36m4167217\u001b[0m, \u001b[1;36m441764\u001b[0m, \u001b[1;36m4180749\u001b[0m, \u001b[1;36m46272734\u001b[0m, \u001b[1;36m37016200\u001b[0m, \u001b[1;36m4060705\u001b[0m, \u001b[1;36m4168834\u001b[0m, \n", + "\u001b[1;36m4182335\u001b[0m, \u001b[1;36m4179242\u001b[0m, \u001b[1;36m441749\u001b[0m, \u001b[1;36m4019967\u001b[0m, \u001b[1;36m4143274\u001b[0m, \u001b[1;36m4178782\u001b[0m, \u001b[1;36m4014023\u001b[0m, \u001b[1;36m4324321\u001b[0m, \u001b[1;36m4323345\u001b[0m, \u001b[1;36m439228\u001b[0m, \u001b[1;36m441192\u001b[0m, \u001b[1;36m439222\u001b[0m, \u001b[1;36m439996\u001b[0m, \n", + "\u001b[1;36m46274064\u001b[0m, \u001b[1;36m4059907\u001b[0m, \u001b[1;36m36717001\u001b[0m, \u001b[1;36m4095498\u001b[0m, \u001b[1;36m43021271\u001b[0m, \u001b[1;36m4005823\u001b[0m, \u001b[1;36m46270032\u001b[0m, \u001b[1;36m4148407\u001b[0m, \u001b[1;36m46274011\u001b[0m, \u001b[1;36m4315085\u001b[0m, \u001b[1;36m441751\u001b[0m, \u001b[1;36m436882\u001b[0m, \n", + "\u001b[1;36m441744\u001b[0m, \u001b[1;36m4279614\u001b[0m, \u001b[1;36m4144274\u001b[0m, \u001b[1;36m438046\u001b[0m, \u001b[1;36m4322482\u001b[0m, \u001b[1;36m44782983\u001b[0m, \u001b[1;36m443367\u001b[0m, \u001b[1;36m4162908\u001b[0m, \u001b[1;36m438950\u001b[0m, \u001b[1;36m4022569\u001b[0m, \u001b[1;36m42539646\u001b[0m, \u001b[1;36m4140830\u001b[0m, \u001b[1;36m4324181\u001b[0m, \n", + "\u001b[1;36m441207\u001b[0m, \u001b[1;36m43020581\u001b[0m, \u001b[1;36m4139934\u001b[0m, \u001b[1;36m4168192\u001b[0m, \u001b[1;36m40481022\u001b[0m, \u001b[1;36m433658\u001b[0m, \u001b[1;36m443370\u001b[0m, \u001b[1;36m4096435\u001b[0m, \u001b[1;36m4152408\u001b[0m, \u001b[1;36m4147565\u001b[0m, \u001b[1;36m4060084\u001b[0m, \u001b[1;36m4305831\u001b[0m, \n", + "\u001b[1;36m43021273\u001b[0m, \u001b[1;36m4059910\u001b[0m, \u001b[1;36m437175\u001b[0m, \u001b[1;36m36716245\u001b[0m, \u001b[1;36m436315\u001b[0m, \u001b[1;36m439371\u001b[0m, \u001b[1;36m4310065\u001b[0m, \u001b[1;36m42709971\u001b[0m, \u001b[1;36m4058728\u001b[0m, \u001b[1;36m4311077\u001b[0m, \u001b[1;36m4190634\u001b[0m, \u001b[1;36m4305297\u001b[0m, \n", + "\u001b[1;36m4325851\u001b[0m, \u001b[1;36m437483\u001b[0m, \u001b[1;36m4216727\u001b[0m, \u001b[1;36m4334494\u001b[0m, \u001b[1;36m441206\u001b[0m, \u001b[1;36m40481819\u001b[0m, \u001b[1;36m4312972\u001b[0m, \u001b[1;36m443340\u001b[0m, \u001b[1;36m4327107\u001b[0m, \u001b[1;36m4144292\u001b[0m, \u001b[1;36m4310928\u001b[0m, \u001b[1;36m442165\u001b[0m, \u001b[1;36m4330220\u001b[0m, \n", + "\u001b[1;36m443548\u001b[0m, \u001b[1;36m4179214\u001b[0m, \u001b[1;36m37016166\u001b[0m, \u001b[1;36m437738\u001b[0m, \u001b[1;36m4323344\u001b[0m, \u001b[1;36m4175576\u001b[0m, \u001b[1;36m436292\u001b[0m\u001b[1m]\u001b[0m in concept table!\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "adata = omop.extract_features(adata, source='observation', map_concept=True, add_aggregation_to_X=False, verbose=True, remove_empty_column=True, columns_in_source_table = ['observation_id', 'observation_datetime', 'observation_type_concept_id', 'value_as_number'])" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AnnData object with n_obs × n_vars = 852 × 2\n", + " obs: 'discharge_to_concept_id', 'death_date', 'ethnicity_source_concept_id', 'visit_start_date', 'gender_source_concept_id', 'discharge_to_source_value', 'provider_id_y', 'visit_source_concept_id', 'death_type_concept_id', 'cause_source_value', 'care_site_id_x', 'preceding_visit_occurrence_id', 'race_source_value', 'admitting_source_value', 'cause_concept_id', 'visit_source_value', 'gender_concept_id', 'race_concept_id', 'care_site_id_y', 'admitting_source_concept_id', 'birth_datetime', 'location_id', 'race_source_concept_id', 'visit_type_concept_id', 'provider_id_x', 'visit_start_datetime', 'visit_concept_id', 'cause_source_concept_id', 'visit_end_datetime', 'day_of_birth', 'visit_end_date', 'death_datetime', 'ethnicity_source_value', 'ethnicity_concept_id', 'person_source_value', 'month_of_birth'\n", + " uns: 'numerical_columns', 'non_numerical_columns'\n", + " layers: 'original'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "discharge_to_concept_id Int64\n", + "death_date category\n", + "ethnicity_source_concept_id Int64\n", + "visit_start_date category\n", + "gender_source_concept_id Int64\n", + "discharge_to_source_value category\n", + "provider_id_y Int64\n", + "visit_source_concept_id Int64\n", + "death_type_concept_id Int64\n", + "cause_source_value category\n", + "care_site_id_x Int64\n", + "preceding_visit_occurrence_id Int64\n", + "race_source_value category\n", + "admitting_source_value category\n", + "cause_concept_id Int64\n", + "visit_source_value category\n", + "gender_concept_id Int64\n", + "race_concept_id Int64\n", + "care_site_id_y Int64\n", + "admitting_source_concept_id Int64\n", + "birth_datetime category\n", + "location_id Int64\n", + "race_source_concept_id Int64\n", + "visit_type_concept_id Int64\n", + "provider_id_x Int64\n", + "visit_start_datetime category\n", + "visit_concept_id Int64\n", + "cause_source_concept_id Int64\n", + "visit_end_datetime category\n", + "day_of_birth Int64\n", + "visit_end_date category\n", + "death_datetime category\n", + "ethnicity_source_value category\n", + "ethnicity_concept_id Int64\n", + "person_source_value category\n", + "month_of_birth Int64\n", + "dtype: object" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata.obs.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "adata1 = adata.copy()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Trying to extarct the following features: [40762499]\n",
+       "
\n" + ], + "text/plain": [ + "Trying to extarct the following features: \u001b[1m[\u001b[0m\u001b[1;36m40762499\u001b[0m\u001b[1m]\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Detected: feature O2 saturation pulseoxymetry, feature ID 40762499 in concept table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mO2 saturation pulseoxymetry\u001b[0m, feature ID \u001b[1;32m40762499\u001b[0m in concept table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/anaconda3/envs/ehrapy_latents/lib/python3.9/site-packages/anndata/utils.py:334: ExperimentalFeatureWarning: Support for Awkward Arrays is currently experimental. Behavior may change in the future. Please report any issues you may encounter!\n", + " warnings.warn(msg, category, stacklevel=stacklevel)\n" + ] + } + ], + "source": [ + "adata = omop.extract_features(adata, source='measurement', features=[40762499], map_concept=True, add_aggregation_to_X=False, verbose=True, remove_empty_column=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata = omop.extract_features(adata, source='observation', features=[2000030003], map_concept=True, add_aggregation_to_X=False, verbose=True, remove_empty_column=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feature Extraction" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Detected: feature O2 saturation pulseoxymetry, feature ID 2000030003 in concept table, feature ID 40762499 in \n",
+       "concept relationship table, match socre = 1.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mO2 saturation pulseoxymetry\u001b[0m, feature ID \u001b[1;32m2000030003\u001b[0m in concept table, feature ID \u001b[1;32m40762499\u001b[0m in \n", + "concept relationship table, match socre = \u001b[1;32m1\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "extracting features\n", + "\u001b[1;35m2024-01-02 17:00:32,078\u001b[0m - \u001b[1;34mroot\u001b[0m \u001b[1;30mINFO - Added `['O2 saturation pulseoxymetry_min', 'O2 saturation pulseoxymetry_max', 'O2 saturation pulseoxymetry_mean']` columns to `obs`.\u001b[0m\n", + "\u001b[1;35m2024-01-02 17:00:32,080\u001b[0m - \u001b[1;34mroot\u001b[0m \u001b[1;30mINFO - Added `['O2 saturation pulseoxymetry_min', 'O2 saturation pulseoxymetry_max', 'O2 saturation pulseoxymetry_mean']` features to `X`.\u001b[0m\n" + ] + } + ], + "source": [ + "# Extract features from tables\n", + "# Different sources are supported: measurement, observation\n", + "\n", + "# Could use feature ID \n", + "adata = omop.extract_features(adata, source='measurement', features=[2000030003], map_concept=True, add_aggregation_to_X=True, add_all_data=True, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Detected: feature Base Excess|Blood|Blood Gas, feature ID 2000001002 in concept table, feature ID 3012501 in \n",
+       "concept relationship table, match socre = 1.0.\n",
+       "
\n" + ], + "text/plain": [ + "Detected: feature \u001b[32mBase Excess|Blood|Blood Gas\u001b[0m, feature ID \u001b[1;32m2000001002\u001b[0m in concept table, feature ID \u001b[1;32m3012501\u001b[0m in \n", + "concept relationship table, match socre = \u001b[1;32m1.0\u001b[0m\u001b[32m.\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "extracting features\n", + "\u001b[1;35m2024-01-02 17:00:35,969\u001b[0m - \u001b[1;34mroot\u001b[0m \u001b[1;30mINFO - Added `['Base Excess|Blood|Blood Gas_min', 'Base Excess|Blood|Blood Gas_max', 'Base Excess|Blood|Blood Gas_mean']` columns to `obs`.\u001b[0m\n", + "\u001b[1;35m2024-01-02 17:00:35,970\u001b[0m - \u001b[1;34mroot\u001b[0m \u001b[1;30mINFO - Added `['Base Excess|Blood|Blood Gas_min', 'Base Excess|Blood|Blood Gas_max', 'Base Excess|Blood|Blood Gas_mean']` features to `X`.\u001b[0m\n" + ] + } + ], + "source": [ + "# Could use feature name\n", + "adata = omop.extract_features(adata, source='measurement', features=[\"Base Excess|Blood|Blood Gas\"], map_concept=True, add_aggregation_to_X=True, add_all_data=True, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unitdomain_idconcept_class_idconcept_code
year_of_birthNaNNaNNaNNaN
gender_source_valueNaNNaNNaNNaN
O2 saturation pulseoxymetry_minNaNNaNNaNNaN
O2 saturation pulseoxymetry_maxNaNNaNNaNNaN
O2 saturation pulseoxymetry_meanNaNNaNNaNNaN
Base Excess|Blood|Blood Gas_minmEq/LMeasurementLab Test50802
Base Excess|Blood|Blood Gas_maxmEq/LMeasurementLab Test50802
Base Excess|Blood|Blood Gas_meanmEq/LMeasurementLab Test50802
\n", + "
" + ], + "text/plain": [ + " Unit domain_id concept_class_id \\\n", + "year_of_birth NaN NaN NaN \n", + "gender_source_value NaN NaN NaN \n", + "O2 saturation pulseoxymetry_min NaN NaN NaN \n", + "O2 saturation pulseoxymetry_max NaN NaN NaN \n", + "O2 saturation pulseoxymetry_mean NaN NaN NaN \n", + "Base Excess|Blood|Blood Gas_min mEq/L Measurement Lab Test \n", + "Base Excess|Blood|Blood Gas_max mEq/L Measurement Lab Test \n", + "Base Excess|Blood|Blood Gas_mean mEq/L Measurement Lab Test \n", + "\n", + " concept_code \n", + "year_of_birth NaN \n", + "gender_source_value NaN \n", + "O2 saturation pulseoxymetry_min NaN \n", + "O2 saturation pulseoxymetry_max NaN \n", + "O2 saturation pulseoxymetry_mean NaN \n", + "Base Excess|Blood|Blood Gas_min 50802 \n", + "Base Excess|Blood|Blood Gas_max 50802 \n", + "Base Excess|Blood|Blood Gas_mean 50802 " + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata.var" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AnnData object with n_obs × n_vars = 852 × 8\n", + " obs: 'death_datetime', 'visit_end_datetime', 'visit_start_datetime'\n", + " var: 'Unit', 'domain_id', 'concept_class_id', 'concept_code'\n", + " uns: 'numerical_columns', 'non_numerical_columns'\n", + " obsm: 'O2 saturation pulseoxymetry', 'Base Excess|Blood|Blood Gas', 'note'" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adata" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ehrapy_latents", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.16" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ehrdata.py b/ehrdata.py index d51d8f3..534839c 100644 --- a/ehrdata.py +++ b/ehrdata.py @@ -1,72 +1,100 @@ import awkward as ak import numpy as np import pandas as pd - - +import csv +import pandas as pd +import matplotlib.pyplot as plt +import seaborn as sns import ehrapy as ep import scanpy as sc from anndata import AnnData import mudata as md from mudata import MuData -from typing import List, Union +from typing import List, Union, Literal import os import glob import dask.dataframe as dd from thefuzz import process import sys from rich import print as rprint +import missingno as msno +import warnings +import numbers + clinical_tables_columns = { - 'person': ['person_id', 'year_of_birth', 'gender_source_value'], - 'observation_period': [], - 'death': ['person_id', 'death_datetime'], - 'visit_occurrence': ['visit_occurrence_id', 'person_id', 'visit_start_datetime', 'visit_end_datetime'], - 'visit_detail': [], - 'condition_occurrence': [], - 'drug_exposure': ['drug_exposure_id', 'person_id', 'visit_occurrence_id', 'drug_concept_id', ], - 'procedure_occurrence': ['visit_occurrence_id', 'person_id', 'visit_start_datetime', 'visit_end_datetime'], - 'device_exposure': [], - 'specimen': [], - 'measurement': ['measurement_id', 'person_id', 'visit_occurrence_id', 'measurement_concept_id', 'measurement_datetime', 'value_as_number', 'unit_source_value'], - 'observation': ['observation_id', 'person_id', 'observation_concept_id', 'observation_datetime', "value_as_number", "value_as_string"], - 'note': [], - 'note_nlp': [], - 'fact_relationship': [], - 'procedure_occurrence': [], + "person": ["person_id", "year_of_birth", "gender_source_value"], + "observation_period": [], + "death": ["person_id", "death_datetime"], + "visit_occurrence": ["visit_occurrence_id", "person_id", "visit_start_datetime", "visit_end_datetime"], + "visit_detail": [], + "condition_occurrence": [], + "drug_exposure": [ + "drug_exposure_id", + "person_id", + "visit_occurrence_id", + "drug_concept_id", + ], + "procedure_occurrence": ["visit_occurrence_id", "person_id", "visit_start_datetime", "visit_end_datetime"], + "device_exposure": [], + "specimen": [], + "measurement": [ + "measurement_id", + "person_id", + "visit_occurrence_id", + "measurement_concept_id", + "measurement_datetime", + "value_as_number", + "unit_source_value", + ], + "observation": [ + "observation_id", + "person_id", + "observation_concept_id", + "observation_datetime", + "value_as_number", + "value_as_string", + ], + "note": [], + "note_nlp": [], + "fact_relationship": [], + "procedure_occurrence": [], } health_system_tables_columns = { - 'location': [], - 'care_site': ['care_site_id', 'care_site_name'], - 'provider': [], + "location": [], + "care_site": ["care_site_id", "care_site_name"], + "provider": [], } -vocabularies_tables_columns ={ - 'concept': ['concept_id', 'concept_name', 'domain_id', 'vocabulary_id', 'concept_class_id', 'standard_concept', 'concept_code'], - 'vocabulary': [], - 'domain': [], - 'concept_class': [], - 'concept_synonym': [], - 'concept_relationship': ["concept_id_1", "concept_id_2", "relationship_id"], - 'relationship': [], - 'concept_ancestor': [], - 'source_to_concept_map': [], - 'drug_strength': [] +vocabularies_tables_columns = { + "concept": [ + "concept_id", + "concept_name", + "domain_id", + "vocabulary_id", + "concept_class_id", + "standard_concept", + "concept_code", + ], + "vocabulary": [], + "domain": [], + "concept_class": [], + "concept_synonym": [], + "concept_relationship": ["concept_id_1", "concept_id_2", "relationship_id"], + "relationship": [], + "concept_ancestor": [], + "source_to_concept_map": [], + "drug_strength": [], } -dtypes_dict = {} -dtypes_dict['concept'] = {'concept_id': int, 'standard_concept': str} -dtypes_dict['measurement']={'measurement_source_concept_id': int, - 'measurement_source_value': str, - 'unit_concept_id': int, - 'value_as_number': 'float64', - 'value_source_value': str} from difflib import SequenceMatcher from heapq import nlargest as _nlargest + def get_close_matches_using_dict(word, possibilities, n=2, cutoff=0.6): - """Use SequenceMatcher to return a list of the indexes of the best - "good enough" matches. word is a sequence for which close matches + """Use SequenceMatcher to return a list of the indexes of the best + "good enough" matches. word is a sequence for which close matches are desired (typically a string). possibilities is a dictionary of sequences. Optional arg n (default 2) is the maximum number of close matches to @@ -75,66 +103,139 @@ def get_close_matches_using_dict(word, possibilities, n=2, cutoff=0.6): that don't score at least that similar to word are ignored. """ - if not n > 0: + if not n > 0: raise ValueError("n must be > 0: %r" % (n,)) if not 0.0 <= cutoff <= 1.0: raise ValueError("cutoff must be in [0.0, 1.0]: %r" % (cutoff,)) result = [] s = SequenceMatcher() s.set_seq2(word) - for _, (key, x) in enumerate(possibilities.items()): - s.set_seq1(x) - if s.real_quick_ratio() >= cutoff and \ - s.quick_ratio() >= cutoff and \ - s.ratio() >= cutoff: - result.append((s.ratio(), x, key)) + for _, (key, value) in enumerate(possibilities.items()): + s.set_seq1(value) + if s.real_quick_ratio() >= cutoff and s.quick_ratio() >= cutoff and s.ratio() >= cutoff: + result.append((s.ratio(), value, key)) # Move the best scorers to head of list result = _nlargest(n, result) - + # Strip scores for the best n matches - return [(x, score, key) for score, x, key in result] + return [(value, key, score) for score, value, key in result] + def df_to_dict(df, key, value): if isinstance(df, dd.DataFrame): return pd.Series(df[value].compute().values, index=df[key].compute()).to_dict() else: return pd.Series(df[value].values, index=df[key]).to_dict() - -class OMOP(): - + +def get_column_types(csv_path=None, columns=None): + column_types = {} + parse_dates = [] + if csv_path: + with open(csv_path, "r") as f: + dict_reader = csv.DictReader(f) + columns = dict_reader.fieldnames + columns_lowercase = [column.lower() for column in columns] + for i, column in enumerate(columns_lowercase): + if column.endswith( + ( + "source_value", + "reason", + "measurement_time", + "as_string", + "title", + "text", + "name", + "concept", + "code", + "domain_id", + "vocabulary_id", + "concept_class_id", + "relationship_id", + "specimen_source_id", + "production_id", + "unique_device_id", + "sig", + "lot_number", + ) + ): + column_types[columns[i]] = str + # TODO quantity in different tables have different types + elif column.endswith(("as_number", "low", "high", "quantity")): + column_types[columns[i]] = float + elif column.endswith("date"): + parse_dates.append(columns[i]) + elif column.endswith("datetime"): + parse_dates.append(columns[i]) + elif column.endswith(("id", "birth", "id_1", "id_2", "refills", "days_supply")): + column_types[columns[i]] = "Int64" + else: + raise KeyError(f"{columns[i]} is not defined in OMOP CDM") + if len(parse_dates) == 0: + parse_dates = None + return column_types, parse_dates + + +class OMOP: def __init__(self, file_paths): self.base = file_paths - file_list = glob.glob(os.path.join(file_paths, '*')) + file_list = glob.glob(os.path.join(file_paths, "*")) self.loaded_tabel = None self.filepath = {} for file_path in file_list: - file_name = file_path.split('/')[-1].removesuffix('.csv') + file_name = file_path.split("/")[-1].removesuffix(".csv") self.filepath[file_name] = file_path - + self.tables = list(self.filepath.keys()) - ''' + """ if "concept" in self.tables: df_concept = dd.read_csv(self.filepath["concept"], usecols=vocabularies_tables_columns["concept"]) self.concept_id_to_name = dict(zip(df_concept['id'], df_concept['name'])) self.concept_name_to_id = dict(zip(df_concept['name'], df_concept['id'])) - ''' + """ @property def clinical_tables(self): """ A dictionary containing all of the ``Clinical`` OMOP CDM tables in the connected database. """ - table_names = ['person','observation_period','specimen','death','visit_occurrence','visit_detail','procedure_occurrence','drug_exposure','device_exposure','condition_occurrence','measurement','note','note_nlp','observation','fact_relationship'] + table_names = [ + "person", + "observation_period", + "specimen", + "death", + "visit_occurrence", + "visit_detail", + "procedure_occurrence", + "drug_exposure", + "device_exposure", + "condition_occurrence", + "measurement", + "note", + "note_nlp", + "observation", + "fact_relationship", + ] return [table_name for table_name in self.tables if table_name in table_names] - + @property def vocabularies_tables(self): """ A dictionary containing all of the ``Vocabularies`` OMOP CDM tables in the connected database. """ - table_names = ['concept','vocabulary','domain','concept_class','concept_relationship','relationship','concept_synonym','concept_ancestor','source_to_concept_map','drug_strength'] + table_names = [ + "concept", + "vocabulary", + "domain", + "concept_class", + "concept_relationship", + "relationship", + "concept_synonym", + "concept_ancestor", + "source_to_concept_map", + "drug_strength", + ] return [table_name for table_name in self.tables if table_name in table_names] @property @@ -142,7 +243,7 @@ def metadata_tables(self): """ A dictionary containing all of the ``MetaData`` OMOP CDM tables in the connected database. """ - table_names = ['cdm_source','metadata'] + table_names = ["cdm_source", "metadata"] return [table_name for table_name in self.tables if table_name in table_names] @property @@ -150,7 +251,7 @@ def health_system_tables(self): """ A dictionary containing all of the ``Health System`` OMOP CDM tables in the connected database. """ - table_names = ['location','care_site','provider'] + table_names = ["location", "care_site", "provider"] return [table_name for table_name in self.tables if table_name in table_names] @property @@ -158,55 +259,52 @@ def derived_elements_tables(self): """ A dictionary containing all of the ``Derived Elements`` OMOP CDM tables in the connected database. """ - table_names = ['cohort','cohort_definition','drug_era','dose_era','condition_era'] + table_names = ["cohort", "cohort_definition", "drug_era", "dose_era", "condition_era"] return [table_name for table_name in self.tables if table_name in table_names] - + @property def health_economics_tables(self): """ A dictionary containing all of the ``Health Economics`` OMOP CDM tables in the connected database. """ - table_names = ['payer_plan_period','cost'] + table_names = ["payer_plan_period", "cost"] return [table_name for table_name in self.tables if table_name in table_names] - - - - def load(self, level='stay_level', tables = ['visit_occurrence', 'person', 'death'], add_to_X=None, features=None): - - if level=='stay_level': - index = {'visit_occurrence': 'visit_occurrence_id', 'person': 'person_id', 'death': "person_id"} + def load(self, level="stay_level", tables=["visit_occurrence", "person", "death"]): + # TODO patient level and hospital level + if level == "stay_level": + index = {"visit_occurrence": "visit_occurrence_id", "person": "person_id", "death": "person_id"} # TODO Only support clinical_tables_columns - for table in tables: - setattr(self, table, dd.read_csv(self.filepath[table], usecols=clinical_tables_columns[table]).set_index("person_id")) - - - #concept_id_list = list(self.concept.concept_id) - #concept_name_list = list(self.concept.concept_id) - #concept_domain_id_list = list(set(self.concept.domain_id)) - - - - - - #self.loaded_tabel = ['visit_occurrence', 'person', 'death', 'measurement', 'observation', 'drug_exposure'] - joined_table = dd.merge(self.visit_occurrence, self.person, left_index=True, right_index=True, how='left') - joined_table = dd.merge(joined_table, self.death, left_index=True, right_index=True, how='left') + for table in tables: + column_types, parse_dates = get_column_types(self.filepath[table]) + setattr( + self, + table, + dd.read_csv(self.filepath[table], dtype=column_types, parse_dates=parse_dates).set_index( + "person_id" + ), + ) + + # concept_id_list = list(self.concept.concept_id) + # concept_name_list = list(self.concept.concept_id) + # concept_domain_id_list = list(set(self.concept.domain_id)) + + # self.loaded_tabel = ['visit_occurrence', 'person', 'death', 'measurement', 'observation', 'drug_exposure'] + joined_table = dd.merge(self.visit_occurrence, self.person, left_index=True, right_index=True, how="left") + joined_table = dd.merge(joined_table, self.death, left_index=True, right_index=True, how="left") joined_table = joined_table.compute() - joined_table = joined_table.set_index('visit_occurrence_id') - - - + joined_table = joined_table.set_index("visit_occurrence_id") - #obs_only_list = list(self.joined_table.columns) - #obs_only_list.remove('visit_occurrence_id') - columns_obs_only = list(set(joined_table.columns) - set(['year_of_birth', 'gender_source_value'])) + # obs_only_list = list(self.joined_table.columns) + # obs_only_list.remove('visit_occurrence_id') + columns_obs_only = list(set(joined_table.columns) - set(["year_of_birth", "gender_source_value"])) adata = ep.ad.df_to_anndata( - joined_table, index_column="visit_occurrence_id", columns_obs_only = columns_obs_only) - - ''' + joined_table, index_column="visit_occurrence_id", columns_obs_only=columns_obs_only + ) + + """ for column in self.measurement.columns: if column != 'visit_occurrence_id': obs_list = [] @@ -227,163 +325,377 @@ def load(self, level='stay_level', tables = ['visit_occurrence', 'person', 'deat for visit_occurrence_id in adata.obs.index: obs_list.append(list(self.observation[self.observation['visit_occurrence_id'] == int(visit_occurrence_id)][column])) adata.obsm[column]= ak.Array(obs_list) - ''' - + """ + + return adata + + def feature_statistics( + self, + source: Literal[ + "observation", + "measurement", + "procedure_occurrence", + "specimen", + "device_exposure", + "drug_exposure", + "condition_occurrence", + ], + map_concept=True, + number=20, + ): + column_types, parse_dates = get_column_types(self.filepath[source]) + df_source = dd.read_csv( + self.filepath[source], dtype=column_types, parse_dates=parse_dates + ) # , usecols=clinical_tables_columns[source]) + feature_counts = df_source.compute().value_counts(f"{source}_concept_id")[0:number] + feature_counts = feature_counts.to_frame().reset_index(drop=False) + + feature_counts[f"{source}_concept_id_1"], feature_counts[f"{source}_concept_id_2"] = self.map_concept_id( + feature_counts[f"{source}_concept_id"], verbose=False + ) + feature_counts["feature_name"] = self.get_concept_name(feature_counts[f"{source}_concept_id_1"]) + if feature_counts[f"{source}_concept_id_1"].equals(feature_counts[f"{source}_concept_id_2"]): + feature_counts.drop(f"{source}_concept_id_2", inplace=True) + feature_counts.rename(columns={f"{source}_concept_id_1": f"{source}_concept_id"}) + feature_counts = feature_counts.reindex(columns=["feature_name", f"{source}_concept_id", "count"]) + else: + feature_counts = feature_counts.reindex( + columns=["feature_name", f"{source}_concept_id_1", f"{source}_concept_id_2", "count"] + ) + + ax = sns.barplot(feature_counts, x="feature_name", y="count") + ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha="right") + plt.tight_layout() + return feature_counts + + def map_concept_id(self, concept_id: Union[str, List], verbose=True): + column_types, parse_dates = get_column_types(self.filepath["concept_relationship"]) + df_concept_relationship = dd.read_csv( + self.filepath["concept_relationship"], dtype=column_types, parse_dates=parse_dates + ).dropna( + subset=["concept_id_1", "concept_id_2", "relationship_id"] + ) # , usecols=vocabularies_tables_columns["concept_relationship"], + concept_relationship_dict = df_to_dict( + df=df_concept_relationship[df_concept_relationship["relationship_id"] == "Maps to"], + key="concept_id_1", + value="concept_id_2", + ) + concept_relationship_dict_reverse = df_to_dict( + df=df_concept_relationship[df_concept_relationship["relationship_id"] == "Mapped from"], + key="concept_id_1", + value="concept_id_2", + ) + + if isinstance(concept_id, numbers.Integral): + concept_id = [concept_id] + + concept_id_1 = [] + concept_id_2 = [] + concept_id_mapped_not_found = [] + for id in concept_id: + try: + concept_id_2.append(concept_relationship_dict[id]) + concept_id_1.append(id) + except KeyError: + try: + concept_id_1.append(concept_relationship_dict_reverse[id]) + concept_id_2.append(id) + except KeyError: + concept_id_1.append(id) + concept_id_2.append(id) + concept_id_mapped_not_found.append(id) + if len(concept_id_mapped_not_found) > 0: + # warnings.warn(f"Couldn't find a map for concept {id} in concept_relationship table!") + if verbose: + rprint(f"Couldn't find a map for concept {concept_id_mapped_not_found} in concept_relationship table!") + if len(concept_id_1) == 1: + return concept_id_1[0], concept_id_2[0] + else: + return concept_id_1, concept_id_2 + + def get_concept_name(self, concept_id: Union[str, List], raise_error=False, verbose=True): + if isinstance(concept_id, numbers.Integral): + concept_id = [concept_id] + + column_types, parse_dates = get_column_types(self.filepath["concept"]) + df_concept = dd.read_csv(self.filepath["concept"], dtype=column_types, parse_dates=parse_dates).dropna( + subset=["concept_id", "concept_name"] + ) # usecols=vocabularies_tables_columns["concept"] + concept_dict = df_to_dict(df=df_concept, key="concept_id", value="concept_name") + concept_name = [] + concept_name_not_found = [] + for id in concept_id: + try: + concept_name.append(concept_dict[id]) + except KeyError: + concept_name.append(id) + concept_name_not_found.append(id) + if len(concept_name_not_found) > 0: + # warnings.warn(f"Couldn't find concept {id} in concept table!") + if verbose: + rprint(f"Couldn't find concept {concept_name_not_found} in concept table!") + if raise_error: + raise KeyError + if len(concept_name) == 1: + return concept_name[0] + else: + return concept_name + + def extract_note(self, adata, source="note"): + column_types, parse_dates = get_column_types(self.filepath[source]) + df_source = dd.read_csv(self.filepath[source], dtype=column_types, parse_dates=parse_dates) + if columns is None: + columns = df_source.columns + obs_dict = [ + { + column: list(df_source[df_source["visit_occurrence_id"] == int(visit_occurrence_id)][column]) + for column in columns + } + for visit_occurrence_id in adata.obs.index + ] + adata.obsm["note"] = ak.Array(obs_dict) return adata - def extract_features(self, - adata, - source: str, - features: str or int or List[Union[str, int]], - map_concept = True, - add_aggregation_to_X: bool=True, - aggregation_methods = None, - add_all_data: bool = True, - exact_match: bool = True, - verbose: bool = False,): - #source = 'measurement' - #features = [3012501] - #add_aggregation_to_X = True - + + def note_nlp_map( + self, + ): + # Got some inspirations from: https://github.com/aws-samples/amazon-comprehend-medical-omop-notes-mapping + pass + + def extract_features( + self, + adata, + source: Literal[ + "observation", + "measurement", + "procedure_occurrence", + "specimen", + "device_exposure", + "drug_exposure", + "condition_occurrence", + ], + features: str or int or List[Union[str, int]] = None, + key: str = None, + columns_in_source_table: str or List[str] = None, + map_concept=True, + add_aggregation_to_X: bool = True, + aggregation_methods=None, + add_all_data: bool = True, + exact_match: bool = True, + remove_empty_column: bool = True, + ignore_not_shown_in_concept_table: bool = True, + verbose: bool = False, + ): + if key is None: + if source in ["measurement", "observation", "specimen"]: + key = f"{source}_concept_id" + elif source in ["device_exposure", "procedure_occurrence", "drug_exposure", "condition_occurrence"]: + key = f"{source.split('_')[0]}_concept_id" + else: + raise KeyError(f"Extracting data from {source} is not supported yet") + """ if source == 'measurement': columns = ["value_as_number", "measurement_datetime"] elif source == 'observation': columns = ["value_as_number", "value_as_string", "measurement_datetime"] + elif source == 'condition_occurrence': + columns = None else: raise KeyError(f"Extracting data from {source} is not supported yet") - - + """ + # TODO load using Dask or Dask-Awkward # Load source table using dask - df_source = dd.read_csv(self.filepath[source], usecols=clinical_tables_columns[source], dtype=dtypes_dict["measurement"]) - - if "concept" in self.tables: - df_concept = dd.read_csv(self.filepath["concept"], usecols=vocabularies_tables_columns["concept"], dtype = dtypes_dict["concept"]).dropna(subset=['concept_id', 'concept_name']) - concept_dict = df_to_dict(df=df_concept, key = 'concept_id', value = 'concept_name') - if map_concept: - df_concept_relationship = dd.read_csv(self.filepath["concept_relationship"], usecols=vocabularies_tables_columns["concept_relationship"]).dropna(subset=['concept_id_1', 'concept_id_2', 'relationship_id']) - concept_relationship_dict = df_to_dict(df=df_concept_relationship[df_concept_relationship['relationship_id'] == 'Maps to'], key = 'concept_id_1', value = 'concept_id_2') - map_concept_id_list = [] - # Input could be feature names/feature id (concept id) - # TODO support features name + column_types, parse_dates = get_column_types(self.filepath[source]) + if len(parse_dates) == 1: + columns = list(column_types.keys()) + [parse_dates] + else: + columns = list(column_types.keys()) + parse_dates + df_source = dd.read_csv( + self.filepath[source], dtype=column_types, parse_dates=parse_dates + ) # , usecols=clinical_tables_columns[source] + if not features: - raise KeyError(f"Please input the desired features you want to extarct") + warnings.warn( + "Please specify desired features you want to extract. Otherwise, it will try to extract all the features!" + ) + features = list(df_source[key].compute().unique()) else: - if isinstance(features, int) or isinstance(features, str): - features = [features] - - # TODO query this in the table - - #concept_name = 'Base Excess|Blood|Blood Gas' - #unit = 'mEq/L' - #domain_id = 'Measurement' - feature_id_list = [] - feature_name_list = [] - domain_id_list = [] - concept_class_id_list = [] - concept_code_list = [] - # Get feature id for each input, and check if each feature occurs in the concept table - for feature in features: - if isinstance(feature, int): - try: - feature_id = feature - feature_name = concept_dict[feature_id] - feature_id_list.append(feature_id) - match_score = 1 - except KeyError: - rprint(f"Feature ID - [red]{feature}[/] could not be found in concept table") + rprint(f"Trying to extarct the following features: {features}") + + # Input could be feature names/feature id (concept id) + # First convert all input feaure names into feature id. Map concept using CONCEPT_RELATIONSHIP table if required. + # Then try to extract feature data from source table using feature id. + + # TODO support features name + + if "concept" in self.tables: + column_types, parse_dates = get_column_types(self.filepath["concept"]) + df_concept = dd.read_csv(self.filepath["concept"], dtype=column_types, parse_dates=parse_dates).dropna( + subset=["concept_id", "concept_name"] + ) # usecols=vocabularies_tables_columns["concept"], + concept_dict = df_to_dict(df=df_concept, key="concept_id", value="concept_name") + + # TODO query this in the table + + feature_id_list = [] + feature_name_list = [] + domain_id_list = [] + concept_class_id_list = [] + concept_code_list = [] + + fetures_not_shown_in_concept_table = [] + + # Get feature id for each input, and check if each feature occurs in the concept table + for feature in features: + # if the input is feature ID + if isinstance(feature, numbers.Integral): + feature_id = feature + feature_id_1, feature_id_2 = self.map_concept_id(feature_id, verbose=False) + try: + feature_name = self.get_concept_name(feature_id_1, raise_error=True, verbose=False) + except KeyError: + if ignore_not_shown_in_concept_table: + fetures_not_shown_in_concept_table.append(feature) + continue + else: + rprint(f"Feature ID - [red]{feature_id_1}[/] could not be found in concept table") raise - elif isinstance(feature, str): - - result = get_close_matches_using_dict(feature, concept_dict, n=2, cutoff=0.2) - if len(result) == 2: - match_score = result[0][1] - - if match_score != 1: - if exact_match: - rprint(f"Unable to find an exact match for [red]{feature}[/] in the concept table. Similar ones: 1) [red]{result[0][0]}[/] 2) [red]{result[1][0]}") - raise ValueError - else: - if result[1][1] == 1: - rprint(f"Found multiple exact matches for [red]{feature}[/] in the concept table: 1) concept id: [red]{result[0][2]}[/] 2) concept id: [red]{result[1][2]}[/]. It is better to specify concept id directly.") - raise ValueError - feature_name = feature - feature_id = result[0][2] - + match_score = 1 + + # if the input is feature name + elif isinstance(feature, str): + # return a list of (value, key, score) + result = get_close_matches_using_dict(feature, concept_dict, n=2, cutoff=0.2) + + # if find 2 best matches + if len(result) == 2: + match_score = result[0][2] + + if match_score != 1: + if exact_match: + rprint( + f"Unable to find an exact match for [red]{feature}[/] in the concept table. Similar ones: 1) [red]{result[0][0]}[/] 2) [red]{result[1][0]}" + ) + raise ValueError else: - feature_name = result[0][0] - match_score = result[0][1] - feature_id = result[0][2] - if exact_match and match_score != 1: - rprint(f"Unable to find an exact match for [red]{feature}[/] in the concept table Similar one is [red]{result[0][0]}") + if result[1][1] == 1: + rprint( + f"Found multiple exact matches for [red]{feature}[/] in the concept table: 1) concept id: [red]{result[0][1]}[/] 2) concept id: [red]{result[1][1]}[/]. It is better to specify concept id directly." + ) raise ValueError - feature_id_list.append(feature_id) + feature_name = feature + feature_id = result[0][1] + # if only find 1 match else: - rprint("Please input either [red]feature name (string)[/] or [red]feature id (integer)[/] you want to extarct") - raise TypeError - if map_concept: - concept_id = concept_relationship_dict[feature_id] - map_concept_id_list.append(concept_id) - - feature_name_list.append(feature_name) - domain_id_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "domain_id"].reset_index(drop=True).compute()[0]) - concept_class_id_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "concept_class_id"].reset_index(drop=True).compute()[0]) - concept_code_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "concept_code"].reset_index(drop=True).compute()[0]) - if verbose: - if map_concept: + feature_name = result[0][0] + match_score = result[0][1] + feature_id = result[0][2] + if exact_match and match_score != 1: rprint( - f"Detected: feature [green]{feature_name}[/], feature ID [green]{feature_id}[/] in concept table, feature ID [green]{concept_id}[/] in concept relationship table, match socre = [green]{match_score}." + f"Unable to find an exact match for [red]{feature}[/] in the concept table Similar one is [red]{result[0][0]}" ) - else: - rprint( - f"Detected: feature [green]{feature_name}[/], feature ID [green]{feature_id}[/] in concept table, match socre = [green]{match_score}." + raise ValueError + feature_id_1, feature_id_2 = self.map_concept_id(feature_id) + + else: + rprint( + "Please input either [red]feature name (string)[/] or [red]feature id (integer)[/] you want to extarct" + ) + raise TypeError + + # feature_name_list.append(feature_name) + # domain_id_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "domain_id"].reset_index(drop=True).compute()[0]) + # concept_class_id_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "concept_class_id"].reset_index(drop=True).compute()[0]) + # concept_code_list.append(df_concept.loc[df_concept["concept_id"] == feature_id, "concept_code"].reset_index(drop=True).compute()[0]) + + if verbose: + """ + if map_concept: + rprint( + f"Detected: feature [green]{feature_name}[/], feature ID [green]{feature_id}[/] in concept table, feature ID [green]{concept_id}[/] in concept relationship table, match socre = [green]{match_score}." + ) + else: + """ + rprint( + f"Detected: feature [green]{feature_name}[/], feature ID [green]{feature_id}[/] in concept table, match socre = [green]{match_score}." + ) + + # for feature_id, feature_name, domain_id, concept_class_id, concept_code in zip(feature_id_list, feature_name_list, domain_id_list, concept_class_id_list, concept_code_list): + try: + feature_df = df_source[df_source[key] == feature_id_2].compute() + except: + print(f"Features ID could not be found in {source} table") + # TODO add checks if all columns exist in source table + if columns_in_source_table: + columns = columns_in_source_table + + if remove_empty_column: + columns = [column for column in columns if not feature_df[column].isna().all()] + + if len(feature_df) > 0: + obs_dict = [ + { + column: list(feature_df[feature_df["visit_occurrence_id"] == int(visit_occurrence_id)][column]) + for column in columns + } + for visit_occurrence_id in adata.obs.index + ] + adata.obsm[feature_name] = ak.Array(obs_dict) + + if add_aggregation_to_X: + unit = feature_df["unit_source_value"].value_counts().index[0] + if aggregation_methods is None: + aggregation_methods = ["min", "max", "mean"] + var_name_list = [ + f"{feature_name}_{aggregation_method}" for aggregation_method in aggregation_methods + ] + for aggregation_method in aggregation_methods: + func = getattr(ak, aggregation_method) + adata.obs[f"{feature_name}_{aggregation_method}"] = list( + func(adata.obsm[feature_name]["value_as_number"], axis=1) ) - - if map_concept: - feature_id_list = map_concept_id_list - for feature_id, feature_name, domain_id, concept_class_id, concept_code in zip(feature_id_list, feature_name_list, domain_id_list, concept_class_id_list, concept_code_list): - try: - feature_df = df_source[df_source[f"{source}_concept_id"] == feature_id].compute() - except: - print(f"Features ID could not be found in {source} table") - - if len(feature_df) > 0: - print("extracting features") - obs_dict = [{column: list(feature_df[feature_df['visit_occurrence_id'] == int(visit_occurrence_id)][column]) for column in columns} for visit_occurrence_id in adata.obs.index] - adata.obsm[feature_name] = ak.Array(obs_dict) - - if add_aggregation_to_X: - unit = feature_df['unit_source_value'].value_counts().index[0] - if aggregation_methods is None: - aggregation_methods = ['min', 'max', 'mean'] - var_name_list = [f'{feature_name}_{aggregation_method}' for aggregation_method in aggregation_methods] - for aggregation_method in aggregation_methods: - func = getattr(ak, aggregation_method) - adata.obs[f'{feature_name}_{aggregation_method}'] = list(func(adata.obsm[feature_name]['value_as_number'], axis=1)) - adata = ep.ad.move_to_x(adata, var_name_list) - adata.var.loc[var_name_list, 'Unit'] = unit - adata.var.loc[var_name_list,'domain_id'] = domain_id - adata.var.loc[var_name_list,'concept_class_id'] = concept_class_id - adata.var.loc[var_name_list,'concept_code'] = concept_code + adata = ep.ad.move_to_x(adata, var_name_list) + adata.var.loc[var_name_list, "Unit"] = unit + adata.var.loc[var_name_list, "domain_id"] = domain_id + adata.var.loc[var_name_list, "concept_class_id"] = concept_class_id + adata.var.loc[var_name_list, "concept_code"] = concept_code + if len(fetures_not_shown_in_concept_table) > 0: + rprint(f"Couldn't find concept {fetures_not_shown_in_concept_table} in concept table!") return adata - # More IO functions - def to_dataframe(self, adata, feature, patient, visit): - df = ak.to_dataframe(adata.obsm['Base Excess|Blood|Blood Gas']) - + # More IO functions + def to_dataframe( + self, + adata, + feature: str, # TODO also support list of features + # patient str or List, # TODO also support subset of patients/visit + ): # TODO # join index (visit_occurrence_id) to df # can be viewed as patient level - only select some patient - + + df = ak.to_dataframe(adata.obsm[feature]) + + df.reset_index(drop=False, inplace=True) + df["entry"] = adata.obs.index[df["entry"]] + df = df.rename(columns={"entry": "visit_occurrence_id"}) + del df["subentry"] + return df # More Plot functions - def plot_timeseries(self,): + def plot_timeseries( + self, + ): # add one function from previous pipeline pass - + # More Pre-processing functions - def sampling(self,): + def sampling( + self, + ): # function from dask - # need to check dask-awkward again + # need to check dask-awkward again pass diff --git a/src/ehrdata/ehrdata.py b/src/ehrdata/ehrdata.py deleted file mode 100644 index b0e3045..0000000 --- a/src/ehrdata/ehrdata.py +++ /dev/null @@ -1,118 +0,0 @@ -import awkward as ak -import numpy as np -import pandas as pd - - -import ehrapy as ep -import scanpy as sc -from anndata import AnnData -import mudata as md -from mudata import MuData -import os -import glob - -class OMOP(): - - def __init__(self, file_paths): - self.base = file_paths - file_list = glob.glob(os.path.join(file_paths, '*')) - self.loaded_tabel = None - self.tables = [] - for file_path in file_list: - file_name = file_path.split('/')[-1].removesuffix('.csv') - self.tables.append(file_name) - - - @property - def clinical_tables(self): - """ - A dictionary containing all of the ``Clinical`` OMOP CDM tables in the connected database. - """ - table_names = ['person','observation_period','specimen','death','visit_occurrence','visit_detail','procedure_occurrence','drug_exposure','device_exposure','condition_occurrence','measurement','note','note_nlp','observation','fact_relationship'] - return [table_name for table_name in self.tables if table_name in table_names] - - @property - def vocabularies_tables(self): - """ - A dictionary containing all of the ``Vocabularies`` OMOP CDM tables in the connected database. - """ - table_names = ['concept','vocabulary','domain','concept_class','concept_relationship','relationship','concept_synonym','concept_ancestor','source_to_concept_map','drug_strength'] - return [table_name for table_name in self.tables if table_name in table_names] - - @property - def metadata_tables(self): - """ - A dictionary containing all of the ``MetaData`` OMOP CDM tables in the connected database. - """ - table_names = ['cdm_source','metadata'] - return [table_name for table_name in self.tables if table_name in table_names] - - @property - def health_system_tables(self): - """ - A dictionary containing all of the ``Health System`` OMOP CDM tables in the connected database. - """ - table_names = ['location','care_site','provider'] - return [table_name for table_name in self.tables if table_name in table_names] - - @property - def derived_elements_tables(self): - """ - A dictionary containing all of the ``Derived Elements`` OMOP CDM tables in the connected database. - """ - table_names = ['cohort','cohort_definition','drug_era','dose_era','condition_era'] - return [table_name for table_name in self.tables if table_name in table_names] - - @property - def health_economics_tables(self): - """ - A dictionary containing all of the ``Health Economics`` OMOP CDM tables in the connected database. - """ - table_names = ['payer_plan_period','cost'] - return [table_name for table_name in self.tables if table_name in table_names] - - - def load(self, level='stay_level', add_to_X=None, features=None): - if level == 'stay_level': - self.visit_occurrence = pd.read_csv(f'{self.base}/visit_occurrence.csv') - self.person = pd.read_csv(f'{self.base}/person.csv', index_col='person_id') - self.death = pd.read_csv(f'{self.base}/death.csv', index_col='person_id') - self.measurement = pd.read_csv(f'{self.base}/measurement.csv') - self.observation = pd.read_csv(f'{self.base}/observation.csv') - self.drug_exposure = pd.read_csv(f'{self.base}/drug_exposure.csv') - - self.loaded_tabel = ['visit_occurrence', 'person', 'death', 'measurement', 'observation', 'drug_exposure'] - self.joined_table = pd.merge(self.visit_occurrence, self.person, on='person_id', how='left') - self.joined_table = pd.merge(self.joined_table, self.death, on='person_id', how='left') - - - - obs_only_list = list(self.joined_table.columns) - obs_only_list.remove('visit_occurrence_id') - adata = ep.ad.df_to_anndata( - self.joined_table, index_column="visit_occurrence_id", columns_obs_only = obs_only_list) - - - for column in self.measurement.columns: - if column != 'visit_occurrence_id': - obs_list = [] - for visit_occurrence_id in adata.obs.index: - obs_list.append(list(self.measurement[self.measurement['visit_occurrence_id'] == int(visit_occurrence_id)][column])) - adata.obsm[column]= ak.Array(obs_list) - - for column in self.drug_exposure.columns: - if column != 'visit_occurrence_id': - obs_list = [] - for visit_occurrence_id in adata.obs.index: - obs_list.append(list(self.drug_exposure[self.drug_exposure['visit_occurrence_id'] == int(visit_occurrence_id)][column])) - adata.obsm[column]= ak.Array(obs_list) - - for column in self.observation.columns: - if column != 'visit_occurrence_id': - obs_list = [] - for visit_occurrence_id in adata.obs.index: - obs_list.append(list(self.observation[self.observation['visit_occurrence_id'] == int(visit_occurrence_id)][column])) - adata.obsm[column]= ak.Array(obs_list) - - - return adata