tnql 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.hound.yml +10 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +11 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Guardfile +15 -0
- data/LICENSE.txt +21 -0
- data/README.md +74 -0
- data/Rakefile +12 -0
- data/bin/console +10 -0
- data/bin/setup +7 -0
- data/code_safety.yml +272 -0
- data/lib/tnql.rb +4 -0
- data/lib/tnql/constants.rb +8 -0
- data/lib/tnql/grammars.rb +16 -0
- data/lib/tnql/grammars/age.treetop +63 -0
- data/lib/tnql/grammars/batch_types.treetop +65 -0
- data/lib/tnql/grammars/dates.treetop +35 -0
- data/lib/tnql/grammars/diagnosis.treetop +23 -0
- data/lib/tnql/grammars/e_base_records.treetop +86 -0
- data/lib/tnql/grammars/main.treetop +54 -0
- data/lib/tnql/grammars/patient.treetop +39 -0
- data/lib/tnql/grammars/provider.treetop +21 -0
- data/lib/tnql/grammars/registration_status.treetop +11 -0
- data/lib/tnql/grammars/registry.treetop +15 -0
- data/lib/tnql/grammars/staging.treetop +23 -0
- data/lib/tnql/grammars/treatment.treetop +35 -0
- data/lib/tnql/grammars/tumour_type.treetop +54 -0
- data/lib/tnql/grammars/vital_status.treetop +19 -0
- data/lib/tnql/nodes.rb +25 -0
- data/lib/tnql/nodes/age.rb +82 -0
- data/lib/tnql/nodes/batch_types.rb +52 -0
- data/lib/tnql/nodes/dates.rb +50 -0
- data/lib/tnql/nodes/diagnosis.rb +31 -0
- data/lib/tnql/nodes/e_base_records.rb +61 -0
- data/lib/tnql/nodes/main.rb +11 -0
- data/lib/tnql/nodes/patient.rb +9 -0
- data/lib/tnql/nodes/provider.rb +24 -0
- data/lib/tnql/nodes/registration_status.rb +27 -0
- data/lib/tnql/nodes/registry.rb +33 -0
- data/lib/tnql/nodes/staging.rb +17 -0
- data/lib/tnql/nodes/treatment.rb +45 -0
- data/lib/tnql/nodes/tumour_type.rb +74 -0
- data/lib/tnql/nodes/vital_status.rb +15 -0
- data/lib/tnql/parser.rb +56 -0
- data/lib/tnql/treetop/extensions.rb +20 -0
- data/lib/tnql/version.rb +4 -0
- data/tnql.gemspec +39 -0
- metadata +286 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tnql
|
2
|
+
grammar Staging
|
3
|
+
rule stage
|
4
|
+
space stage_detail word_break
|
5
|
+
end
|
6
|
+
|
7
|
+
rule stage_detail
|
8
|
+
('stage' space stages:stage_value* / 'unstaged' / 'valid stage') <Nodes::StageDetailNode>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule stage_value
|
12
|
+
number / unstageable / insufficient_info
|
13
|
+
end
|
14
|
+
|
15
|
+
rule unstageable
|
16
|
+
'u'
|
17
|
+
end
|
18
|
+
|
19
|
+
rule insufficient_info
|
20
|
+
'?'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Tnql
|
2
|
+
grammar Treatment
|
3
|
+
rule treatment
|
4
|
+
treated_keyword conditions:treatment_conditions+
|
5
|
+
end
|
6
|
+
|
7
|
+
rule treated_keyword
|
8
|
+
space 'treated' word_break
|
9
|
+
end
|
10
|
+
|
11
|
+
rule treatment_conditions
|
12
|
+
treatmentdate_range / treatmentdate_detail / treatment_provider
|
13
|
+
end
|
14
|
+
|
15
|
+
rule treatmentdate_range
|
16
|
+
space 'between' space start:date_fragment space 'and' space finish:date_fragment <Nodes::TreatmentDateRangeNode>
|
17
|
+
end
|
18
|
+
|
19
|
+
rule treatmentdate_detail
|
20
|
+
space ('in' / 'on') space date_fragment <Nodes::TreatmentPreciseDateNode>
|
21
|
+
end
|
22
|
+
|
23
|
+
rule treatment_provider
|
24
|
+
space 'at' space provider:(treatment_provider_code / treatment_provider_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
rule treatment_provider_name
|
28
|
+
(!(space provider_type) .)+ space provider_type <Nodes::TreatmentProviderNameNode>
|
29
|
+
end
|
30
|
+
|
31
|
+
rule treatment_provider_code
|
32
|
+
provider_type space code:(!' ' .)+ <Nodes::TreatmentProviderCodeNode>
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Tnql
|
2
|
+
grammar TumourType
|
3
|
+
rule behaviour
|
4
|
+
space behaviour_detail word_break
|
5
|
+
end
|
6
|
+
|
7
|
+
rule behaviour_detail
|
8
|
+
('behaviour' space number / 'noninvasive' / 'non-invasive' / 'invasive' / 'metastatic') <Nodes::BehaviourDetailNode>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule tumour_type
|
12
|
+
space (site_group / names_type / sites) word_break
|
13
|
+
end
|
14
|
+
|
15
|
+
rule site_group
|
16
|
+
('brain' / 'breast' / 'endocrine' / 'gynaecological'
|
17
|
+
/ 'haematological' / 'head' space 'and' space 'neck'
|
18
|
+
/ 'lower' space 'gi' / 'lung' / 'other' / 'sarcoma'
|
19
|
+
/ 'skin' / 'upper' space 'gi' / 'urological') <Nodes::SiteGroupNode>
|
20
|
+
end
|
21
|
+
|
22
|
+
rule names_type
|
23
|
+
( melanoma / non_melanoma ) word_break
|
24
|
+
end
|
25
|
+
|
26
|
+
rule melanoma
|
27
|
+
'melanoma' <Nodes::MelanomaNode>
|
28
|
+
end
|
29
|
+
|
30
|
+
rule non_melanoma
|
31
|
+
('nmsc' / 'non-melanoma' / 'non' space 'melanoma') <Nodes::NonMelanomaNode>
|
32
|
+
end
|
33
|
+
|
34
|
+
rule sites
|
35
|
+
first:site rest:more_sites* <Nodes::SitesNode>
|
36
|
+
end
|
37
|
+
|
38
|
+
rule more_sites
|
39
|
+
','? space? ('and' space)? site <Nodes::AdditionalSiteNode>
|
40
|
+
end
|
41
|
+
|
42
|
+
rule site
|
43
|
+
(icd_site / snomed_site) <Nodes::SingleSiteNode>
|
44
|
+
end
|
45
|
+
|
46
|
+
rule icd_site
|
47
|
+
[cd] [0-9] [0-9] '.'? [0-9]?
|
48
|
+
end
|
49
|
+
|
50
|
+
rule snomed_site
|
51
|
+
't' [0-9fxy] [0-9fxy] [0-9fxy]? [0-9fxy]? [0-9y]?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Tnql
|
2
|
+
grammar VitalStatus
|
3
|
+
rule dead_or_alive
|
4
|
+
space vital_status:('dead' / 'alive') word_break <Nodes::DeadOrAliveNode>
|
5
|
+
end
|
6
|
+
|
7
|
+
rule death_certificate
|
8
|
+
have_keyword space modifier:('no' / 'a') death_certificate_keywords <Nodes::DeathCertificateNode>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule death_certificate_keywords
|
12
|
+
space 'death' space 'certificate' word_break
|
13
|
+
end
|
14
|
+
|
15
|
+
rule have_keyword
|
16
|
+
space 'have' word_break
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/tnql/nodes.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# These file contain custom mixins for treetop
|
2
|
+
# nodes that enable them to generate meta_data_items, etc.
|
3
|
+
|
4
|
+
# Treetop documentation seems to be out of date;
|
5
|
+
# it says to create subclasses of nodes. However,
|
6
|
+
# treetop 1.4.10 expects to extend the node with
|
7
|
+
# the specified <MODULE> from the grammar.
|
8
|
+
|
9
|
+
require 'tnql/treetop/extensions'
|
10
|
+
require 'tnql/constants'
|
11
|
+
|
12
|
+
require 'tnql/nodes/age'
|
13
|
+
require 'tnql/nodes/batch_types'
|
14
|
+
require 'tnql/nodes/dates'
|
15
|
+
require 'tnql/nodes/diagnosis'
|
16
|
+
require 'tnql/nodes/e_base_records'
|
17
|
+
require 'tnql/nodes/main'
|
18
|
+
require 'tnql/nodes/patient'
|
19
|
+
require 'tnql/nodes/provider'
|
20
|
+
require 'tnql/nodes/registration_status'
|
21
|
+
require 'tnql/nodes/registry'
|
22
|
+
require 'tnql/nodes/staging'
|
23
|
+
require 'tnql/nodes/treatment'
|
24
|
+
require 'tnql/nodes/tumour_type'
|
25
|
+
require 'tnql/nodes/vital_status'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Tnql #:nodoc: all
|
2
|
+
module Nodes
|
3
|
+
module AgeNode
|
4
|
+
def to_limits
|
5
|
+
age.to_limits
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ExactAgeNode
|
10
|
+
def to_exact
|
11
|
+
text_value.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_limits
|
15
|
+
i = to_exact
|
16
|
+
[i, i]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module FuzzyAgeNode
|
21
|
+
def to_limits
|
22
|
+
[start.to_exact, finish.to_exact]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module AgeAtDiagnosisNode
|
27
|
+
def meta_data_item
|
28
|
+
{ 'patient.age' => { Tnql::LIMITS => age.to_limits } }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module DeathDateNode
|
33
|
+
def meta_data_item
|
34
|
+
range = fuzzy_date.to_daterange
|
35
|
+
{
|
36
|
+
'patient.deathdate' => {
|
37
|
+
Tnql::LIMITS => [
|
38
|
+
range.date1.try(:to_date).try(:iso8601), range.date2.try(:to_date).try(:iso8601)
|
39
|
+
]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module BirthDateNode
|
46
|
+
def meta_data_item
|
47
|
+
range = fuzzy_date.to_daterange
|
48
|
+
{
|
49
|
+
'patient.birthdate' => {
|
50
|
+
Tnql::LIMITS => [
|
51
|
+
range.date1.try(:to_date).try(:iso8601), range.date2.try(:to_date).try(:iso8601)
|
52
|
+
]
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module CtyaNode
|
59
|
+
def meta_data_item
|
60
|
+
{ 'patient.age' => { Tnql::LIMITS => [0, 24] } }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module PaediatricNode
|
65
|
+
def meta_data_item
|
66
|
+
{ 'patient.age' => { Tnql::LIMITS => [0, 15] } }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module TeenageNode
|
71
|
+
def meta_data_item
|
72
|
+
{ 'patient.age' => { Tnql::LIMITS => [16, 18] } }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module YoungAdultNode
|
77
|
+
def meta_data_item
|
78
|
+
{ 'patient.age' => { Tnql::LIMITS => [19, 24] } }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Tnql #:nodoc: all
|
2
|
+
module Nodes
|
3
|
+
module BatchTypeNode
|
4
|
+
def to_type
|
5
|
+
string = respond_to?(:normalise) ? normalise : text_value
|
6
|
+
string.upcase
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module USomNode
|
11
|
+
def normalise
|
12
|
+
'usom'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module UPathNode
|
17
|
+
def normalise
|
18
|
+
'upath'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module UPasNode
|
23
|
+
def normalise
|
24
|
+
'upas'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module UCwtNode
|
29
|
+
def normalise
|
30
|
+
'ucwt'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module UCdNode
|
35
|
+
def normalise
|
36
|
+
'ucd'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module UNcdNode
|
41
|
+
def normalise
|
42
|
+
'uncd'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module UExtregNode
|
47
|
+
def normalise
|
48
|
+
'uextreg'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'chronic'
|
2
|
+
require 'ndr_support/daterange'
|
3
|
+
|
4
|
+
module Tnql #:nodoc: all
|
5
|
+
module Nodes
|
6
|
+
module FuzzyDateNode
|
7
|
+
def to_daterange
|
8
|
+
date.to_daterange
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module SpecificDateNode
|
13
|
+
def to_daterange
|
14
|
+
date_fragment.to_daterange
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module FragmentedDateRangeNode
|
19
|
+
def to_daterange
|
20
|
+
d1 = start.to_daterange.date1
|
21
|
+
d2 = finish.to_daterange.date2
|
22
|
+
|
23
|
+
Daterange.new(d1, d2)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module DateFragmentNode
|
28
|
+
def to_daterange
|
29
|
+
fragment.to_daterange
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module DateRangeNode
|
34
|
+
def to_daterange
|
35
|
+
Daterange.new(text_value.to_s)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ChronicDateNode
|
40
|
+
def to_daterange
|
41
|
+
chronic = Chronic.parse(text_value.to_s, context: :past, guess: false)
|
42
|
+
if chronic.instance_of?(Chronic::Span)
|
43
|
+
Daterange.new(chronic.begin, chronic.end - 1.day)
|
44
|
+
else
|
45
|
+
Daterange.new(chronic)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Tnql #:nodoc: all
|
2
|
+
module Nodes
|
3
|
+
module DiagnosisDateRangeNode
|
4
|
+
def meta_data_item
|
5
|
+
{
|
6
|
+
'tumour.diagnosisdate' => {
|
7
|
+
Tnql::LIMITS => [
|
8
|
+
start.to_daterange.date1.try(:to_date).try(:iso8601),
|
9
|
+
finish.to_daterange.date2.try(:to_date).try(:iso8601)
|
10
|
+
]
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module DiagnosisDetailNode
|
17
|
+
def meta_data_item
|
18
|
+
range = date_fragment.to_daterange
|
19
|
+
|
20
|
+
{
|
21
|
+
'tumour.diagnosisdate' => {
|
22
|
+
Tnql::LIMITS => [
|
23
|
+
range.date1.try(:to_date).try(:iso8601),
|
24
|
+
range.date2.try(:to_date).try(:iso8601)
|
25
|
+
]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Tnql #:nodoc: all
|
2
|
+
module Nodes
|
3
|
+
module EBaseRecordsNode
|
4
|
+
def meta_data_item
|
5
|
+
filter =
|
6
|
+
if types.empty?
|
7
|
+
{ Tnql::ALL => true }
|
8
|
+
else
|
9
|
+
{ Tnql::EQUALS => types.to_list }
|
10
|
+
end
|
11
|
+
{ 'unprocessed_records.sources' => filter }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module BatchTypesNode
|
16
|
+
def to_list
|
17
|
+
allowed_types.to_list
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module AllowedTypesNode
|
22
|
+
def to_list
|
23
|
+
list = [batch_type.to_type]
|
24
|
+
list.concat types.elements.map(&:extract_type)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module MoreTypesNode
|
29
|
+
def extract_type
|
30
|
+
batch_type.to_type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module ActionsNode
|
35
|
+
def meta_data_item
|
36
|
+
{ 'action.actioninitiated' => { Tnql::EQUALS => action_type.text_value.upcase.strip } }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module ActionProviderCodeNode
|
41
|
+
def meta_data_item
|
42
|
+
# default to provider
|
43
|
+
key = provider_type.text_value == 'cancer network' ? 'cn_ukacr' : 'providercode'
|
44
|
+
{ "action.#{key}" => { Tnql::EQUALS => code.text_value.upcase } }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module ActionProviderNameNode
|
49
|
+
def meta_data_item
|
50
|
+
# default to provider
|
51
|
+
key = provider_type.text_value == 'cancer network' ? 'cn_ukacrname' : 'providername'
|
52
|
+
{
|
53
|
+
"action.#{key}" => {
|
54
|
+
Tnql::BEGINS => short_desc.text_value.upcase,
|
55
|
+
:interval => interval
|
56
|
+
}
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|