conceptql 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +32 -104
- data/Gemfile +2 -0
- data/README.md +43 -21
- data/Rakefile +34 -0
- data/conceptql.gemspec +3 -4
- data/config/provenance.yml +454 -0
- data/doc/converter.rb +33 -0
- data/doc/metadata.md +89 -0
- data/doc/spec.md +1775 -861
- data/doc/spec.md.cql +1930 -0
- data/doc/spec/02f44ad35d266ddd0a4df1691d26bf4a297b30604fc3f44b0391d6d852d23a9f.png +0 -0
- data/doc/spec/0360fc0c2b7a88fd82ffc4d13387b76766649d5d42aa8f9349bbf60a81ac6119.png +0 -0
- data/doc/spec/04491942fcbd741982514f9eb12aeecf3d54b5b69a2b50c8331f7700169d5521.png +0 -0
- data/doc/spec/05f9b844571ffceeed2def3025fb60c68552817b8b73d3c8a76939dbc08b7c65.png +0 -0
- data/doc/spec/067241a3579767a802d4f8e20fd35b60adbe377c9a6512ef135f164a5accfb27.png +0 -0
- data/doc/spec/1102fa717b1c2df67af5220bf3ae219afafd79be7bba0c117e301983385ada52.png +0 -0
- data/doc/spec/11f57941951bad5a75f9a16f38a31a3c6bf3046a475aac6e398e780892fab4ad.png +0 -0
- data/doc/spec/15268bc45993d3f57ccf915877f91e48bdee684f24faa614249915833cac4af9.png +0 -0
- data/doc/spec/253845fe6162621af407ebd110296ff4f6d8a3f23ec75dfb4ea8cda30be71262.png +0 -0
- data/doc/spec/26fd52b5ac55438dd9f81b4a3f3913f1058c9f225c8a5e129007c1e9413d5881.png +0 -0
- data/doc/spec/2b57886a9cba66bb696e4b399c51ad0dc95cd64b952709fafc819a79d573f09e.png +0 -0
- data/doc/spec/307a8b5a7edd6e42f8be16523a4c939faf1a0533385c861d7004b6af8addd7d1.png +0 -0
- data/doc/spec/328467a6a419c7c05e299b8097e5e000686068ded8dc6d5f2e2de6f51976c315.png +0 -0
- data/doc/spec/39d6a8eb71cae51b1d6937c97134e51f04fd47c54535ff0915fe6a8b4f197fb2.png +0 -0
- data/doc/spec/3f46dee4d775d1a29d52b68af6552f8ea3abd8303094e749714fc77bd7958155.png +0 -0
- data/doc/spec/44ec6743d5d77d15b8a487c2058bf3e455d34adc91c46ea05767f6e0e471a75e.png +0 -0
- data/doc/spec/462153be527b28dc2cb5259c0aec62e1f529e8b60dc6e9c23fd1e06e8be933c9.png +0 -0
- data/doc/spec/4a3b47ed1c54f96ebdae693d41c36c51884c4546ef799a4108085708fb7b964e.png +0 -0
- data/doc/spec/514f263e976d07c0d9e0a86c79bcbdcddc7d444d7b72135294ad78758effd28f.png +0 -0
- data/doc/spec/58113a57a37431a402d2547369eba3a481bf1dbbfd82dc384406a5c91f6df01f.png +0 -0
- data/doc/spec/5d331d74c460d75814b2d3138a9b7d90b5ddb2dcd85e1f5f260d183745fc3a1e.png +0 -0
- data/doc/spec/5d6ff62038b75d6f240d65f35d1520a131c221f47d3801554c8c2be5d528ebb0.png +0 -0
- data/doc/spec/62323426e381ec21c967971a67e1f4a6d89dae92154bd937284e00b67f67fdd3.png +0 -0
- data/doc/spec/6705af65d728c0d5c50d6c4d46253017a91eb459dbb1f40f92449f05d5562f4a.png +0 -0
- data/doc/spec/68fac940a32c7e40caacf8e560c61da552d57633d015ba98f2e98ec040a00c5b.png +0 -0
- data/doc/spec/6a34c0ef589c9c976fe41f3e67e799e198499f5b9c3ebfd240fb91f73e893573.png +0 -0
- data/doc/spec/6b48534236697d1ccfa1f5403764782f9d228f9eb706789cfa80203882b7b13a.png +0 -0
- data/doc/spec/7aa76b4d29874719466c2cbafc9936e9f12e504bf31e1a09d26ca3fffa8ba1a6.png +0 -0
- data/doc/spec/7b9db2986ab9ada45cfb9451ef87ff1a2d99c908083334b7ccdceb8a92387fa9.png +0 -0
- data/doc/spec/8101d9b89d9ba8070d585432707b43a8acdb4c2a3e9d37c3f7114b5e3ea9e800.png +0 -0
- data/doc/spec/886bf85249a704668a55c5161bceaac10be4a41a94b91606f49851dfa017526c.png +0 -0
- data/doc/spec/8ed478d8c81a58a202d0c51348fca246df206fc24a0567b163d4e0bdab56ca46.png +0 -0
- data/doc/spec/9139440329dcb815df89bc70182c3827868402a74ff64d0253706dcaff723dca.png +0 -0
- data/doc/spec/99392f56dfb0e5be3f45a12a7f1ba846d094e430f526dfeaa30b606837cd34c0.png +0 -0
- data/doc/spec/a4450e8c0fe0e2fde92fe9bd61952f907b1976c1aa3ba963b809bed079d42b09.png +0 -0
- data/doc/spec/a4bc7382a1154ea9856544fd48418f3dd9ce474ca94b8859fc323749c6cc1f55.png +0 -0
- data/doc/spec/a79274742cf6fac6f6c9f4a0eb651aeb452f9c43b537c8e6ccaefecd05b7105c.png +0 -0
- data/doc/spec/a9b4528726adec2a90f3f00139d8d0492f13c51f03c2f9ed6a5134b1b26b44a9.png +0 -0
- data/doc/spec/af5ae3787e80bf0771f18f1a04fe4c5d9291e1e0f963ac408a7bc198d2f1ee28.png +0 -0
- data/doc/spec/ba572c4f4dbade65be55f141df16cf7b3e7d09e0aec4e4e5debc4f2075277371.png +0 -0
- data/doc/spec/ba90ef705f7be91c53c5eb4a81a439fa0f7c48532214bd3db3cc5c069160543e.png +0 -0
- data/doc/spec/c1d0402862221d85aceedc7d76b3f82149b612cbd972f14d0ca9011e1e2c455c.png +0 -0
- data/doc/spec/c2157d8a6b73abe4f22ba5042159f32502c74bf6d762be28d2df6831586822c7.png +0 -0
- data/doc/spec/c5329a7f4937096a57b2e01efb9d542f84a4e2329a1e9381d08c630583ccad37.png +0 -0
- data/doc/spec/c82077b9455d0f9abc2c45ee1a298e38b99c9ce9cd685f65d87b376d7718d7ad.png +0 -0
- data/doc/spec/c93dd18894a245a5647f99e1867d3779e4cd34c9c8f8860600ff0c837a5ffa53.png +0 -0
- data/doc/spec/cc960a268d51ccf2ebde657d36848f780213834844900018bce3d111843f7b0f.png +0 -0
- data/doc/spec/d39452b58257c95a7cba07afed4877417b0c227f3690e2bff22c9eca89eac845.png +0 -0
- data/doc/spec/d64993258ffbef9406d9ab9136de7af530626b3a69e9eeb75835e11f11dabf62.png +0 -0
- data/doc/spec/da450cdd0c94a1301bd98560339a45caa8041e09974352a56ecfb144e9a5e4d4.png +0 -0
- data/doc/spec/dbc66b3ae6bd7123d77dd04b64f8a24498d048725a55c5340b15f5ae0a1ff307.png +0 -0
- data/doc/spec/de589af36fa854e006a1563c93e644e2210f2a5616babb779f7f38aadb6c1ed7.png +0 -0
- data/doc/spec/defbd0b853d895802663f507761ad297d82e167f516c6082686a2a19b76012c5.png +0 -0
- data/doc/spec/e1cb0863b21e14256d61a54200316791f6547c78ba2f0156c110f4500f9bbd49.png +0 -0
- data/doc/spec/e8630103287f7c9d28eff40b3b1826e24846e776b877f7b8554257acbe621e1c.png +0 -0
- data/doc/spec/e9b384fa7dec5f1a06479c4b289e06b1e60e4f23f7630aff6d03c52595f500f8.png +0 -0
- data/doc/spec/ea935ac31f3b57ff373646780a1fba34a38c9e086dc771eb7fc16c65a7e20cfc.png +0 -0
- data/doc/spec/eb8f5511f7d88bd0f8ba73420fc10f7c78405db7f4373d778a827058707f888e.png +0 -0
- data/doc/spec/ebacbd092e3d1a3c7b745a381e51e8ff9d63a21db23a16940193e18e57bc866f.png +0 -0
- data/doc/spec/ed039f82867241393b1a6a7153d3690461103934c72c1f3eaa3d99a12bb40885.png +0 -0
- data/doc/spec/ee283d6a4b69cf10da2df703be3a16830be9cd8cd4f68c5f7afdf558ea28fa76.png +0 -0
- data/doc/spec/f0c734b099841a754ae0366afb00e992ad4814479b65e4a7de23c6e3dd85c09a.png +0 -0
- data/doc/spec/f6b4fc31703cfb6327bbbd4614af8bb72da6d39fa3d53ada63a70157f2fad80e.png +0 -0
- data/doc/spec/f766f2e3aa13420e3ba0f823ac7956b311ed7c6c20be26b72324fadd87f36712.png +0 -0
- data/doc/spec/ff7d5b5573d09bd7c4cdd3aeda124d18bf82ec46673a62881b399a75d69f3f53.png +0 -0
- data/lib/conceptql.rb +21 -1
- data/lib/conceptql/annotate_grapher.rb +127 -0
- data/lib/conceptql/behaviors/drugish.rb +12 -0
- data/lib/conceptql/behaviors/labish.rb +13 -0
- data/lib/conceptql/behaviors/metadatable.rb +156 -71
- data/lib/conceptql/behaviors/provenanceable.rb +30 -0
- data/lib/conceptql/cli.rb +81 -37
- data/lib/conceptql/database.rb +42 -0
- data/lib/conceptql/date_adjuster.rb +22 -4
- data/lib/conceptql/fake_annotater.rb +129 -0
- data/lib/conceptql/knitter.rb +221 -0
- data/lib/conceptql/nodifier.rb +34 -23
- data/lib/conceptql/operators/after.rb +20 -3
- data/lib/conceptql/operators/any_overlap.rb +3 -1
- data/lib/conceptql/operators/before.rb +19 -3
- data/lib/conceptql/operators/binary_operator_operator.rb +24 -20
- data/lib/conceptql/operators/casting_operator.rb +39 -31
- data/lib/conceptql/operators/co_reported.rb +42 -0
- data/lib/conceptql/operators/complement.rb +21 -16
- data/lib/conceptql/operators/concurrent_within.rb +57 -0
- data/lib/conceptql/operators/condition_occurrence_source_vocabulary_operator.rb +34 -0
- data/lib/conceptql/operators/condition_occurrence_source_vocabulary_operator_union.rb +28 -0
- data/lib/conceptql/operators/condition_type.rb +12 -4
- data/lib/conceptql/operators/contains.rb +6 -2
- data/lib/conceptql/operators/count.rb +10 -2
- data/lib/conceptql/operators/cpt.rb +5 -2
- data/lib/conceptql/operators/cpt_or_hcpcs.rb +27 -0
- data/lib/conceptql/operators/date_range.rb +20 -8
- data/lib/conceptql/operators/death.rb +4 -2
- data/lib/conceptql/operators/drg.rb +42 -0
- data/lib/conceptql/operators/drug_type_concept.rb +11 -2
- data/lib/conceptql/operators/during.rb +4 -2
- data/lib/conceptql/operators/equal.rb +4 -1
- data/lib/conceptql/operators/except.rb +16 -4
- data/lib/conceptql/operators/filter.rb +6 -3
- data/lib/conceptql/operators/first.rb +3 -1
- data/lib/conceptql/operators/from.rb +32 -5
- data/lib/conceptql/operators/from_seer_visits.rb +11 -5
- data/lib/conceptql/operators/gender.rb +9 -2
- data/lib/conceptql/operators/hcpcs.rb +5 -2
- data/lib/conceptql/operators/icd10.rb +6 -15
- data/lib/conceptql/operators/icd10_pcs.rb +28 -0
- data/lib/conceptql/operators/icd9.rb +6 -15
- data/lib/conceptql/operators/icd9_procedure.rb +5 -2
- data/lib/conceptql/operators/intersect.rb +15 -10
- data/lib/conceptql/operators/invalid.rb +36 -0
- data/lib/conceptql/operators/last.rb +3 -1
- data/lib/conceptql/operators/loinc.rb +5 -2
- data/lib/conceptql/operators/medcode.rb +5 -16
- data/lib/conceptql/operators/medcode_procedure.rb +3 -2
- data/lib/conceptql/operators/ndc.rb +5 -2
- data/lib/conceptql/operators/numeric.rb +30 -11
- data/lib/conceptql/operators/observation_by_enttype.rb +5 -2
- data/lib/conceptql/operators/observation_period.rb +6 -4
- data/lib/conceptql/operators/occurrence.rb +47 -11
- data/lib/conceptql/operators/one_in_two_out.rb +96 -33
- data/lib/conceptql/operators/operator.rb +628 -95
- data/lib/conceptql/operators/overlapped_by.rb +8 -5
- data/lib/conceptql/operators/overlaps.rb +7 -5
- data/lib/conceptql/operators/pass_thru.rb +12 -2
- data/lib/conceptql/operators/person.rb +7 -5
- data/lib/conceptql/operators/person_filter.rb +5 -1
- data/lib/conceptql/operators/place_of_service_code.rb +12 -5
- data/lib/conceptql/operators/place_of_service_filter.rb +47 -0
- data/lib/conceptql/operators/procedure_occurrence.rb +4 -2
- data/lib/conceptql/operators/prodcode.rb +5 -2
- data/lib/conceptql/operators/provenance.rb +66 -0
- data/lib/conceptql/operators/provider_filter.rb +36 -0
- data/lib/conceptql/operators/race.rb +11 -4
- data/lib/conceptql/operators/read.rb +149 -0
- data/lib/conceptql/operators/recall.rb +42 -7
- data/lib/conceptql/operators/revenue_code.rb +40 -0
- data/lib/conceptql/operators/rxnorm.rb +5 -1
- data/lib/conceptql/operators/snomed.rb +3 -2
- data/lib/conceptql/operators/source_vocabulary_operator.rb +44 -14
- data/lib/conceptql/operators/standard_vocabulary_operator.rb +36 -15
- data/lib/conceptql/operators/started_by.rb +2 -1
- data/lib/conceptql/operators/sum.rb +7 -1
- data/lib/conceptql/operators/temporal_operator.rb +75 -9
- data/lib/conceptql/operators/time_window.rb +13 -23
- data/lib/conceptql/operators/to_seer_visits.rb +6 -1
- data/lib/conceptql/operators/trim_date_end.rb +20 -12
- data/lib/conceptql/operators/trim_date_start.rb +22 -12
- data/lib/conceptql/operators/union.rb +39 -2
- data/lib/conceptql/operators/visit_occurrence.rb +5 -3
- data/lib/conceptql/operators/vocabulary_operator.rb +45 -0
- data/lib/conceptql/query.rb +68 -22
- data/lib/conceptql/query_modifiers/drug_query_modifier.rb +45 -0
- data/lib/conceptql/query_modifiers/pos_query_modifier.rb +31 -0
- data/lib/conceptql/query_modifiers/query_modifier.rb +16 -0
- data/lib/conceptql/scope.rb +169 -31
- data/lib/conceptql/sql_formatter.rb +22 -0
- data/lib/conceptql/version.rb +1 -1
- data/test/all.rb +3 -0
- data/test/all_operations_test.rb +45 -0
- data/test/code_list_test.rb +23 -0
- data/test/data/omopv4/care_site.csv +0 -0
- data/test/data/omopv4/cohort.csv +0 -0
- data/test/data/omopv4/condition_era.csv +0 -0
- data/test/data/omopv4/condition_occurrence.csv +34044 -0
- data/test/data/omopv4/death.csv +1 -0
- data/test/data/omopv4/drug_cost.csv +0 -0
- data/test/data/omopv4/drug_era.csv +0 -0
- data/test/data/omopv4/drug_exposure.csv +2 -0
- data/test/data/omopv4/location.csv +0 -0
- data/test/data/omopv4/observation.csv +2 -0
- data/test/data/omopv4/observation_period.csv +1 -0
- data/test/data/omopv4/organization.csv +0 -0
- data/test/data/omopv4/payer_plan_period.csv +0 -0
- data/test/data/omopv4/person.csv +250 -0
- data/test/data/omopv4/procedure_cost.csv +0 -0
- data/test/data/omopv4/procedure_occurrence.csv +35099 -0
- data/test/data/omopv4/provider.csv +0 -0
- data/test/data/omopv4/visit_occurrence.csv +14931 -0
- data/test/data/omopv4_plus/care_site.csv +0 -0
- data/test/data/omopv4_plus/cohort.csv +0 -0
- data/test/data/omopv4_plus/concept.csv +352 -0
- data/test/data/omopv4_plus/condition_era.csv +0 -0
- data/test/data/omopv4_plus/condition_occurrence.csv +46673 -0
- data/test/data/omopv4_plus/death.csv +9 -0
- data/test/data/omopv4_plus/drug_cost.csv +13921 -0
- data/test/data/omopv4_plus/drug_era.csv +0 -0
- data/test/data/omopv4_plus/drug_exposure.csv +13921 -0
- data/test/data/omopv4_plus/headers/care_site.csv +1 -0
- data/test/data/omopv4_plus/headers/cohort.csv +1 -0
- data/test/data/omopv4_plus/headers/concept.csv +1 -0
- data/test/data/omopv4_plus/headers/condition_era.csv +1 -0
- data/test/data/omopv4_plus/headers/condition_occurrence.csv +1 -0
- data/test/data/omopv4_plus/headers/death.csv +1 -0
- data/test/data/omopv4_plus/headers/drug_cost.csv +1 -0
- data/test/data/omopv4_plus/headers/drug_era.csv +1 -0
- data/test/data/omopv4_plus/headers/drug_exposure.csv +1 -0
- data/test/data/omopv4_plus/headers/location.csv +1 -0
- data/test/data/omopv4_plus/headers/observation.csv +1 -0
- data/test/data/omopv4_plus/headers/observation_period.csv +1 -0
- data/test/data/omopv4_plus/headers/organization.csv +1 -0
- data/test/data/omopv4_plus/headers/payer_plan_period.csv +1 -0
- data/test/data/omopv4_plus/headers/person.csv +1 -0
- data/test/data/omopv4_plus/headers/procedure_cost.csv +1 -0
- data/test/data/omopv4_plus/headers/procedure_occurrence.csv +1 -0
- data/test/data/omopv4_plus/headers/provider.csv +1 -0
- data/test/data/omopv4_plus/headers/source_to_concept_map.csv +1 -0
- data/test/data/omopv4_plus/headers/visit_occurrence.csv +1 -0
- data/test/data/omopv4_plus/headers/vocabulary.csv +1 -0
- data/test/data/omopv4_plus/location.csv +0 -0
- data/test/data/omopv4_plus/observation.csv +0 -0
- data/test/data/omopv4_plus/observation_period.csv +147 -0
- data/test/data/omopv4_plus/organization.csv +736 -0
- data/test/data/omopv4_plus/payer_plan_period.csv +808 -0
- data/test/data/omopv4_plus/person.csv +250 -0
- data/test/data/omopv4_plus/procedure_cost.csv +20123 -0
- data/test/data/omopv4_plus/procedure_occurrence.csv +27273 -0
- data/test/data/omopv4_plus/provider.csv +10193 -0
- data/test/data/omopv4_plus/source_to_concept_map.csv +285 -0
- data/test/data/omopv4_plus/visit_occurrence.csv +45125 -0
- data/test/data/omopv4_plus/vocabulary.csv +60 -0
- data/test/db.rb +15 -0
- data/test/db_setup.rb +408 -0
- data/test/db_teardown.rb +33 -0
- data/test/fake_annotater_test.rb +31 -0
- data/test/helper.rb +129 -0
- data/test/knitter/conceptql.md.cql +39 -0
- data/test/knitter/conceptql.md.expect +43 -0
- data/test/knitter/empty.md.cql +0 -0
- data/test/knitter/except.md.cql +13 -0
- data/test/knitter/except.md.expect +14 -0
- data/test/knitter/fake.md.cql +10 -0
- data/test/knitter/fake.md.expect +13 -0
- data/test/knitter/many.md.cql +7 -0
- data/test/knitter/many.md.expect +14 -0
- data/test/knitter/no_conceptql.md.cql +36 -0
- data/test/knitter/title.md.cql +12 -0
- data/test/knitter/title.md.expect +15 -0
- data/test/knitter/union.md.cql +11 -0
- data/test/knitter/union.md.expect +14 -0
- data/test/knitter_test.rb +69 -0
- data/test/query_test.rb +36 -0
- data/test/results/omopv4/after/anno_1 +25 -0
- data/test/results/omopv4/after/anno_2 +48 -0
- data/test/results/omopv4/after/anno_3 +34 -0
- data/test/results/omopv4/after/anno_4 +60 -0
- data/test/results/omopv4/after/anno_5 +68 -0
- data/test/results/omopv4/after/anno_6 +60 -0
- data/test/results/omopv4/after/crit_at_least +7 -0
- data/test/results/omopv4/after/crit_basic +32 -0
- data/test/results/omopv4/after/crit_occurrences +12 -0
- data/test/results/omopv4/after/crit_within +6 -0
- data/test/results/omopv4/any_overlap/crit_basic1 +15 -0
- data/test/results/omopv4/any_overlap/crit_basic2 +15 -0
- data/test/results/omopv4/any_overlap/crit_occurrences1 +2 -0
- data/test/results/omopv4/any_overlap/crit_occurrences2 +15 -0
- data/test/results/omopv4/any_overlap/crit_within +8 -0
- data/test/results/omopv4/before/crit_at_least +6 -0
- data/test/results/omopv4/before/crit_basic1 +48 -0
- data/test/results/omopv4/before/crit_basic2 +7 -0
- data/test/results/omopv4/before/crit_occurrences +13 -0
- data/test/results/omopv4/before/crit_within +18 -0
- data/test/results/omopv4/co_reported/anno_1 +43 -0
- data/test/results/omopv4/co_reported/anno_2 +66 -0
- data/test/results/omopv4/complement/anno_duplicate_params +52 -0
- data/test/results/omopv4/complement/anno_invalid_params +37 -0
- data/test/results/omopv4/complement/anno_no_params +18 -0
- data/test/results/omopv4/complement/count_3way_intersect +4 -0
- data/test/results/omopv4/complement/count_3way_union +4 -0
- data/test/results/omopv4/complement/count_intersect +3 -0
- data/test/results/omopv4/complement/count_union +3 -0
- data/test/results/omopv4/complement/count_union_and_intersect +4 -0
- data/test/results/omopv4/complement/crit_3way_intersect +1 -0
- data/test/results/omopv4/complement/crit_3way_union +1 -0
- data/test/results/omopv4/complement/crit_basic1 +33998 -0
- data/test/results/omopv4/complement/crit_icd9_selector +54 -0
- data/test/results/omopv4/complement/crit_intersect +1 -0
- data/test/results/omopv4/complement/crit_union +1 -0
- data/test/results/omopv4/complement/crit_union_and_intersect +1 -0
- data/test/results/omopv4/complex/anno_1 +85 -0
- data/test/results/omopv4/complex/crit_1 +2 -0
- data/test/results/omopv4/complex/crit_2 +2 -0
- data/test/results/omopv4/complex/crit_3 +2 -0
- data/test/results/omopv4/complex/crit_4 +5 -0
- data/test/results/omopv4/complex/crit_5 +6 -0
- data/test/results/omopv4/complex/crit_6 +28 -0
- data/test/results/omopv4/complex/crit_7 +46 -0
- data/test/results/omopv4/complex/crit_out_of_order_ctes +7 -0
- data/test/results/omopv4/complex/scanno_1 +3 -0
- data/test/results/omopv4/concurrent_within/crit_icd9 +54 -0
- data/test/results/omopv4/concurrent_within/crit_icd9_and_place_of_service +23 -0
- data/test/results/omopv4/concurrent_within/crit_negative_start +5 -0
- data/test/results/omopv4/condition_type/anno_icd9 +39 -0
- data/test/results/omopv4/condition_type/count_condition_era +2 -0
- data/test/results/omopv4/condition_type/count_condition_era_30_day_window +2 -0
- data/test/results/omopv4/condition_type/count_ehr_problem_list +2 -0
- data/test/results/omopv4/condition_type/count_era_0 +2 -0
- data/test/results/omopv4/condition_type/count_inpatient +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_detail +2 -0
- data/test/results/omopv4/condition_type/count_inpatient_header +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_header_2 +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_header_3 +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_header_4 +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_header_5 +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_outpatient_detail +3 -0
- data/test/results/omopv4/condition_type/count_inpatient_primary +2 -0
- data/test/results/omopv4/condition_type/count_inpatient_primary_or_first +3 -0
- data/test/results/omopv4/condition_type/count_outpatient +3 -0
- data/test/results/omopv4/condition_type/count_outpatient_detail +3 -0
- data/test/results/omopv4/condition_type/count_outpatient_header +2 -0
- data/test/results/omopv4/condition_type/count_outpatient_primary +3 -0
- data/test/results/omopv4/condition_type/count_primary +3 -0
- data/test/results/omopv4/condition_type/crit_condition_era +1 -0
- data/test/results/omopv4/condition_type/crit_condition_era_30_day_window +1 -0
- data/test/results/omopv4/condition_type/crit_ehr_problem_list +1 -0
- data/test/results/omopv4/condition_type/crit_era_0 +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_detail +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_header +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_header_2 +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_header_3 +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_header_4 +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_header_5 +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_primary +1 -0
- data/test/results/omopv4/condition_type/crit_inpatient_primary_or_first +1 -0
- data/test/results/omopv4/condition_type/crit_outpatient +1 -0
- data/test/results/omopv4/condition_type/crit_outpatient_detail +1 -0
- data/test/results/omopv4/condition_type/crit_outpatient_header +1 -0
- data/test/results/omopv4/condition_type/crit_outpatient_primary +1 -0
- data/test/results/omopv4/condition_type/crit_primary +1 -0
- data/test/results/omopv4/contains/crit_1 +5 -0
- data/test/results/omopv4/contains/crit_2 +2 -0
- data/test/results/omopv4/contains/crit_3 +2 -0
- data/test/results/omopv4/count/anno_multiple_upstreams +52 -0
- data/test/results/omopv4/count/anno_no_upstream1 +18 -0
- data/test/results/omopv4/count/anno_no_upstream2 +25 -0
- data/test/results/omopv4/count/crit_icd9_ndc +8 -0
- data/test/results/omopv4/count/crit_ndc +5 -0
- data/test/results/omopv4/count/crit_person +254 -0
- data/test/results/omopv4/cpt/anno_icd9_upstream +40 -0
- data/test/results/omopv4/cpt/anno_invalid_code +22 -0
- data/test/results/omopv4/cpt/count_1 +3 -0
- data/test/results/omopv4/cpt/crit_1 +174 -0
- data/test/results/omopv4/cpt/crit_2 +1 -0
- data/test/results/omopv4/cpt/scanno_1 +17 -0
- data/test/results/omopv4/cpt_or_hcpcs/anno_bad_format +25 -0
- data/test/results/omopv4/cpt_or_hcpcs/count_1 +3 -0
- data/test/results/omopv4/cpt_or_hcpcs/crit_1 +179 -0
- data/test/results/omopv4/cpt_or_hcpcs/crit_2 +1 -0
- data/test/results/omopv4/date_range/anno_1 +15 -0
- data/test/results/omopv4/date_range/anno_extra_argument +24 -0
- data/test/results/omopv4/date_range/anno_invalid_argument +25 -0
- data/test/results/omopv4/date_range/anno_missing_argument1 +20 -0
- data/test/results/omopv4/date_range/anno_missing_argument2 +20 -0
- data/test/results/omopv4/date_range/anno_no_upstreams +38 -0
- data/test/results/omopv4/date_range/count_1 +3 -0
- data/test/results/omopv4/date_range/count_2 +3 -0
- data/test/results/omopv4/date_range/crit_1 +1 -0
- data/test/results/omopv4/date_range/crit_2 +1 -0
- data/test/results/omopv4/death/anno_multiple_upstreams +50 -0
- data/test/results/omopv4/death/anno_no_upstreams +22 -0
- data/test/results/omopv4/death/crit_basic +5 -0
- data/test/results/omopv4/death/crit_person +5 -0
- data/test/results/omopv4/drug_type_concept/anno_has_upstreams +37 -0
- data/test/results/omopv4/drug_type_concept/anno_no_arguments +18 -0
- data/test/results/omopv4/drug_type_concept/crit_basic1 +5 -0
- data/test/results/omopv4/drug_type_concept/crit_basic2 +2 -0
- data/test/results/omopv4/during/crit_1 +15 -0
- data/test/results/omopv4/during/crit_2 +2 -0
- data/test/results/omopv4/equal/crit_1 +5 -0
- data/test/results/omopv4/equal/crit_2 +5 -0
- data/test/results/omopv4/except/anno_1 +42 -0
- data/test/results/omopv4/except/anno_2 +43 -0
- data/test/results/omopv4/except/count_complex +5 -0
- data/test/results/omopv4/except/crit_412_cpt +54 -0
- data/test/results/omopv4/except/crit_412_inpatient +46 -0
- data/test/results/omopv4/except/crit_complex +1 -0
- data/test/results/omopv4/filter/crit_1 +54 -0
- data/test/results/omopv4/first/anno_argument +25 -0
- data/test/results/omopv4/first/anno_no_upstream +18 -0
- data/test/results/omopv4/first/crit_cpt +207 -0
- data/test/results/omopv4/first/crit_icd9 +42 -0
- data/test/results/omopv4/first/crit_union +45 -0
- data/test/results/omopv4/from/anno_has_upstreams +39 -0
- data/test/results/omopv4/from/anno_multiple_arguments +24 -0
- data/test/results/omopv4/from/count_condition_occurrence +3 -0
- data/test/results/omopv4/from/count_observation_period +3 -0
- data/test/results/omopv4/from/count_person +3 -0
- data/test/results/omopv4/from_seer_visits/anno_multiple_upstreams +78 -0
- data/test/results/omopv4/from_seer_visits/anno_no_upstream +18 -0
- data/test/results/omopv4/from_seer_visits/crit_1 +6 -0
- data/test/results/omopv4/from_seer_visits/crit_2 +5 -0
- data/test/results/omopv4/from_seer_visits/crit_3 +5 -0
- data/test/results/omopv4/from_seer_visits/crit_4 +6 -0
- data/test/results/omopv4/gender/anno_has_upstreams +39 -0
- data/test/results/omopv4/gender/crit_male +130 -0
- data/test/results/omopv4/hcpcs/anno_bad_format +24 -0
- data/test/results/omopv4/hcpcs/crit_A0382 +9 -0
- data/test/results/omopv4/icd10/anno_bad_format +22 -0
- data/test/results/omopv4/icd10/anno_has_upstreams +40 -0
- data/test/results/omopv4/icd10/crit_1 +5 -0
- data/test/results/omopv4/icd10pcs/anno_bad_format +28 -0
- data/test/results/omopv4/icd10pcs/anno_has_upstreams +40 -0
- data/test/results/omopv4/icd10pcs/crit_1 +2 -0
- data/test/results/omopv4/icd9/anno_empty_label +15 -0
- data/test/results/omopv4/icd9/anno_invalid_code +21 -0
- data/test/results/omopv4/icd9/crit_1 +54 -0
- data/test/results/omopv4/icd9_procedure/crit_1 +5 -0
- data/test/results/omopv4/intersect/anno_412_inpatient +42 -0
- data/test/results/omopv4/intersect/anno_has_arguments +25 -0
- data/test/results/omopv4/intersect/anno_no_upstream +18 -0
- data/test/results/omopv4/intersect/crit_412_inpatient +12 -0
- data/test/results/omopv4/intersect/crit_412_male +182 -0
- data/test/results/omopv4/intersect/crit_complex +118 -0
- data/test/results/omopv4/invalid/anno_bad_op +55 -0
- data/test/results/omopv4/invalid/scanno_1 +23 -0
- data/test/results/omopv4/last/crit_icd9 +42 -0
- data/test/results/omopv4/loinc/crit_basic +5 -0
- data/test/results/omopv4/ndc/crit_basic +5 -0
- data/test/results/omopv4/numeric/anno_multiple_upstreams +59 -0
- data/test/results/omopv4/numeric/num_values_1 +254 -0
- data/test/results/omopv4/numeric/num_values_2 +5 -0
- data/test/results/omopv4/numeric/num_values_3 +5 -0
- data/test/results/omopv4/observation_period/anno_has_arguments +36 -0
- data/test/results/omopv4/observation_period/anno_multiple_upstreams +51 -0
- data/test/results/omopv4/observation_period/count_all_periods +3 -0
- data/test/results/omopv4/observation_period/crit_female +2 -0
- data/test/results/omopv4/observation_period/crit_icd9 +5 -0
- data/test/results/omopv4/observation_period/crit_male +5 -0
- data/test/results/omopv4/occurrence/anno_no_upstream +22 -0
- data/test/results/omopv4/occurrence/cc_412_410 +1 -0
- data/test/results/omopv4/occurrence/count_412_410 +3 -0
- data/test/results/omopv4/occurrence/crit_1 +16 -0
- data/test/results/omopv4/occurrence/crit_2 +2 -0
- data/test/results/omopv4/occurrence/crit_3 +42 -0
- data/test/results/omopv4/one_in_two_out/anno_has_arguments +27 -0
- data/test/results/omopv4/one_in_two_out/anno_multiple_upstreams +54 -0
- data/test/results/omopv4/one_in_two_out/anno_no_upstream +20 -0
- data/test/results/omopv4/one_in_two_out/count_1 +3 -0
- data/test/results/omopv4/one_in_two_out/crit_hcpcs +7 -0
- data/test/results/omopv4/one_in_two_out/crit_icd9 +21 -0
- data/test/results/omopv4/overlapped_by/crit_1 +5 -0
- data/test/results/omopv4/overlapped_by/crit_2 +2 -0
- data/test/results/omopv4/overlapped_by/crit_3 +5 -0
- data/test/results/omopv4/overlapped_by/crit_4 +2 -0
- data/test/results/omopv4/overlaps/crit_1 +5 -0
- data/test/results/omopv4/overlaps/crit_2 +2 -0
- data/test/results/omopv4/overlaps/crit_3 +5 -0
- data/test/results/omopv4/overlaps/crit_4 +2 -0
- data/test/results/omopv4/person/anno_has_arguments +22 -0
- data/test/results/omopv4/person/anno_multiple_upstreams +52 -0
- data/test/results/omopv4/person/count_2 +3 -0
- data/test/results/omopv4/person/crit_1 +42 -0
- data/test/results/omopv4/person/crit_2 +1 -0
- data/test/results/omopv4/person_filter/count_1 +4 -0
- data/test/results/omopv4/person_filter/crit_1 +54 -0
- data/test/results/omopv4/person_filter/crit_2 +5 -0
- data/test/results/omopv4/person_filter/crit_3 +32 -0
- data/test/results/omopv4/person_filter/crit_4 +52 -0
- data/test/results/omopv4/person_filter/crit_5 +1 -0
- data/test/results/omopv4/place_of_service_code/anno_has_upstreams +37 -0
- data/test/results/omopv4/place_of_service_code/anno_no_arguments +18 -0
- data/test/results/omopv4/place_of_service_code/crit_basic +174 -0
- data/test/results/omopv4/place_of_service_filter/anno_1 +29 -0
- data/test/results/omopv4/procedure_occurrence/anno_has_arguments +37 -0
- data/test/results/omopv4/procedure_occurrence/anno_multiple_upstreams +51 -0
- data/test/results/omopv4/procedure_occurrence/count_gender +3 -0
- data/test/results/omopv4/procedure_occurrence/count_icd9 +3 -0
- data/test/results/omopv4/procedure_occurrence/count_started_by +3 -0
- data/test/results/omopv4/procedure_occurrence/crit_gender +1 -0
- data/test/results/omopv4/procedure_occurrence/crit_icd9 +1 -0
- data/test/results/omopv4/procedure_occurrence/crit_started_by +1 -0
- data/test/results/omopv4/provenance/anno_1 +29 -0
- data/test/results/omopv4/provider_filter/anno_1 +29 -0
- data/test/results/omopv4/race/anno_1 +37 -0
- data/test/results/omopv4/race/anno_2 +18 -0
- data/test/results/omopv4/race/crit_1 +28 -0
- data/test/results/omopv4/read/anno_1 +21 -0
- data/test/results/omopv4/read/crit_1 +2 -0
- data/test/results/omopv4/recall/anno_1 +54 -0
- data/test/results/omopv4/recall/anno_2 +66 -0
- data/test/results/omopv4/recall/anno_3 +20 -0
- data/test/results/omopv4/recall/anno_4 +18 -0
- data/test/results/omopv4/recall/anno_5 +24 -0
- data/test/results/omopv4/recall/anno_6 +270 -0
- data/test/results/omopv4/recall/crit_1 +21 -0
- data/test/results/omopv4/recall/crit_2 +54 -0
- data/test/results/omopv4/recall/crit_3 +2 -0
- data/test/results/omopv4/recall/crit_cte_1 +42 -0
- data/test/results/omopv4/recall/crit_cte_2 +42 -0
- data/test/results/omopv4/recall/crit_nested_perm_0 +54 -0
- data/test/results/omopv4/revenue_code/crit_1 +2 -0
- data/test/results/omopv4/revenue_code/crit_basic +2 -0
- data/test/results/omopv4/revenue_code/domains_1 +3 -0
- data/test/results/omopv4/revenue_code/domains_drg100 +3 -0
- data/test/results/omopv4/rxnorm/crit_1 +5 -0
- data/test/results/omopv4/snomed/crit_1 +84 -0
- data/test/results/omopv4/started_by/crit_1 +5 -0
- data/test/results/omopv4/started_by/crit_2 +2 -0
- data/test/results/omopv4/started_by/crit_3 +2 -0
- data/test/results/omopv4/sum/anno_1 +18 -0
- data/test/results/omopv4/sum/anno_2 +36 -0
- data/test/results/omopv4/sum/num_1 +5 -0
- data/test/results/omopv4/sum/num_2 +8 -0
- data/test/results/omopv4/sum/num_3 +254 -0
- data/test/results/omopv4/time_window/anno_1 +20 -0
- data/test/results/omopv4/time_window/anno_2 +40 -0
- data/test/results/omopv4/time_window/anno_3 +36 -0
- data/test/results/omopv4/time_window/anno_4 +39 -0
- data/test/results/omopv4/time_window/anno_5 +57 -0
- data/test/results/omopv4/time_window/crit_1 +54 -0
- data/test/results/omopv4/time_window/crit_2 +174 -0
- data/test/results/omopv4/time_window/crit_3 +54 -0
- data/test/results/omopv4/time_window/crit_4 +174 -0
- data/test/results/omopv4/trim_date_end/crit_1 +5 -0
- data/test/results/omopv4/trim_date_end/crit_2 +2 -0
- data/test/results/omopv4/trim_date_end/crit_3 +6 -0
- data/test/results/omopv4/trim_date_end/crit_at_least +5 -0
- data/test/results/omopv4/trim_date_end/crit_occurrences_1 +2 -0
- data/test/results/omopv4/trim_date_end/crit_occurrences_2 +6 -0
- data/test/results/omopv4/trim_date_end/crit_within +5 -0
- data/test/results/omopv4/trim_date_start/crit_1 +5 -0
- data/test/results/omopv4/trim_date_start/crit_2 +2 -0
- data/test/results/omopv4/trim_date_start/crit_3 +6 -0
- data/test/results/omopv4/trim_date_start/crit_at_least +5 -0
- data/test/results/omopv4/trim_date_start/crit_occurrences_1 +2 -0
- data/test/results/omopv4/trim_date_start/crit_occurrences_2 +6 -0
- data/test/results/omopv4/trim_date_start/crit_within +5 -0
- data/test/results/omopv4/union/anno_1 +43 -0
- data/test/results/omopv4/union/anno_2 +74 -0
- data/test/results/omopv4/union/anno_3 +18 -0
- data/test/results/omopv4/union/anno_4 +25 -0
- data/test/results/omopv4/union/anno_5 +33 -0
- data/test/results/omopv4/union/anno_6 +46 -0
- data/test/results/omopv4/union/cc_1 +1 -0
- data/test/results/omopv4/union/cc_2 +1 -0
- data/test/results/omopv4/union/cc_3 +1 -0
- data/test/results/omopv4/union/cc_4 +1 -0
- data/test/results/omopv4/union/cc_5 +1 -0
- data/test/results/omopv4/union/count_1 +3 -0
- data/test/results/omopv4/union/count_2 +3 -0
- data/test/results/omopv4/union/count_3 +3 -0
- data/test/results/omopv4/union/count_4 +3 -0
- data/test/results/omopv4/union/count_5 +4 -0
- data/test/results/omopv4/union/scanno_1 +22 -0
- data/test/results/omopv4/union/scanno_2 +36 -0
- data/test/results/omopv4/visit_occurrence/anno_1 +52 -0
- data/test/results/omopv4/visit_occurrence/anno_2 +37 -0
- data/test/results/omopv4/visit_occurrence/crit_1 +54 -0
- data/test/results/omopv4/visit_occurrence/crit_2 +7566 -0
- data/test/results/omopv4/visit_occurrence/crit_3 +14935 -0
- data/test/results/omopv4_plus/after/anno_1 +25 -0
- data/test/results/omopv4_plus/after/anno_2 +48 -0
- data/test/results/omopv4_plus/after/anno_3 +34 -0
- data/test/results/omopv4_plus/after/anno_4 +60 -0
- data/test/results/omopv4_plus/after/anno_5 +68 -0
- data/test/results/omopv4_plus/after/anno_6 +60 -0
- data/test/results/omopv4_plus/after/crit_at_least +7 -0
- data/test/results/omopv4_plus/after/crit_basic +32 -0
- data/test/results/omopv4_plus/after/crit_occurrences +12 -0
- data/test/results/omopv4_plus/after/crit_within +5 -0
- data/test/results/omopv4_plus/any_overlap/crit_basic1 +14 -0
- data/test/results/omopv4_plus/any_overlap/crit_basic2 +14 -0
- data/test/results/omopv4_plus/any_overlap/crit_occurrences1 +2 -0
- data/test/results/omopv4_plus/any_overlap/crit_occurrences2 +14 -0
- data/test/results/omopv4_plus/any_overlap/crit_within +8 -0
- data/test/results/omopv4_plus/before/crit_at_least +6 -0
- data/test/results/omopv4_plus/before/crit_basic1 +48 -0
- data/test/results/omopv4_plus/before/crit_basic2 +8 -0
- data/test/results/omopv4_plus/before/crit_occurrences +13 -0
- data/test/results/omopv4_plus/before/crit_within +17 -0
- data/test/results/omopv4_plus/co_reported/anno_1 +43 -0
- data/test/results/omopv4_plus/co_reported/anno_2 +66 -0
- data/test/results/omopv4_plus/co_reported/anno_3 +47 -0
- data/test/results/omopv4_plus/complement/anno_duplicate_params +52 -0
- data/test/results/omopv4_plus/complement/anno_invalid_params +37 -0
- data/test/results/omopv4_plus/complement/anno_no_params +18 -0
- data/test/results/omopv4_plus/complement/count_3way_intersect +4 -0
- data/test/results/omopv4_plus/complement/count_3way_union +4 -0
- data/test/results/omopv4_plus/complement/count_intersect +3 -0
- data/test/results/omopv4_plus/complement/count_union +3 -0
- data/test/results/omopv4_plus/complement/count_union_and_intersect +4 -0
- data/test/results/omopv4_plus/complement/crit_basic1 +52483 -0
- data/test/results/omopv4_plus/complement/crit_icd9_selector +52 -0
- data/test/results/omopv4_plus/complex/anno_1 +85 -0
- data/test/results/omopv4_plus/complex/crit_1 +2 -0
- data/test/results/omopv4_plus/complex/crit_2 +2 -0
- data/test/results/omopv4_plus/complex/crit_3 +2 -0
- data/test/results/omopv4_plus/complex/crit_4 +2 -0
- data/test/results/omopv4_plus/complex/crit_5 +2 -0
- data/test/results/omopv4_plus/complex/crit_6 +24 -0
- data/test/results/omopv4_plus/complex/crit_7 +45 -0
- data/test/results/omopv4_plus/complex/crit_out_of_order_ctes +15 -0
- data/test/results/omopv4_plus/complex/scanno_1 +108 -0
- data/test/results/omopv4_plus/concurrent_within/crit_icd9 +52 -0
- data/test/results/omopv4_plus/concurrent_within/crit_icd9_and_place_of_service +21 -0
- data/test/results/omopv4_plus/concurrent_within/crit_negative_start +5 -0
- data/test/results/omopv4_plus/condition_type/anno_icd9 +39 -0
- data/test/results/omopv4_plus/condition_type/count_condition_era +2 -0
- data/test/results/omopv4_plus/condition_type/count_condition_era_30_day_window +2 -0
- data/test/results/omopv4_plus/condition_type/count_ehr_problem_list +2 -0
- data/test/results/omopv4_plus/condition_type/count_era_0 +2 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_detail +2 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_header +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_header_2 +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_header_3 +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_header_4 +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_header_5 +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_outpatient_detail +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_primary +3 -0
- data/test/results/omopv4_plus/condition_type/count_inpatient_primary_or_first +3 -0
- data/test/results/omopv4_plus/condition_type/count_outpatient +3 -0
- data/test/results/omopv4_plus/condition_type/count_outpatient_detail +2 -0
- data/test/results/omopv4_plus/condition_type/count_outpatient_header +3 -0
- data/test/results/omopv4_plus/condition_type/count_outpatient_primary +3 -0
- data/test/results/omopv4_plus/condition_type/count_primary +3 -0
- data/test/results/omopv4_plus/contains/crit_1 +5 -0
- data/test/results/omopv4_plus/contains/crit_2 +2 -0
- data/test/results/omopv4_plus/contains/crit_3 +2 -0
- data/test/results/omopv4_plus/count/anno_multiple_upstreams +52 -0
- data/test/results/omopv4_plus/count/anno_no_upstream1 +18 -0
- data/test/results/omopv4_plus/count/anno_no_upstream2 +25 -0
- data/test/results/omopv4_plus/count/crit_icd9_ndc +5 -0
- data/test/results/omopv4_plus/count/crit_ndc +2 -0
- data/test/results/omopv4_plus/count/crit_person +254 -0
- data/test/results/omopv4_plus/cpt/anno_icd9_upstream +40 -0
- data/test/results/omopv4_plus/cpt/anno_invalid_code +22 -0
- data/test/results/omopv4_plus/cpt/count_1 +3 -0
- data/test/results/omopv4_plus/cpt/crit_1 +158 -0
- data/test/results/omopv4_plus/cpt/scanno_1 +17 -0
- data/test/results/omopv4_plus/cpt_or_hcpcs/anno_bad_format +25 -0
- data/test/results/omopv4_plus/cpt_or_hcpcs/count_1 +3 -0
- data/test/results/omopv4_plus/cpt_or_hcpcs/crit_1 +161 -0
- data/test/results/omopv4_plus/date_range/anno_1 +15 -0
- data/test/results/omopv4_plus/date_range/anno_extra_argument +24 -0
- data/test/results/omopv4_plus/date_range/anno_invalid_argument +25 -0
- data/test/results/omopv4_plus/date_range/anno_missing_argument1 +20 -0
- data/test/results/omopv4_plus/date_range/anno_missing_argument2 +20 -0
- data/test/results/omopv4_plus/date_range/anno_no_upstreams +38 -0
- data/test/results/omopv4_plus/date_range/count_1 +3 -0
- data/test/results/omopv4_plus/date_range/count_2 +3 -0
- data/test/results/omopv4_plus/death/anno_multiple_upstreams +50 -0
- data/test/results/omopv4_plus/death/anno_no_upstreams +22 -0
- data/test/results/omopv4_plus/death/crit_basic +14 -0
- data/test/results/omopv4_plus/death/crit_person +14 -0
- data/test/results/omopv4_plus/drug_type_concept/anno_has_upstreams +37 -0
- data/test/results/omopv4_plus/drug_type_concept/anno_no_arguments +18 -0
- data/test/results/omopv4_plus/drug_type_concept/crit_basic1 +2 -0
- data/test/results/omopv4_plus/drug_type_concept/crit_basic2 +2 -0
- data/test/results/omopv4_plus/during/crit_1 +14 -0
- data/test/results/omopv4_plus/during/crit_2 +2 -0
- data/test/results/omopv4_plus/equal/crit_1 +2 -0
- data/test/results/omopv4_plus/equal/crit_2 +2 -0
- data/test/results/omopv4_plus/except/anno_1 +42 -0
- data/test/results/omopv4_plus/except/anno_2 +43 -0
- data/test/results/omopv4_plus/except/count_complex +5 -0
- data/test/results/omopv4_plus/except/crit_412_cpt +52 -0
- data/test/results/omopv4_plus/except/crit_412_inpatient +45 -0
- data/test/results/omopv4_plus/filter/crit_1 +52 -0
- data/test/results/omopv4_plus/first/anno_argument +25 -0
- data/test/results/omopv4_plus/first/anno_no_upstream +18 -0
- data/test/results/omopv4_plus/first/crit_cpt +180 -0
- data/test/results/omopv4_plus/first/crit_icd9 +41 -0
- data/test/results/omopv4_plus/first/crit_union +52 -0
- data/test/results/omopv4_plus/from/anno_has_upstreams +39 -0
- data/test/results/omopv4_plus/from/anno_multiple_arguments +24 -0
- data/test/results/omopv4_plus/from/count_condition_occurrence +3 -0
- data/test/results/omopv4_plus/from/count_observation_period +3 -0
- data/test/results/omopv4_plus/from/count_person +3 -0
- data/test/results/omopv4_plus/from_seer_visits/anno_multiple_upstreams +78 -0
- data/test/results/omopv4_plus/from_seer_visits/anno_no_upstream +18 -0
- data/test/results/omopv4_plus/from_seer_visits/crit_1 +2 -0
- data/test/results/omopv4_plus/from_seer_visits/crit_2 +2 -0
- data/test/results/omopv4_plus/from_seer_visits/crit_3 +2 -0
- data/test/results/omopv4_plus/from_seer_visits/crit_4 +2 -0
- data/test/results/omopv4_plus/gender/anno_has_upstreams +39 -0
- data/test/results/omopv4_plus/gender/crit_male +128 -0
- data/test/results/omopv4_plus/hcpcs/anno_bad_format +24 -0
- data/test/results/omopv4_plus/hcpcs/crit_A0382 +7 -0
- data/test/results/omopv4_plus/icd10/anno_bad_format +22 -0
- data/test/results/omopv4_plus/icd10/anno_has_upstreams +40 -0
- data/test/results/omopv4_plus/icd10/crit_1 +2 -0
- data/test/results/omopv4_plus/icd10pcs/anno_bad_format +28 -0
- data/test/results/omopv4_plus/icd10pcs/anno_has_upstreams +40 -0
- data/test/results/omopv4_plus/icd10pcs/crit_1 +2 -0
- data/test/results/omopv4_plus/icd9/anno_empty_label +15 -0
- data/test/results/omopv4_plus/icd9/anno_invalid_code +21 -0
- data/test/results/omopv4_plus/icd9/anno_valid_code +3 -0
- data/test/results/omopv4_plus/icd9/crit_1 +52 -0
- data/test/results/omopv4_plus/icd9_procedure/crit_1 +5 -0
- data/test/results/omopv4_plus/intersect/anno_412_inpatient +42 -0
- data/test/results/omopv4_plus/intersect/anno_has_arguments +25 -0
- data/test/results/omopv4_plus/intersect/anno_no_upstream +18 -0
- data/test/results/omopv4_plus/intersect/crit_412_inpatient +11 -0
- data/test/results/omopv4_plus/intersect/crit_412_male +178 -0
- data/test/results/omopv4_plus/intersect/crit_complex +110 -0
- data/test/results/omopv4_plus/invalid/anno_bad_op +55 -0
- data/test/results/omopv4_plus/invalid/scanno_1 +23 -0
- data/test/results/omopv4_plus/last/crit_icd9 +41 -0
- data/test/results/omopv4_plus/loinc/crit_basic +2 -0
- data/test/results/omopv4_plus/ndc/crit_basic +2 -0
- data/test/results/omopv4_plus/ndc/results_1 +41 -0
- data/test/results/omopv4_plus/numeric/anno_multiple_upstreams +59 -0
- data/test/results/omopv4_plus/numeric/num_values_1 +254 -0
- data/test/results/omopv4_plus/numeric/num_values_2 +5 -0
- data/test/results/omopv4_plus/numeric/num_values_3 +5 -0
- data/test/results/omopv4_plus/observation_period/anno_has_arguments +36 -0
- data/test/results/omopv4_plus/observation_period/anno_multiple_upstreams +51 -0
- data/test/results/omopv4_plus/observation_period/count_all_periods +3 -0
- data/test/results/omopv4_plus/observation_period/crit_female +87 -0
- data/test/results/omopv4_plus/observation_period/crit_icd9 +28 -0
- data/test/results/omopv4_plus/observation_period/crit_male +75 -0
- data/test/results/omopv4_plus/occurrence/anno_no_upstream +22 -0
- data/test/results/omopv4_plus/occurrence/count_412_410 +3 -0
- data/test/results/omopv4_plus/occurrence/crit_1 +15 -0
- data/test/results/omopv4_plus/occurrence/crit_2 +2 -0
- data/test/results/omopv4_plus/occurrence/crit_3 +41 -0
- data/test/results/omopv4_plus/one_in_two_out/anno_has_arguments +27 -0
- data/test/results/omopv4_plus/one_in_two_out/anno_multiple_upstreams +54 -0
- data/test/results/omopv4_plus/one_in_two_out/anno_no_upstream +20 -0
- data/test/results/omopv4_plus/one_in_two_out/count_1 +3 -0
- data/test/results/omopv4_plus/one_in_two_out/count_same_as_1 +3 -0
- data/test/results/omopv4_plus/one_in_two_out/crit_hcpcs +2 -0
- data/test/results/omopv4_plus/one_in_two_out/crit_icd9 +19 -0
- data/test/results/omopv4_plus/one_in_two_out/results_1 +803 -0
- data/test/results/omopv4_plus/one_in_two_out/results_2 +803 -0
- data/test/results/omopv4_plus/overlapped_by/crit_1 +5 -0
- data/test/results/omopv4_plus/overlapped_by/crit_2 +2 -0
- data/test/results/omopv4_plus/overlapped_by/crit_3 +5 -0
- data/test/results/omopv4_plus/overlapped_by/crit_4 +2 -0
- data/test/results/omopv4_plus/overlaps/crit_1 +5 -0
- data/test/results/omopv4_plus/overlaps/crit_2 +2 -0
- data/test/results/omopv4_plus/overlaps/crit_3 +5 -0
- data/test/results/omopv4_plus/overlaps/crit_4 +2 -0
- data/test/results/omopv4_plus/person/anno_has_arguments +22 -0
- data/test/results/omopv4_plus/person/anno_multiple_upstreams +52 -0
- data/test/results/omopv4_plus/person/count_2 +3 -0
- data/test/results/omopv4_plus/person/crit_1 +41 -0
- data/test/results/omopv4_plus/person_filter/count_1 +4 -0
- data/test/results/omopv4_plus/person_filter/crit_1 +52 -0
- data/test/results/omopv4_plus/person_filter/crit_2 +10 -0
- data/test/results/omopv4_plus/person_filter/crit_3 +32 -0
- data/test/results/omopv4_plus/person_filter/crit_4 +50 -0
- data/test/results/omopv4_plus/place_of_service_code/anno_has_upstreams +37 -0
- data/test/results/omopv4_plus/place_of_service_code/anno_no_arguments +18 -0
- data/test/results/omopv4_plus/place_of_service_code/crit_basic +157 -0
- data/test/results/omopv4_plus/place_of_service_filter/anno_1 +29 -0
- data/test/results/omopv4_plus/procedure_occurrence/anno_has_arguments +37 -0
- data/test/results/omopv4_plus/procedure_occurrence/anno_multiple_upstreams +51 -0
- data/test/results/omopv4_plus/procedure_occurrence/count_gender +3 -0
- data/test/results/omopv4_plus/procedure_occurrence/count_icd9 +3 -0
- data/test/results/omopv4_plus/procedure_occurrence/count_started_by +3 -0
- data/test/results/omopv4_plus/provenance/anno_1 +29 -0
- data/test/results/omopv4_plus/provenance/anno_bad_keyword +38 -0
- data/test/results/omopv4_plus/provenance/count_1 +3 -0
- data/test/results/omopv4_plus/provenance/count_2 +3 -0
- data/test/results/omopv4_plus/provider_filter/anno_1 +29 -0
- data/test/results/omopv4_plus/race/anno_1 +37 -0
- data/test/results/omopv4_plus/race/anno_2 +18 -0
- data/test/results/omopv4_plus/race/crit_1 +32 -0
- data/test/results/omopv4_plus/read/anno_1 +15 -0
- data/test/results/omopv4_plus/read/crit_1 +2 -0
- data/test/results/omopv4_plus/recall/anno_1 +54 -0
- data/test/results/omopv4_plus/recall/anno_2 +66 -0
- data/test/results/omopv4_plus/recall/anno_3 +20 -0
- data/test/results/omopv4_plus/recall/anno_4 +18 -0
- data/test/results/omopv4_plus/recall/anno_5 +24 -0
- data/test/results/omopv4_plus/recall/anno_6 +270 -0
- data/test/results/omopv4_plus/recall/crit_1 +19 -0
- data/test/results/omopv4_plus/recall/crit_2 +52 -0
- data/test/results/omopv4_plus/recall/crit_3 +2 -0
- data/test/results/omopv4_plus/recall/crit_cte_1 +41 -0
- data/test/results/omopv4_plus/recall/crit_cte_2 +41 -0
- data/test/results/omopv4_plus/recall/crit_nested_perm_0 +52 -0
- data/test/results/omopv4_plus/revenue_code/crit_1 +2 -0
- data/test/results/omopv4_plus/revenue_code/crit_basic +2 -0
- data/test/results/omopv4_plus/revenue_code/domains_1 +3 -0
- data/test/results/omopv4_plus/revenue_code/domains_drg100 +3 -0
- data/test/results/omopv4_plus/rxnorm/crit_1 +2 -0
- data/test/results/omopv4_plus/snomed/crit_1 +2 -0
- data/test/results/omopv4_plus/started_by/crit_1 +5 -0
- data/test/results/omopv4_plus/started_by/crit_2 +2 -0
- data/test/results/omopv4_plus/started_by/crit_3 +2 -0
- data/test/results/omopv4_plus/sum/anno_1 +18 -0
- data/test/results/omopv4_plus/sum/anno_2 +36 -0
- data/test/results/omopv4_plus/sum/num_1 +2 -0
- data/test/results/omopv4_plus/sum/num_2 +5 -0
- data/test/results/omopv4_plus/sum/num_3 +254 -0
- data/test/results/omopv4_plus/time_window/anno_1 +20 -0
- data/test/results/omopv4_plus/time_window/anno_2 +40 -0
- data/test/results/omopv4_plus/time_window/anno_3 +36 -0
- data/test/results/omopv4_plus/time_window/anno_4 +39 -0
- data/test/results/omopv4_plus/time_window/anno_5 +57 -0
- data/test/results/omopv4_plus/time_window/crit_1 +52 -0
- data/test/results/omopv4_plus/time_window/crit_2 +157 -0
- data/test/results/omopv4_plus/time_window/crit_3 +52 -0
- data/test/results/omopv4_plus/time_window/crit_4 +157 -0
- data/test/results/omopv4_plus/trim_date_end/crit_1 +5 -0
- data/test/results/omopv4_plus/trim_date_end/crit_2 +2 -0
- data/test/results/omopv4_plus/trim_date_end/crit_3 +6 -0
- data/test/results/omopv4_plus/trim_date_end/crit_at_least +5 -0
- data/test/results/omopv4_plus/trim_date_end/crit_occurrences_1 +2 -0
- data/test/results/omopv4_plus/trim_date_end/crit_occurrences_2 +6 -0
- data/test/results/omopv4_plus/trim_date_end/crit_within +5 -0
- data/test/results/omopv4_plus/trim_date_start/crit_1 +5 -0
- data/test/results/omopv4_plus/trim_date_start/crit_2 +2 -0
- data/test/results/omopv4_plus/trim_date_start/crit_3 +6 -0
- data/test/results/omopv4_plus/trim_date_start/crit_at_least +5 -0
- data/test/results/omopv4_plus/trim_date_start/crit_occurrences_1 +2 -0
- data/test/results/omopv4_plus/trim_date_start/crit_occurrences_2 +6 -0
- data/test/results/omopv4_plus/trim_date_start/crit_within +5 -0
- data/test/results/omopv4_plus/union/anno_1 +43 -0
- data/test/results/omopv4_plus/union/anno_2 +74 -0
- data/test/results/omopv4_plus/union/anno_3 +18 -0
- data/test/results/omopv4_plus/union/anno_4 +25 -0
- data/test/results/omopv4_plus/union/anno_5 +33 -0
- data/test/results/omopv4_plus/union/anno_6 +46 -0
- data/test/results/omopv4_plus/union/count_1 +3 -0
- data/test/results/omopv4_plus/union/count_2 +3 -0
- data/test/results/omopv4_plus/union/count_3 +3 -0
- data/test/results/omopv4_plus/union/count_4 +3 -0
- data/test/results/omopv4_plus/union/count_5 +4 -0
- data/test/results/omopv4_plus/union/optcc_1 +3 -0
- data/test/results/omopv4_plus/union/optcc_2 +3 -0
- data/test/results/omopv4_plus/union/optcc_3 +3 -0
- data/test/results/omopv4_plus/union/optcc_4 +3 -0
- data/test/results/omopv4_plus/union/optcc_5 +3 -0
- data/test/results/omopv4_plus/union/optcc_6 +3 -0
- data/test/results/omopv4_plus/union/scanno_1 +22 -0
- data/test/results/omopv4_plus/union/scanno_2 +36 -0
- data/test/results/omopv4_plus/visit_occurrence/anno_1 +52 -0
- data/test/results/omopv4_plus/visit_occurrence/anno_2 +37 -0
- data/test/results/omopv4_plus/visit_occurrence/crit_1 +52 -0
- data/test/results/omopv4_plus/visit_occurrence/crit_2 +22945 -0
- data/test/results/omopv4_plus/visit_occurrence/crit_3 +46851 -0
- data/test/statements/after/anno_1 +7 -0
- data/test/statements/after/anno_2 +16 -0
- data/test/statements/after/anno_3 +9 -0
- data/test/statements/after/anno_4 +19 -0
- data/test/statements/after/anno_5 +21 -0
- data/test/statements/after/anno_6 +16 -0
- data/test/statements/after/crit_at_least +21 -0
- data/test/statements/after/crit_basic +20 -0
- data/test/statements/after/crit_occurrences +21 -0
- data/test/statements/after/crit_within +21 -0
- data/test/statements/any_overlap/crit_basic1 +16 -0
- data/test/statements/any_overlap/crit_basic2 +16 -0
- data/test/statements/any_overlap/crit_occurrences1 +17 -0
- data/test/statements/any_overlap/crit_occurrences2 +17 -0
- data/test/statements/any_overlap/crit_within +17 -0
- data/test/statements/before/crit_at_least +14 -0
- data/test/statements/before/crit_basic1 +13 -0
- data/test/statements/before/crit_basic2 +16 -0
- data/test/statements/before/crit_occurrences +14 -0
- data/test/statements/before/crit_within +14 -0
- data/test/statements/co_reported/anno_1 +13 -0
- data/test/statements/co_reported/anno_2 +21 -0
- data/test/statements/co_reported/anno_3 +14 -0
- data/test/statements/complement/anno_duplicate_params +11 -0
- data/test/statements/complement/anno_invalid_params +8 -0
- data/test/statements/complement/anno_no_params +3 -0
- data/test/statements/complement/count_3way_intersect +24 -0
- data/test/statements/complement/count_3way_union +18 -0
- data/test/statements/complement/count_intersect +17 -0
- data/test/statements/complement/count_union +14 -0
- data/test/statements/complement/count_union_and_intersect +27 -0
- data/test/statements/complement/crit_basic1 +7 -0
- data/test/statements/complement/crit_icd9_selector +10 -0
- data/test/statements/complex/anno_1 +29 -0
- data/test/statements/complex/crit_1 +278 -0
- data/test/statements/complex/crit_2 +43 -0
- data/test/statements/complex/crit_3 +54 -0
- data/test/statements/complex/crit_4 +17 -0
- data/test/statements/complex/crit_5 +17 -0
- data/test/statements/complex/crit_6 +20 -0
- data/test/statements/complex/crit_7 +14 -0
- data/test/statements/complex/crit_out_of_order_ctes +39 -0
- data/test/statements/complex/scanno_1 +1508 -0
- data/test/statements/concurrent_within/crit_icd9 +11 -0
- data/test/statements/concurrent_within/crit_icd9_and_place_of_service +15 -0
- data/test/statements/concurrent_within/crit_negative_start +15 -0
- data/test/statements/condition_type/anno_icd9 +7 -0
- data/test/statements/condition_type/count_condition_era +4 -0
- data/test/statements/condition_type/count_condition_era_30_day_window +4 -0
- data/test/statements/condition_type/count_ehr_problem_list +4 -0
- data/test/statements/condition_type/count_era_0 +4 -0
- data/test/statements/condition_type/count_inpatient +4 -0
- data/test/statements/condition_type/count_inpatient_detail +4 -0
- data/test/statements/condition_type/count_inpatient_header +4 -0
- data/test/statements/condition_type/count_inpatient_header_2 +4 -0
- data/test/statements/condition_type/count_inpatient_header_3 +4 -0
- data/test/statements/condition_type/count_inpatient_header_4 +4 -0
- data/test/statements/condition_type/count_inpatient_header_5 +4 -0
- data/test/statements/condition_type/count_inpatient_outpatient_detail +5 -0
- data/test/statements/condition_type/count_inpatient_primary +4 -0
- data/test/statements/condition_type/count_inpatient_primary_or_first +4 -0
- data/test/statements/condition_type/count_outpatient +4 -0
- data/test/statements/condition_type/count_outpatient_detail +4 -0
- data/test/statements/condition_type/count_outpatient_header +4 -0
- data/test/statements/condition_type/count_outpatient_primary +4 -0
- data/test/statements/condition_type/count_primary +4 -0
- data/test/statements/contains/crit_1 +16 -0
- data/test/statements/contains/crit_2 +16 -0
- data/test/statements/contains/crit_3 +16 -0
- data/test/statements/count/anno_multiple_upstreams +11 -0
- data/test/statements/count/anno_no_upstream1 +3 -0
- data/test/statements/count/anno_no_upstream2 +4 -0
- data/test/statements/count/crit_icd9_ndc +15 -0
- data/test/statements/count/crit_ndc +11 -0
- data/test/statements/count/crit_person +7 -0
- data/test/statements/cpt/anno_icd9_upstream +7 -0
- data/test/statements/cpt/anno_invalid_code +5 -0
- data/test/statements/cpt/count_1 +4 -0
- data/test/statements/cpt/crit_1 +4 -0
- data/test/statements/cpt/scanno_1 +4 -0
- data/test/statements/cpt_or_hcpcs/anno_bad_format +7 -0
- data/test/statements/cpt_or_hcpcs/count_1 +5 -0
- data/test/statements/cpt_or_hcpcs/crit_1 +5 -0
- data/test/statements/date_range/anno_1 +7 -0
- data/test/statements/date_range/anno_extra_argument +8 -0
- data/test/statements/date_range/anno_invalid_argument +7 -0
- data/test/statements/date_range/anno_missing_argument1 +6 -0
- data/test/statements/date_range/anno_missing_argument2 +6 -0
- data/test/statements/date_range/anno_no_upstreams +11 -0
- data/test/statements/date_range/count_1 +7 -0
- data/test/statements/date_range/count_2 +7 -0
- data/test/statements/death/anno_multiple_upstreams +10 -0
- data/test/statements/death/anno_no_upstreams +4 -0
- data/test/statements/death/crit_basic +3 -0
- data/test/statements/death/crit_person +7 -0
- data/test/statements/drug_type_concept/anno_has_upstreams +8 -0
- data/test/statements/drug_type_concept/anno_no_arguments +3 -0
- data/test/statements/drug_type_concept/crit_basic1 +4 -0
- data/test/statements/drug_type_concept/crit_basic2 +4 -0
- data/test/statements/during/crit_1 +16 -0
- data/test/statements/during/crit_2 +16 -0
- data/test/statements/equal/crit_1 +17 -0
- data/test/statements/equal/crit_2 +21 -0
- data/test/statements/except/anno_1 +13 -0
- data/test/statements/except/anno_2 +14 -0
- data/test/statements/except/count_complex +31 -0
- data/test/statements/except/crit_412_cpt +13 -0
- data/test/statements/except/crit_412_inpatient +13 -0
- data/test/statements/filter/crit_1 +15 -0
- data/test/statements/first/anno_argument +4 -0
- data/test/statements/first/anno_no_upstream +3 -0
- data/test/statements/first/crit_cpt +7 -0
- data/test/statements/first/crit_icd9 +7 -0
- data/test/statements/first/crit_union +14 -0
- data/test/statements/from/anno_has_upstreams +7 -0
- data/test/statements/from/anno_multiple_arguments +5 -0
- data/test/statements/from_seer_visits/anno_multiple_upstreams +17 -0
- data/test/statements/from_seer_visits/anno_no_upstream +3 -0
- data/test/statements/from_seer_visits/crit_1 +10 -0
- data/test/statements/from_seer_visits/crit_2 +11 -0
- data/test/statements/from_seer_visits/crit_3 +11 -0
- data/test/statements/from_seer_visits/crit_4 +12 -0
- data/test/statements/gender/anno_has_upstreams +7 -0
- data/test/statements/gender/crit_male +4 -0
- data/test/statements/hcpcs/anno_bad_format +6 -0
- data/test/statements/hcpcs/crit_A0382 +4 -0
- data/test/statements/icd10/anno_bad_format +5 -0
- data/test/statements/icd10/anno_has_upstreams +7 -0
- data/test/statements/icd10/crit_1 +4 -0
- data/test/statements/icd10pcs/anno_bad_format +6 -0
- data/test/statements/icd10pcs/anno_has_upstreams +7 -0
- data/test/statements/icd10pcs/crit_1 +4 -0
- data/test/statements/icd9/anno_empty_label +7 -0
- data/test/statements/icd9/anno_invalid_code +4 -0
- data/test/statements/icd9/anno_valid_code +4 -0
- data/test/statements/icd9/crit_1 +4 -0
- data/test/statements/icd9_procedure/crit_1 +4 -0
- data/test/statements/intersect/anno_412_inpatient +11 -0
- data/test/statements/intersect/anno_has_arguments +4 -0
- data/test/statements/intersect/anno_no_upstream +3 -0
- data/test/statements/intersect/crit_412_inpatient +11 -0
- data/test/statements/intersect/crit_412_male +11 -0
- data/test/statements/intersect/crit_complex +19 -0
- data/test/statements/invalid/anno_bad_op +13 -0
- data/test/statements/invalid/scanno_1 +7 -0
- data/test/statements/last/crit_icd9 +7 -0
- data/test/statements/loinc/crit_basic +4 -0
- data/test/statements/ndc/crit_basic +4 -0
- data/test/statements/ndc/results_1 +4 -0
- data/test/statements/numeric/anno_multiple_upstreams +11 -0
- data/test/statements/numeric/num_values_1 +4 -0
- data/test/statements/numeric/num_values_2 +8 -0
- data/test/statements/numeric/num_values_3 +8 -0
- data/test/statements/observation_period/anno_has_arguments +8 -0
- data/test/statements/observation_period/anno_multiple_upstreams +11 -0
- data/test/statements/observation_period/count_all_periods +4 -0
- data/test/statements/observation_period/crit_female +7 -0
- data/test/statements/observation_period/crit_icd9 +7 -0
- data/test/statements/observation_period/crit_male +7 -0
- data/test/statements/occurrence/anno_no_upstream +3 -0
- data/test/statements/occurrence/count_412_410 +17 -0
- data/test/statements/occurrence/crit_1 +8 -0
- data/test/statements/occurrence/crit_2 +11 -0
- data/test/statements/occurrence/crit_3 +11 -0
- data/test/statements/one_in_two_out/anno_has_arguments +8 -0
- data/test/statements/one_in_two_out/anno_multiple_upstreams +15 -0
- data/test/statements/one_in_two_out/anno_no_upstream +7 -0
- data/test/statements/one_in_two_out/count_1 +10 -0
- data/test/statements/one_in_two_out/count_same_as_1 +11 -0
- data/test/statements/one_in_two_out/crit_hcpcs +10 -0
- data/test/statements/one_in_two_out/crit_icd9 +11 -0
- data/test/statements/one_in_two_out/results_1 +9 -0
- data/test/statements/one_in_two_out/results_2 +9 -0
- data/test/statements/overlapped_by/crit_1 +16 -0
- data/test/statements/overlapped_by/crit_2 +16 -0
- data/test/statements/overlapped_by/crit_3 +16 -0
- data/test/statements/overlapped_by/crit_4 +16 -0
- data/test/statements/overlaps/crit_1 +16 -0
- data/test/statements/overlaps/crit_2 +16 -0
- data/test/statements/overlaps/crit_3 +16 -0
- data/test/statements/overlaps/crit_4 +16 -0
- data/test/statements/person/anno_has_arguments +4 -0
- data/test/statements/person/anno_multiple_upstreams +11 -0
- data/test/statements/person/count_2 +3 -0
- data/test/statements/person/crit_1 +7 -0
- data/test/statements/person_filter/count_1 +20 -0
- data/test/statements/person_filter/crit_1 +20 -0
- data/test/statements/person_filter/crit_2 +13 -0
- data/test/statements/person_filter/crit_3 +13 -0
- data/test/statements/person_filter/crit_4 +13 -0
- data/test/statements/place_of_service_code/anno_has_upstreams +8 -0
- data/test/statements/place_of_service_code/anno_no_arguments +3 -0
- data/test/statements/place_of_service_code/crit_basic +4 -0
- data/test/statements/place_of_service_filter/anno_1 +8 -0
- data/test/statements/procedure_occurrence/anno_has_arguments +8 -0
- data/test/statements/procedure_occurrence/anno_multiple_upstreams +11 -0
- data/test/statements/procedure_occurrence/count_gender +7 -0
- data/test/statements/procedure_occurrence/count_icd9 +7 -0
- data/test/statements/procedure_occurrence/count_started_by +19 -0
- data/test/statements/provenance/anno_1 +8 -0
- data/test/statements/provenance/anno_bad_keyword +10 -0
- data/test/statements/provenance/count_1 +8 -0
- data/test/statements/provenance/count_2 +8 -0
- data/test/statements/provider_filter/anno_1 +10 -0
- data/test/statements/race/anno_1 +8 -0
- data/test/statements/race/anno_2 +3 -0
- data/test/statements/race/crit_1 +4 -0
- data/test/statements/read/anno_1 +4 -0
- data/test/statements/read/crit_1 +8 -0
- data/test/statements/recall/anno_1 +16 -0
- data/test/statements/recall/anno_2 +18 -0
- data/test/statements/recall/anno_3 +4 -0
- data/test/statements/recall/anno_4 +3 -0
- data/test/statements/recall/anno_5 +5 -0
- data/test/statements/recall/anno_6 +107 -0
- data/test/statements/recall/crit_1 +17 -0
- data/test/statements/recall/crit_2 +14 -0
- data/test/statements/recall/crit_3 +16 -0
- data/test/statements/recall/crit_cte_1 +17 -0
- data/test/statements/recall/crit_cte_2 +17 -0
- data/test/statements/recall/crit_nested_perm_0 +28 -0
- data/test/statements/revenue_code/crit_1 +4 -0
- data/test/statements/revenue_code/crit_basic +4 -0
- data/test/statements/revenue_code/domains_1 +4 -0
- data/test/statements/revenue_code/domains_drg100 +4 -0
- data/test/statements/rxnorm/crit_1 +4 -0
- data/test/statements/snomed/crit_1 +4 -0
- data/test/statements/started_by/crit_1 +16 -0
- data/test/statements/started_by/crit_2 +16 -0
- data/test/statements/started_by/crit_3 +16 -0
- data/test/statements/sum/anno_1 +3 -0
- data/test/statements/sum/anno_2 +8 -0
- data/test/statements/sum/num_1 +11 -0
- data/test/statements/sum/num_2 +15 -0
- data/test/statements/sum/num_3 +7 -0
- data/test/statements/time_window/anno_1 +7 -0
- data/test/statements/time_window/anno_2 +11 -0
- data/test/statements/time_window/anno_3 +11 -0
- data/test/statements/time_window/anno_4 +12 -0
- data/test/statements/time_window/anno_5 +15 -0
- data/test/statements/time_window/crit_1 +11 -0
- data/test/statements/time_window/crit_2 +11 -0
- data/test/statements/time_window/crit_3 +11 -0
- data/test/statements/time_window/crit_4 +11 -0
- data/test/statements/trim_date_end/crit_1 +16 -0
- data/test/statements/trim_date_end/crit_2 +16 -0
- data/test/statements/trim_date_end/crit_3 +16 -0
- data/test/statements/trim_date_end/crit_at_least +17 -0
- data/test/statements/trim_date_end/crit_occurrences_1 +17 -0
- data/test/statements/trim_date_end/crit_occurrences_2 +17 -0
- data/test/statements/trim_date_end/crit_within +17 -0
- data/test/statements/trim_date_start/crit_1 +16 -0
- data/test/statements/trim_date_start/crit_2 +16 -0
- data/test/statements/trim_date_start/crit_3 +16 -0
- data/test/statements/trim_date_start/crit_at_least +17 -0
- data/test/statements/trim_date_start/crit_occurrences_1 +17 -0
- data/test/statements/trim_date_start/crit_occurrences_2 +17 -0
- data/test/statements/trim_date_start/crit_within +17 -0
- data/test/statements/union/anno_1 +11 -0
- data/test/statements/union/anno_2 +18 -0
- data/test/statements/union/anno_3 +3 -0
- data/test/statements/union/anno_4 +4 -0
- data/test/statements/union/anno_5 +7 -0
- data/test/statements/union/anno_6 +10 -0
- data/test/statements/union/count_1 +11 -0
- data/test/statements/union/count_2 +11 -0
- data/test/statements/union/count_3 +15 -0
- data/test/statements/union/count_4 +18 -0
- data/test/statements/union/count_5 +18 -0
- data/test/statements/union/scanno_1 +3 -0
- data/test/statements/union/scanno_2 +18 -0
- data/test/statements/visit_occurrence/anno_1 +11 -0
- data/test/statements/visit_occurrence/anno_2 +8 -0
- data/test/statements/visit_occurrence/crit_1 +7 -0
- data/test/statements/visit_occurrence/crit_2 +7 -0
- data/test/statements/visit_occurrence/crit_3 +3 -0
- metadata +2016 -150
- data/lib/conceptql/behaviors/debuggable.rb +0 -70
- data/lib/conceptql/behaviors/dottable.rb +0 -103
- data/lib/conceptql/behaviors/preppable.rb +0 -20
- data/lib/conceptql/converter.rb +0 -65
- data/lib/conceptql/debugger.rb +0 -48
- data/lib/conceptql/fake_grapher.rb +0 -20
- data/lib/conceptql/graph.rb +0 -52
- data/lib/conceptql/graph_nodifier.rb +0 -203
- data/lib/conceptql/operators/concept.rb +0 -70
- data/lib/conceptql/operators/snomed_condition.rb +0 -26
- data/lib/conceptql/operators/visit.rb +0 -15
- data/lib/conceptql/tree.rb +0 -53
- data/lib/conceptql/utils/temp_table.rb +0 -72
- data/spec/conceptql/behaviors/dottable_spec.rb +0 -99
- data/spec/conceptql/converter_spec.rb +0 -51
- data/spec/conceptql/date_adjuster_spec.rb +0 -68
- data/spec/conceptql/operators/after_spec.rb +0 -16
- data/spec/conceptql/operators/before_spec.rb +0 -16
- data/spec/conceptql/operators/casting_operator_spec.rb +0 -68
- data/spec/conceptql/operators/complement_spec.rb +0 -15
- data/spec/conceptql/operators/concept_spec.rb +0 -40
- data/spec/conceptql/operators/condition_type_spec.rb +0 -128
- data/spec/conceptql/operators/contains_spec.rb +0 -19
- data/spec/conceptql/operators/cpt_spec.rb +0 -29
- data/spec/conceptql/operators/date_range_spec.rb +0 -33
- data/spec/conceptql/operators/death_spec.rb +0 -10
- data/spec/conceptql/operators/during_spec.rb +0 -30
- data/spec/conceptql/operators/except_spec.rb +0 -15
- data/spec/conceptql/operators/first_spec.rb +0 -35
- data/spec/conceptql/operators/from_spec.rb +0 -13
- data/spec/conceptql/operators/gender_spec.rb +0 -27
- data/spec/conceptql/operators/hcpcs_spec.rb +0 -29
- data/spec/conceptql/operators/icd10_spec.rb +0 -34
- data/spec/conceptql/operators/icd9_procedure_spec.rb +0 -29
- data/spec/conceptql/operators/icd9_spec.rb +0 -34
- data/spec/conceptql/operators/intersect_spec.rb +0 -28
- data/spec/conceptql/operators/last_spec.rb +0 -36
- data/spec/conceptql/operators/loinc_spec.rb +0 -29
- data/spec/conceptql/operators/medcode_procedure_spec.rb +0 -34
- data/spec/conceptql/operators/medcode_spec.rb +0 -34
- data/spec/conceptql/operators/observation_period_spec.rb +0 -10
- data/spec/conceptql/operators/occurrence_spec.rb +0 -87
- data/spec/conceptql/operators/overlapped_by_spec.rb +0 -32
- data/spec/conceptql/operators/overlaps_spec.rb +0 -21
- data/spec/conceptql/operators/person_filter_spec.rb +0 -15
- data/spec/conceptql/operators/person_spec.rb +0 -10
- data/spec/conceptql/operators/place_of_service_code_spec.rb +0 -24
- data/spec/conceptql/operators/procedure_occurrence_spec.rb +0 -10
- data/spec/conceptql/operators/prodcode_spec.rb +0 -35
- data/spec/conceptql/operators/query_double.rb +0 -20
- data/spec/conceptql/operators/query_double_spec.rb +0 -7
- data/spec/conceptql/operators/race_spec.rb +0 -21
- data/spec/conceptql/operators/rxnorm_spec.rb +0 -29
- data/spec/conceptql/operators/snomed_spec.rb +0 -29
- data/spec/conceptql/operators/source_vocabulary_operator_spec.rb +0 -35
- data/spec/conceptql/operators/standard_vocabulary_operator_spec.rb +0 -35
- data/spec/conceptql/operators/started_by_spec.rb +0 -22
- data/spec/conceptql/operators/temporal_operator_spec.rb +0 -51
- data/spec/conceptql/operators/time_window_spec.rb +0 -77
- data/spec/conceptql/operators/union_spec.rb +0 -21
- data/spec/conceptql/operators/visit_occurrence_spec.rb +0 -10
- data/spec/conceptql/query_spec.rb +0 -22
- data/spec/conceptql/tree_spec.rb +0 -50
- data/spec/doubles/stream_for_casting_double.rb +0 -9
- data/spec/doubles/stream_for_occurrence_double.rb +0 -25
- data/spec/doubles/stream_for_temporal_double.rb +0 -6
- data/spec/spec_helper.rb +0 -102
data/doc/converter.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../lib/conceptql'
|
2
|
+
require 'pp'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
$converter = ConceptQL::Converter.new
|
6
|
+
def my_pp(obj)
|
7
|
+
#PP.pp(obj, ''.dup, 10)
|
8
|
+
JSON.pretty_generate(obj)
|
9
|
+
end
|
10
|
+
|
11
|
+
def convert(cql)
|
12
|
+
header = []
|
13
|
+
header << cql.shift while cql.first =~ /^[`#]/
|
14
|
+
footer = [cql.pop]
|
15
|
+
if cql.first =~ /^\[/
|
16
|
+
cql = my_pp(eval(cql.join))
|
17
|
+
else
|
18
|
+
cql = my_pp($converter.convert(eval(cql.join)))
|
19
|
+
end
|
20
|
+
[header, cql, "\n", footer].flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
lines = File.readlines('doc/spec.md')
|
24
|
+
chunks = lines.slice_before { |l| l =~ /```ConceptQL/ }.to_a
|
25
|
+
outputs = []
|
26
|
+
outputs << chunks.shift unless chunks.first =~ /```ConceptQL/
|
27
|
+
puts chunks.count
|
28
|
+
outputs += chunks.map do |chunk|
|
29
|
+
cql, *remainder = chunk.slice_after { |l| l =~ /^```\n$/ }.to_a
|
30
|
+
cql = convert(cql)
|
31
|
+
[cql, remainder].flatten#.tap { |arr| pp arr; gets }
|
32
|
+
end.flatten
|
33
|
+
File.write('/tmp/test.md', outputs.join)
|
data/doc/metadata.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# A Bit About Metadata
|
2
|
+
|
3
|
+
`ConceptQL.metadata` produces a hash containing all relevant metadata about ConceptQL, specifically which categories and operators are available in ConceptQL.
|
4
|
+
|
5
|
+
The hash contains two keys: "categories" and "operators".
|
6
|
+
|
7
|
+
## Metadata about Categories
|
8
|
+
|
9
|
+
The value of the "categories" hash is an array of hashes representing each available category in ConceptQL. Each hash has two key/value pairs:
|
10
|
+
|
11
|
+
- name
|
12
|
+
- The category's name
|
13
|
+
- priority
|
14
|
+
- The position the category should have if you were to list the categories in order
|
15
|
+
|
16
|
+
## Metadata about Operators
|
17
|
+
|
18
|
+
Each operator in ConceptQL is listed in the metadata.json file under the "operators" key.
|
19
|
+
|
20
|
+
The operator metadata is a hash where the key is the name of an operator and the hash is the metadata specific to that operator.
|
21
|
+
|
22
|
+
The metadata for each operator should be complete enough that a UI can understand all of the parameters and constraints specific to that operator and render it accordingly. Essentially, the metadata should be complete enough that entirely new operators can appear in the metadata and the UI should be able to render that operator and its parameters without needing to change anything in the code for the UI.
|
23
|
+
|
24
|
+
### Operator Metadata Outline
|
25
|
+
|
26
|
+
- min_upstreams
|
27
|
+
- 0 or 1
|
28
|
+
- 0 means this operator does not need inputs from an upstream operator
|
29
|
+
- 1 means this operator needs input from at least one upstream operator
|
30
|
+
- max_upstreams
|
31
|
+
- 0, 1, or 99
|
32
|
+
- 0 means this operator does not take input from an upstream operator
|
33
|
+
- 1 means this operator takes input from up to one upstream operator
|
34
|
+
- 99 means this operator takes input from unlimited upstream operators
|
35
|
+
- preferred_name
|
36
|
+
- If this option is present, this is the name of the operator to display in the UI
|
37
|
+
- If this option is missing, run the name of the operator through the equivalent of ActiveSupport#humanize
|
38
|
+
- operation
|
39
|
+
- The name of the operation
|
40
|
+
- This is the name to use when translating the structure in the UI into a ConceptQL statement
|
41
|
+
- options
|
42
|
+
- A hash of the parameters that an operation expects
|
43
|
+
- Key is the name of the parameters (run through ActiveSupport#humanize to get the name to display in the UI)
|
44
|
+
- Value is a hash described in Option Metadata Outline below
|
45
|
+
- categories
|
46
|
+
- An array of arrays representing the categories this operator is assigned to
|
47
|
+
- Each sub-array represents a path of categories and sub-categories that the operator is assigned to
|
48
|
+
- At the moment, all sub-arrays are single element arrays and no sub-categories are used
|
49
|
+
- So, it's safe to flatten the array of arrays and assign an operator to each of the categories in the flattened array
|
50
|
+
- **If an operator has no categories assigned, it should NOT appear in the UI**
|
51
|
+
- arguments
|
52
|
+
- Similar to options
|
53
|
+
- When the UI generates the corresponding ConceptQL, values assigned to arguments should be listed as elements 1 thru XX in the array that represents the current operator
|
54
|
+
- desc
|
55
|
+
- Description of the operator, to be displayed when the user is interacting with that operator
|
56
|
+
- predominant_domains
|
57
|
+
- A list of one or more domains that the operator is known to represent
|
58
|
+
- This should be used as a means to declare what domain color(s) to use to represent the operator and how many lines the operator should generate
|
59
|
+
- This option should only appear in selection operators and casting operators
|
60
|
+
- basic_type
|
61
|
+
- I don't know what this does but it seemed like information needed for Envy's JAM
|
62
|
+
|
63
|
+
### Option Metadata Outline
|
64
|
+
|
65
|
+
- type
|
66
|
+
- Dictates what type of input the operator expects for this parameter
|
67
|
+
- Can be one of the following types:
|
68
|
+
- string
|
69
|
+
- A string of text
|
70
|
+
- integer
|
71
|
+
- A whole number, positive or negative
|
72
|
+
- boolean
|
73
|
+
- Either true or false
|
74
|
+
- Can be respresented by a checkbox or similar, toggleable UI item
|
75
|
+
- codelist
|
76
|
+
- Eventually the UI should provide a sophisticated means of selecting codes from a specific terminology (specified by the vocab option)
|
77
|
+
- For now, expect a comma delimited list of codes in a textarea
|
78
|
+
- upstream
|
79
|
+
- Indicates that we need input from an upstream operator
|
80
|
+
- vocab
|
81
|
+
- Specifies which terminology to use when presenting a list of codes to select from
|
82
|
+
- Should only be used when type is codelist
|
83
|
+
- options
|
84
|
+
- An array representing an enumeration of all possible values that can be used for this option/argument
|
85
|
+
- The UI should present only these options for a user to choose and disallow any other input from the user
|
86
|
+
- default
|
87
|
+
- The default value for this parameter
|
88
|
+
- required
|
89
|
+
- True if this parameter must have a value
|
data/doc/spec.md
CHANGED
@@ -3,12 +3,13 @@
|
|
3
3
|
ConceptQL (pronounced concept-Q-L) is a high-level language that allows researchers to unambiguously define their research algorithms.
|
4
4
|
|
5
5
|
## Motivation for ConceptQL
|
6
|
+
|
6
7
|
Outcomes Insights intends to build a vast library of research algorithms and apply those algorithms to large databases of claims data. Early into building the library, we realized we had to overcome two major issues:
|
7
8
|
|
8
9
|
1. Methods sections of research papers commonly use natural language to specify the criteria used to build cohorts from a claims database.
|
9
10
|
- Algorithms defined in natural language are often imprecise, open to multiple interpretations, and generally difficult to reproduce.
|
10
11
|
- Researchers could benefit from a language that removes the ambiguity of natural language while increasing the reproducibility of their research algorithms.
|
11
|
-
|
12
|
+
1. Querying against claims databases is often difficult.
|
12
13
|
- Hand-coding algorithms to extract cohorts from datasets is time-consuming, error-prone, and opaque.
|
13
14
|
- Researchers could benefit from a language that allows algorithms to be defined at a high-level and then gets translated into the appropriate queries against a database.
|
14
15
|
|
@@ -17,16 +18,38 @@ We developed ConceptQL to address these two issues.
|
|
17
18
|
We are writing a tool that can read research algorithms defined in ConceptQL. The tool can create a diagram for the algorithm which makes it easy to visualize and understand. The tool can also translate the algorithm into a SQL query which runs against data structured in [OMOP's Common Data Model (CDM)](http://omop.org/CDM). The purpose of the CDM is to standardize the format and content of observational data, so standardized applications, tools and methods can be applied to them.
|
18
19
|
|
19
20
|
For instance, using ConceptQL we can take a statement that looks like this:
|
21
|
+
|
20
22
|
```YAML
|
21
23
|
:icd9: '412'
|
22
24
|
```
|
23
25
|
|
24
26
|
And generate a diagram that looks like this:
|
25
|
-
|
26
|
-
|
27
|
+
|
28
|
+
|
29
|
+
```YAML
|
30
|
+
---
|
31
|
+
- icd9
|
32
|
+
- '412'
|
33
|
+
|
27
34
|
```
|
28
35
|
|
36
|
+
![](spec/f6b4fc31703cfb6327bbbd4614af8bb72da6d39fa3d53ada63a70157f2fad80e.png)
|
37
|
+
|
38
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
39
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
40
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
41
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
42
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
43
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
44
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
45
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
46
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
47
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
48
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
49
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
50
|
+
|
29
51
|
And generate SQL that looks like this:
|
52
|
+
|
30
53
|
```SQL
|
31
54
|
SELECT *
|
32
55
|
FROM cdm_data.condition_occurrence AS co
|
@@ -36,10 +59,10 @@ AND scm.source_vocabulary_id = 2
|
|
36
59
|
AND scm.source_code = co.condition_source_value
|
37
60
|
```
|
38
61
|
|
39
|
-
As stated above, one of the goals of
|
40
|
-
|
62
|
+
As stated above, one of the goals of ConceptQL is to make it easy to assemble fairly complex queries without having to roll up our sleeves and write raw SQL. To accommodate this complexity, ConceptQL itself has some complexities of its own. That said, we believe ConceptQL will help researchers define, hone, and share their research algorithms.
|
41
63
|
|
42
64
|
## ConceptQL Overview
|
65
|
+
|
43
66
|
### What ConceptQL Looks Like
|
44
67
|
|
45
68
|
I find seeing examples to be the quickest way to get a sense of a language. Here is a trivial example to whet your appetite. The example is in YAML, but could just as easily be in JSON or any other markup language capable of representing nested sets of heterogeneous arrays and hashes. In fact, the ConceptQL "language" is a just set of nested hashes and arrays representing search criteria and some set operations and temporal operations to glue those criteria together.
|
@@ -47,43 +70,77 @@ I find seeing examples to be the quickest way to get a sense of a language. Her
|
|
47
70
|
```YAML
|
48
71
|
# Example 1: A simple example in YAML
|
49
72
|
# This is just a simple hash with a key of :icd9 and a value of 412
|
50
|
-
# This example will search the condition_occurrence table for all conditions that match the ICD-9
|
73
|
+
# This example will search the condition_occurrence table for all conditions that match the ICD-9 code 412.
|
51
74
|
---
|
52
75
|
:icd9: '412'
|
53
76
|
```
|
54
77
|
|
55
78
|
### ConceptQL Diagrams
|
79
|
+
|
56
80
|
Reading ConceptQL in YAML or JSON seems hard to me. I prefer to explore ConceptQL using directed graphs. For instance, the diagram for the simple example listed in YAML above is:
|
57
|
-
|
58
|
-
|
59
|
-
|
81
|
+
|
82
|
+
|
83
|
+
```YAML
|
84
|
+
---
|
85
|
+
- icd9
|
86
|
+
- '412'
|
87
|
+
|
60
88
|
```
|
61
89
|
|
90
|
+
![](spec/f6b4fc31703cfb6327bbbd4614af8bb72da6d39fa3d53ada63a70157f2fad80e.png)
|
91
|
+
|
92
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
93
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
94
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
95
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
96
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
97
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
98
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
99
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
100
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
101
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
102
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
103
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
104
|
+
|
105
|
+
Each oval depicts a "operator", or rather, a ConceptQL expression. An arrow between a pair of operators indicates that the results from the operator on the tail of the arrow pass on to the operator at the head of the arrow. A simple example should help here:
|
106
|
+
|
107
|
+
|
108
|
+
```YAML
|
109
|
+
---
|
110
|
+
- first
|
111
|
+
- - cpt
|
112
|
+
- '99214'
|
62
113
|
|
63
|
-
Each oval depicts a "node", or rather, a ConceptQL expression. An arrow between a pair of nodes indicates that the results from the node on the tail of the arrow pass on to the node at the head of the arrow. A simple example should help here:
|
64
|
-
```ConceptQL
|
65
|
-
# First Office Visit Per Patient
|
66
|
-
{
|
67
|
-
first: {
|
68
|
-
cpt: '99214'
|
69
|
-
}
|
70
|
-
}
|
71
114
|
```
|
72
115
|
|
116
|
+
![](spec/39d6a8eb71cae51b1d6937c97134e51f04fd47c54535ff0915fe6a8b4f197fb2.png)
|
73
117
|
|
74
|
-
|
118
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
119
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
120
|
+
| 2 | 48 | procedure_occurrence | 2009-07-03 | 2009-07-03 | 99214 |
|
121
|
+
| 5 | 118 | procedure_occurrence | 2008-12-14 | 2008-12-14 | 99214 |
|
122
|
+
| 6 | 167 | procedure_occurrence | 2009-09-12 | 2009-09-12 | 99214 |
|
123
|
+
| 7 | 376 | procedure_occurrence | 2008-08-13 | 2008-08-13 | 99214 |
|
124
|
+
| 8 | 609 | procedure_occurrence | 2008-02-27 | 2008-02-27 | 99214 |
|
125
|
+
| 9 | 652 | procedure_occurrence | 2009-09-11 | 2009-09-11 | 99214 |
|
126
|
+
| 10 | 681 | procedure_occurrence | 2009-05-09 | 2009-05-09 | 99214 |
|
127
|
+
| 11 | 758 | procedure_occurrence | 2008-06-17 | 2008-06-17 | 99214 |
|
128
|
+
| 12 | 847 | procedure_occurrence | 2008-02-11 | 2008-02-11 | 99214 |
|
129
|
+
| 13 | 1102 | procedure_occurrence | 2008-01-24 | 2008-01-24 | 99214 |
|
75
130
|
|
76
|
-
|
131
|
+
The diagram above reads "get all procedures that match the CPT 99214 (Office Visit) and then filter them down to the first occurrence for each person". The diagram is much more terse than that and to accurately read the diagram, you need a lot of implicit knowledge about how each operator operates. Fortunately, this document will (hopefully) impart that knowledge to you.
|
77
132
|
|
133
|
+
Please note that all of my diagrams end with an arrow pointing at nothing. You'll see why soon.
|
78
134
|
|
79
135
|
### Think of Results as a Stream
|
80
|
-
I draw my ConceptQL diagrams with leaf nodes at the top and the "trunk" nodes at the bottom. I like to think of the results of a ConceptQL statement as a flowing stream of data. The leaf nodes, or nodes that gather results out of the database, act like tributaries. The results flow downwards and either join with other results, or filter out other results until the streams emerge at the bottom of the diagram. Think of each arrow as a stream of results, flowing down through one node to the next.
|
81
136
|
|
82
|
-
|
137
|
+
I draw my ConceptQL diagrams with leaf operators at the top and the "trunk" operators at the bottom. I like to think of the results of a ConceptQL statement as a flowing stream of data. The leaf operators, or operators that gather results out of the database, act like tributaries. The results flow downwards and either join with other results, or filter out other results until the streams emerge at the bottom of the diagram. Think of each arrow as a stream of results, flowing down through one operator to the next.
|
83
138
|
|
139
|
+
The trailing arrow in the diagrams serves as a reminder that ConceptQL yields a stream of results.
|
84
140
|
|
85
141
|
### Streams have Types
|
86
|
-
|
142
|
+
|
143
|
+
You might have noticed that the operators and edges in the diagrams often have a color. That color represents what "type" of stream the operator or edge represents. There are many types in ConceptQL, and you'll notice they are __strongly__ correlated with the tables found in [CDM v4.0](http://omop.org/CDM):
|
87
144
|
|
88
145
|
- condition_occurrence
|
89
146
|
- red
|
@@ -106,28 +163,66 @@ You might have noticed that the nodes and edges in the diagrams often have a col
|
|
106
163
|
- visit_occurrence
|
107
164
|
- orange
|
108
165
|
|
109
|
-
Each stream has a point of origin (essentially, the table from which we pulled the results for a stream). Based on that origin, each stream will have a particular type. The stream carries this type information as it moves through each
|
166
|
+
Each stream has a point of origin (essentially, the table from which we pulled the results for a stream). Based on that origin, each stream will have a particular type. The stream carries this type information as it moves through each operator. When certain operators, particularly set and temporal operators, need to perform filtering, they can use this type information to determine how to best filter a stream. There will be much more discussion about types woven throughout this document. For now, it is sufficient to know that each stream has a type.
|
110
167
|
|
111
168
|
You'll also notice that the trailing arrow(s) at the end of the diagrams indicate which types of streams are ultimately passed on at the end of a ConceptQL statement.
|
112
169
|
|
113
|
-
|
114
170
|
### What *are* Streams Really?
|
171
|
+
|
115
172
|
Though I think that a "stream" is a helpful abstraction when thinking in ConceptQL, on a few occasions we need to know what's going on under the hood.
|
116
173
|
|
117
174
|
Every table in the CDM structure has a surrogate key column (an ID column). When we execute a ConceptQL statement, the "streams" that are generated by the statement are just sets of these IDs for rows that matched the ConceptQL criteria. So each stream is just a set of IDs that point back to some rows in one of the CDM tables. When a stream has a "type" it is really just that the stream contains IDs associated with its table of origin.
|
118
175
|
|
119
176
|
So when we execute this ConceptQL statement, the resulting "stream" is all the person IDs for all male patients in the database:
|
120
|
-
|
121
|
-
|
122
|
-
|
177
|
+
|
178
|
+
|
179
|
+
```YAML
|
180
|
+
---
|
181
|
+
- gender
|
182
|
+
- Male
|
183
|
+
|
123
184
|
```
|
124
185
|
|
186
|
+
![](spec/c82077b9455d0f9abc2c45ee1a298e38b99c9ce9cd685f65d87b376d7718d7ad.png)
|
187
|
+
|
188
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
189
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
190
|
+
| 1 | 1 | person | 1923-05-01 | 1923-05-01 | 00013D2EFD8E45D1 |
|
191
|
+
| 2 | 2 | person | 1943-01-01 | 1943-01-01 | 00016F745862898F |
|
192
|
+
| 4 | 4 | person | 1941-06-01 | 1941-06-01 | 00021CA6FF03E670 |
|
193
|
+
| 5 | 5 | person | 1936-08-01 | 1936-08-01 | 00024B3D2352D2D0 |
|
194
|
+
| 6 | 6 | person | 1943-10-01 | 1943-10-01 | 0002DAE1C81CC70D |
|
195
|
+
| 7 | 7 | person | 1922-07-01 | 1922-07-01 | 0002F28CE057345B |
|
196
|
+
| 8 | 8 | person | 1935-09-01 | 1935-09-01 | 000308435E3E5B76 |
|
197
|
+
| 12 | 12 | person | 1929-06-01 | 1929-06-01 | 00048EF1F4791C68 |
|
198
|
+
| 14 | 14 | person | 1934-05-01 | 1934-05-01 | 00052705243EA128 |
|
199
|
+
| 16 | 16 | person | 1934-01-01 | 1934-01-01 | 0007E57CC13CE880 |
|
200
|
+
|
125
201
|
When we execute this ConceptQL statement, the resulting "stream" is all condition_occurrence IDs that match ICD-9 799.22:
|
126
|
-
|
127
|
-
|
128
|
-
|
202
|
+
|
203
|
+
|
204
|
+
```YAML
|
205
|
+
---
|
206
|
+
- icd9
|
207
|
+
- '799.22'
|
208
|
+
|
129
209
|
```
|
130
210
|
|
211
|
+
![](spec/05f9b844571ffceeed2def3025fb60c68552817b8b73d3c8a76939dbc08b7c65.png)
|
212
|
+
|
213
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
214
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
215
|
+
| 273 | 33363 | condition_occurrence | 2010-06-17 | 2010-06-17 | 799.22 |
|
216
|
+
| 440 | 51450 | condition_occurrence | 2009-01-12 | 2009-01-12 | 799.22 |
|
217
|
+
| 1783 | 206904 | condition_occurrence | 2008-03-08 | 2008-03-08 | 799.22 |
|
218
|
+
| 1830 | 211909 | condition_occurrence | 2010-06-24 | 2010-06-24 | 799.22 |
|
219
|
+
| 2086 | 238625 | condition_occurrence | 2008-05-24 | 2008-05-24 | 799.22 |
|
220
|
+
| 2272 | 260093 | condition_occurrence | 2009-09-19 | 2009-09-19 | 799.22 |
|
221
|
+
| 2525 | 288414 | condition_occurrence | 2009-04-17 | 2009-04-17 | 799.22 |
|
222
|
+
| 2772 | 317847 | condition_occurrence | 2009-09-08 | 2009-09-08 | 799.22 |
|
223
|
+
| 2924 | 334949 | condition_occurrence | 2009-01-24 | 2009-01-24 | 799.22 |
|
224
|
+
| 4072 | 473603 | condition_occurrence | 2008-05-15 | 2008-05-15 | 799.22 |
|
225
|
+
|
131
226
|
Generally, I find it helpful to just think of those queries generating a "stream of people" or a "stream of conditions" and not worry about the table of origin or the fact that they are just IDs.
|
132
227
|
|
133
228
|
When a ConceptQL statement is executed, it yields a final set of streams that are just all the IDs that passed through all the criteria. What is done with that set of IDs is up to the user who assembled the ConceptQL statement. If a user gathers all 799.22 Conditions, they will end up with a set of condition_occurrence_ids. They could take those IDs and do all sorts of things like:
|
@@ -139,274 +234,499 @@ When a ConceptQL statement is executed, it yields a final set of streams that ar
|
|
139
234
|
|
140
235
|
This kind of aggregation and analysis is beyond the scope of ConceptQL. ConceptQL will get you the IDs of the rows you're interested in, its up to other parts of the calling system to determine what you do with them.
|
141
236
|
|
142
|
-
##
|
237
|
+
## Selection Operators
|
143
238
|
|
144
|
-
|
239
|
+
Selection operators are the parts of a ConceptQL query that search for specific values within the CDM data, e.g. searching the condition_occurrence table for a diagnosis of an old myocardial infarction (ICD-9 412) is a selection. Selection operators are always leaf operators.
|
145
240
|
|
146
|
-
There are _many_
|
241
|
+
There are _many_ selection operators. A list of currently implemented operators is available in Appendix A.
|
147
242
|
|
148
|
-
## All Other
|
243
|
+
## All Other Operators i.e. Mutation Operators
|
149
244
|
|
150
|
-
Virtually all other
|
245
|
+
Virtually all other operators add, remove, filter, or otherwise alter streams of results. They are discussed in this section.
|
151
246
|
|
152
|
-
## Set
|
153
|
-
|
247
|
+
## Set Operators
|
248
|
+
|
249
|
+
Because streams represent sets of results, its makes sense to include a operators that operate on sets
|
154
250
|
|
155
251
|
### Union
|
156
|
-
|
252
|
+
|
253
|
+
- Takes any number of upstream operators and aggregates their streams
|
157
254
|
- Unions together streams with identical types
|
158
255
|
- Think of streams with the same type flowing together into a single stream
|
159
256
|
- We're really just gathering the union of all IDs for identically-typed streams
|
160
257
|
- Streams with the different types flow along together concurrently without interacting
|
161
258
|
- It does not make sense to union, say, condition_occurrence_ids with visit_occurrence_ids, so streams with different types won't mingle together, but will continue to flow downstream in parallel
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
# Two streams of the same type (condition_occurrence) joined into a single stream, then a different stream (visit_occurrence) flows concurrently
|
173
|
-
{
|
174
|
-
union: [
|
175
|
-
{union: [
|
176
|
-
{ icd9: '412' },
|
177
|
-
{ icd9: '799.22' }
|
178
|
-
]},
|
179
|
-
{ place_of_service: 'Inpatient' }
|
180
|
-
]
|
181
|
-
}
|
182
|
-
```
|
183
|
-
```ConceptQL
|
184
|
-
# Two streams of the same type (condition_occurrence) joined into a single stream, along with a different stream (visit_occurrence) flows concurrently (same as above example)
|
185
|
-
{
|
186
|
-
union: [
|
187
|
-
{ icd9: '412' },
|
188
|
-
{ icd9: '799.22' },
|
189
|
-
{ place_of_service: 'Inpatient' }
|
190
|
-
]
|
191
|
-
}
|
259
|
+
|
260
|
+
|
261
|
+
```YAML
|
262
|
+
---
|
263
|
+
- union
|
264
|
+
- - icd9
|
265
|
+
- '412'
|
266
|
+
- - icd9
|
267
|
+
- '799.22'
|
268
|
+
|
192
269
|
```
|
193
270
|
|
271
|
+
![](spec/ea935ac31f3b57ff373646780a1fba34a38c9e086dc771eb7fc16c65a7e20cfc.png)
|
272
|
+
|
273
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
274
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
275
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
276
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
277
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
278
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
279
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
280
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
281
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
282
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
283
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
284
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
285
|
+
|
286
|
+
|
287
|
+
```YAML
|
288
|
+
---
|
289
|
+
- union
|
290
|
+
- - union
|
291
|
+
- - icd9
|
292
|
+
- '412'
|
293
|
+
- - icd9
|
294
|
+
- '799.22'
|
295
|
+
- - place_of_service_code
|
296
|
+
- '21'
|
297
|
+
|
298
|
+
```
|
299
|
+
|
300
|
+
![](spec/f766f2e3aa13420e3ba0f823ac7956b311ed7c6c20be26b72324fadd87f36712.png)
|
301
|
+
|
302
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
303
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
304
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
305
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
306
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
307
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
308
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
309
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
310
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
311
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
312
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
313
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
314
|
+
|
315
|
+
|
316
|
+
```YAML
|
317
|
+
---
|
318
|
+
- union
|
319
|
+
- - icd9
|
320
|
+
- '412'
|
321
|
+
- - icd9
|
322
|
+
- '799.22'
|
323
|
+
- - place_of_service_code
|
324
|
+
- '21'
|
325
|
+
|
326
|
+
```
|
327
|
+
|
328
|
+
![](spec/a79274742cf6fac6f6c9f4a0eb651aeb452f9c43b537c8e6ccaefecd05b7105c.png)
|
329
|
+
|
330
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
331
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
332
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
333
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
334
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
335
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
336
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
337
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
338
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
339
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
340
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
341
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
342
|
+
|
194
343
|
### Intersect
|
344
|
+
|
195
345
|
1. Group incoming streams by type
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# Yields two streams: a stream of all MI Conditions and a stream of all Male patients. This is essentially the same behavior as Union in this case
|
211
|
-
{
|
212
|
-
intersect: [
|
213
|
-
{ icd9: '412' },
|
214
|
-
{ gender: 'Male' }
|
215
|
-
]
|
216
|
-
}
|
217
|
-
```
|
218
|
-
```ConceptQL
|
219
|
-
# Yields two streams: a stream of all Conditions where MI was Primary Diagnosis and a stream of all White, Male patients.
|
220
|
-
{
|
221
|
-
intersect: [
|
222
|
-
{ icd9: '412' },
|
223
|
-
{ primary_diagnosis: true },
|
224
|
-
{ gender: 'Male' },
|
225
|
-
{ race: 'White' }
|
226
|
-
]
|
227
|
-
}
|
346
|
+
1. For each group of same-type streams
|
347
|
+
a. Intersect all streams, yielding a single stream that contains only those IDs common to those streams
|
348
|
+
1. A single stream for each incoming type is sent downstream
|
349
|
+
a. If only a single stream of a type is upstream, that stream is essentially unaltered as it is passed downstream
|
350
|
+
|
351
|
+
|
352
|
+
```YAML
|
353
|
+
---
|
354
|
+
- intersect
|
355
|
+
- - icd9
|
356
|
+
- '412'
|
357
|
+
- - primary_diagnosis
|
358
|
+
- true
|
359
|
+
|
228
360
|
```
|
229
361
|
|
362
|
+
![](spec/af5ae3787e80bf0771f18f1a04fe4c5d9291e1e0f963ac408a7bc198d2f1ee28.png)
|
363
|
+
|
364
|
+
```No Results. Statement is experimental.```
|
365
|
+
|
366
|
+
|
367
|
+
```YAML
|
368
|
+
---
|
369
|
+
- intersect
|
370
|
+
- - icd9
|
371
|
+
- '412'
|
372
|
+
- - gender
|
373
|
+
- Male
|
374
|
+
|
375
|
+
```
|
376
|
+
|
377
|
+
![](spec/514f263e976d07c0d9e0a86c79bcbdcddc7d444d7b72135294ad78758effd28f.png)
|
378
|
+
|
379
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
380
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
381
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
382
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
383
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
384
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
385
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
386
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
387
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
388
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
389
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
390
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
391
|
+
|
392
|
+
|
393
|
+
```YAML
|
394
|
+
---
|
395
|
+
- intersect
|
396
|
+
- - icd9
|
397
|
+
- '412'
|
398
|
+
- - primary_diagnosis
|
399
|
+
- true
|
400
|
+
- - gender
|
401
|
+
- Male
|
402
|
+
- - race
|
403
|
+
- White
|
404
|
+
|
405
|
+
```
|
406
|
+
|
407
|
+
![](spec/11f57941951bad5a75f9a16f38a31a3c6bf3046a475aac6e398e780892fab4ad.png)
|
408
|
+
|
409
|
+
```No Results. Statement is experimental.```
|
410
|
+
|
230
411
|
### Complement
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
412
|
+
|
413
|
+
This operator will take the complement of each set of IDs in the incoming streams.
|
414
|
+
|
415
|
+
|
416
|
+
```YAML
|
417
|
+
---
|
418
|
+
- complement
|
419
|
+
- - icd9
|
420
|
+
- '412'
|
421
|
+
|
237
422
|
```
|
238
423
|
|
424
|
+
![](spec/c2157d8a6b73abe4f22ba5042159f32502c74bf6d762be28d2df6831586822c7.png)
|
425
|
+
|
426
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
427
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
428
|
+
| 1 | 1 | condition_occurrence | 2010-03-12 | 2010-03-13 | 780.2 |
|
429
|
+
| 1 | 2 | condition_occurrence | 2010-03-12 | 2010-03-13 | 788.20 |
|
430
|
+
| 1 | 3 | condition_occurrence | 2010-03-12 | 2010-03-13 | V45.01 |
|
431
|
+
| 1 | 4 | condition_occurrence | 2010-03-12 | 2010-03-13 | 428.0 |
|
432
|
+
| 1 | 5 | condition_occurrence | 2010-03-12 | 2010-03-13 | 272.0 |
|
433
|
+
| 1 | 6 | condition_occurrence | 2010-03-12 | 2010-03-13 | 401.9 |
|
434
|
+
| 1 | 7 | condition_occurrence | 2010-03-12 | 2010-03-13 | V45.02 |
|
435
|
+
| 1 | 8 | condition_occurrence | 2010-03-12 | 2010-03-13 | 733.00 |
|
436
|
+
| 1 | 9 | condition_occurrence | 2010-03-12 | 2010-03-13 | E933.0 |
|
437
|
+
| 1 | 10 | condition_occurrence | 2008-09-04 | 2008-09-04 | V58.41 |
|
438
|
+
|
239
439
|
If you're familiar with set operations, the complement of a union is the intersect of the complements of the items unioned. So in our world, these next two examples are identical:
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
```ConceptQL
|
252
|
-
# All Conditions where the Condition isn't an MI as the Primary Diagnosis (same as above)
|
253
|
-
{
|
254
|
-
intersect: [
|
255
|
-
{ complement: { icd9: '412' } },
|
256
|
-
{ complement: { primary_diagnosis: true } }
|
257
|
-
]
|
258
|
-
}
|
440
|
+
|
441
|
+
|
442
|
+
```YAML
|
443
|
+
---
|
444
|
+
- complement
|
445
|
+
- - union
|
446
|
+
- - icd9
|
447
|
+
- '412'
|
448
|
+
- - primary_diagnosis
|
449
|
+
- true
|
450
|
+
|
259
451
|
```
|
260
452
|
|
453
|
+
![](spec/02f44ad35d266ddd0a4df1691d26bf4a297b30604fc3f44b0391d6d852d23a9f.png)
|
454
|
+
|
455
|
+
```No Results. Statement is experimental.```
|
456
|
+
|
457
|
+
|
458
|
+
```YAML
|
459
|
+
---
|
460
|
+
- intersect
|
461
|
+
- - complement
|
462
|
+
- - icd9
|
463
|
+
- '412'
|
464
|
+
- - complement
|
465
|
+
- - primary_diagnosis
|
466
|
+
- true
|
467
|
+
|
468
|
+
```
|
469
|
+
|
470
|
+
![](spec/a4450e8c0fe0e2fde92fe9bd61952f907b1976c1aa3ba963b809bed079d42b09.png)
|
471
|
+
|
472
|
+
```No Results. Statement is experimental.```
|
473
|
+
|
261
474
|
But please be aware that this behavior of complement only affects streams of the same type. If more than one stream is involved, you need to evaluate the effects of complement on a stream-by-stream basis:
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
475
|
+
|
476
|
+
|
477
|
+
```YAML
|
478
|
+
---
|
479
|
+
- complement
|
480
|
+
- - union
|
481
|
+
- - icd9
|
482
|
+
- '412'
|
483
|
+
- - primary_diagnosis
|
484
|
+
- true
|
485
|
+
- - cpt
|
486
|
+
- '99214'
|
487
|
+
|
488
|
+
```
|
489
|
+
|
490
|
+
![](spec/dbc66b3ae6bd7123d77dd04b64f8a24498d048725a55c5340b15f5ae0a1ff307.png)
|
491
|
+
|
492
|
+
```No Results. Statement is experimental.```
|
493
|
+
|
494
|
+
|
495
|
+
```YAML
|
496
|
+
---
|
497
|
+
- intersect
|
498
|
+
- - complement
|
499
|
+
- - icd9
|
500
|
+
- '412'
|
501
|
+
- - complement
|
502
|
+
- - primary_diagnosis
|
503
|
+
- true
|
504
|
+
- - complement
|
505
|
+
- - cpt
|
506
|
+
- '99214'
|
507
|
+
|
508
|
+
```
|
509
|
+
|
510
|
+
![](spec/a9b4528726adec2a90f3f00139d8d0492f13c51f03c2f9ed6a5134b1b26b44a9.png)
|
511
|
+
|
512
|
+
```No Results. Statement is experimental.```
|
513
|
+
|
514
|
+
|
515
|
+
```YAML
|
516
|
+
---
|
517
|
+
- union
|
518
|
+
- - intersect
|
519
|
+
- - complement
|
520
|
+
- - icd9
|
521
|
+
- '412'
|
522
|
+
- - complement
|
523
|
+
- - primary_diagnosis
|
524
|
+
- true
|
525
|
+
- - complement
|
526
|
+
- - cpt
|
527
|
+
- '99214'
|
528
|
+
|
297
529
|
```
|
298
530
|
|
531
|
+
![](spec/a4bc7382a1154ea9856544fd48418f3dd9ce474ca94b8859fc323749c6cc1f55.png)
|
532
|
+
|
533
|
+
```No Results. Statement is experimental.```
|
299
534
|
|
300
535
|
### Except
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
{ icd9: '412' },
|
316
|
-
{ complement: { primary_diagnosis: true } }
|
317
|
-
]
|
318
|
-
}
|
536
|
+
|
537
|
+
This operator takes two sets of incoming streams, a left-hand stream and a right-hand stream. The operator matches like-type streams between the left-hand and right-hand streams. The operator removes any results in the left-hand stream if they appear in the right-hand stream. The operator passes only results for the left-hand stream downstream. The operator discards all results in the right-hand stream. For example:
|
538
|
+
|
539
|
+
|
540
|
+
```YAML
|
541
|
+
---
|
542
|
+
- except
|
543
|
+
- :left:
|
544
|
+
- icd9
|
545
|
+
- '412'
|
546
|
+
:right:
|
547
|
+
- primary_diagnosis
|
548
|
+
- true
|
549
|
+
|
319
550
|
```
|
320
551
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
552
|
+
![](spec/462153be527b28dc2cb5259c0aec62e1f529e8b60dc6e9c23fd1e06e8be933c9.png)
|
553
|
+
|
554
|
+
```No Results. Statement is experimental.```
|
555
|
+
|
556
|
+
|
557
|
+
```YAML
|
558
|
+
---
|
559
|
+
- intersect
|
560
|
+
- - icd9
|
561
|
+
- '412'
|
562
|
+
- - complement
|
563
|
+
- - primary_diagnosis
|
564
|
+
- true
|
565
|
+
|
330
566
|
```
|
331
567
|
|
568
|
+
![](spec/da450cdd0c94a1301bd98560339a45caa8041e09974352a56ecfb144e9a5e4d4.png)
|
569
|
+
|
570
|
+
```No Results. Statement is experimental.```
|
571
|
+
|
572
|
+
If the left-hand stream has no types that match the right-hand stream, the left-hand stream passes through unaffected:
|
573
|
+
|
574
|
+
|
575
|
+
```YAML
|
576
|
+
---
|
577
|
+
- except
|
578
|
+
- :left:
|
579
|
+
- icd9
|
580
|
+
- '412'
|
581
|
+
:right:
|
582
|
+
- cpt
|
583
|
+
- '99214'
|
584
|
+
|
585
|
+
```
|
586
|
+
|
587
|
+
![](spec/253845fe6162621af407ebd110296ff4f6d8a3f23ec75dfb4ea8cda30be71262.png)
|
588
|
+
|
589
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
590
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
591
|
+
| 6354 | 730080 | condition_occurrence | 2009-05-22 | 2009-05-22 | 412 |
|
592
|
+
| 405 | 47310 | condition_occurrence | 2010-04-21 | 2010-04-21 | 412 |
|
593
|
+
| 37067 | 4195911 | condition_occurrence | 2009-02-26 | 2009-02-26 | 412 |
|
594
|
+
| 31965 | 3622631 | condition_occurrence | 2008-05-09 | 2008-05-09 | 412 |
|
595
|
+
| 62025 | 6984372 | condition_occurrence | 2009-08-24 | 2009-08-24 | 412 |
|
596
|
+
| 7548 | 861875 | condition_occurrence | 2010-08-19 | 2010-09-08 | 412 |
|
597
|
+
| 72056 | 8102530 | condition_occurrence | 2008-02-14 | 2008-02-17 | 412 |
|
598
|
+
| 29548 | 3346625 | condition_occurrence | 2008-02-12 | 2008-02-19 | 412 |
|
599
|
+
| 51224 | 5768620 | condition_occurrence | 2010-04-21 | 2010-04-21 | 412 |
|
600
|
+
| 62051 | 6987562 | condition_occurrence | 2009-06-16 | 2009-06-16 | 412 |
|
601
|
+
|
332
602
|
And just to show how multiple streams behave:
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
603
|
+
|
604
|
+
|
605
|
+
```YAML
|
606
|
+
---
|
607
|
+
- except
|
608
|
+
- :left:
|
609
|
+
- union
|
610
|
+
- - icd9
|
611
|
+
- '412'
|
612
|
+
- - gender
|
613
|
+
- Male
|
614
|
+
- - cpt
|
615
|
+
- '99214'
|
616
|
+
:right:
|
617
|
+
- union
|
618
|
+
- - primary_diagnosis
|
619
|
+
- true
|
620
|
+
- - race
|
621
|
+
- White
|
622
|
+
|
623
|
+
```
|
624
|
+
|
625
|
+
![](spec/f0c734b099841a754ae0366afb00e992ad4814479b65e4a7de23c6e3dd85c09a.png)
|
626
|
+
|
627
|
+
```No Results. Statement is experimental.```
|
628
|
+
|
629
|
+
### Discussion about Set Operators
|
630
|
+
|
631
|
+
#### Union Operators
|
632
|
+
|
633
|
+
##### Q. Why should we allow two different types of streams to continue downstream concurrently?
|
356
634
|
|
357
635
|
- This feature lets us do interesting things, like find the first occurrence of either an MI or Death as in the example below
|
358
636
|
- Throw in a few more criteria and you could find the first occurrence of all censor events for each patient
|
359
637
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
638
|
+
|
639
|
+
```YAML
|
640
|
+
---
|
641
|
+
- first
|
642
|
+
- - union
|
643
|
+
- - icd9
|
644
|
+
- '412'
|
645
|
+
- - death
|
646
|
+
- true
|
647
|
+
|
370
648
|
```
|
371
649
|
|
650
|
+
![](spec/1102fa717b1c2df67af5220bf3ae219afafd79be7bba0c117e301983385ada52.png)
|
372
651
|
|
373
|
-
|
652
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
653
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
654
|
+
| 16 | 16 | death | 2010-12-01 | 2010-12-01 | |
|
655
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
656
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
657
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
658
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
659
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
660
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
661
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
662
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
663
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
664
|
+
|
665
|
+
##### Q. Why aren't all streams passed forward unaltered? Why union like-typed streams?
|
374
666
|
|
375
667
|
- The way Intersect works, if we passed like-typed streams forward without unioning them, Intersect would end up intersecting the two un-unioned like-type streams and that's not what we intended
|
376
668
|
- Essentially, these two diagrams would be identical:
|
377
669
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
670
|
+
|
671
|
+
```YAML
|
672
|
+
---
|
673
|
+
- intersect
|
674
|
+
- - union
|
675
|
+
- - icd9
|
676
|
+
- '412'
|
677
|
+
- - icd9
|
678
|
+
- '799.22'
|
679
|
+
- - cpt
|
680
|
+
- '99214'
|
681
|
+
|
682
|
+
```
|
683
|
+
|
684
|
+
![](spec/d64993258ffbef9406d9ab9136de7af530626b3a69e9eeb75835e11f11dabf62.png)
|
685
|
+
|
686
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
687
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
688
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
689
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
690
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
691
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
692
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
693
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
694
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
695
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
696
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
697
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
698
|
+
|
699
|
+
|
700
|
+
```YAML
|
701
|
+
---
|
702
|
+
- intersect
|
703
|
+
- - intersect
|
704
|
+
- - icd9
|
705
|
+
- '412'
|
706
|
+
- - icd9
|
707
|
+
- '799.22'
|
708
|
+
- - cpt
|
709
|
+
- '99214'
|
710
|
+
|
711
|
+
```
|
712
|
+
|
713
|
+
![](spec/defbd0b853d895802663f507761ad297d82e167f516c6082686a2a19b76012c5.png)
|
714
|
+
|
715
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
716
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
717
|
+
| 2 | 48 | procedure_occurrence | 2009-07-03 | 2009-07-03 | 99214 |
|
718
|
+
| 2 | 95 | procedure_occurrence | 2009-12-02 | 2009-12-02 | 99214 |
|
719
|
+
| 5 | 118 | procedure_occurrence | 2008-12-14 | 2008-12-14 | 99214 |
|
720
|
+
| 5 | 134 | procedure_occurrence | 2009-12-21 | 2009-12-21 | 99214 |
|
721
|
+
| 5 | 144 | procedure_occurrence | 2009-07-04 | 2009-07-04 | 99214 |
|
722
|
+
| 6 | 167 | procedure_occurrence | 2009-09-12 | 2009-09-12 | 99214 |
|
723
|
+
| 6 | 176 | procedure_occurrence | 2010-02-23 | 2010-02-23 | 99214 |
|
724
|
+
| 7 | 291 | procedure_occurrence | 2009-09-27 | 2009-09-27 | 99214 |
|
725
|
+
| 7 | 350 | procedure_occurrence | 2010-05-23 | 2010-05-23 | 99214 |
|
726
|
+
| 7 | 357 | procedure_occurrence | 2008-09-21 | 2008-09-21 | 99214 |
|
727
|
+
|
728
|
+
## Time-oriented Operators
|
729
|
+
|
410
730
|
All results in a stream carry a start_date and end_date with them. All temporal comparisons of streams use these two date columns. Each result in a stream derives its start and end date from its corresponding row in its table of origin.
|
411
731
|
|
412
732
|
For instance, a visit_occurrence result derives its start_date from visit_start_date and its end_date from visit_end_date.
|
@@ -415,11 +735,12 @@ If a result comes from a table that only has a single date value, the result der
|
|
415
735
|
|
416
736
|
The person stream is a special case. Person results use the person's date of birth as the start_date and end_date. This may sound strange, but we will explain below why this makes sense.
|
417
737
|
|
738
|
+
### Relative Temporal Operators
|
418
739
|
|
419
|
-
|
420
|
-
When looking at a set of results for a person, perhaps we want to select just the chronologically first or last result. Or maybe we want to select the 2nd result or 2nd to last result. Relative temporal nodes provide this type of filtering. Relative temporal nodes use a result's start_date to do chronological ordering.
|
740
|
+
When looking at a set of results for a person, perhaps we want to select just the chronologically first or last result. Or maybe we want to select the 2nd result or 2nd to last result. Relative temporal operators provide this type of filtering. Relative temporal operators use a result's start_date to do chronological ordering.
|
421
741
|
|
422
742
|
#### occurrence
|
743
|
+
|
423
744
|
- Takes a two arguments: the stream to select from and an integer argument
|
424
745
|
- For the integer argument
|
425
746
|
- Positive numbers mean 1st, 2nd, 3rd occurrence in chronological order
|
@@ -428,57 +749,107 @@ When looking at a set of results for a person, perhaps we want to select just th
|
|
428
749
|
- Negative numbers mean 1st, 2nd, 3rd occurrence in reverse chronological order
|
429
750
|
- e.g. -1 => last
|
430
751
|
- e.g. -4 => fourth from last
|
431
|
-
|
752
|
+
- 0 is undefined?
|
753
|
+
|
754
|
+
|
755
|
+
```YAML
|
756
|
+
---
|
757
|
+
- occurrence
|
758
|
+
- 3
|
759
|
+
- - icd9
|
760
|
+
- '412'
|
432
761
|
|
433
|
-
```ConceptQL
|
434
|
-
# For each patient, select the Condition that represents the third occurrence of an MI
|
435
|
-
{
|
436
|
-
occurrence: [
|
437
|
-
{ icd9: '412' },
|
438
|
-
3
|
439
|
-
]
|
440
|
-
}
|
441
762
|
```
|
442
763
|
|
764
|
+
![](spec/328467a6a419c7c05e299b8097e5e000686068ded8dc6d5f2e2de6f51976c315.png)
|
765
|
+
|
766
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
767
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
768
|
+
| 487 | 56319 | condition_occurrence | 2009-01-15 | 2009-01-19 | 412 |
|
769
|
+
| 506 | 59000 | condition_occurrence | 2010-07-19 | 2010-07-19 | 412 |
|
770
|
+
| 629 | 73033 | condition_occurrence | 2010-09-20 | 2010-09-20 | 412 |
|
771
|
+
| 985 | 114982 | condition_occurrence | 2009-09-29 | 2009-09-29 | 412 |
|
772
|
+
| 1336 | 156290 | condition_occurrence | 2009-10-03 | 2009-10-03 | 412 |
|
773
|
+
| 1779 | 206548 | condition_occurrence | 2010-02-09 | 2010-02-09 | 412 |
|
774
|
+
| 2475 | 282601 | condition_occurrence | 2009-02-28 | 2009-02-28 | 412 |
|
775
|
+
| 2529 | 289044 | condition_occurrence | 2010-07-18 | 2010-07-19 | 412 |
|
776
|
+
| 2942 | 337181 | condition_occurrence | 2010-01-22 | 2010-01-22 | 412 |
|
777
|
+
| 3206 | 365939 | condition_occurrence | 2009-03-25 | 2009-03-25 | 412 |
|
443
778
|
|
444
779
|
#### first
|
445
|
-
- Node that is shorthand for writing "occurrence: 1"
|
446
780
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
781
|
+
- Operator that is shorthand for writing "occurrence: 1"
|
782
|
+
|
783
|
+
|
784
|
+
```YAML
|
785
|
+
---
|
786
|
+
- first
|
787
|
+
- - icd9
|
788
|
+
- '412'
|
789
|
+
|
452
790
|
```
|
453
791
|
|
792
|
+
![](spec/04491942fcbd741982514f9eb12aeecf3d54b5b69a2b50c8331f7700169d5521.png)
|
793
|
+
|
794
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
795
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
796
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
797
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
798
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
799
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
800
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
801
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
802
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
803
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
804
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
805
|
+
| 88 | 10443 | condition_occurrence | 2010-05-26 | 2010-05-26 | 412 |
|
454
806
|
|
455
807
|
#### last
|
456
|
-
- Node that is just shorthand for writing "occurrence: -1"
|
457
808
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
809
|
+
- Operator that is just shorthand for writing "occurrence: -1"
|
810
|
+
|
811
|
+
|
812
|
+
```YAML
|
813
|
+
---
|
814
|
+
- last
|
815
|
+
- - icd9
|
816
|
+
- '412'
|
817
|
+
|
463
818
|
```
|
464
819
|
|
820
|
+
![](spec/ebacbd092e3d1a3c7b745a381e51e8ff9d63a21db23a16940193e18e57bc866f.png)
|
821
|
+
|
822
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
823
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
824
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
825
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
826
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
827
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
828
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
829
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
830
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
831
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
832
|
+
| 86 | 10196 | condition_occurrence | 2009-05-30 | 2009-05-30 | 412 |
|
833
|
+
| 88 | 10443 | condition_occurrence | 2010-05-26 | 2010-05-26 | 412 |
|
465
834
|
|
466
835
|
### Date Literals
|
467
|
-
|
836
|
+
|
837
|
+
For situations where we need to represent pre-defined date ranges, we can use "date literal" operators.
|
468
838
|
|
469
839
|
#### date_range
|
840
|
+
|
470
841
|
- Takes a hash with two elements: { start: \<date-format\>, end: \<date-format\> }
|
471
842
|
- Creates an inclusive, continuous range of dates defined by a start and end date
|
472
843
|
|
473
|
-
|
474
844
|
#### day
|
845
|
+
|
475
846
|
- Takes a single argument: \<date-format\>
|
476
847
|
- Represents a single day
|
477
848
|
- Shorthand for creating a date range that starts and ends on the same date
|
478
849
|
- *Not yet implemented*
|
479
850
|
|
480
|
-
|
481
851
|
#### What is <date-format\>?
|
852
|
+
|
482
853
|
Dates follow these formats:
|
483
854
|
|
484
855
|
- "YYYY-MM-DD"
|
@@ -488,13 +859,13 @@ Dates follow these formats:
|
|
488
859
|
- "END"
|
489
860
|
- Represents the last date of information available from the data source.
|
490
861
|
|
862
|
+
### Temporal Comparison Operators
|
491
863
|
|
492
|
-
|
493
|
-
As described above, each result carries a start and end date, defining its own date range. It is through these date ranges that we are able to do temporal filtering of streams via temporal nodes.
|
864
|
+
As described above, each result carries a start and end date, defining its own date range. It is through these date ranges that we are able to do temporal filtering of streams via temporal operators.
|
494
865
|
|
495
|
-
Temporal
|
866
|
+
Temporal operators work by comparing a left-hand stream (L) against a right-hand stream (R). R can be either a set of streams or a pre-defined date range. Each temporal operator has a comparison operator which defines how it compares dates between L and R. A temporal operator passes results only from L downstream. A temporal operator discards all results in the R stream after it makes all comparisons.
|
496
867
|
|
497
|
-
The available set of temporal
|
868
|
+
The available set of temporal operators comes from the work of Allen's Interval Algebra[^AIA]. Interval Algebra defines 13 distinct temporal relationships, as shown in this handy chart [borrowed from this website](http://people.kmi.open.ac.uk/carlos/174): ![](http://people.kmi.open.ac.uk/carlos/wp-content/uploads/2011/02/Allens-Algebra.png)
|
498
869
|
|
499
870
|
Our implementation of this algebra is originally going to be as strict as listed here, meaning that:
|
500
871
|
|
@@ -519,79 +890,138 @@ Ryan's Sidebar on These Definitions:
|
|
519
890
|
> We may want to adopt a less strict set of definitions, though their meaning may not be as easily defined as the one provided by Allen's Interval Algebra
|
520
891
|
|
521
892
|
When comparing results in L against a date range, results in L continue downstream only if they pass the comparison.
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
```
|
536
|
-
|
537
|
-
|
893
|
+
|
894
|
+
|
895
|
+
```YAML
|
896
|
+
---
|
897
|
+
- during
|
898
|
+
- :left:
|
899
|
+
- icd9
|
900
|
+
- '412'
|
901
|
+
:right:
|
902
|
+
- date_range
|
903
|
+
- :start: '2010-01-01'
|
904
|
+
:end: '2010-12-31'
|
905
|
+
|
906
|
+
```
|
907
|
+
|
908
|
+
![](spec/ba90ef705f7be91c53c5eb4a81a439fa0f7c48532214bd3db3cc5c069160543e.png)
|
909
|
+
|
910
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
911
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
912
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
913
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
914
|
+
| 88 | 10443 | condition_occurrence | 2010-05-26 | 2010-05-26 | 412 |
|
915
|
+
| 108 | 13741 | condition_occurrence | 2010-06-27 | 2010-06-27 | 412 |
|
916
|
+
| 149 | 17774 | condition_occurrence | 2010-11-22 | 2010-11-22 | 412 |
|
917
|
+
| 183 | 21619 | condition_occurrence | 2010-12-26 | 2010-12-26 | 412 |
|
918
|
+
| 206 | 24437 | condition_occurrence | 2010-02-07 | 2010-02-07 | 412 |
|
919
|
+
| 209 | 24989 | condition_occurrence | 2010-06-22 | 2010-06-23 | 412 |
|
920
|
+
| 231 | 28188 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
921
|
+
| 255 | 31542 | condition_occurrence | 2010-11-21 | 2010-11-21 | 412 |
|
922
|
+
|
923
|
+
When comparing results in L against a set of results in R, the temporal operator compares results in stream L against results in stream R on a person-by-person basis.
|
538
924
|
|
539
925
|
- If a person has results in L or R stream, but not in both, none of their results continue downstream
|
540
|
-
- On a per person basis, the temporal
|
926
|
+
- On a per person basis, the temporal operator joins all results in the L stream to all results in the R stream
|
541
927
|
- Any results in the L stream that meet the temporal comparison against any results in the R stream continue downstream
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
928
|
+
|
929
|
+
|
930
|
+
```YAML
|
931
|
+
---
|
932
|
+
- during
|
933
|
+
- :left:
|
934
|
+
- icd9
|
935
|
+
- '412'
|
936
|
+
:right:
|
937
|
+
- payer
|
938
|
+
- Part A
|
939
|
+
|
550
940
|
```
|
551
941
|
|
942
|
+
![](spec/ed039f82867241393b1a6a7153d3690461103934c72c1f3eaa3d99a12bb40885.png)
|
943
|
+
|
944
|
+
```No Results. Statement is experimental.```
|
945
|
+
|
552
946
|
#### Edge behaviors
|
553
|
-
|
947
|
+
|
948
|
+
For 11 of the 13 temporal operators, comparison of results is straight-forward. However, the before/after operators have a slight twist.
|
554
949
|
|
555
950
|
Imagine events 1-1-2-1-2-1. In my mind, three 1's come before a 2 and two 1's come after a 2. Accordingly:
|
556
951
|
|
557
|
-
- When comparing L **before** R, the temporal
|
558
|
-
- When comparing L **after** R, the temporal
|
952
|
+
- When comparing L **before** R, the temporal operator compares L against the **LAST** occurrence of R per person
|
953
|
+
- When comparing L **after** R, the temporal operator compares L against the **FIRST** occurrence of R per person
|
559
954
|
|
560
955
|
If we're looking for events in L that occur before events in R, then any event in L that occurs before the last event in R technically meet the comparison of "before". The reverse is true for after: all events in L that occur after the first event in R technically occur after R.
|
561
956
|
|
562
957
|
|
563
|
-
```
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
958
|
+
```YAML
|
959
|
+
---
|
960
|
+
- before
|
961
|
+
- :left:
|
962
|
+
- icd9
|
963
|
+
- '412'
|
964
|
+
:right:
|
965
|
+
- icd9
|
966
|
+
- '799.22'
|
572
967
|
|
573
|
-
If this is not the behavior you desire, use one of the sequence nodes to select which event in R should be the one used to do comparison
|
574
|
-
```ConceptQL
|
575
|
-
# All MIs that occurred before a patient's __first__ case of irritability (799.22)
|
576
|
-
{
|
577
|
-
before: {
|
578
|
-
left: { icd9: '412' },
|
579
|
-
right: {
|
580
|
-
first: {
|
581
|
-
icd9: '799.22'
|
582
|
-
}
|
583
|
-
}
|
584
|
-
}
|
585
|
-
}
|
586
968
|
```
|
587
969
|
|
970
|
+
![](spec/ee283d6a4b69cf10da2df703be3a16830be9cd8cd4f68c5f7afdf558ea28fa76.png)
|
971
|
+
|
972
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
973
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
974
|
+
| 53785 | 6053034 | condition_occurrence | 2008-07-18 | 2008-07-18 | 412 |
|
975
|
+
| 4289 | 496274 | condition_occurrence | 2008-07-19 | 2008-07-19 | 412 |
|
976
|
+
| 103062 | 11580605 | condition_occurrence | 2008-08-28 | 2008-08-28 | 412 |
|
977
|
+
| 12524 | 1422629 | condition_occurrence | 2009-08-25 | 2009-08-25 | 412 |
|
978
|
+
| 20306 | 2302248 | condition_occurrence | 2010-01-04 | 2010-01-04 | 412 |
|
979
|
+
| 81188 | 9131971 | condition_occurrence | 2010-02-15 | 2010-02-15 | 412 |
|
980
|
+
| 81188 | 9132070 | condition_occurrence | 2009-11-07 | 2009-11-07 | 412 |
|
981
|
+
| 97169 | 10930462 | condition_occurrence | 2008-02-05 | 2008-02-05 | 412 |
|
982
|
+
| 98040 | 11029333 | condition_occurrence | 2008-10-02 | 2008-10-02 | 412 |
|
983
|
+
| 98040 | 11029388 | condition_occurrence | 2008-08-09 | 2008-08-09 | 412 |
|
984
|
+
|
985
|
+
If this is not the behavior you desire, use one of the sequence operators to select which event in R should be the one used to do comparison
|
986
|
+
|
987
|
+
|
988
|
+
```YAML
|
989
|
+
---
|
990
|
+
- before
|
991
|
+
- :left:
|
992
|
+
- icd9
|
993
|
+
- '412'
|
994
|
+
:right:
|
995
|
+
- first
|
996
|
+
- - icd9
|
997
|
+
- '799.22'
|
998
|
+
|
999
|
+
```
|
1000
|
+
|
1001
|
+
![](spec/de589af36fa854e006a1563c93e644e2210f2a5616babb779f7f38aadb6c1ed7.png)
|
1002
|
+
|
1003
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1004
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1005
|
+
| 53785 | 6053034 | condition_occurrence | 2008-07-18 | 2008-07-18 | 412 |
|
1006
|
+
| 4289 | 496274 | condition_occurrence | 2008-07-19 | 2008-07-19 | 412 |
|
1007
|
+
| 103062 | 11580605 | condition_occurrence | 2008-08-28 | 2008-08-28 | 412 |
|
1008
|
+
| 12524 | 1422629 | condition_occurrence | 2009-08-25 | 2009-08-25 | 412 |
|
1009
|
+
| 20306 | 2302248 | condition_occurrence | 2010-01-04 | 2010-01-04 | 412 |
|
1010
|
+
| 81188 | 9131971 | condition_occurrence | 2010-02-15 | 2010-02-15 | 412 |
|
1011
|
+
| 81188 | 9132070 | condition_occurrence | 2009-11-07 | 2009-11-07 | 412 |
|
1012
|
+
| 97169 | 10930462 | condition_occurrence | 2008-02-05 | 2008-02-05 | 412 |
|
1013
|
+
| 98040 | 11029333 | condition_occurrence | 2008-10-02 | 2008-10-02 | 412 |
|
1014
|
+
| 98040 | 11029388 | condition_occurrence | 2008-08-09 | 2008-08-09 | 412 |
|
1015
|
+
|
588
1016
|
### Time Windows
|
1017
|
+
|
589
1018
|
There are situations when the date columns associated with a result should have their values shifted forward or backward in time to make a comparison with another set of dates.
|
590
1019
|
|
591
1020
|
#### time_window
|
1021
|
+
|
592
1022
|
- Takes 2 arguments
|
593
1023
|
- First argument is the stream on which to operate
|
594
|
-
- Second argument is a hash with two keys: [:start, :end] each with a value in the following format: "(-?\d
|
1024
|
+
- Second argument is a hash with two keys: \[:start, :end\] each with a value in the following format: "(-?\d+\[dmy\])+"
|
595
1025
|
- Both start and end must be defined, even if you are only adjusting one of the dates
|
596
1026
|
- Some examples
|
597
1027
|
- 30d => 30 days
|
@@ -608,378 +1038,669 @@ There are situations when the date columns associated with a result should have
|
|
608
1038
|
- 'end' represents the end_date for each result
|
609
1039
|
- See the example below
|
610
1040
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
```ConceptQL
|
627
|
-
# Shift the window for all MIs back by 2 years
|
628
|
-
{
|
629
|
-
time_window: [
|
630
|
-
{ icd9: '412' },
|
631
|
-
{ start: '-2y', end: '-2y' }
|
632
|
-
]
|
633
|
-
}
|
634
|
-
```
|
635
|
-
|
636
|
-
```ConceptQL
|
637
|
-
# Expand the dates for all MIs to a window ranging from 2 months and 2 days prior to 1 year and 3 days after the MI
|
638
|
-
{
|
639
|
-
time_window: [
|
640
|
-
{ icd9: '412' },
|
641
|
-
{ start: '-2m-2d', end: '3d1y' }
|
642
|
-
]
|
643
|
-
}
|
644
|
-
```
|
645
|
-
|
646
|
-
```ConceptQL
|
647
|
-
# Collapse all hospital visits' date ranges down to just the date of admission by leaving start_date unaffected and setting end_date to start_date
|
648
|
-
{
|
649
|
-
time_window: [
|
650
|
-
{ place_of_service: 'inpatient' },
|
651
|
-
{ start: '', end: 'start' }
|
652
|
-
]
|
653
|
-
}
|
654
|
-
```
|
655
|
-
|
656
|
-
```ConceptQL
|
657
|
-
# Nonsensical, but allowed: swap the start_date and end_date for a range
|
658
|
-
{
|
659
|
-
time_window: [
|
660
|
-
{ icd9: '412' },
|
661
|
-
{ start: 'end', end: 'start' }
|
662
|
-
]
|
663
|
-
}
|
664
|
-
```
|
665
|
-
|
666
|
-
#### Temporal Nodes and Person Streams
|
667
|
-
Person streams carry a patient's date of birth in their date columns. This makes them almost useless when they are part of the L stream of a temporal node. But person streams are useful as the R stream. By ```time_window```ing the patient's date of birth, we can filter based on the patient's age like so:
|
668
|
-
```ConceptQL
|
669
|
-
# All MIs that occurred after a male patient's 50th birthday
|
670
|
-
{
|
671
|
-
after: {
|
672
|
-
left: { icd9: '412' },
|
673
|
-
right: {
|
674
|
-
time_window: [
|
675
|
-
{ gender: 'Male' },
|
676
|
-
{
|
677
|
-
start: '50y',
|
678
|
-
end: '50y'
|
679
|
-
}
|
680
|
-
]
|
681
|
-
}
|
682
|
-
}
|
683
|
-
}
|
1041
|
+
|
1042
|
+
```YAML
|
1043
|
+
---
|
1044
|
+
- during
|
1045
|
+
- :left:
|
1046
|
+
- icd9
|
1047
|
+
- '799.22'
|
1048
|
+
:right:
|
1049
|
+
- time_window
|
1050
|
+
- - icd9
|
1051
|
+
- '412'
|
1052
|
+
- :start: "-30d"
|
1053
|
+
:end: 30d
|
1054
|
+
|
684
1055
|
```
|
685
1056
|
|
1057
|
+
![](spec/8101d9b89d9ba8070d585432707b43a8acdb4c2a3e9d37c3f7114b5e3ea9e800.png)
|
1058
|
+
|
1059
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1060
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1061
|
+
| 2086 | 238625 | condition_occurrence | 2008-05-24 | 2008-05-24 | 799.22 |
|
1062
|
+
| 5121 | 590274 | condition_occurrence | 2009-03-26 | 2009-04-04 | 799.22 |
|
1063
|
+
| 11427 | 1298251 | condition_occurrence | 2008-09-06 | 2008-09-06 | 799.22 |
|
1064
|
+
| 16432 | 1870381 | condition_occurrence | 2009-02-16 | 2009-02-16 | 799.22 |
|
1065
|
+
| 37733 | 4272148 | condition_occurrence | 2010-03-09 | 2010-03-09 | 799.22 |
|
1066
|
+
| 54141 | 6093274 | condition_occurrence | 2010-06-13 | 2010-06-13 | 799.22 |
|
1067
|
+
| 110498 | 12420479 | condition_occurrence | 2009-04-30 | 2009-04-30 | 799.22 |
|
1068
|
+
|
1069
|
+
|
1070
|
+
```YAML
|
1071
|
+
---
|
1072
|
+
- time_window
|
1073
|
+
- - icd9
|
1074
|
+
- '412'
|
1075
|
+
- :start: "-2y"
|
1076
|
+
:end: "-2y"
|
1077
|
+
|
1078
|
+
```
|
1079
|
+
|
1080
|
+
![](spec/15268bc45993d3f57ccf915877f91e48bdee684f24faa614249915833cac4af9.png)
|
1081
|
+
|
1082
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1083
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1084
|
+
| 17 | 1712 | condition_occurrence | 2006-08-25 | 2006-08-25 | 412 |
|
1085
|
+
| 17 | 1829 | condition_occurrence | 2007-04-30 | 2007-04-30 | 412 |
|
1086
|
+
| 37 | 4359 | condition_occurrence | 2008-02-12 | 2008-02-12 | 412 |
|
1087
|
+
| 53 | 5751 | condition_occurrence | 2006-06-05 | 2006-06-05 | 412 |
|
1088
|
+
| 59 | 6083 | condition_occurrence | 2007-07-19 | 2007-07-22 | 412 |
|
1089
|
+
| 64 | 6902 | condition_occurrence | 2007-07-25 | 2007-07-25 | 412 |
|
1090
|
+
| 71 | 7865 | condition_occurrence | 2006-11-16 | 2006-11-16 | 412 |
|
1091
|
+
| 75 | 8397 | condition_occurrence | 2008-10-06 | 2008-10-06 | 412 |
|
1092
|
+
| 79 | 8618 | condition_occurrence | 2007-01-28 | 2007-01-30 | 412 |
|
1093
|
+
| 86 | 9882 | condition_occurrence | 2007-01-03 | 2007-01-09 | 412 |
|
1094
|
+
|
1095
|
+
|
1096
|
+
```YAML
|
1097
|
+
---
|
1098
|
+
- time_window
|
1099
|
+
- - icd9
|
1100
|
+
- '412'
|
1101
|
+
- :start: "-2m-2d"
|
1102
|
+
:end: 3d1y
|
1103
|
+
|
1104
|
+
```
|
1105
|
+
|
1106
|
+
![](spec/cc960a268d51ccf2ebde657d36848f780213834844900018bce3d111843f7b0f.png)
|
1107
|
+
|
1108
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1109
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1110
|
+
| 17 | 1712 | condition_occurrence | 2008-06-23 | 2009-08-28 | 412 |
|
1111
|
+
| 17 | 1829 | condition_occurrence | 2009-02-26 | 2010-05-03 | 412 |
|
1112
|
+
| 37 | 4359 | condition_occurrence | 2009-12-10 | 2011-02-15 | 412 |
|
1113
|
+
| 53 | 5751 | condition_occurrence | 2008-04-03 | 2009-06-08 | 412 |
|
1114
|
+
| 59 | 6083 | condition_occurrence | 2009-05-17 | 2010-07-25 | 412 |
|
1115
|
+
| 64 | 6902 | condition_occurrence | 2009-05-23 | 2010-07-28 | 412 |
|
1116
|
+
| 71 | 7865 | condition_occurrence | 2008-09-14 | 2009-11-19 | 412 |
|
1117
|
+
| 75 | 8397 | condition_occurrence | 2010-08-04 | 2011-10-09 | 412 |
|
1118
|
+
| 79 | 8618 | condition_occurrence | 2008-11-26 | 2010-02-02 | 412 |
|
1119
|
+
| 86 | 9882 | condition_occurrence | 2008-11-01 | 2010-01-12 | 412 |
|
1120
|
+
|
1121
|
+
|
1122
|
+
```YAML
|
1123
|
+
---
|
1124
|
+
- time_window
|
1125
|
+
- - place_of_service_code
|
1126
|
+
- '21'
|
1127
|
+
- :start: ''
|
1128
|
+
:end: start
|
1129
|
+
|
1130
|
+
```
|
1131
|
+
|
1132
|
+
![](spec/886bf85249a704668a55c5161bceaac10be4a41a94b91606f49851dfa017526c.png)
|
1133
|
+
|
1134
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1135
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1136
|
+
| 1 | 1 | visit_occurrence | 2010-03-12 | 2010-03-12 | Inpatient |
|
1137
|
+
| 2 | 8 | visit_occurrence | 2009-09-17 | 2009-09-17 | Inpatient |
|
1138
|
+
| 2 | 9 | visit_occurrence | 2009-04-12 | 2009-04-12 | Inpatient |
|
1139
|
+
| 2 | 10 | visit_occurrence | 2010-06-26 | 2010-06-26 | Inpatient |
|
1140
|
+
| 2 | 11 | visit_occurrence | 2009-08-31 | 2009-08-31 | Inpatient |
|
1141
|
+
| 14 | 507 | visit_occurrence | 2008-09-12 | 2008-09-12 | Inpatient |
|
1142
|
+
| 17 | 729 | visit_occurrence | 2010-05-22 | 2010-05-22 | Inpatient |
|
1143
|
+
| 17 | 730 | visit_occurrence | 2008-09-19 | 2008-09-19 | Inpatient |
|
1144
|
+
| 17 | 731 | visit_occurrence | 2010-06-02 | 2010-06-02 | Inpatient |
|
1145
|
+
| 17 | 732 | visit_occurrence | 2010-06-16 | 2010-06-16 | Inpatient |
|
1146
|
+
|
1147
|
+
|
1148
|
+
```YAML
|
1149
|
+
---
|
1150
|
+
- time_window
|
1151
|
+
- - icd9
|
1152
|
+
- '412'
|
1153
|
+
- :start: end
|
1154
|
+
:end: start
|
1155
|
+
|
1156
|
+
```
|
1157
|
+
|
1158
|
+
![](spec/6705af65d728c0d5c50d6c4d46253017a91eb459dbb1f40f92449f05d5562f4a.png)
|
1159
|
+
|
1160
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1161
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1162
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
1163
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
1164
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
1165
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
1166
|
+
| 59 | 6083 | condition_occurrence | 2009-07-22 | 2009-07-19 | 412 |
|
1167
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
1168
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
1169
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
1170
|
+
| 79 | 8618 | condition_occurrence | 2009-01-30 | 2009-01-28 | 412 |
|
1171
|
+
| 86 | 9882 | condition_occurrence | 2009-01-09 | 2009-01-03 | 412 |
|
1172
|
+
|
1173
|
+
#### Temporal Operators and Person Streams
|
1174
|
+
|
1175
|
+
Person streams carry a patient's date of birth in their date columns. This makes them almost useless when they are part of the L stream of a temporal operator. But person streams are useful as the R stream. By ```time_window```ing the patient's date of birth, we can filter based on the patient's age like so:
|
1176
|
+
|
1177
|
+
|
1178
|
+
```YAML
|
1179
|
+
---
|
1180
|
+
- after
|
1181
|
+
- :left:
|
1182
|
+
- icd9
|
1183
|
+
- '412'
|
1184
|
+
:right:
|
1185
|
+
- time_window
|
1186
|
+
- - gender
|
1187
|
+
- Male
|
1188
|
+
- :start: 50y
|
1189
|
+
:end: 50y
|
1190
|
+
|
1191
|
+
```
|
1192
|
+
|
1193
|
+
![](spec/68fac940a32c7e40caacf8e560c61da552d57633d015ba98f2e98ec040a00c5b.png)
|
1194
|
+
|
1195
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1196
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1197
|
+
| 92077 | 10363643 | condition_occurrence | 2010-03-08 | 2010-03-08 | 412 |
|
1198
|
+
| 66609 | 7497031 | condition_occurrence | 2009-05-25 | 2009-05-28 | 412 |
|
1199
|
+
| 13729 | 1563187 | condition_occurrence | 2008-06-13 | 2008-06-13 | 412 |
|
1200
|
+
| 10876 | 1237925 | condition_occurrence | 2008-09-13 | 2008-09-13 | 412 |
|
1201
|
+
| 10876 | 1237830 | condition_occurrence | 2008-02-02 | 2008-02-03 | 412 |
|
1202
|
+
| 54683 | 6153652 | condition_occurrence | 2008-10-24 | 2008-10-28 | 412 |
|
1203
|
+
| 16106 | 1833669 | condition_occurrence | 2009-07-06 | 2009-07-13 | 412 |
|
1204
|
+
| 68518 | 7706073 | condition_occurrence | 2009-02-22 | 2009-02-22 | 412 |
|
1205
|
+
| 52736 | 5937885 | condition_occurrence | 2008-05-07 | 2008-05-07 | 412 |
|
1206
|
+
| 62215 | 7004785 | condition_occurrence | 2008-06-10 | 2008-06-10 | 412 |
|
1207
|
+
|
686
1208
|
## Type Conversion
|
1209
|
+
|
687
1210
|
There are situations where it is appropriate to convert the type of a stream of results into a different type. In programmer parlance, we say "typecasting" or "casting", which is the terminology we'll use here. A good analogy and mnemonic for casting is to think of taking a piece of metal, say a candle holder, melting it down, and recasting it into, say, a lamp. We'll do something similar with streams. We'll take, for example, a visit_occurrence stream and recast it into a stream of person.
|
688
1211
|
|
689
1212
|
### Casting to person
|
1213
|
+
|
690
1214
|
- Useful if we're just checking for the presence of a condition for a person
|
691
1215
|
- E.g. We want to know *if* a person has an old MI, not when an MI or how many MIs occurred
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
1216
|
+
|
1217
|
+
|
1218
|
+
```YAML
|
1219
|
+
---
|
1220
|
+
- person
|
1221
|
+
- - icd9
|
1222
|
+
- '412'
|
1223
|
+
|
699
1224
|
```
|
1225
|
+
|
1226
|
+
![](spec/8ed478d8c81a58a202d0c51348fca246df206fc24a0567b163d4e0bdab56ca46.png)
|
1227
|
+
|
1228
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1229
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1230
|
+
| 251 | 251 | person | 1928-10-01 | 1928-10-01 | 008645209D3E025E |
|
1231
|
+
| 66532 | 66532 | person | 1943-04-01 | 1943-04-01 | 96AB8ADC5FA7AD8C |
|
1232
|
+
| 64221 | 64221 | person | 1934-04-01 | 1934-04-01 | 916F76F7FDF6B6CF |
|
1233
|
+
| 111839 | 111839 | person | 1938-12-01 | 1938-12-01 | FDE56ED4546D17F6 |
|
1234
|
+
| 25643 | 25643 | person | 1916-06-01 | 1916-06-01 | 39BA7D25EC6D1B14 |
|
1235
|
+
| 79317 | 79317 | person | 1943-02-01 | 1943-02-01 | B441BDCB76C7C267 |
|
1236
|
+
| 108128 | 108128 | person | 1935-02-01 | 1935-02-01 | F58409ED69652B4A |
|
1237
|
+
| 77900 | 77900 | person | 1934-05-01 | 1934-05-01 | B0E710725FE3FE97 |
|
1238
|
+
| 61145 | 61145 | person | 1942-07-01 | 1942-07-01 | 8A595528CF5E2859 |
|
1239
|
+
| 18149 | 18149 | person | 1946-09-01 | 1946-09-01 | 28AFD67E63039098 |
|
1240
|
+
|
700
1241
|
### Casting to a visit_occurrence
|
1242
|
+
|
701
1243
|
- It is common to look for a set of conditions that coincide with a set of procedures
|
702
1244
|
- Gathering conditions yields a condition stream, gathering procedures yields a procedure stream
|
703
1245
|
- It is not possible to compare those two streams directly using AND
|
704
1246
|
- It is possible to compare the streams temporally, but CDM provides a visit_occurrence table to explicitly tie a set of conditions to a set of procedures
|
705
1247
|
- Casting both streams to visit_occurrence streams allows us to gather all visit_occurrences for which a set of conditions/procedures occurred in the same visit
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
1248
|
+
|
1249
|
+
|
1250
|
+
```YAML
|
1251
|
+
---
|
1252
|
+
- intersect
|
1253
|
+
- - visit_occurrence
|
1254
|
+
- - icd9
|
1255
|
+
- '412'
|
1256
|
+
- - visit_occurrence
|
1257
|
+
- - cpt
|
1258
|
+
- '99214'
|
1259
|
+
|
1260
|
+
```
|
1261
|
+
|
1262
|
+
![](spec/62323426e381ec21c967971a67e1f4a6d89dae92154bd937284e00b67f67fdd3.png)
|
1263
|
+
|
1264
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1265
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1266
|
+
| 59633 | 2958903 | visit_occurrence | 2010-07-08 | 2010-07-08 | Office |
|
1267
|
+
| 8462 | 423786 | visit_occurrence | 2008-08-24 | 2008-08-24 | Office |
|
1268
|
+
| 48614 | 2410554 | visit_occurrence | 2009-06-05 | 2009-06-05 | Office |
|
1269
|
+
| 92639 | 4587768 | visit_occurrence | 2009-04-25 | 2009-04-25 | Office |
|
1270
|
+
| 46156 | 2292353 | visit_occurrence | 2008-06-18 | 2008-06-18 | Office |
|
1271
|
+
| 105614 | 5223564 | visit_occurrence | 2008-02-03 | 2008-02-03 | Office |
|
1272
|
+
| 21343 | 1061266 | visit_occurrence | 2008-04-25 | 2008-04-25 | Office |
|
1273
|
+
| 62315 | 3086112 | visit_occurrence | 2008-05-27 | 2008-05-27 | Office |
|
1274
|
+
| 18286 | 914814 | visit_occurrence | 2010-02-10 | 2010-02-10 | Office |
|
1275
|
+
| 27340 | 1365178 | visit_occurrence | 2009-06-17 | 2009-06-17 | Office |
|
723
1276
|
|
724
1277
|
Many tables have a foreign key (FK) reference to the visit_occurrence table. If we cast a result to a visit_occurrence, and its table of origin has a visit_occurrence_id FK column, the result becomes a visit_occurrence result corresponding to the row pointed to by visit_occurrence_id. If the row's visit_occurrence_id is NULL, the result is discarded from the stream.
|
725
1278
|
|
726
1279
|
If the result's table of origin has no visit_occurrence_id column, we will instead replace the result with ALL visit_occurrences for the person assigned to the result. This allows us to convert between a person stream and visit_occurrence stream and back. E.g. we can get all male patients, then ask for their visit_occurrences later downstream.
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
1280
|
+
|
1281
|
+
|
1282
|
+
```YAML
|
1283
|
+
---
|
1284
|
+
- visit_occurrence
|
1285
|
+
- - gender
|
1286
|
+
- Male
|
1287
|
+
|
734
1288
|
```
|
735
1289
|
|
1290
|
+
![](spec/e8630103287f7c9d28eff40b3b1826e24846e776b877f7b8554257acbe621e1c.png)
|
1291
|
+
|
1292
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1293
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1294
|
+
| 10295 | 516092 | visit_occurrence | 2008-04-08 | 2008-04-08 | Outpatient |
|
1295
|
+
| 10295 | 516093 | visit_occurrence | 2008-07-28 | 2008-07-28 | Outpatient |
|
1296
|
+
| 10295 | 516094 | visit_occurrence | 2009-05-27 | 2009-05-27 | Outpatient |
|
1297
|
+
| 10295 | 516095 | visit_occurrence | 2008-09-03 | 2008-09-03 | Outpatient |
|
1298
|
+
| 10295 | 516096 | visit_occurrence | 2008-05-31 | 2008-05-31 | Outpatient |
|
1299
|
+
| 10295 | 516097 | visit_occurrence | 2008-09-13 | 2008-09-13 | Outpatient |
|
1300
|
+
| 10295 | 516098 | visit_occurrence | 2008-08-23 | 2008-08-23 | Outpatient |
|
1301
|
+
| 10295 | 516099 | visit_occurrence | 2008-04-28 | 2008-04-28 | Office |
|
1302
|
+
| 10295 | 516100 | visit_occurrence | 2009-03-26 | 2009-03-26 | Office |
|
1303
|
+
| 10295 | 516101 | visit_occurrence | 2009-09-22 | 2009-09-22 | Office |
|
1304
|
+
|
736
1305
|
### Casting Loses All Original Information
|
737
|
-
After a result undergoes casting, it loses its original information. E.g. casting a visit_occurrence to a person loses the visit_occurrence information and resets the start_date and end_date columns to the person's date of birth. As a side note, this is actually handy if a stream’s dates have been altered by a time_window node and you want the original dates later on. Just cast the stream to its same type and it will regain its original dates.
|
738
1306
|
|
1307
|
+
After a result undergoes casting, it loses its original information. E.g. casting a visit_occurrence to a person loses the visit_occurrence information and resets the start_date and end_date columns to the person's date of birth. As a side note, this is actually handy if a stream’s dates have been altered by a time_window operator and you want the original dates later on. Just cast the stream to its same type and it will regain its original dates.
|
739
1308
|
|
740
1309
|
### Cast all the Things!
|
1310
|
+
|
741
1311
|
Although casting to visit_occurrence and person are the most common types of casting, we can cast to and from any of the types in the ConceptQL system.
|
742
1312
|
|
743
1313
|
The general rule will be that if the source type has a defined relationship with the target type, we'll cast using that relationship, e.g. casting visit_occurrences to procedures will turn all visit_occurrence results into the set of procedure results that point at those original visit_occurrences. But if there is no direct relationship, we'll do a generous casting, e.g. casting observations to procedures will return all procedures for all persons in the observation stream.
|
744
1314
|
|
745
1315
|
INSERT HANDY TABLE SHOWING CONVERSION MATRIX HERE
|
746
1316
|
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
}
|
763
|
-
}
|
1317
|
+
|
1318
|
+
```YAML
|
1319
|
+
---
|
1320
|
+
- procedure_cost
|
1321
|
+
- - intersect
|
1322
|
+
- - cpt
|
1323
|
+
- '70012'
|
1324
|
+
- - procedure
|
1325
|
+
- - intersect
|
1326
|
+
- - place_of_service_code
|
1327
|
+
- '21'
|
1328
|
+
- - visit_occurrence
|
1329
|
+
- - icd9
|
1330
|
+
- '412'
|
1331
|
+
|
764
1332
|
```
|
765
1333
|
|
1334
|
+
![](spec/6a34c0ef589c9c976fe41f3e67e799e198499f5b9c3ebfd240fb91f73e893573.png)
|
1335
|
+
|
1336
|
+
```No Results. Statement is experimental.```
|
1337
|
+
|
766
1338
|
### Casting as a way to fetch all rows
|
767
|
-
|
768
|
-
```
|
769
|
-
|
770
|
-
|
1339
|
+
|
1340
|
+
The casting operator doubles as a way to fetch all rows for a single type. Provide the casting operator with an argument of ```true``` (instead of an upstream operator) to get all rows as results:
|
1341
|
+
|
1342
|
+
|
1343
|
+
```YAML
|
1344
|
+
---
|
1345
|
+
- death
|
1346
|
+
- true
|
1347
|
+
|
771
1348
|
```
|
772
1349
|
|
1350
|
+
![](spec/e9b384fa7dec5f1a06479c4b289e06b1e60e4f23f7630aff6d03c52595f500f8.png)
|
1351
|
+
|
1352
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1353
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1354
|
+
| 16 | 16 | death | 2010-12-01 | 2010-12-01 | |
|
1355
|
+
| 177 | 177 | death | 2010-07-01 | 2010-07-01 | |
|
1356
|
+
| 293 | 293 | death | 2010-01-01 | 2010-01-01 | |
|
1357
|
+
| 306 | 306 | death | 2010-05-01 | 2010-05-01 | |
|
1358
|
+
| 375 | 375 | death | 2010-03-01 | 2010-03-01 | |
|
1359
|
+
| 429 | 429 | death | 2010-03-01 | 2010-03-01 | |
|
1360
|
+
| 450 | 450 | death | 2010-11-01 | 2010-11-01 | |
|
1361
|
+
| 555 | 555 | death | 2010-11-01 | 2010-11-01 | |
|
1362
|
+
| 565 | 565 | death | 2010-06-01 | 2010-06-01 | |
|
1363
|
+
| 603 | 603 | death | 2010-06-01 | 2010-06-01 | |
|
1364
|
+
|
773
1365
|
This comes in handy for situations like these:
|
774
|
-
```ConceptQL
|
775
|
-
# All Male patients who died
|
776
|
-
{
|
777
|
-
person_filter: {
|
778
|
-
left: { gender: 'Male' },
|
779
|
-
right: { death: true },
|
780
|
-
}
|
781
|
-
}
|
782
|
-
```
|
783
1366
|
|
784
1367
|
|
1368
|
+
```YAML
|
1369
|
+
---
|
1370
|
+
- person_filter
|
1371
|
+
- :left:
|
1372
|
+
- gender
|
1373
|
+
- Male
|
1374
|
+
:right:
|
1375
|
+
- death
|
1376
|
+
- true
|
1377
|
+
|
1378
|
+
```
|
1379
|
+
|
1380
|
+
![](spec/58113a57a37431a402d2547369eba3a481bf1dbbfd82dc384406a5c91f6df01f.png)
|
1381
|
+
|
1382
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1383
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1384
|
+
| 55510 | 55510 | person | 1930-08-01 | 1930-08-01 | 7D34060FA1EF58C6 |
|
1385
|
+
| 74808 | 74808 | person | 1927-02-01 | 1927-02-01 | A9BE60D395FEE13D |
|
1386
|
+
| 32780 | 32780 | person | 1961-09-01 | 1961-09-01 | 49BF11D11CEF2328 |
|
1387
|
+
| 87909 | 87909 | person | 1934-04-01 | 1934-04-01 | C7727009E7DDF6B8 |
|
1388
|
+
| 43890 | 43890 | person | 1920-03-01 | 1920-03-01 | 6309F87AE1E03227 |
|
1389
|
+
| 46052 | 46052 | person | 1941-09-01 | 1941-09-01 | 67D8035124FE474E |
|
1390
|
+
| 88540 | 88540 | person | 1952-08-01 | 1952-08-01 | C8E882134C354ADF |
|
1391
|
+
| 10616 | 10616 | person | 1946-07-01 | 1946-07-01 | 179C0EDEB061D6E3 |
|
1392
|
+
| 74892 | 74892 | person | 1927-02-01 | 1927-02-01 | A9F0108311BE3424 |
|
1393
|
+
| 84318 | 84318 | person | 1938-06-01 | 1938-06-01 | BF7387DC991F39A9 |
|
1394
|
+
|
785
1395
|
## Filtering by People
|
786
|
-
Often we want to filter out a set of results by people. For instance, say we wanted to find all MIs for all males. We'd use the person_filter node for that. Like the Except node, it takes a left-hand stream and a right-hand stream.
|
787
1396
|
|
788
|
-
|
1397
|
+
Often we want to filter out a set of results by people. For instance, say we wanted to find all MIs for all males. We'd use the person_filter operator for that. Like the Except operator, it takes a left-hand stream and a right-hand stream.
|
789
1398
|
|
1399
|
+
Unlike the ```except``` operator, the person_filter operator will use all types of all streams in the right-hand side to filter out results in all types of all streams on the left hand side.
|
790
1400
|
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
1401
|
+
|
1402
|
+
```YAML
|
1403
|
+
---
|
1404
|
+
- person_filter
|
1405
|
+
- :left:
|
1406
|
+
- icd9
|
1407
|
+
- '412'
|
1408
|
+
:right:
|
1409
|
+
- gender
|
1410
|
+
- Male
|
1411
|
+
|
1412
|
+
```
|
1413
|
+
|
1414
|
+
![](spec/0360fc0c2b7a88fd82ffc4d13387b76766649d5d42aa8f9349bbf60a81ac6119.png)
|
1415
|
+
|
1416
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1417
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1418
|
+
| 92077 | 10363643 | condition_occurrence | 2010-03-08 | 2010-03-08 | 412 |
|
1419
|
+
| 66609 | 7497031 | condition_occurrence | 2009-05-25 | 2009-05-28 | 412 |
|
1420
|
+
| 13729 | 1563187 | condition_occurrence | 2008-06-13 | 2008-06-13 | 412 |
|
1421
|
+
| 10876 | 1237925 | condition_occurrence | 2008-09-13 | 2008-09-13 | 412 |
|
1422
|
+
| 10876 | 1237830 | condition_occurrence | 2008-02-02 | 2008-02-03 | 412 |
|
1423
|
+
| 54683 | 6153652 | condition_occurrence | 2008-10-24 | 2008-10-28 | 412 |
|
1424
|
+
| 16106 | 1833669 | condition_occurrence | 2009-07-06 | 2009-07-13 | 412 |
|
1425
|
+
| 33793 | 3829115 | condition_occurrence | 2008-01-17 | 2008-01-21 | 412 |
|
1426
|
+
| 68518 | 7706073 | condition_occurrence | 2009-02-22 | 2009-02-22 | 412 |
|
1427
|
+
| 52736 | 5937885 | condition_occurrence | 2008-05-07 | 2008-05-07 | 412 |
|
800
1428
|
|
801
1429
|
But we can get crazier. The right-hand side doesn't have to be a person stream. If a non-person stream is used in the right-hand side, the person_filter will cast all right-hand streams to person first and use the union of those streams:
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
person_filter: {
|
815
|
-
left: { icd9: '412' },
|
816
|
-
right: { person: { cpt: '99214' } }
|
817
|
-
}
|
818
|
-
}
|
819
|
-
```
|
820
|
-
```ConceptQL
|
821
|
-
# All MI Conditions for people who are Male OR had an office visit at some point in the data
|
822
|
-
{
|
823
|
-
person_filter: {
|
824
|
-
left: { icd9: '412' },
|
825
|
-
right: {
|
826
|
-
union: [
|
827
|
-
{ cpt: '99214' },
|
828
|
-
{ gender: 'Male' }
|
829
|
-
]
|
830
|
-
}
|
831
|
-
}
|
832
|
-
}
|
1430
|
+
|
1431
|
+
|
1432
|
+
```YAML
|
1433
|
+
---
|
1434
|
+
- person_filter
|
1435
|
+
- :left:
|
1436
|
+
- icd9
|
1437
|
+
- '412'
|
1438
|
+
:right:
|
1439
|
+
- cpt
|
1440
|
+
- '99214'
|
1441
|
+
|
833
1442
|
```
|
834
1443
|
|
1444
|
+
![](spec/26fd52b5ac55438dd9f81b4a3f3913f1058c9f225c8a5e129007c1e9413d5881.png)
|
1445
|
+
|
1446
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1447
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1448
|
+
| 92077 | 10363643 | condition_occurrence | 2010-03-08 | 2010-03-08 | 412 |
|
1449
|
+
| 108031 | 12142323 | condition_occurrence | 2009-11-25 | 2009-11-25 | 412 |
|
1450
|
+
| 56414 | 6351863 | condition_occurrence | 2008-11-15 | 2008-11-15 | 412 |
|
1451
|
+
| 66609 | 7497031 | condition_occurrence | 2009-05-25 | 2009-05-28 | 412 |
|
1452
|
+
| 10876 | 1237830 | condition_occurrence | 2008-02-02 | 2008-02-03 | 412 |
|
1453
|
+
| 10876 | 1237925 | condition_occurrence | 2008-09-13 | 2008-09-13 | 412 |
|
1454
|
+
| 33463 | 3787772 | condition_occurrence | 2009-08-08 | 2009-08-08 | 412 |
|
1455
|
+
| 48678 | 5484541 | condition_occurrence | 2009-09-09 | 2009-09-09 | 412 |
|
1456
|
+
| 54683 | 6153652 | condition_occurrence | 2008-10-24 | 2008-10-28 | 412 |
|
1457
|
+
| 68518 | 7706073 | condition_occurrence | 2009-02-22 | 2009-02-22 | 412 |
|
1458
|
+
|
1459
|
+
|
1460
|
+
```YAML
|
1461
|
+
---
|
1462
|
+
- person_filter
|
1463
|
+
- :left:
|
1464
|
+
- icd9
|
1465
|
+
- '412'
|
1466
|
+
:right:
|
1467
|
+
- person
|
1468
|
+
- - cpt
|
1469
|
+
- '99214'
|
1470
|
+
|
1471
|
+
```
|
1472
|
+
|
1473
|
+
![](spec/e1cb0863b21e14256d61a54200316791f6547c78ba2f0156c110f4500f9bbd49.png)
|
1474
|
+
|
1475
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1476
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1477
|
+
| 92077 | 10363643 | condition_occurrence | 2010-03-08 | 2010-03-08 | 412 |
|
1478
|
+
| 108031 | 12142323 | condition_occurrence | 2009-11-25 | 2009-11-25 | 412 |
|
1479
|
+
| 56414 | 6351863 | condition_occurrence | 2008-11-15 | 2008-11-15 | 412 |
|
1480
|
+
| 66609 | 7497031 | condition_occurrence | 2009-05-25 | 2009-05-28 | 412 |
|
1481
|
+
| 10876 | 1237830 | condition_occurrence | 2008-02-02 | 2008-02-03 | 412 |
|
1482
|
+
| 10876 | 1237925 | condition_occurrence | 2008-09-13 | 2008-09-13 | 412 |
|
1483
|
+
| 33463 | 3787772 | condition_occurrence | 2009-08-08 | 2009-08-08 | 412 |
|
1484
|
+
| 48678 | 5484541 | condition_occurrence | 2009-09-09 | 2009-09-09 | 412 |
|
1485
|
+
| 54683 | 6153652 | condition_occurrence | 2008-10-24 | 2008-10-28 | 412 |
|
1486
|
+
| 68518 | 7706073 | condition_occurrence | 2009-02-22 | 2009-02-22 | 412 |
|
1487
|
+
|
1488
|
+
|
1489
|
+
```YAML
|
1490
|
+
---
|
1491
|
+
- person_filter
|
1492
|
+
- :left:
|
1493
|
+
- icd9
|
1494
|
+
- '412'
|
1495
|
+
:right:
|
1496
|
+
- union
|
1497
|
+
- - cpt
|
1498
|
+
- '99214'
|
1499
|
+
- - gender
|
1500
|
+
- Male
|
1501
|
+
|
1502
|
+
```
|
1503
|
+
|
1504
|
+
![](spec/5d331d74c460d75814b2d3138a9b7d90b5ddb2dcd85e1f5f260d183745fc3a1e.png)
|
1505
|
+
|
1506
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1507
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1508
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
1509
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
1510
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
1511
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
1512
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
1513
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
1514
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
1515
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
1516
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
1517
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
1518
|
+
|
835
1519
|
And don't forget the left-hand side can have multiple types of streams:
|
836
|
-
```ConceptQL
|
837
|
-
# Yields two streams: a stream of all MI Conditions for people who are Male and a stream of all office visit Procedures for people who are Male
|
838
|
-
{
|
839
|
-
person_filter: {
|
840
|
-
left: {
|
841
|
-
union: [
|
842
|
-
{ icd9: '412' },
|
843
|
-
{ cpt: '99214' }
|
844
|
-
]
|
845
|
-
},
|
846
|
-
right: { gender: 'Male' }
|
847
|
-
}
|
848
|
-
}
|
849
|
-
```
|
850
|
-
|
851
|
-
|
852
|
-
## Sub-concepts within a Larger Concept
|
853
|
-
If a concept is particularly complex, or has a stream of results that are used more than once, it can be helpful to break the concept into a set of sub-concepts. This can be done using two nodes: define and recall
|
854
|
-
|
855
|
-
#### define
|
856
|
-
- Takes 2 arguments
|
857
|
-
- First argument is a string of arbitrary length that describe the stream to be save. This is the "name" assigned to the stream for later recall
|
858
|
-
- Second argument is the stream to save under the name specified
|
859
1520
|
|
860
1521
|
|
861
|
-
|
862
|
-
|
863
|
-
|
1522
|
+
```YAML
|
1523
|
+
---
|
1524
|
+
- person_filter
|
1525
|
+
- :left:
|
1526
|
+
- union
|
1527
|
+
- - icd9
|
1528
|
+
- '412'
|
1529
|
+
- - cpt
|
1530
|
+
- '99214'
|
1531
|
+
:right:
|
1532
|
+
- gender
|
1533
|
+
- Male
|
1534
|
+
|
1535
|
+
```
|
1536
|
+
|
1537
|
+
![](spec/c93dd18894a245a5647f99e1867d3779e4cd34c9c8f8860600ff0c837a5ffa53.png)
|
1538
|
+
|
1539
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1540
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1541
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
1542
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
1543
|
+
| 91 | 10865 | condition_occurrence | 2009-11-08 | 2009-11-08 | 412 |
|
1544
|
+
| 108 | 13741 | condition_occurrence | 2010-06-27 | 2010-06-27 | 412 |
|
1545
|
+
| 128 | 15149 | condition_occurrence | 2008-03-22 | 2008-03-23 | 412 |
|
1546
|
+
| 146 | 17041 | condition_occurrence | 2008-04-07 | 2008-04-07 | 412 |
|
1547
|
+
| 149 | 17772 | condition_occurrence | 2008-08-16 | 2008-08-16 | 412 |
|
1548
|
+
| 149 | 17774 | condition_occurrence | 2010-11-22 | 2010-11-22 | 412 |
|
1549
|
+
| 158 | 18412 | condition_occurrence | 2009-10-25 | 2009-10-29 | 412 |
|
1550
|
+
| 183 | 21619 | condition_occurrence | 2010-12-26 | 2010-12-26 | 412 |
|
1551
|
+
|
1552
|
+
## Sub-algorithms within a Larger Algorithm
|
1553
|
+
|
1554
|
+
If a algorithm is particularly complex, or has a stream of results that are used more than once, it can be helpful to break the algorithm into a set of sub-algorithms. This can be done using the `label` options and the `recall` operator.
|
1555
|
+
|
1556
|
+
### `label` option
|
1557
|
+
|
1558
|
+
Any ConceptQL operator can be assigned a label. The label simply provides a way to apply a brief description to an operator, generally, what kind of results the operator is producing. Any operator that has a label can be accessed via the `recall` operator.
|
864
1559
|
|
1560
|
+
### `recall` operator
|
1561
|
+
|
1562
|
+
- Takes 1 argument
|
1563
|
+
- The "label" of an operator from which you'd like to pull the exact same set of results
|
865
1564
|
|
866
1565
|
A stream must be `define`d before `recall` can use it.
|
867
1566
|
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
]
|
917
|
-
}
|
918
|
-
}
|
919
|
-
}
|
920
|
-
]
|
921
|
-
},
|
922
|
-
|
923
|
-
{
|
924
|
-
first: {
|
925
|
-
union: [
|
926
|
-
{ recall: 'Inpatient Heart Attack' },
|
927
|
-
{ recall: 'Earlier of Two Outpatient Heart Attacks'}
|
928
|
-
]
|
929
|
-
}
|
930
|
-
}
|
931
|
-
]
|
932
|
-
```
|
933
|
-
|
934
|
-
|
935
|
-
## Concepts within Concepts
|
1567
|
+
|
1568
|
+
```YAML
|
1569
|
+
---
|
1570
|
+
- first
|
1571
|
+
- - union
|
1572
|
+
- - intersect
|
1573
|
+
- - visit_occurrence
|
1574
|
+
- - icd9
|
1575
|
+
- '412'
|
1576
|
+
- :label: Heart Attack Visit
|
1577
|
+
- - place_of_service_code
|
1578
|
+
- '21'
|
1579
|
+
- - before
|
1580
|
+
- :left:
|
1581
|
+
- intersect
|
1582
|
+
- - recall
|
1583
|
+
- Heart Attack Visit
|
1584
|
+
- - complement
|
1585
|
+
- - place_of_service_code
|
1586
|
+
- 21
|
1587
|
+
- :label: Outpatient Heart Attack
|
1588
|
+
:right:
|
1589
|
+
- time_window
|
1590
|
+
- - recall
|
1591
|
+
- Outpatient Heart Attack
|
1592
|
+
- :start: "-30d"
|
1593
|
+
:end: '0'
|
1594
|
+
:label: Earliest of Two Outpatient Heart Attacks
|
1595
|
+
|
1596
|
+
```
|
1597
|
+
|
1598
|
+
![](spec/4a3b47ed1c54f96ebdae693d41c36c51884c4546ef799a4108085708fb7b964e.png)
|
1599
|
+
|
1600
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1601
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1602
|
+
| 59 | 2705 | visit_occurrence | 2009-07-19 | 2009-07-22 | Inpatient |
|
1603
|
+
| 79 | 3847 | visit_occurrence | 2009-01-28 | 2009-01-30 | Inpatient |
|
1604
|
+
| 86 | 4378 | visit_occurrence | 2009-01-03 | 2009-01-09 | Inpatient |
|
1605
|
+
| 128 | 6640 | visit_occurrence | 2008-03-22 | 2008-03-23 | Inpatient |
|
1606
|
+
| 158 | 8108 | visit_occurrence | 2009-10-25 | 2009-10-29 | Inpatient |
|
1607
|
+
| 173 | 8806 | visit_occurrence | 2009-06-13 | 2009-06-16 | Inpatient |
|
1608
|
+
| 222 | 11783 | visit_occurrence | 2008-03-14 | 2008-03-21 | Inpatient |
|
1609
|
+
| 260 | 13972 | visit_occurrence | 2010-05-29 | 2010-06-21 | Inpatient |
|
1610
|
+
| 352 | 18458 | visit_occurrence | 2008-07-02 | 2008-07-09 | Inpatient |
|
1611
|
+
| 407 | 20925 | visit_occurrence | 2008-08-25 | 2008-08-27 | Inpatient |
|
1612
|
+
|
1613
|
+
## Algorithms within Algorithms
|
1614
|
+
|
936
1615
|
One of the main motivations behind keeping ConceptQL so flexible is to allow users to build ConceptQL statements from other ConceptQL statements. This section loosely describes how this feature will work. Its actual execution and implementation will differ from what is presented here.
|
937
1616
|
|
938
1617
|
Say a ConceptQL statement gathers all visit_occurrences where a patient had an MI and a Hospital encounter (CPT 99231):
|
939
1618
|
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
1619
|
+
|
1620
|
+
```YAML
|
1621
|
+
---
|
1622
|
+
- intersect
|
1623
|
+
- - visit_occurrence
|
1624
|
+
- - icd9
|
1625
|
+
- '412'
|
1626
|
+
- - visit_occurrence
|
1627
|
+
- - cpt
|
1628
|
+
- '99231'
|
1629
|
+
|
948
1630
|
```
|
949
1631
|
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
1632
|
+
![](spec/5d6ff62038b75d6f240d65f35d1520a131c221f47d3801554c8c2be5d528ebb0.png)
|
1633
|
+
|
1634
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1635
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1636
|
+
| 108335 | 5357904 | visit_occurrence | 2009-12-07 | 2009-12-07 | Office |
|
1637
|
+
| 23251 | 1158016 | visit_occurrence | 2009-07-24 | 2009-07-24 | Office |
|
1638
|
+
| 13270 | 662308 | visit_occurrence | 2010-07-23 | 2010-07-25 | Office |
|
1639
|
+
| 24119 | 1199980 | visit_occurrence | 2008-11-30 | 2008-12-05 | Office |
|
1640
|
+
| 91102 | 4511328 | visit_occurrence | 2008-09-01 | 2008-09-01 | Office |
|
1641
|
+
| 3646 | 184096 | visit_occurrence | 2009-01-09 | 2009-01-09 | Office |
|
1642
|
+
| 21338 | 1061186 | visit_occurrence | 2008-07-11 | 2008-07-11 | Office |
|
1643
|
+
| 86004 | 4256504 | visit_occurrence | 2008-04-18 | 2008-04-18 | Office |
|
1644
|
+
| 112447 | 5561049 | visit_occurrence | 2008-12-22 | 2008-12-25 | Office |
|
1645
|
+
| 20229 | 1009400 | visit_occurrence | 2008-09-06 | 2008-09-06 | Office |
|
1646
|
+
|
1647
|
+
If we wanted to gather all costs for all procedures for those visits, we could use the "algorithm" operator to represent the algorithm defined above in a new concept:
|
1648
|
+
|
1649
|
+
|
1650
|
+
```YAML
|
1651
|
+
---
|
1652
|
+
- procedure_cost
|
1653
|
+
- - algorithm
|
1654
|
+
- |2-
|
1655
|
+
|
1656
|
+
All Visits
|
1657
|
+
where a Patient had
|
1658
|
+
both an MI and
|
1659
|
+
a Hospital Encounter
|
1660
|
+
|
958
1661
|
```
|
959
|
-
The color and edge coming from the concept node are black to denote that we don't know what types or streams are coming from the concept. In reality, any program that uses ConceptQL can ask the concept represented by the concept node for the concept's types. The result of nesting one concept within another is exactly the same had we taken concept node and replaced it with the ConceptQL statement for the concept it represents.
|
960
1662
|
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
1663
|
+
![](spec/eb8f5511f7d88bd0f8ba73420fc10f7c78405db7f4373d778a827058707f888e.png)
|
1664
|
+
|
1665
|
+
```No Results. Statement is experimental.```
|
1666
|
+
|
1667
|
+
The color and edge coming from the algorithm operator are black to denote that we don't know what types or streams are coming from the concept. In reality, any program that uses ConceptQL can ask the algorithm represented by the algorithm operator for the concept's types. The result of nesting one algorithm within another is exactly the same had we taken algorithm operator and replaced it with the ConceptQL statement for the algorithm it represents.
|
1668
|
+
|
1669
|
+
|
1670
|
+
```YAML
|
1671
|
+
---
|
1672
|
+
- procedure_cost
|
1673
|
+
- - intersect
|
1674
|
+
- - visit_occurrence
|
1675
|
+
- - icd9
|
1676
|
+
- '412'
|
1677
|
+
- - visit_occurrence
|
1678
|
+
- - cpt
|
1679
|
+
- '99231'
|
1680
|
+
|
971
1681
|
```
|
972
1682
|
|
973
|
-
|
1683
|
+
![](spec/6b48534236697d1ccfa1f5403764782f9d228f9eb706789cfa80203882b7b13a.png)
|
1684
|
+
|
1685
|
+
```No Results. Statement is experimental.```
|
1686
|
+
|
1687
|
+
In the actual implementation of the algorithm operator, each ConceptQL statement will have a unique identifier which the algorithm operator will use. So, assuming that the ID 2031 represents the algorithm we want to gather all procedure costs for, our example should really read:
|
1688
|
+
|
1689
|
+
|
1690
|
+
```YAML
|
1691
|
+
---
|
1692
|
+
- procedure_cost
|
1693
|
+
- - algorithm
|
1694
|
+
- 2031
|
974
1695
|
|
975
|
-
```ConceptQL
|
976
|
-
{
|
977
|
-
procedure_cost: { concept: 2031 }
|
978
|
-
}
|
979
1696
|
```
|
980
1697
|
|
1698
|
+
![](spec/067241a3579767a802d4f8e20fd35b60adbe377c9a6512ef135f164a5accfb27.png)
|
1699
|
+
|
1700
|
+
```No Results. Statement is experimental.```
|
981
1701
|
|
982
1702
|
## Values
|
1703
|
+
|
983
1704
|
A result can carry forward three different types of values, modeled after the behavior of the observation table:
|
984
1705
|
|
985
1706
|
- value_as_numeric
|
@@ -989,113 +1710,181 @@ A result can carry forward three different types of values, modeled after the be
|
|
989
1710
|
- value_as_concept_id
|
990
1711
|
- For values that are like factors from the observation value_as_concept_id column
|
991
1712
|
|
992
|
-
|
993
|
-
By default, all value fields are set to NULL, unless a criterion node is explicitly written to populate one or more of those fields.
|
1713
|
+
By default, all value fields are set to NULL, unless a selection operator is explicitly written to populate one or more of those fields.
|
994
1714
|
|
995
1715
|
There are many operations that can be performed on the value_as\_\* columns and as those operations are implemented, this section will grow.
|
996
1716
|
|
997
|
-
For now we'll cover some of the general behavior of the value_as_numeric column and it's associated
|
1717
|
+
For now we'll cover some of the general behavior of the value_as_numeric column and it's associated operators.
|
1718
|
+
|
1719
|
+
### numeric
|
998
1720
|
|
999
|
-
#### numeric
|
1000
1721
|
- Takes 2 arguments
|
1001
1722
|
- A stream
|
1002
1723
|
- And a numeric value or a symbol representing the name of a column in CDM
|
1003
1724
|
|
1004
|
-
Passing streams through a `numeric`
|
1725
|
+
Passing streams through a `numeric` operator changes the number stored in the value column:
|
1726
|
+
|
1727
|
+
|
1728
|
+
```YAML
|
1729
|
+
---
|
1730
|
+
- numeric
|
1731
|
+
- 2
|
1732
|
+
- - icd9
|
1733
|
+
- '412'
|
1005
1734
|
|
1006
|
-
```ConceptQL
|
1007
|
-
# All MIs, setting value_as_numeric to 2
|
1008
|
-
{
|
1009
|
-
numeric: [
|
1010
|
-
{ icd9: '412' },
|
1011
|
-
2
|
1012
|
-
]
|
1013
|
-
}
|
1014
1735
|
```
|
1015
1736
|
|
1737
|
+
![](spec/d39452b58257c95a7cba07afed4877417b0c227f3690e2bff22c9eca89eac845.png)
|
1738
|
+
|
1739
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1740
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1741
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
1742
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
1743
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
1744
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
1745
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
1746
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
1747
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
1748
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
1749
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
1750
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
1751
|
+
|
1016
1752
|
`numeric` can also take a column name instead of a number. It will derive the results row's value from the value stored in the column specified.
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1753
|
+
|
1754
|
+
|
1755
|
+
```YAML
|
1756
|
+
---
|
1757
|
+
- numeric
|
1758
|
+
- paid_copay
|
1759
|
+
- - procedure_cost
|
1760
|
+
- - cpt
|
1761
|
+
- '99214'
|
1762
|
+
|
1025
1763
|
```
|
1026
1764
|
|
1765
|
+
![](spec/3f46dee4d775d1a29d52b68af6552f8ea3abd8303094e749714fc77bd7958155.png)
|
1766
|
+
|
1767
|
+
```No Results. Statement is experimental.```
|
1768
|
+
|
1027
1769
|
If something nonsensical happens, like the column specified isn't present in the table pointed to by a result row, value_as_numeric in the result row will be unaffected:
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1770
|
+
|
1771
|
+
|
1772
|
+
```YAML
|
1773
|
+
---
|
1774
|
+
- value
|
1775
|
+
- paid_copay
|
1776
|
+
- - icd9
|
1777
|
+
- '412'
|
1778
|
+
|
1036
1779
|
```
|
1037
1780
|
|
1781
|
+
![](spec/2b57886a9cba66bb696e4b399c51ad0dc95cd64b952709fafc819a79d573f09e.png)
|
1782
|
+
|
1783
|
+
```No Results. Statement is experimental.```
|
1784
|
+
|
1038
1785
|
Or if the column specified exists, but refers to a non-numerical column, we'll set the value to 0
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
With a `numeric` node defined, we could introduce a sum node that will sum by patient and type. This allows us to implement the Charlson comorbidity algorithm:
|
1050
|
-
```ConceptQL
|
1051
|
-
{
|
1052
|
-
sum: [
|
1053
|
-
{
|
1054
|
-
union: [
|
1055
|
-
{
|
1056
|
-
numeric: [
|
1057
|
-
{ person: { icd9: '412' } },
|
1058
|
-
1
|
1059
|
-
]
|
1060
|
-
},
|
1061
|
-
{
|
1062
|
-
numeric: [
|
1063
|
-
{ person: { icd9: '278.02' } },
|
1064
|
-
2
|
1065
|
-
]
|
1066
|
-
}
|
1067
|
-
]
|
1068
|
-
}
|
1069
|
-
]
|
1070
|
-
}
|
1786
|
+
|
1787
|
+
|
1788
|
+
```YAML
|
1789
|
+
---
|
1790
|
+
- value
|
1791
|
+
- stop_reason
|
1792
|
+
- - icd9
|
1793
|
+
- '412'
|
1794
|
+
|
1071
1795
|
```
|
1072
1796
|
|
1797
|
+
![](spec/7b9db2986ab9ada45cfb9451ef87ff1a2d99c908083334b7ccdceb8a92387fa9.png)
|
1798
|
+
|
1799
|
+
```No Results. Statement is experimental.```
|
1800
|
+
|
1801
|
+
With a `numeric` operator defined, we could introduce a sum operator that will sum by patient and type. This allows us to implement the Charlson comorbidity algorithm:
|
1802
|
+
|
1803
|
+
|
1804
|
+
```YAML
|
1805
|
+
---
|
1806
|
+
- sum
|
1807
|
+
- - union
|
1808
|
+
- - numeric
|
1809
|
+
- 1
|
1810
|
+
- - person
|
1811
|
+
- - icd9
|
1812
|
+
- '412'
|
1813
|
+
- - numeric
|
1814
|
+
- 2
|
1815
|
+
- - person
|
1816
|
+
- - icd9
|
1817
|
+
- '278.02'
|
1818
|
+
|
1819
|
+
```
|
1820
|
+
|
1821
|
+
![](spec/ba572c4f4dbade65be55f141df16cf7b3e7d09e0aec4e4e5debc4f2075277371.png)
|
1822
|
+
|
1823
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1824
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1825
|
+
| 20485 | 0 | person | 1939-04-01 | 1939-04-01 | 2DDD007275DD21E0 |
|
1826
|
+
| 79028 | 0 | person | 1959-02-01 | 1959-02-01 | B392FC430DF921CD |
|
1827
|
+
| 100859 | 0 | person | 1956-05-01 | 1956-05-01 | E52898242C537BA0 |
|
1828
|
+
| 14065 | 0 | person | 1946-11-01 | 1946-11-01 | 1F60AFE3D4FBB0F8 |
|
1829
|
+
| 19728 | 0 | person | 1929-03-01 | 1929-03-01 | 2C18DC0853458E88 |
|
1830
|
+
| 6249 | 0 | person | 1941-03-01 | 1941-03-01 | 0DD88DF606E34410 |
|
1831
|
+
| 81868 | 0 | person | 1942-09-01 | 1942-09-01 | BA17E53F3EB2C999 |
|
1832
|
+
| 111550 | 0 | person | 1943-06-01 | 1943-06-01 | FD35C56E74BFB4AB |
|
1833
|
+
| 93771 | 0 | person | 1941-01-01 | 1941-01-01 | D4BF3A123E98674C |
|
1834
|
+
| 92853 | 0 | person | 1932-06-01 | 1932-06-01 | D2945588C9CE4481 |
|
1835
|
+
|
1073
1836
|
### Counting
|
1074
|
-
It might be helpful to count the number of occurrences of a result row in a stream. A simple "count" node could group identical rows and store the number of occurrences in the value_as_numeric column.
|
1075
1837
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1838
|
+
It might be helpful to count the number of occurrences of a result row in a stream. A simple "count" operator could group identical rows and store the number of occurrences in the value_as_numeric column.
|
1839
|
+
|
1840
|
+
I need examples of algorithms that could benefit from this operator. I'm concerned that we'll want to roll up occurrences by person most of the time and that would require us to first cast streams to person before passing the person stream to count.
|
1841
|
+
|
1842
|
+
|
1843
|
+
```YAML
|
1844
|
+
---
|
1845
|
+
- count
|
1846
|
+
- - person
|
1847
|
+
- - icd9
|
1848
|
+
- '799.22'
|
1849
|
+
|
1082
1850
|
```
|
1083
1851
|
|
1852
|
+
![](spec/ff7d5b5573d09bd7c4cdd3aeda124d18bf82ec46673a62881b399a75d69f3f53.png)
|
1853
|
+
|
1854
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
1855
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
1856
|
+
| 84506 | 84506 | person | 1946-11-01 | 1946-11-01 | BFD9934105A902C5 |
|
1857
|
+
| 8511 | 8511 | person | 1934-02-01 | 1934-02-01 | 12F9E8CFD305414D |
|
1858
|
+
| 58597 | 58597 | person | 1922-11-01 | 1922-11-01 | 84841824E5D1516F |
|
1859
|
+
| 17481 | 17481 | person | 1952-04-01 | 1952-04-01 | 272C688CA4CFC78F |
|
1860
|
+
| 79930 | 79930 | person | 1940-04-01 | 1940-04-01 | B5AA192186CEFC33 |
|
1861
|
+
| 83321 | 83321 | person | 1928-06-01 | 1928-06-01 | BD49BED9C6228FA1 |
|
1862
|
+
| 111134 | 111134 | person | 1960-05-01 | 1960-05-01 | FC4C2599EA86941A |
|
1863
|
+
| 112745 | 112745 | person | 1959-07-01 | 1959-07-01 | FFFA950301FCA748 |
|
1864
|
+
| 11368 | 11368 | person | 1955-08-01 | 1955-08-01 | 19546CD71F65766E |
|
1865
|
+
| 24243 | 24243 | person | 1930-01-01 | 1930-01-01 | 3695943370154829 |
|
1866
|
+
|
1084
1867
|
We could do dumb things like count the number of times a row shows up in a union:
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1868
|
+
|
1869
|
+
|
1870
|
+
```YAML
|
1871
|
+
---
|
1872
|
+
- count
|
1873
|
+
- - union
|
1874
|
+
- - icd9
|
1875
|
+
- '412'
|
1876
|
+
- - primary_diagnosis
|
1877
|
+
- true
|
1878
|
+
|
1095
1879
|
```
|
1096
1880
|
|
1881
|
+
![](spec/7aa76b4d29874719466c2cbafc9936e9f12e504bf31e1a09d26ca3fffa8ba1a6.png)
|
1882
|
+
|
1883
|
+
```No Results. Statement is experimental.```
|
1884
|
+
|
1097
1885
|
#### Numeric Value Comparison
|
1098
|
-
|
1886
|
+
|
1887
|
+
Acts like any other binary operator. L and R streams, joined by person. Any L that pass comparison go downstream. R is thrown out. Comparison based on result row's value column.
|
1099
1888
|
|
1100
1889
|
- Less than
|
1101
1890
|
- Less than or equal
|
@@ -1104,32 +1893,41 @@ Acts like any other binary node. L and R streams, joined by person. Any L that
|
|
1104
1893
|
- Greater than
|
1105
1894
|
- Not equal
|
1106
1895
|
|
1896
|
+
### numeric as selection operator
|
1897
|
+
|
1898
|
+
Numeric doesn't have to take a stream. If it doesn't have a stream as an argument, it acts like a selection operator much like date_range
|
1107
1899
|
|
1108
|
-
### numeric as criterion node
|
1109
|
-
Numeric doesn't have to take a stream. If it doesn't have a stream as an argument, it acts like a criterion node much like date_range
|
1110
|
-
```ConceptQL
|
1111
|
-
# People with more than 1 MI
|
1112
|
-
{
|
1113
1900
|
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1901
|
+
```YAML
|
1902
|
+
---
|
1903
|
+
- greater_than
|
1904
|
+
- :left:
|
1905
|
+
- count
|
1906
|
+
- - person
|
1907
|
+
- - icd9
|
1908
|
+
- '412'
|
1909
|
+
:right:
|
1910
|
+
- numeric
|
1911
|
+
- 1
|
1912
|
+
|
1119
1913
|
```
|
1120
1914
|
|
1915
|
+
![](spec/c1d0402862221d85aceedc7d76b3f82149b612cbd972f14d0ca9011e1e2c455c.png)
|
1916
|
+
|
1917
|
+
```No Results. Statement is experimental.```
|
1918
|
+
|
1121
1919
|
#### sum
|
1920
|
+
|
1122
1921
|
- Takes a stream of results and does some wild things
|
1123
1922
|
- Groups all results by person and type
|
1124
1923
|
- Sums the value_as_numeric column within that grouping
|
1125
1924
|
- Sets start_date to the earliest start_date in the group
|
1126
1925
|
- Sets the end_date to the most recent end_date in the group
|
1127
|
-
- Sets
|
1926
|
+
- Sets selection_id to 0 since there is no particular single row that the result refers to anymore
|
1128
1927
|
|
1928
|
+
## Appendix A - Selection Operators
|
1129
1929
|
|
1130
|
-
|
1131
|
-
|
1132
|
-
| Node Name | Stream Type | Arguments | Returns |
|
1930
|
+
| Operator Name | Stream Type | Arguments | Returns |
|
1133
1931
|
| ---- | ---- | --------- | ------- |
|
1134
1932
|
| cpt | procedure_occurrence | 1 or more CPT codes | All results whose source_value match any of the CPT codes |
|
1135
1933
|
| icd9 | condition_occurrence | 1 or more ICD-9 codes | All results whose source_value match any of the ICD-9 codes |
|
@@ -1143,148 +1941,229 @@ Numeric doesn't have to take a stream. If it doesn't have a stream as an argume
|
|
1143
1941
|
| rxnorm | drug_exposure | 1 or more RxNorm IDs | All results whose drug_concept_id match any of the RxNorm IDs|
|
1144
1942
|
| snomed | condition_occurrence | 1 or more SNOMED codes | All results whose source_value match any of the SNOMED codes |
|
1145
1943
|
|
1944
|
+
## Appendix B - Algorithm Showcase
|
1146
1945
|
|
1147
|
-
|
1148
|
-
Here I take some concepts from [OMOP's Health Outcomes of Interest](http://omop.org/HOI) and turn them into ConceptQL statements to give more examples. I truncated some of the sets of codes to help ensure the diagrams didn't get too large.
|
1946
|
+
Here I take some algorithms from [OMOP's Health Outcomes of Interest](http://omop.org/HOI) and turn them into ConceptQL statements to give more examples. I truncated some of the sets of codes to help ensure the diagrams didn't get too large.
|
1149
1947
|
|
1150
1948
|
### Acute Kidney Injury - Narrow Definition and diagnositc procedure
|
1151
1949
|
|
1152
1950
|
- ICD-9 of 584
|
1153
1951
|
- AND
|
1154
|
-
|
1952
|
+
- ICD-9 procedure codes of 39.95 or 54.98 within 60 days after diagnosis
|
1155
1953
|
- AND NOT
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1954
|
+
- A diagnostic code of chronic dialysis any time before initial diagnosis
|
1955
|
+
- V45.1, V56.0, V56.31, V56.32, V56.8
|
1956
|
+
|
1957
|
+
|
1958
|
+
```YAML
|
1959
|
+
---
|
1960
|
+
- during
|
1961
|
+
- :left:
|
1962
|
+
- except
|
1963
|
+
- :left:
|
1964
|
+
- icd9
|
1965
|
+
- '584'
|
1966
|
+
:right:
|
1967
|
+
- after
|
1968
|
+
- :left:
|
1969
|
+
- icd9
|
1970
|
+
- '584'
|
1971
|
+
:right:
|
1972
|
+
- icd9
|
1973
|
+
- V45.1
|
1974
|
+
- V56.0
|
1975
|
+
- V56.31
|
1976
|
+
- V56.32
|
1977
|
+
- V56.8
|
1978
|
+
:right:
|
1979
|
+
- time_window
|
1980
|
+
- - icd9_procedure
|
1981
|
+
- '39.95'
|
1982
|
+
- '54.98'
|
1983
|
+
- :start: '0'
|
1984
|
+
:end: 60d
|
1985
|
+
|
1986
|
+
```
|
1987
|
+
|
1988
|
+
![](spec/44ec6743d5d77d15b8a487c2058bf3e455d34adc91c46ea05767f6e0e471a75e.png)
|
1989
|
+
|
1990
|
+
```No Results found.```
|
1181
1991
|
|
1182
1992
|
### Mortality after Myocardial Infarction #3
|
1993
|
+
|
1183
1994
|
- Person Died
|
1184
1995
|
- And Occurrence of 410\* prior to death
|
1185
1996
|
- And either
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1997
|
+
- MI diagnosis within 30 days prior to 410
|
1998
|
+
- MI therapy within 60 days after 410
|
1999
|
+
|
2000
|
+
|
2001
|
+
```YAML
|
2002
|
+
---
|
2003
|
+
- during
|
2004
|
+
- :left:
|
2005
|
+
- before
|
2006
|
+
- :left:
|
2007
|
+
- icd9
|
2008
|
+
- 410*
|
2009
|
+
:right:
|
2010
|
+
- death
|
2011
|
+
- true
|
2012
|
+
:right:
|
2013
|
+
- union
|
2014
|
+
- - time_window
|
2015
|
+
- - union
|
2016
|
+
- - cpt
|
2017
|
+
- 0146T
|
2018
|
+
- '75898'
|
2019
|
+
- '82554'
|
2020
|
+
- '92980'
|
2021
|
+
- '93010'
|
2022
|
+
- '93233'
|
2023
|
+
- '93508'
|
2024
|
+
- '93540'
|
2025
|
+
- '93545'
|
2026
|
+
- - icd9_procedure
|
2027
|
+
- '00.24'
|
2028
|
+
- '36.02'
|
2029
|
+
- '89.53'
|
2030
|
+
- '89.57'
|
2031
|
+
- '89.69'
|
2032
|
+
- - loinc
|
2033
|
+
- 10839-9
|
2034
|
+
- 13969-1
|
2035
|
+
- 18843-3
|
2036
|
+
- 2154-3
|
2037
|
+
- 33204-9
|
2038
|
+
- 48425-3
|
2039
|
+
- 49259-5
|
2040
|
+
- 6597-9
|
2041
|
+
- 8634-8
|
2042
|
+
- :start: "-30d"
|
2043
|
+
:end: '0'
|
2044
|
+
- - time_window
|
2045
|
+
- - union
|
2046
|
+
- - cpt
|
2047
|
+
- 0146T
|
2048
|
+
- '75898'
|
2049
|
+
- '82554'
|
2050
|
+
- '92980'
|
2051
|
+
- '93010'
|
2052
|
+
- '93233'
|
2053
|
+
- - icd9_procedure
|
2054
|
+
- '00.24'
|
2055
|
+
- '36.02'
|
2056
|
+
- '89.53'
|
2057
|
+
- '89.57'
|
2058
|
+
- '89.69'
|
2059
|
+
- :start: ''
|
2060
|
+
:end: 60d
|
2061
|
+
|
2062
|
+
```
|
2063
|
+
|
2064
|
+
![](spec/307a8b5a7edd6e42f8be16523a4c939faf1a0533385c861d7004b6af8addd7d1.png)
|
2065
|
+
|
2066
|
+
```No Results found.```
|
1227
2067
|
|
1228
2068
|
### GI Ulcer Hospitalization 2 (5000001002)
|
2069
|
+
|
1229
2070
|
- Occurrence of GI Ulcer diagnostic code
|
1230
2071
|
- Hospitalization at time of diagnostic code
|
1231
2072
|
- At least one diagnostic procedure during same hospitalization
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
2073
|
+
|
2074
|
+
|
2075
|
+
```YAML
|
2076
|
+
---
|
2077
|
+
- union
|
2078
|
+
- - place_of_service_code
|
2079
|
+
- '21'
|
2080
|
+
- - visit_occurrence
|
2081
|
+
- - icd9
|
2082
|
+
- '410'
|
2083
|
+
- - visit_occurrence
|
2084
|
+
- - union
|
2085
|
+
- - cpt
|
2086
|
+
- 0008T
|
2087
|
+
- 3142F
|
2088
|
+
- '43205'
|
2089
|
+
- '43236'
|
2090
|
+
- '76975'
|
2091
|
+
- '91110'
|
2092
|
+
- '91111'
|
2093
|
+
- - hcpcs
|
2094
|
+
- B4081
|
2095
|
+
- B4082
|
2096
|
+
- - icd9_procedure
|
2097
|
+
- '42.22'
|
2098
|
+
- '42.23'
|
2099
|
+
- '44.13'
|
2100
|
+
- '45.13'
|
2101
|
+
- '52.21'
|
2102
|
+
- '97.01'
|
2103
|
+
- - loinc
|
2104
|
+
- 16125-7
|
2105
|
+
- 17780-8
|
2106
|
+
- 40820-3
|
2107
|
+
- 50320-1
|
2108
|
+
- 5177-1
|
2109
|
+
- 7901-2
|
2110
|
+
|
2111
|
+
```
|
2112
|
+
|
2113
|
+
![](spec/99392f56dfb0e5be3f45a12a7f1ba846d094e430f526dfeaa30b606837cd34c0.png)
|
2114
|
+
|
2115
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
2116
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
2117
|
+
| 1 | 1 | visit_occurrence | 2010-03-12 | 2010-03-13 | Inpatient |
|
2118
|
+
| 2 | 8 | visit_occurrence | 2009-09-17 | 2009-09-20 | Inpatient |
|
2119
|
+
| 2 | 9 | visit_occurrence | 2009-04-12 | 2009-04-18 | Inpatient |
|
2120
|
+
| 2 | 10 | visit_occurrence | 2010-06-26 | 2010-07-01 | Inpatient |
|
2121
|
+
| 2 | 11 | visit_occurrence | 2009-08-31 | 2009-09-02 | Inpatient |
|
2122
|
+
| 14 | 507 | visit_occurrence | 2008-09-12 | 2008-09-12 | Inpatient |
|
2123
|
+
| 17 | 729 | visit_occurrence | 2010-05-22 | 2010-06-12 | Inpatient |
|
2124
|
+
| 17 | 730 | visit_occurrence | 2008-09-19 | 2008-09-22 | Inpatient |
|
2125
|
+
| 17 | 731 | visit_occurrence | 2010-06-02 | 2010-06-06 | Inpatient |
|
2126
|
+
| 17 | 732 | visit_occurrence | 2010-06-16 | 2010-06-19 | Inpatient |
|
2127
|
+
|
2128
|
+
## Appendix C - Under Development
|
2129
|
+
|
1253
2130
|
ConceptQL is not yet fully specified. These are modifications/enhancements that are under consideration. These ideas are most likely not completely refined and might actually represent changes that would fundamentally break ConceptQL.
|
1254
2131
|
|
1255
2132
|
### Todo List
|
2133
|
+
|
1256
2134
|
1. Handle costs
|
1257
2135
|
- How do we aggregate?
|
1258
|
-
|
1259
|
-
|
2136
|
+
1. How do we count?
|
2137
|
+
1. How do we handle missing values in streams?
|
1260
2138
|
- For instance, missing DoB on patient?
|
1261
|
-
|
2139
|
+
1. What does it mean to pass a date range as an L stream?
|
1262
2140
|
- I'm thinking we pass through no results
|
1263
2141
|
- Turns out that, as implemented, a date_range is really a person_stream where the start and end dates represent the range (instead of the date of birth) so we're probably OK
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
Some statements maybe very useful and it would be handy to reuse the bulk of the statement, but perhaps vary just a few things about it. ConceptQL supports the idea of using variables to represent sub-expressions. The variable node is used as a place holder to say "some criteria set belongs here". That variable can be defined in another part of the criteria set and will be used in all places the variable node appears.
|
2142
|
+
1. How do we want to look up standard vocab concepts?
|
2143
|
+
- I think Marc’s approach is a bit heavy-handed
|
1268
2144
|
|
2145
|
+
Some statements maybe very useful and it would be handy to reuse the bulk of the statement, but perhaps vary just a few things about it. ConceptQL supports the idea of using variables to represent sub-expressions. The variable operator is used as a place holder to say "some criteria set belongs here". That variable can be defined in another part of the criteria set and will be used in all places the variable operator appears.
|
1269
2146
|
|
1270
2147
|
### Future Work for Define and Recall
|
1271
|
-
|
2148
|
+
|
2149
|
+
I'd like to make it so if a variable operator is used, but not defined, the algorithm is still valid, but will fail to run until a definition for all missing variables is provided.
|
1272
2150
|
|
1273
2151
|
But I don't have a good feel for:
|
1274
2152
|
|
1275
2153
|
- Whether we should have users name the variables, or auto-assign a name?
|
1276
|
-
- We risk name collisions if a
|
2154
|
+
- We risk name collisions if a algorithm includes a sub-algorithm with the same variable name
|
1277
2155
|
- Probably need to name space all variables
|
1278
2156
|
- How to prompt users to enter values for variables in a concept
|
1279
|
-
- If we have name-spaced variables and sub-
|
1280
|
-
- We'll need to do a pass through a
|
2157
|
+
- If we have name-spaced variables and sub-algorithms needing values, how do we show this in a coherent manner to a user?
|
2158
|
+
- We'll need to do a pass through a algorithm to find all variables and prompt a user, then do another pass through the algorithm before attempting to execute it to ensure all variables have values
|
1281
2159
|
- Do we throw an exception if not?
|
1282
|
-
- Do we require calling programs to invoke a check on the
|
1283
|
-
- Perhaps slot is a different
|
1284
|
-
|
2160
|
+
- Do we require calling programs to invoke a check on the algorithm before generating the query?
|
2161
|
+
- Perhaps slot is a different operator from "define"
|
1285
2162
|
|
1286
2163
|
### Considerations for Values
|
2164
|
+
|
1287
2165
|
I'm considering defaulting each value_as\_\* column to some value.
|
2166
|
+
|
1288
2167
|
- numeric => 1
|
1289
2168
|
- concept_id => 0
|
1290
2169
|
- Or maybe the concept_id of the main concept_id value from the row?
|
@@ -1295,47 +2174,82 @@ I'm considering defaulting each value_as\_\* column to some value.
|
|
1295
2174
|
- source_value?
|
1296
2175
|
- Boy, this one is even harder to default
|
1297
2176
|
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
2177
|
+
|
2178
|
+
```YAML
|
2179
|
+
---
|
2180
|
+
- icd9
|
2181
|
+
- '412'
|
2182
|
+
|
1301
2183
|
```
|
1302
2184
|
|
2185
|
+
![](spec/f6b4fc31703cfb6327bbbd4614af8bb72da6d39fa3d53ada63a70157f2fad80e.png)
|
2186
|
+
|
2187
|
+
| person_id | criterion_id | criterion_type | start_date | end_date | source_value |
|
2188
|
+
| --------- | ------------ | -------------- | ---------- | -------- | ------------ |
|
2189
|
+
| 17 | 1712 | condition_occurrence | 2008-08-25 | 2008-08-25 | 412 |
|
2190
|
+
| 17 | 1829 | condition_occurrence | 2009-04-30 | 2009-04-30 | 412 |
|
2191
|
+
| 37 | 4359 | condition_occurrence | 2010-02-12 | 2010-02-12 | 412 |
|
2192
|
+
| 53 | 5751 | condition_occurrence | 2008-06-05 | 2008-06-05 | 412 |
|
2193
|
+
| 59 | 6083 | condition_occurrence | 2009-07-19 | 2009-07-22 | 412 |
|
2194
|
+
| 64 | 6902 | condition_occurrence | 2009-07-25 | 2009-07-25 | 412 |
|
2195
|
+
| 71 | 7865 | condition_occurrence | 2008-11-16 | 2008-11-16 | 412 |
|
2196
|
+
| 75 | 8397 | condition_occurrence | 2010-10-06 | 2010-10-06 | 412 |
|
2197
|
+
| 79 | 8618 | condition_occurrence | 2009-01-28 | 2009-01-30 | 412 |
|
2198
|
+
| 86 | 9882 | condition_occurrence | 2009-01-03 | 2009-01-09 | 412 |
|
2199
|
+
|
2200
|
+
### Filter Operator
|
2201
|
+
|
2202
|
+
Inspired by person_filter, why not just have a "filter" operator that filters L by R. Takes L, R, and an "as" option. As option temporarily casts the L and R streams to the type specified by :as and then does person by person comparison, only keeping rows that occur on both sides. Handy for keeping procedures that coincide with conditions without fully casting the streams:
|
2203
|
+
|
2204
|
+
|
2205
|
+
```YAML
|
2206
|
+
---
|
2207
|
+
- filter
|
2208
|
+
- :left:
|
2209
|
+
- cpt
|
2210
|
+
- '99214'
|
2211
|
+
:right:
|
2212
|
+
- icd9
|
2213
|
+
- '799.22'
|
2214
|
+
:as: visit_occurrence
|
1303
2215
|
|
1304
|
-
### Filter Node
|
1305
|
-
Inspired by person_filter, why not just have a "filter" node that filters L by R. Takes L, R, and an "as" option. As option temporarily casts the L and R streams to the type specified by :as and then does person by person comparison, only keeping rows that occur on both sides. Handy for keeping procedures that coincide with conditions without fully casting the streams:
|
1306
|
-
```ConceptQL
|
1307
|
-
# All 99214's where person was irritable during a visit
|
1308
|
-
{
|
1309
|
-
filter: {
|
1310
|
-
left: { cpt: '99214' },
|
1311
|
-
right: { icd9: '799.22' },
|
1312
|
-
as: 'visit_occurrence'
|
1313
|
-
}
|
1314
|
-
}
|
1315
2216
|
```
|
1316
2217
|
|
2218
|
+
![](spec/c5329a7f4937096a57b2e01efb9d542f84a4e2329a1e9381d08c630583ccad37.png)
|
2219
|
+
|
2220
|
+
```No Results found.```
|
2221
|
+
|
1317
2222
|
person_filter then becomes a special case of general filter:
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
2223
|
+
|
2224
|
+
|
2225
|
+
```YAML
|
2226
|
+
---
|
2227
|
+
- filter
|
2228
|
+
- :left:
|
2229
|
+
- cpt
|
2230
|
+
- '99214'
|
2231
|
+
:right:
|
2232
|
+
- icd9
|
2233
|
+
- '799.22'
|
2234
|
+
:as: person
|
2235
|
+
|
1327
2236
|
```
|
1328
2237
|
|
1329
|
-
|
2238
|
+
![](spec/9139440329dcb815df89bc70182c3827868402a74ff64d0253706dcaff723dca.png)
|
2239
|
+
|
2240
|
+
```No Results found.```
|
2241
|
+
|
2242
|
+
Filter operator is the opposite of Except. It only includes L if R matches.
|
1330
2243
|
|
1331
2244
|
### AS option for Except
|
1332
|
-
Just like Filter has an :as option, add one to Except node. This would simplify some of the algorithms I've developed.
|
1333
2245
|
|
2246
|
+
Just like Filter has an :as option, add one to Except operator. This would simplify some of the algorithms I've developed.
|
1334
2247
|
|
1335
2248
|
### How to Handle fact_relationship Table from CDMv5
|
1336
|
-
Each relationship type could be a binary node box read as L <relationship> R. E.g. L 'downstream of' R would take a L stream and only pass on downstreams of rows in R stream.
|
1337
2249
|
|
1338
|
-
|
2250
|
+
Each relationship type could be a binary operator box read as L <relationship\> R. E.g. L 'downstream of' R would take a L stream and only pass on downstreams of rows in R stream.
|
2251
|
+
|
2252
|
+
We could implement a single operator that takes a relationship as an argument (on top of the L and R arguments) or we could create a operator class for each relationship. I think it would be better to have a single relationship operator class and take the relationship as the argument.
|
1339
2253
|
|
1340
2254
|
The next question is: how do we actually join the two streams? I suppose we could translate each "type" into a "domain" and then join where l.domain = domain_concept_id_1 and l.entity_id = fact_id_1 and R.domain = domain_concept_id_2 and R.entity_id = fact_id_2 where the relationship chosen = relationship_concept_id.
|
1341
2255
|
|