hqmf-parser 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/lib/hqmf-generator/hqmf-generator.rb +1 -1
- data/lib/hqmf-model/document.rb +1 -1
- data/lib/hqmf-model/population_criteria.rb +4 -3
- data/lib/hqmf-parser/1.0/population_criteria.rb +1 -5
- data/lib/hqmf-parser/2.0/document.rb +1 -1
- data/lib/hqmf-parser/2.0/population_criteria.rb +1 -1
- data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +6 -4
- data/lib/hqmf-parser/converter/pass1/document_converter.rb +1 -1
- data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +7 -3
- data/lib/hqmf-parser/converter/pass1/simple_data_criteria.rb +1 -10
- metadata +2 -4
- data/lib/hqmf-parser/converter/pass3/specific_occurrence_converter.rb +0 -86
- data/lib/hqmf-parser/converter/pass3/specific_occurrence_converter_bak.rb +0 -70
data/Gemfile
CHANGED
@@ -7,7 +7,7 @@ gem 'nokogiri'
|
|
7
7
|
gem 'rubyzip'
|
8
8
|
|
9
9
|
#gem "health-data-standards", :git => 'http://github.com/projectcypress/health-data-standards.git', :branch => 'develop'
|
10
|
-
gem "health-data-standards", '~> 2.1.
|
10
|
+
gem "health-data-standards", '~> 2.1.3'
|
11
11
|
gem "bson_ext"
|
12
12
|
|
13
13
|
# below are gems required for excel spreadsheet processing
|
@@ -278,7 +278,7 @@ module HQMF2
|
|
278
278
|
'denominator'
|
279
279
|
when HQMF::PopulationCriteria::NUMER
|
280
280
|
'numerator'
|
281
|
-
when HQMF::PopulationCriteria::
|
281
|
+
when HQMF::PopulationCriteria::DENEXCEP
|
282
282
|
'denominatorException'
|
283
283
|
when HQMF::PopulationCriteria::DENEX
|
284
284
|
'denominatorExclusion'
|
data/lib/hqmf-model/document.rb
CHANGED
@@ -40,7 +40,7 @@ module HQMF
|
|
40
40
|
HQMF::PopulationCriteria::IPP => HQMF::PopulationCriteria::IPP,
|
41
41
|
HQMF::PopulationCriteria::DENOM => HQMF::PopulationCriteria::DENOM,
|
42
42
|
HQMF::PopulationCriteria::NUMER => HQMF::PopulationCriteria::NUMER,
|
43
|
-
HQMF::PopulationCriteria::
|
43
|
+
HQMF::PopulationCriteria::DENEXCEP => HQMF::PopulationCriteria::DENEXCEP,
|
44
44
|
HQMF::PopulationCriteria::DENEX => HQMF::PopulationCriteria::DENEX
|
45
45
|
}
|
46
46
|
]
|
@@ -10,10 +10,11 @@ module HQMF
|
|
10
10
|
IPP = 'IPP'
|
11
11
|
DENOM = 'DENOM'
|
12
12
|
NUMER = 'NUMER'
|
13
|
-
|
13
|
+
DENEXCEP = 'DENEXCEP'
|
14
14
|
DENEX = 'DENEX'
|
15
|
+
MSRPOPL = 'MSRPOPL'
|
15
16
|
|
16
|
-
ALL_POPULATION_CODES = [IPP, DENOM, NUMER,
|
17
|
+
ALL_POPULATION_CODES = [IPP, DENOM, NUMER, DENEXCEP, DENEX, MSRPOPL]
|
17
18
|
|
18
19
|
# Create a new population criteria
|
19
20
|
# @param [String] id
|
@@ -64,7 +65,7 @@ module HQMF
|
|
64
65
|
case @type
|
65
66
|
when IPP, DENOM, NUMER
|
66
67
|
HQMF::Precondition::ALL_TRUE
|
67
|
-
when
|
68
|
+
when DENEXCEP, DENEX
|
68
69
|
HQMF::Precondition::AT_LEAST_ONE_TRUE
|
69
70
|
else
|
70
71
|
raise "Unknown population type [#{@type}]"
|
@@ -24,7 +24,7 @@ module HQMF1
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Get the code for the population criteria
|
27
|
-
# @return [String] the code (e.g. IPP, DEMON, NUMER, DENEX,
|
27
|
+
# @return [String] the code (e.g. IPP, DEMON, NUMER, DENEX, DENEXCEP)
|
28
28
|
def code
|
29
29
|
value = attr_val('cda:observation/cda:value/@code')
|
30
30
|
# exclusion population criteria has id of DENOM with actionNegationInd of true
|
@@ -32,10 +32,6 @@ module HQMF1
|
|
32
32
|
if attr_val('cda:observation/@actionNegationInd')=='true'
|
33
33
|
value = HQMF::PopulationCriteria::DENEX
|
34
34
|
end
|
35
|
-
# replace measure population with NUMER. MSRPOPL is used in continuous variable calculations.
|
36
|
-
value = HQMF::PopulationCriteria::NUMER if value == 'MSRPOPL'
|
37
|
-
# replace DENEXCEP with EXCEP. DENEXCEP is used by the MAT instead of EXCEP as required by HQMF V2 and QRDA.
|
38
|
-
value = HQMF::PopulationCriteria::EXCEP if value == 'DENEXCEP'
|
39
35
|
value.upcase
|
40
36
|
end
|
41
37
|
|
@@ -57,7 +57,7 @@ module HQMF2
|
|
57
57
|
HQMF::PopulationCriteria::IPP => 'patientPopulationCriteria',
|
58
58
|
HQMF::PopulationCriteria::DENOM => 'denominatorCriteria',
|
59
59
|
HQMF::PopulationCriteria::NUMER => 'numeratorCriteria',
|
60
|
-
HQMF::PopulationCriteria::
|
60
|
+
HQMF::PopulationCriteria::DENEXCEP => 'denominatorExceptionCriteria',
|
61
61
|
HQMF::PopulationCriteria::DENEX => 'denominatorExclusionCriteria'
|
62
62
|
}.each_pair do |criteria_id, criteria_element_name|
|
63
63
|
criteria_def = population_def.at_xpath("cda:component[cda:#{criteria_element_name}]", NAMESPACES)
|
@@ -36,7 +36,7 @@ module HQMF2
|
|
36
36
|
case @type
|
37
37
|
when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER
|
38
38
|
HQMF::Precondition::ALL_TRUE
|
39
|
-
when HQMF::PopulationCriteria::
|
39
|
+
when HQMF::PopulationCriteria::DENEXCEP, HQMF::PopulationCriteria::DENEX
|
40
40
|
HQMF::Precondition::AT_LEAST_ONE_TRUE
|
41
41
|
else
|
42
42
|
raise "Unknown population type [#{@type}]"
|
@@ -22,10 +22,6 @@ module HQMF
|
|
22
22
|
# the restrictions added may be different for the numerator, denominator, different IPP_1, IPP_2, etc.
|
23
23
|
def duplicate_data_criteria(data_criteria, parent_id)
|
24
24
|
|
25
|
-
# if this is a specific occurrence, then we do not want to duplicate it.
|
26
|
-
# we may need to duplicate it for a population however.
|
27
|
-
# return data_criteria if (specific_occurrences[data_criteria.id])
|
28
|
-
|
29
25
|
if (data_criteria.is_a? HQMF::Converter::SimpleDataCriteria and data_criteria.precondition_id == parent_id)
|
30
26
|
new_data_criteria = data_criteria
|
31
27
|
else
|
@@ -176,6 +172,12 @@ module HQMF
|
|
176
172
|
specific_occurrence = criteria[:specific_occurrence]
|
177
173
|
specific_occurrence_const = criteria[:specific_occurrence_const]
|
178
174
|
|
175
|
+
# specific occurrences do not properly set the description, so we want to add the definition and status
|
176
|
+
if (specific_occurrence)
|
177
|
+
_status = ", #{status.titleize}" if status
|
178
|
+
description = "#{definition.titleize}#{_status}: #{description}"
|
179
|
+
end
|
180
|
+
|
179
181
|
value = nil # value is filled out by backfill_patient_characteristics for things like gender and by REFR restrictions
|
180
182
|
effective_time = nil # filled out by temporal reference code
|
181
183
|
temporal_references = # filled out by operator code
|
@@ -169,7 +169,7 @@ module HQMF
|
|
169
169
|
|
170
170
|
oid_fields = document.all_data_criteria.select {|dc| dc.field_values != nil}
|
171
171
|
if oid_fields.size > 0
|
172
|
-
referenced_oids = (oid_fields.map{|dc| dc.field_values.map {|key,field| puts "field: #{key} is nil" unless field; field.code_list_id if field != nil and field.type == 'CD'}}).flatten.compact.uniq
|
172
|
+
referenced_oids = (oid_fields.map{|dc| dc.field_values.map {|key,field| puts "field: #{key} is nil" unless field || key.match(/DATETIME/); field.code_list_id if field != nil and field.type == 'CD'}}).flatten.compact.uniq
|
173
173
|
referenced_oids.each do |oid|
|
174
174
|
value_set = codes[oid]
|
175
175
|
puts "\tFIELDS (#{document.id},#{document.title}): referenced OID could not be found #{oid}" unless value_set
|
@@ -25,8 +25,9 @@ module HQMF
|
|
25
25
|
ipps = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::IPP}
|
26
26
|
denoms = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::DENOM}
|
27
27
|
nums = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::NUMER}
|
28
|
+
msrpopls = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::MSRPOPL}
|
28
29
|
excls = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::DENEX}
|
29
|
-
denexcs = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::
|
30
|
+
denexcs = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::DENEXCEP}
|
30
31
|
|
31
32
|
if (ipps.size<=1 and denoms.size<=1 and nums.size<=1 and excls.size<=1 and denexcs.size<=1 )
|
32
33
|
@sub_measures <<
|
@@ -34,7 +35,7 @@ module HQMF
|
|
34
35
|
HQMF::PopulationCriteria::IPP => HQMF::PopulationCriteria::IPP,
|
35
36
|
HQMF::PopulationCriteria::DENOM => HQMF::PopulationCriteria::DENOM,
|
36
37
|
HQMF::PopulationCriteria::NUMER => HQMF::PopulationCriteria::NUMER,
|
37
|
-
HQMF::PopulationCriteria::
|
38
|
+
HQMF::PopulationCriteria::DENEXCEP => HQMF::PopulationCriteria::DENEXCEP,
|
38
39
|
HQMF::PopulationCriteria::DENEX => HQMF::PopulationCriteria::DENEX
|
39
40
|
}
|
40
41
|
else
|
@@ -42,10 +43,13 @@ module HQMF
|
|
42
43
|
nums.each do |num_id, num|
|
43
44
|
@sub_measures << {HQMF::PopulationCriteria::NUMER => num.id}
|
44
45
|
end
|
46
|
+
msrpopls.each do |popl_id, popl|
|
47
|
+
@sub_measures << {HQMF::PopulationCriteria::MSRPOPL => popl.id}
|
48
|
+
end
|
45
49
|
apply_to_submeasures(@sub_measures, HQMF::PopulationCriteria::DENOM, denoms.values)
|
46
50
|
apply_to_submeasures(@sub_measures, HQMF::PopulationCriteria::IPP, ipps.values)
|
47
51
|
apply_to_submeasures(@sub_measures, HQMF::PopulationCriteria::DENEX, excls.values)
|
48
|
-
apply_to_submeasures(@sub_measures, HQMF::PopulationCriteria::
|
52
|
+
apply_to_submeasures(@sub_measures, HQMF::PopulationCriteria::DENEXCEP, denexcs.values)
|
49
53
|
|
50
54
|
keep = []
|
51
55
|
@sub_measures.each do |sub|
|
@@ -7,9 +7,7 @@ module HQMF
|
|
7
7
|
attr_accessor :precondition_id
|
8
8
|
|
9
9
|
def self.from_data_criteria(data_criteria)
|
10
|
-
description
|
11
|
-
|
12
|
-
HQMF::Converter::SimpleDataCriteria.new(data_criteria.id, data_criteria.title, data_criteria.display_name, description, data_criteria.code_list_id,
|
10
|
+
HQMF::Converter::SimpleDataCriteria.new(data_criteria.id, data_criteria.title, data_criteria.display_name, data_criteria.description, data_criteria.code_list_id,
|
13
11
|
data_criteria.children_criteria, data_criteria.derivation_operator, data_criteria.definition,data_criteria.status, data_criteria.value, data_criteria.field_values,
|
14
12
|
data_criteria.effective_time, data_criteria.inline_code_list,data_criteria.negation,data_criteria.negation_code_list_id,data_criteria.temporal_references, data_criteria.subset_operators, data_criteria.specific_occurrence,data_criteria.specific_occurrence_const)
|
15
13
|
end
|
@@ -21,13 +19,6 @@ module HQMF
|
|
21
19
|
@id = "#{@id}_precondition_#{precondtion_id}"
|
22
20
|
end
|
23
21
|
|
24
|
-
def self.get_description(data_criteria)
|
25
|
-
description = data_criteria.description
|
26
|
-
status = ", #{data_criteria.status.titleize}" if data_criteria.status
|
27
|
-
description = "#{data_criteria.definition.titleize}#{status}: #{data_criteria.description}" if (data_criteria.description.downcase.match /#{data_criteria.definition.titleize.downcase}/).nil? and (data_criteria.description.downcase.match /#{data_criteria.status}/).nil?
|
28
|
-
description
|
29
|
-
end
|
30
|
-
|
31
22
|
end
|
32
23
|
end
|
33
24
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hqmf-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-11-
|
14
|
+
date: 2012-11-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rubyzip
|
@@ -119,8 +119,6 @@ files:
|
|
119
119
|
- lib/hqmf-parser/converter/pass1/simple_restriction.rb
|
120
120
|
- lib/hqmf-parser/converter/pass2/comparison_converter.rb
|
121
121
|
- lib/hqmf-parser/converter/pass2/operator_converter.rb
|
122
|
-
- lib/hqmf-parser/converter/pass3/specific_occurrence_converter.rb
|
123
|
-
- lib/hqmf-parser/converter/pass3/specific_occurrence_converter_bak.rb
|
124
122
|
- lib/hqmf-parser/parser.rb
|
125
123
|
- lib/hqmf-parser/value_sets/value_set_parser.rb
|
126
124
|
- lib/hqmf-parser.rb
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module HQMF
|
2
|
-
# Class for cleaning up references to specific occurrences in the tree
|
3
|
-
class SpecificOccurrenceConverter
|
4
|
-
|
5
|
-
def initialize(data_criteria_converter)
|
6
|
-
@data_criteria_converter = data_criteria_converter
|
7
|
-
end
|
8
|
-
|
9
|
-
def convert_specific_occurrences(population_criteria)
|
10
|
-
population_criteria.each do |population|
|
11
|
-
walk_up_tree(population.preconditions)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def walk_up_tree(preconditions)
|
16
|
-
preconditions.each do |precondition|
|
17
|
-
if (has_child_comparison(precondition))
|
18
|
-
walk_up_tree(precondition.preconditions)
|
19
|
-
end
|
20
|
-
unless (precondition.comparison?)
|
21
|
-
occurrence_map = get_grouped_occurrences(precondition.preconditions)
|
22
|
-
occurrence_map.each do |key, value|
|
23
|
-
|
24
|
-
##
|
25
|
-
##### figure out negations
|
26
|
-
##
|
27
|
-
|
28
|
-
if (precondition.conjunction_code == 'atLeastOneTrue')
|
29
|
-
|
30
|
-
group = @data_criteria_converter.build_group_data_criteria(value, "#{key}_union", precondition.id, HQMF::DataCriteria::UNION)
|
31
|
-
binding.pry
|
32
|
-
elsif (precondition.conjunction_code == 'allTrue')
|
33
|
-
binding.pry
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def get_grouped_occurrences(preconditions)
|
42
|
-
|
43
|
-
result = {}
|
44
|
-
preconditions.each do |precondition|
|
45
|
-
if (precondition.preconditions and !precondition.preconditions.empty?)
|
46
|
-
get_grouped_occurrences(precondition.preconditions).each do |key, value|
|
47
|
-
if (result[key])
|
48
|
-
result[key].concat(value)
|
49
|
-
else
|
50
|
-
result[key] = value
|
51
|
-
end
|
52
|
-
end
|
53
|
-
else
|
54
|
-
data_criteria = @data_criteria_converter.v2_data_criteria_by_id[precondition.reference.id]
|
55
|
-
if is_specific_occurrence(data_criteria)
|
56
|
-
binding.pry
|
57
|
-
result[data_criteria.source_data_criteria] ||= []
|
58
|
-
result[data_criteria.source_data_criteria] << data_criteria
|
59
|
-
preconditions.delete(precondition)
|
60
|
-
binding.pry
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
result
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def is_specific_occurrence(data_criteria)
|
69
|
-
!data_criteria.specific_occurrence.nil?
|
70
|
-
end
|
71
|
-
|
72
|
-
def has_child_comparison(node)
|
73
|
-
value = false
|
74
|
-
node.preconditions.each do |precondition|
|
75
|
-
if (precondition.comparison?)
|
76
|
-
value ||= true
|
77
|
-
elsif precondition.has_preconditions?
|
78
|
-
value ||= has_child_comparison(precondition)
|
79
|
-
end
|
80
|
-
end if node.preconditions
|
81
|
-
value
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module HQMF
|
2
|
-
# Class for cleaning up references to specific occurrences in the tree
|
3
|
-
class SpecificOccurrenceConverter
|
4
|
-
|
5
|
-
def initialize(data_criteria_converter)
|
6
|
-
@data_criteria_converter = data_criteria_converter
|
7
|
-
end
|
8
|
-
|
9
|
-
def convert_specific_occurrences(population_criteria)
|
10
|
-
create_precondition_map(population_criteria)
|
11
|
-
|
12
|
-
@specific_occurrence_key_mapper = {}
|
13
|
-
|
14
|
-
specific_occurrences = {}
|
15
|
-
@data_criteria_converter.v2_data_criteria.each do |data_criteria|
|
16
|
-
if (is_specific_occurrence(data_criteria))
|
17
|
-
if (data_criteria.respond_to? :precondition_id and @precondition_map[data_criteria.precondition_id])
|
18
|
-
specific_occurrences[data_criteria.source_data_criteria] ||= []
|
19
|
-
specific_occurrences[data_criteria.source_data_criteria] << data_criteria
|
20
|
-
elsif (data_criteria.children_criteria or data_criteria.subset_operators or data_criteria.temporal_references)
|
21
|
-
binding.pry
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
specific_occurrences.each do |key, occurrences|
|
26
|
-
|
27
|
-
occurrences.sort! do |left, right|
|
28
|
-
@precondition_map[right.precondition_id].depth <=> @precondition_map[left.precondition_id].depth
|
29
|
-
end
|
30
|
-
|
31
|
-
occurrences.each_cons(2) do |pair|
|
32
|
-
parent = get_common_parent(@precondition_map[pair[0].precondition_id], @precondition_map[pair[1].precondition_id])
|
33
|
-
binding.pry
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def get_common_parent(left, right)
|
40
|
-
return left if left == right
|
41
|
-
get_common_parent(@precondition_parent_map[left.id], @precondition_parent_map[right.id])
|
42
|
-
end
|
43
|
-
|
44
|
-
def create_precondition_map(population_criteria)
|
45
|
-
@precondition_map = {}
|
46
|
-
@precondition_parent_map = {}
|
47
|
-
depth = 0
|
48
|
-
population_criteria.each do |population|
|
49
|
-
recurse_precondition_map(population, depth)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def recurse_precondition_map(node, depth)
|
54
|
-
node.preconditions.each do |precondition|
|
55
|
-
precondition.depth = depth
|
56
|
-
@precondition_map[precondition.id] = precondition
|
57
|
-
@precondition_parent_map[precondition.id] = node
|
58
|
-
if precondition.has_preconditions?
|
59
|
-
depth += 1
|
60
|
-
recurse_precondition_map(precondition, depth)
|
61
|
-
end
|
62
|
-
end if node.preconditions
|
63
|
-
end
|
64
|
-
|
65
|
-
def is_specific_occurrence(data_criteria)
|
66
|
-
!data_criteria.specific_occurrence.nil?
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|