conceptql 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +498 -0
- data/config/vocabularies.csv +85 -87
- data/config/vocabulary_formats.sha +1 -0
- data/config/vocabulary_formats.tsv +39 -0
- data/doc/spec.md +2091 -0
- data/lib/conceptql/behaviors/metadatable.rb +15 -3
- data/lib/conceptql/behaviors/provenanceable.rb +82 -8
- data/lib/conceptql/behaviors/utilizable.rb +5 -3
- data/lib/conceptql/cli.rb +1 -1
- data/lib/conceptql/data_model/base.rb +3 -171
- data/lib/conceptql/data_model/gdm.rb +3 -1
- data/lib/conceptql/data_model.rb +20 -4
- data/lib/conceptql/database.rb +9 -2
- data/lib/conceptql/date_adjuster.rb +12 -5
- data/lib/conceptql/lexicon/lexicon_gdm.rb +4 -1
- data/lib/conceptql/lexicon/lexicon_ohdsi.rb +19 -1
- data/lib/conceptql/lexicon/lexicon_strategy.rb +58 -4
- data/lib/conceptql/lexicon.rb +218 -2
- data/lib/conceptql/nodifier.rb +7 -1
- data/lib/conceptql/one_query_counts.rb +120 -0
- data/lib/conceptql/operators/co_reported.rb +4 -31
- data/lib/conceptql/operators/count.rb +4 -0
- data/lib/conceptql/operators/death.rb +1 -1
- data/lib/conceptql/operators/dedup.rb +1 -1
- data/lib/conceptql/operators/episode.rb +10 -2
- data/lib/conceptql/operators/ethnicity.rb +0 -4
- data/lib/conceptql/operators/except.rb +5 -0
- data/lib/conceptql/operators/filter.rb +12 -2
- data/lib/conceptql/operators/hospice.rb +2 -3
- data/lib/conceptql/operators/hospitalization.rb +2 -3
- data/lib/conceptql/operators/information_periods.rb +5 -4
- data/lib/conceptql/operators/invalid.rb +7 -1
- data/lib/conceptql/operators/multiple_vocabularies.rb +19 -6
- data/lib/conceptql/operators/numeric.rb +51 -14
- data/lib/conceptql/operators/occurrence.rb +16 -4
- data/lib/conceptql/operators/one_in_two_out.rb +1 -2
- data/lib/conceptql/operators/operator.rb +66 -30
- data/lib/conceptql/operators/person.rb +1 -1
- data/lib/conceptql/operators/person_filter.rb +5 -0
- data/lib/conceptql/operators/place_of_service_filter.rb +38 -10
- data/lib/conceptql/operators/provenance.rb +13 -4
- data/lib/conceptql/operators/provider_filter.rb +5 -1
- data/lib/conceptql/operators/race.rb +2 -10
- data/lib/conceptql/operators/read.rb +1 -100
- data/lib/conceptql/operators/recall.rb +1 -1
- data/lib/conceptql/operators/snf.rb +3 -4
- data/lib/conceptql/operators/sum.rb +46 -5
- data/lib/conceptql/operators/temporal_operator.rb +6 -2
- data/lib/conceptql/operators/trim_date.rb +52 -6
- data/lib/conceptql/operators/trim_date_end.rb +11 -1
- data/lib/conceptql/operators/trim_date_start.rb +11 -1
- data/lib/conceptql/operators/union.rb +45 -1
- data/lib/conceptql/operators/vocabulary.rb +21 -4
- data/lib/conceptql/paths.rb +16 -0
- data/lib/conceptql/query.rb +78 -24
- data/lib/conceptql/query_modifiers/gdm/provider_query_modifier.rb +7 -7
- data/lib/conceptql/rdbms/generic.rb +21 -1
- data/lib/conceptql/rdbms/spark.rb +12 -0
- data/lib/conceptql/scope.rb +187 -24
- data/lib/conceptql/version.rb +1 -1
- data/lib/conceptql/vocabularies/drg_systems.rb +118 -0
- data/lib/conceptql/vocabularies/dynamic_vocabularies.rb +10 -4
- data/lib/conceptql/vocabularies/entry.rb +15 -23
- data/lib/conceptql/vocabularies/formats.rb +59 -0
- data/lib/conceptql/vocabularies/vocabulary_class_factory.rb +8 -16
- data/lib/conceptql/window/table.rb +12 -3
- metadata +9 -14
- data/lib/conceptql/data_model/omopv4_plus.rb +0 -12
- data/lib/conceptql/operators/concurrent_within.rb +0 -69
- data/lib/conceptql/query_modifiers/omopv4_plus/admission_date_query_modifier.rb +0 -45
- data/lib/conceptql/query_modifiers/omopv4_plus/drug_query_modifier.rb +0 -80
- data/lib/conceptql/query_modifiers/omopv4_plus/pos_query_modifier.rb +0 -47
- data/lib/conceptql/query_modifiers/omopv4_plus/provenance_query_modifier.rb +0 -45
- data/lib/conceptql/query_modifiers/omopv4_plus/provider_query_modifier.rb +0 -26
- data/lib/conceptql/vocabularies/behaviors/costish.rb +0 -24
- data/lib/conceptql/vocabularies/behaviors/omopish.rb +0 -32
- data/schemas/omopv4_plus.yml +0 -729
- data/schemas/omopv4_plus_more_ignorables.tsv +0 -13
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "csv"
|
|
4
|
+
require_relative "../paths"
|
|
5
|
+
|
|
6
|
+
module ConceptQL
|
|
7
|
+
module Vocabularies
|
|
8
|
+
# The code formats that a Vocabulary operator checks its codes against.
|
|
9
|
+
# They come from config/vocabulary_formats.tsv, a pinned copy of the
|
|
10
|
+
# published table of the public repository
|
|
11
|
+
# outcomesinsights/vocabulary_formats (bead conceptql-bns, seed
|
|
12
|
+
# conceptql-ysx). config/vocabulary_formats.sha records the commit, and
|
|
13
|
+
# `just vocabulary-formats <ref>` refreshes both.
|
|
14
|
+
#
|
|
15
|
+
# Only the DEFAULT row of a vocabulary is used: the row whose vocabulary_id
|
|
16
|
+
# is the vocabulary's id. A variant row (ICD9CM.DOTLESS) is never used. The
|
|
17
|
+
# published patterns carry no anchors, so each one is anchored here as
|
|
18
|
+
# \A(?:pattern)\z. A vocabulary with no row has no format to check.
|
|
19
|
+
#
|
|
20
|
+
# A pattern is case-exact unless its row declares case-insensitivity with
|
|
21
|
+
# the scoped flag (?i:...) (vocabulary_formats seed vfm-8k1, seed
|
|
22
|
+
# conceptql-oji ruling "b"). Ruby honors the flag natively, so a pattern
|
|
23
|
+
# is compiled with no flag of its own: an ignore-case flag would override
|
|
24
|
+
# what the row says.
|
|
25
|
+
module Formats
|
|
26
|
+
DECLARES_CASE_INSENSITIVE = "(?i:"
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
# The anchored pattern of a vocabulary as a string, or nil. The
|
|
30
|
+
# vocabulary_id finds its row in any case.
|
|
31
|
+
def pattern(vocabulary_id)
|
|
32
|
+
patterns[vocabulary_id.to_s.downcase]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The anchored pattern as a Regexp, or nil.
|
|
36
|
+
def regexp(vocabulary_id)
|
|
37
|
+
(str = pattern(vocabulary_id)) && Regexp.new(str)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# True when the vocabulary's row declares case-insensitivity with
|
|
41
|
+
# (?i:...). The lexicon then matches the vocabulary's codes without
|
|
42
|
+
# regard to case (LexiconStrategy#code_condition). A vocabulary with no
|
|
43
|
+
# row is case-exact.
|
|
44
|
+
def case_insensitive?(vocabulary_id)
|
|
45
|
+
pattern(vocabulary_id).to_s.include?(DECLARES_CASE_INSENSITIVE)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def patterns
|
|
51
|
+
@patterns ||= CSV.foreach(ConceptQL.vocabulary_formats_file_path, col_sep: "\t", headers: true)
|
|
52
|
+
.reject { |row| row["vocabulary_id"].include?(".") }
|
|
53
|
+
.to_h { |row| [ row["vocabulary_id"].downcase, "\\A(?:#{row.fetch("regexp")})\\z" ] }
|
|
54
|
+
.freeze
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
require_relative "../behaviors/drugish"
|
|
4
4
|
require_relative "../behaviors/labish"
|
|
5
5
|
require_relative "behaviors/gdmish"
|
|
6
|
-
require_relative "
|
|
7
|
-
require_relative "behaviors/costish"
|
|
6
|
+
require_relative "drg_systems"
|
|
8
7
|
require_relative "../operators/vocabulary"
|
|
9
8
|
|
|
10
9
|
module ConceptQL
|
|
@@ -19,9 +18,8 @@ module ConceptQL
|
|
|
19
18
|
def get_klasses
|
|
20
19
|
{
|
|
21
20
|
gdm: get_gdm_klass,
|
|
22
|
-
gdm_wide: get_gdm_klass
|
|
23
|
-
|
|
24
|
-
}.compact
|
|
21
|
+
gdm_wide: get_gdm_klass
|
|
22
|
+
}
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
def get_gdm_klass
|
|
@@ -30,16 +28,6 @@ module ConceptQL
|
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
|
|
33
|
-
def get_omopv4_plus_klass
|
|
34
|
-
return nil unless entry.belongs_in_omopv4_plus?
|
|
35
|
-
|
|
36
|
-
get_klass do
|
|
37
|
-
include Behaviors::Omopish
|
|
38
|
-
|
|
39
|
-
include Behaviors::Costish if entry.is_costish?
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
31
|
def get_klass(&block)
|
|
44
32
|
ventry = entry
|
|
45
33
|
Class.new(ConceptQL::Operators::Vocabulary) do |klass|
|
|
@@ -52,7 +40,7 @@ module ConceptQL
|
|
|
52
40
|
preferred_name entry.preferred_name
|
|
53
41
|
argument :codes, type: :codelist
|
|
54
42
|
aliases entry.aliases
|
|
55
|
-
predominant_domains
|
|
43
|
+
predominant_domains(*entry.predominant_domains)
|
|
56
44
|
short_name entry.short_name
|
|
57
45
|
long_name entry.long_name
|
|
58
46
|
conceptql_spec_id "vocabulary"
|
|
@@ -75,6 +63,10 @@ module ConceptQL
|
|
|
75
63
|
|
|
76
64
|
include ConceptQL::Behaviors::Drugish if entry.is_drugish?
|
|
77
65
|
|
|
66
|
+
include DrgSystems::OperatorBehavior if DrgSystems.system(entry.id)
|
|
67
|
+
|
|
68
|
+
deprecated DrgSystems::DRG_DEPRECATION if entry.id == DrgSystems::DRG_OPERATOR
|
|
69
|
+
|
|
78
70
|
def vocab_entry
|
|
79
71
|
self.class.entry
|
|
80
72
|
end
|
|
@@ -25,8 +25,11 @@ module ConceptQL
|
|
|
25
25
|
|
|
26
26
|
rhs = query.db[get_table_window(query)]
|
|
27
27
|
|
|
28
|
+
# select_group replaces the select list, so rhs needs no
|
|
29
|
+
# remove_window_id. Its select_remove asked the database for the
|
|
30
|
+
# columns of the window table while the SQL was built (bead
|
|
31
|
+
# conceptql-6k8).
|
|
28
32
|
unless opts[:precalculated_window_id]
|
|
29
|
-
rhs = remove_window_id(rhs)
|
|
30
33
|
rhs = rhs
|
|
31
34
|
.select_group(:person_id, :start_date, :end_date)
|
|
32
35
|
.select_append do
|
|
@@ -37,7 +40,7 @@ module ConceptQL
|
|
|
37
40
|
|
|
38
41
|
rhs = rhs.as(:r)
|
|
39
42
|
|
|
40
|
-
remove_window_id(query)
|
|
43
|
+
remove_window_id(query, op.dynamic_columns)
|
|
41
44
|
.from_self(alias: :l)
|
|
42
45
|
.join(rhs, expr)
|
|
43
46
|
.select_all(:l)
|
|
@@ -52,12 +55,18 @@ module ConceptQL
|
|
|
52
55
|
db[get_table_window(nil)].select(:person_id)
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
# columns: the names of the columns of ds, when the caller knows them.
|
|
59
|
+
# For a ds without a select list, select_remove asks the database for
|
|
60
|
+
# them, and a table that ds reads may not exist while the SQL is built
|
|
61
|
+
# (bead conceptql-6k8).
|
|
62
|
+
def remove_window_id(ds, columns = nil)
|
|
56
63
|
cols = ds.opts[:select]
|
|
57
64
|
if cols && !cols.empty? && cols.any? { |c| !c.is_a?(Symbol) }
|
|
58
65
|
# When select has non-symbol expressions (e.g. CAST...AS),
|
|
59
66
|
# select_remove can't match them by symbol name, so filter manually
|
|
60
67
|
ds.select(*cols.reject { |c| window_id_column?(c) })
|
|
68
|
+
elsif columns && cols.blank?
|
|
69
|
+
ds.select(*(columns - [ :window_id ]))
|
|
61
70
|
else
|
|
62
71
|
ds.select_remove(:window_id)
|
|
63
72
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: conceptql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Duryea
|
|
@@ -102,7 +102,7 @@ dependencies:
|
|
|
102
102
|
version: 0.3.0
|
|
103
103
|
- - "<"
|
|
104
104
|
- !ruby/object:Gem::Version
|
|
105
|
-
version: '0.
|
|
105
|
+
version: '0.6'
|
|
106
106
|
type: :runtime
|
|
107
107
|
prerelease: false
|
|
108
108
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -112,7 +112,7 @@ dependencies:
|
|
|
112
112
|
version: 0.3.0
|
|
113
113
|
- - "<"
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: '0.
|
|
115
|
+
version: '0.6'
|
|
116
116
|
- !ruby/object:Gem::Dependency
|
|
117
117
|
name: thor
|
|
118
118
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -328,6 +328,9 @@ files:
|
|
|
328
328
|
- config/provenance.yml
|
|
329
329
|
- config/race.yml
|
|
330
330
|
- config/vocabularies.csv
|
|
331
|
+
- config/vocabulary_formats.sha
|
|
332
|
+
- config/vocabulary_formats.tsv
|
|
333
|
+
- doc/spec.md
|
|
331
334
|
- lib/conceptql.rb
|
|
332
335
|
- lib/conceptql/behaviors/code_lister.rb
|
|
333
336
|
- lib/conceptql/behaviors/drugish.rb
|
|
@@ -344,7 +347,6 @@ files:
|
|
|
344
347
|
- lib/conceptql/data_model/base.rb
|
|
345
348
|
- lib/conceptql/data_model/gdm.rb
|
|
346
349
|
- lib/conceptql/data_model/gdm_wide.rb
|
|
347
|
-
- lib/conceptql/data_model/omopv4_plus.rb
|
|
348
350
|
- lib/conceptql/database.rb
|
|
349
351
|
- lib/conceptql/date_adjuster.rb
|
|
350
352
|
- lib/conceptql/diagram.rb
|
|
@@ -354,13 +356,13 @@ files:
|
|
|
354
356
|
- lib/conceptql/lexicon/lexicon_ohdsi.rb
|
|
355
357
|
- lib/conceptql/lexicon/lexicon_strategy.rb
|
|
356
358
|
- lib/conceptql/nodifier.rb
|
|
359
|
+
- lib/conceptql/one_query_counts.rb
|
|
357
360
|
- lib/conceptql/operators/after.rb
|
|
358
361
|
- lib/conceptql/operators/any_overlap.rb
|
|
359
362
|
- lib/conceptql/operators/before.rb
|
|
360
363
|
- lib/conceptql/operators/binary_operator_operator.rb
|
|
361
364
|
- lib/conceptql/operators/casting_operator.rb
|
|
362
365
|
- lib/conceptql/operators/co_reported.rb
|
|
363
|
-
- lib/conceptql/operators/concurrent_within.rb
|
|
364
366
|
- lib/conceptql/operators/contains.rb
|
|
365
367
|
- lib/conceptql/operators/count.rb
|
|
366
368
|
- lib/conceptql/operators/date_range.rb
|
|
@@ -418,11 +420,6 @@ files:
|
|
|
418
420
|
- lib/conceptql/query_modifiers/gdm_wide/lab_query_modifier.rb
|
|
419
421
|
- lib/conceptql/query_modifiers/gdm_wide/pos_query_modifier.rb
|
|
420
422
|
- lib/conceptql/query_modifiers/gdm_wide/provenance_query_modifier.rb
|
|
421
|
-
- lib/conceptql/query_modifiers/omopv4_plus/admission_date_query_modifier.rb
|
|
422
|
-
- lib/conceptql/query_modifiers/omopv4_plus/drug_query_modifier.rb
|
|
423
|
-
- lib/conceptql/query_modifiers/omopv4_plus/pos_query_modifier.rb
|
|
424
|
-
- lib/conceptql/query_modifiers/omopv4_plus/provenance_query_modifier.rb
|
|
425
|
-
- lib/conceptql/query_modifiers/omopv4_plus/provider_query_modifier.rb
|
|
426
423
|
- lib/conceptql/query_modifiers/query_modifier.rb
|
|
427
424
|
- lib/conceptql/rdbms.rb
|
|
428
425
|
- lib/conceptql/rdbms/duckdb.rb
|
|
@@ -434,11 +431,11 @@ files:
|
|
|
434
431
|
- lib/conceptql/utils_cli.rb
|
|
435
432
|
- lib/conceptql/version.rb
|
|
436
433
|
- lib/conceptql/visitors/metadata_extractor.rb
|
|
437
|
-
- lib/conceptql/vocabularies/behaviors/costish.rb
|
|
438
434
|
- lib/conceptql/vocabularies/behaviors/gdmish.rb
|
|
439
|
-
- lib/conceptql/vocabularies/
|
|
435
|
+
- lib/conceptql/vocabularies/drg_systems.rb
|
|
440
436
|
- lib/conceptql/vocabularies/dynamic_vocabularies.rb
|
|
441
437
|
- lib/conceptql/vocabularies/entry.rb
|
|
438
|
+
- lib/conceptql/vocabularies/formats.rb
|
|
442
439
|
- lib/conceptql/vocabularies/vocabulary_class_factory.rb
|
|
443
440
|
- lib/conceptql/window.rb
|
|
444
441
|
- lib/conceptql/window/base.rb
|
|
@@ -449,8 +446,6 @@ files:
|
|
|
449
446
|
- schemas/gdm.yml
|
|
450
447
|
- schemas/gdm_wide.yml
|
|
451
448
|
- schemas/ohdsi_vocabs.yml
|
|
452
|
-
- schemas/omopv4_plus.yml
|
|
453
|
-
- schemas/omopv4_plus_more_ignorables.tsv
|
|
454
449
|
homepage: https://github.com/outcomesinsights/conceptql
|
|
455
450
|
licenses:
|
|
456
451
|
- MIT
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "operator"
|
|
4
|
-
require_relative "../date_adjuster"
|
|
5
|
-
|
|
6
|
-
module ConceptQL
|
|
7
|
-
module Operators
|
|
8
|
-
class ConcurrentWithin < Operator
|
|
9
|
-
register __FILE__
|
|
10
|
-
|
|
11
|
-
def events_per_patient
|
|
12
|
-
upstreams.all? { |u| u.events_per_patient == :single } ? :single : :multiple
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def multiple_vocabularies
|
|
16
|
-
return true if upstreams.any?(&:multiple_vocabularies)
|
|
17
|
-
|
|
18
|
-
vocabularies.length > 1
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
desc "Filters each upstream to only include records where other upstreams' date ranges overlap"
|
|
22
|
-
option :start, type: :string
|
|
23
|
-
option :end, type: :string
|
|
24
|
-
allows_many_upstreams
|
|
25
|
-
validate_at_least_one_upstream
|
|
26
|
-
validate_no_arguments
|
|
27
|
-
validate_option DateAdjuster::VALID_INPUT, :start, :end
|
|
28
|
-
category "Combine Streams"
|
|
29
|
-
basic_type :set
|
|
30
|
-
default_query_columns
|
|
31
|
-
|
|
32
|
-
def query(db)
|
|
33
|
-
datasets = upstreams.map do |stream|
|
|
34
|
-
stream.evaluate(db)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
return datasets.first.from_self if datasets.length == 1
|
|
38
|
-
|
|
39
|
-
adjusted_start_date = DateAdjuster.new(self, options[:start]).adjust(Sequel[:l][:start_date], true)
|
|
40
|
-
adjusted_end_date = DateAdjuster.new(self, options[:end]).adjust(Sequel[:l][:end_date])
|
|
41
|
-
|
|
42
|
-
datasets = datasets.map do |ds|
|
|
43
|
-
matching = ds.from_self(alias: :l)
|
|
44
|
-
|
|
45
|
-
(datasets - [ ds ]).each do |other|
|
|
46
|
-
other = other
|
|
47
|
-
.from_self(alias: :r)
|
|
48
|
-
.where(adjusted_start_date <= Sequel[:r][:start_date])
|
|
49
|
-
.where(adjusted_end_date >= Sequel[:r][:end_date])
|
|
50
|
-
.select(*matching_columns)
|
|
51
|
-
|
|
52
|
-
matching = matching.where(other.where(matching_columns.map do |x|
|
|
53
|
-
[ Sequel.qualify(:l, x), Sequel.qualify(:r, x) ]
|
|
54
|
-
end).exists)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
matching
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
ds, *rest = datasets
|
|
61
|
-
rest.each do |other|
|
|
62
|
-
ds = ds.union(other, from_self: nil)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
ds.from_self
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../query_modifier"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module QueryModifiers
|
|
7
|
-
module Omopv4Plus
|
|
8
|
-
class AdmissionDateQueryModifier < QueryModifier
|
|
9
|
-
def self.provided_columns
|
|
10
|
-
%i[
|
|
11
|
-
admission_date
|
|
12
|
-
discharge_date
|
|
13
|
-
]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def self.has_required_columns?(cols)
|
|
17
|
-
cols.map(&:to_s).any? { |col| col =~ /start_date/i }
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def modified_query
|
|
21
|
-
cols = dm.table_cols(source_table).map(&:to_s)
|
|
22
|
-
return query unless cols.any? { |col| col =~ /start_date/i }
|
|
23
|
-
|
|
24
|
-
start_col = cols.find { |col| col =~ /start_date/i }.to_sym
|
|
25
|
-
end_col = cols.find { |col| col =~ /end_date/i }.to_sym
|
|
26
|
-
|
|
27
|
-
query.from_self(alias: :t)
|
|
28
|
-
.select_all(:t)
|
|
29
|
-
.select_append(Sequel[:t][start_col].as(:admission_date))
|
|
30
|
-
.select_append(Sequel.function(:coalesce, Sequel[:t][end_col],
|
|
31
|
-
Sequel[:t][start_col]).as(:discharge_date))
|
|
32
|
-
.from_self
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def domain
|
|
38
|
-
op.domain
|
|
39
|
-
rescue StandardError
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../query_modifier"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module QueryModifiers
|
|
7
|
-
module Omopv4Plus
|
|
8
|
-
class DrugQueryModifier < QueryModifier
|
|
9
|
-
attr_reader :db
|
|
10
|
-
|
|
11
|
-
def self.provided_columns
|
|
12
|
-
%i[
|
|
13
|
-
drug_name
|
|
14
|
-
drug_amount
|
|
15
|
-
drug_amount_units
|
|
16
|
-
drug_quantity
|
|
17
|
-
drug_days_supply
|
|
18
|
-
]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.has_required_columns?(cols)
|
|
22
|
-
needed = [ :drug_concept_id ]
|
|
23
|
-
found = needed & cols
|
|
24
|
-
needed == found
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def initialize(*args)
|
|
28
|
-
super
|
|
29
|
-
@db = query.db
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def modified_query
|
|
33
|
-
return query unless dm.table_cols(source_table).include?(:drug_concept_id)
|
|
34
|
-
|
|
35
|
-
query.db
|
|
36
|
-
drug_concept_ids = query.select(:drug_concept_id).distinct
|
|
37
|
-
query.from_self(alias: :de)
|
|
38
|
-
.left_join(micro_table(drug_concept_ids).as(:mt), drug_concept_id: :drug_concept_id)
|
|
39
|
-
.select_all(:de)
|
|
40
|
-
.select_append(Sequel[:de][:quantity].as(:drug_quantity))
|
|
41
|
-
.select_append(Sequel[:de][:days_supply].as(:drug_days_supply))
|
|
42
|
-
.select_append(Sequel[:mt][:amount_value].as(:drug_amount))
|
|
43
|
-
.select_append(Sequel[:mt][:amount_unit].as(:drug_amount_units))
|
|
44
|
-
.select_append(Sequel[:mt][:drug_name].as(:drug_name))
|
|
45
|
-
.from_self
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def micro_table(drug_concept_ids)
|
|
51
|
-
# TODO: Does drug_strength only have RXNORM concept_ids?
|
|
52
|
-
# TODO: What is vocabulary for units? Can we shrink concept table to just that vocab before joining?
|
|
53
|
-
collapsed_strengths = db[:drug_strength]
|
|
54
|
-
.where(drug_concept_id: drug_concept_ids)
|
|
55
|
-
.select_group(:drug_concept_id)
|
|
56
|
-
.select_append(
|
|
57
|
-
Sequel.function(:min, :amount_value).as(:amount_value),
|
|
58
|
-
Sequel.function(:min, :amount_unit).as(:amount_unit),
|
|
59
|
-
Sequel.function(:count, 1).as(:dcount)
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
value_case = Sequel.case({ 1 => :amount_value }, nil, :dcount).as(:amount_value)
|
|
63
|
-
unit_case = Sequel.case({ 1 => :amount_unit }, nil, :dcount).as(:amount_unit)
|
|
64
|
-
|
|
65
|
-
collapsed_strengths = collapsed_strengths.from_self.select(:drug_concept_id, value_case, unit_case)
|
|
66
|
-
|
|
67
|
-
db.from(Sequel[:concept].as(:dc))
|
|
68
|
-
.left_join(collapsed_strengths, { drug_concept_id: :concept_id }, { table_alias: :ds })
|
|
69
|
-
.where(Sequel[:dc][:concept_id] => drug_concept_ids)
|
|
70
|
-
.select(
|
|
71
|
-
Sequel[:dc][:concept_id].as(:drug_concept_id),
|
|
72
|
-
Sequel[:dc][:concept_name].as(:drug_name),
|
|
73
|
-
Sequel[:ds][:amount_value].as(:amount_value),
|
|
74
|
-
Sequel[:ds][:amount_unit].as(:amount_unit)
|
|
75
|
-
)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../query_modifier"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module QueryModifiers
|
|
7
|
-
module Omopv4Plus
|
|
8
|
-
class PoSQueryModifier < QueryModifier
|
|
9
|
-
attr_reader :join_id, :table, :source_column, :column
|
|
10
|
-
|
|
11
|
-
def self.provided_columns
|
|
12
|
-
[ :visit_source_concept_id ]
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.has_required_columns?(cols)
|
|
16
|
-
needed = [ :visit_occurrence_id ]
|
|
17
|
-
found = needed & cols
|
|
18
|
-
needed == found
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def initialize(*args)
|
|
22
|
-
super
|
|
23
|
-
@column = :visit_source_concept_id
|
|
24
|
-
@join_id = :visit_occurrence_id
|
|
25
|
-
@table = :visit_occurrence
|
|
26
|
-
@source_column = :visit_source_concept_id
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def modified_query
|
|
30
|
-
return query unless dm.table_cols(source_table).include?(join_id)
|
|
31
|
-
return query if dm.table_cols(source_table).include?(column)
|
|
32
|
-
|
|
33
|
-
left_alias = "tab1".to_sym
|
|
34
|
-
right_alias = "tab2".to_sym
|
|
35
|
-
|
|
36
|
-
extra_table = query.db.from(table).select(Sequel.as(source_column, column), join_id)
|
|
37
|
-
ds = query.from_self(alias: left_alias)
|
|
38
|
-
ds.left_join(extra_table.as(right_alias),
|
|
39
|
-
Sequel.qualify(left_alias, join_id) => Sequel.qualify(right_alias, join_id))
|
|
40
|
-
.select_all(left_alias)
|
|
41
|
-
.select_append(Sequel.qualify(right_alias, column).as(column))
|
|
42
|
-
.from_self
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../query_modifier"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module QueryModifiers
|
|
7
|
-
module Omopv4Plus
|
|
8
|
-
class ProvenanceQueryModifier < QueryModifier
|
|
9
|
-
RELATED_COLUMNS = %w[
|
|
10
|
-
condition_type_concept_id
|
|
11
|
-
procedure_type_concept_id
|
|
12
|
-
death_type_concept_id
|
|
13
|
-
observation_type_concept_id
|
|
14
|
-
drug_type_concept_id
|
|
15
|
-
].sort.map(&:to_sym)
|
|
16
|
-
|
|
17
|
-
attr_reader :db
|
|
18
|
-
|
|
19
|
-
def self.provided_columns
|
|
20
|
-
%i[
|
|
21
|
-
file_provenance_type
|
|
22
|
-
code_provenance_type
|
|
23
|
-
]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def self.has_required_columns?(cols)
|
|
27
|
-
!(RELATED_COLUMNS & cols).empty?
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def initialize(*args)
|
|
31
|
-
super
|
|
32
|
-
@db = query.db
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def modified_query
|
|
36
|
-
return query unless self.class.has_required_columns?(dm.table_cols(source_table))
|
|
37
|
-
|
|
38
|
-
query.select_append(Sequel[dm.file_provenance_type_column(query, source_table)].as(:file_provenance_type),
|
|
39
|
-
Sequel[dm.code_provenance_type_column(query,
|
|
40
|
-
source_table)].as(:code_provenance_type)).from_self
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../query_modifier"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module QueryModifiers
|
|
7
|
-
module Omopv4Plus
|
|
8
|
-
class ProviderQueryModifier < QueryModifier
|
|
9
|
-
def self.provided_columns
|
|
10
|
-
[ :provider_id ]
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.has_required_columns?(cols)
|
|
14
|
-
cols.find { |col| col.to_s =~ /provider_id/ }
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def modified_query
|
|
18
|
-
col = self.class.has_required_columns?(dm.table_cols(source_table))
|
|
19
|
-
return query if col.nil? || col.to_sym == :provider_id
|
|
20
|
-
|
|
21
|
-
query.select_append(Sequel[col].as(:provider_id)).from_self
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../../operators/vocabulary"
|
|
4
|
-
|
|
5
|
-
module ConceptQL
|
|
6
|
-
module Vocabularies
|
|
7
|
-
module Behaviors
|
|
8
|
-
module Costish
|
|
9
|
-
def query(db)
|
|
10
|
-
costs = db[:procedure_cost].where(column_to_search => values).select(:procedure_occurrence_id)
|
|
11
|
-
db[:procedure_occurrence].where(procedure_occurrence_id: costs)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def table
|
|
15
|
-
:procedure_occurrence
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def column_to_search
|
|
19
|
-
vocab_entry.id == "revenue_code" ? :revenue_code_source_value : :disease_class_source_value
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ConceptQL
|
|
4
|
-
module Vocabularies
|
|
5
|
-
module Behaviors
|
|
6
|
-
module Omopish
|
|
7
|
-
# Overrides Operator#tables
|
|
8
|
-
def tables
|
|
9
|
-
domains
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def vocabulary_condition
|
|
13
|
-
{ dm.source_vocabulary_id(domain) => vocabulary_id.to_i }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def where_clause(_db)
|
|
17
|
-
conds = vocabulary_condition
|
|
18
|
-
conds[dm.source_value_column(domain)] = arguments unless select_all?
|
|
19
|
-
conds
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def query_cols
|
|
23
|
-
dm.table_columns(domain)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def translated_vocabulary_id
|
|
27
|
-
vocab_entry.omopv4_id
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|