rbbt-entities 1.1.1 → 2.0.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.
data/lib/rbbt/entity.rb CHANGED
@@ -5,27 +5,34 @@ module Entity
5
5
  attr_accessor :formats, :entity_property_cache, :entity_list_cache
6
6
  end
7
7
 
8
- self.entity_property_cache = "cache/entity_property"
9
- self.entity_list_cache = "cache/entity_list"
8
+ self.entity_property_cache = "var/entity_property"
9
+ self.entity_list_cache = "var/entity_list"
10
10
  self.formats = {}
11
11
 
12
+ UNPERSISTED_PREFIX = "entity_unpersisted_property_"
13
+
12
14
  def self.extended(base)
13
15
  base.extend Annotation unless Annotation === base
14
16
 
17
+
15
18
  Entity.formats[base.to_s] = base
16
19
  base.module_eval do
20
+ attr_accessor :_ary_property_cache
21
+
17
22
  if not methods.include? "prev_entity_extended"
18
23
  class << self
19
- attr_accessor :template, :list_template, :action_template, :list_action_template
24
+ attr_accessor :template, :list_template, :action_template, :list_action_template, :keep_id
20
25
  alias prev_entity_extended extended
21
26
  end
22
27
 
23
28
  def self.extended(data)
24
29
  prev_entity_extended(data)
25
30
 
31
+ data._ary_property_cache = {}
32
+
26
33
  if Array === data and
27
34
  not AnnotatedArray === data and
28
- not (Annotated === data.compact.first and (data.annotation_types - data.compact.first.annotation_types).any?)
35
+ not (data.compact.first != nil and Annotated === data.compact.first and (data.annotation_types - data.compact.first.annotation_types).any?)
29
36
 
30
37
  data.extend AnnotatedArray
31
38
  end
@@ -41,25 +48,49 @@ module Entity
41
48
  end
42
49
  end
43
50
 
44
- def clean_annotations
51
+ def clean_annotations_old
52
+ return nil if self.nil?
53
+ return self.dup
45
54
  case
46
55
  when self.nil?
47
- self
56
+ nil
48
57
  when String === self
49
58
  "" << self
50
59
  when self.respond_to?(:annotated_array_clean_collect)
51
60
  self.annotated_array_clean_collect{|e| e.respond_to?(:clean_annotations)? e.clean_annotations : e}
52
61
  when Array === self
53
62
  self.collect{|e| e.respond_to?(:clean_annotations)? e.clean_annotations : e}
63
+ when (Fixnum === self)
64
+ 0 + self
65
+ when (Float === self)
66
+ 0.0 + self
54
67
  else
55
68
  raise "Unknown casuistic in clean_annotations for object: #{self.inspect}"
56
69
  end
57
70
  end
58
71
 
72
+ def clean_annotations
73
+ case
74
+ when self.nil?
75
+ nil
76
+ when Array === self
77
+ self.dup.collect{|e| e.respond_to?(:clean_annotations)? e.clean_annotations : e}
78
+ when String === self
79
+ "" << self
80
+ else
81
+ self.dup
82
+ end
83
+ end
84
+
59
85
  def to_yaml(*args)
60
- clean_annotations.to_yaml(*args)
86
+ self.clean_annotations.dup.to_yaml(*args)
87
+ end
88
+
89
+ def encode_with(coder)
90
+ coder.scalar = clean_annotations
61
91
  end
62
92
 
93
+
63
94
  def marshal_dump
64
95
  clean_annotations
65
96
  end
@@ -73,81 +104,105 @@ module Entity
73
104
  end
74
105
  }
75
106
  end
76
- end
77
- end
78
107
 
79
- def property(name, &block)
80
- case
81
- when (Hash === name and name.size == 1)
82
- name, type = name.collect.first
83
- when (String === name or Symbol === name)
84
- type = :single
85
- else
86
- raise "Format of name ( => type) not understood: #{name.inspect}"
87
- end
88
-
89
- name = name.to_s unless String === name
90
-
91
- case type
92
- when :single, :single2array
93
- self.module_eval do
94
- single_name = "_single_" << name
95
- define_method single_name, &block
96
- define_method name do |*args|
97
- if Array === self
98
- self.collect{|e| e.send(name, *args)}
99
- else
100
- self.send(single_name, *args)
101
- end
108
+ def self.property(name, &block)
109
+ case
110
+ when (Hash === name and name.size == 1)
111
+ name, type = name.collect.first
112
+ when (String === name or Symbol === name)
113
+ type = :single
114
+ else
115
+ raise "Format of name ( => type) not understood: #{name.inspect}"
102
116
  end
103
- end
104
- when :array, :array2single
105
- self.module_eval do
106
- ary_name = "_ary_" << name
107
- define_method ary_name, &block
108
-
109
- define_method name do |*args|
110
- case
111
- when Array === self
112
- self.send(ary_name, *args)
113
- when (Array === self.container and self.container.respond_to? ary_name)
114
- res = self.container.send(name, *args)
115
- if Hash === res
116
- res[self]
117
+
118
+ name = name.to_s unless String === name
119
+
120
+ persisted_name = UNPERSISTED_PREFIX + name
121
+ self.remove_method persisted_name if methods.include? persisted_name
122
+
123
+ case type
124
+ when :both
125
+ define_method name, &block
126
+
127
+ when :single, :single2array
128
+ single_name = "_single_" << name
129
+ define_method single_name, &block
130
+ define_method name do |*args|
131
+ if Array === self
132
+ self.collect{|e| e.send(name, *args)}
117
133
  else
118
- res[self.container_index]
134
+ self.send(single_name, *args)
135
+ end
136
+ end
137
+ when :array, :array2single
138
+ ary_name = "_ary_" << name
139
+ define_method ary_name, &block
140
+
141
+ define_method name do |*args|
142
+ #ary_name = "_ary_" << __method__.to_s
143
+ case
144
+ when Array === self
145
+ self.send(ary_name, *args)
146
+ when (Array === self.container and self.container.respond_to? ary_name)
147
+ cache_code = Misc.hash2md5({:name => ary_name, :args => args})
148
+ res = (self.container._ary_property_cache[cache_code] ||= self.container.send(name, *args))
149
+ if Hash === res
150
+ res[self]
151
+ else
152
+ res[self.container_index]
153
+ end
154
+ else
155
+ res = self.make_list.send(ary_name, *args)
156
+ Hash === res ? res[self] : res[0]
119
157
  end
120
- else
121
- res = self.make_list.send(ary_name, *args)
122
- Hash === res ? res[self] : res[0]
123
158
  end
124
- end
125
159
 
160
+ end
126
161
  end
127
- end
128
- end
129
162
 
130
- UNPERSISTED_PREFIX = "entity_unpersisted_property_"
131
- def persist(method_name, type = nil, options = {})
132
- type = :memory if type.nil?
133
- options = Misc.add_defaults options, :dir => Entity.entity_property_cache
163
+ def self.persist(method_name, type = nil, options = {})
164
+ type = :memory if type.nil?
165
+ options = Misc.add_defaults options, :dir => Entity.entity_property_cache
134
166
 
135
- self.module_eval do
136
- orig_name = UNPERSISTED_PREFIX + method_name.to_s
137
- alias_method orig_name, method_name unless instance_methods.include? orig_name
167
+ orig_name = UNPERSISTED_PREFIX + method_name.to_s
168
+ alias_method orig_name, method_name unless self.instance_methods.include? orig_name.to_sym
138
169
 
139
- define_method method_name do |*args|
140
- persist_name = __method__.to_s << ":" << self.id
170
+ define_method method_name do |*args|
171
+ id = self.id
172
+ persist_name = __method__.to_s << ":" << (Array === id ? Misc.hash2md5(:id => id) : id)
173
+ persist_name << ":" << Misc.hash2md5({:args => args}) unless args.nil? or args.empty?
141
174
 
142
- persist_options = options
143
- persist_options = persist_options.merge(:other => {:args => args}) if args.any?
175
+ persist_options = options
176
+ persist_options = persist_options.merge(:other => {:args => args}) if args.any?
144
177
 
145
- Persist.persist(persist_name, type, persist_options) do
146
- self.send(orig_name, *args)
178
+ Persist.persist(persist_name, type, persist_options) do
179
+ self.send(orig_name, *args)
180
+ end
147
181
  end
148
182
  end
149
- end
150
- end
151
183
 
184
+ def self.unpersist(method_name)
185
+ return unless persisted? method_name
186
+ orig_name = UNPERSISTED_PREFIX + method_name.to_s
187
+
188
+ alias_method method_name, orig_name
189
+ remove_method orig_name
190
+ end
191
+
192
+ def self.persisted?(method_name)
193
+ orig_name = UNPERSISTED_PREFIX + method_name.to_s
194
+ instance_methods.include? orig_name.to_sym
195
+ end
196
+
197
+ def self.with_persisted(method_name)
198
+ persisted = persisted? method_name
199
+ persist method_name unless persisted
200
+ res = yield
201
+ unpersist method_name unless persisted
202
+ res
203
+ end
204
+
205
+ end
206
+ end
152
207
  end
153
208
 
@@ -45,8 +45,22 @@ class TestGene < Test::Unit::TestCase
45
45
  end
46
46
 
47
47
  def test_range
48
- assert Range === CDK5.range
49
- assert Range === CDK5.make_list.range.first
48
+ assert Range === CDK5.chr_range
49
+ assert Range === CDK5.make_list.chr_range.first
50
+ end
51
+
52
+ def test_total_bases
53
+ require 'rbbt/entity/gene'
54
+ require 'rbbt/sources/kegg'
55
+
56
+ assert Gene.gene_list_bases(Gene.setup(KeggPathway.setup("hsa03040", "Hsa/jun2011").genes, "KEGG Gene ID", "Hsa/jun2011").ensembl) > 100000
57
+ end
58
+
59
+ def test_total_exon_bases
60
+ require 'rbbt/entity/gene'
61
+ require 'rbbt/sources/kegg'
62
+
63
+ assert Gene.gene_list_exon_bases(Gene.setup(KeggPathway.setup("hsa03040", "Hsa/jun2011").genes, "KEGG Gene ID", "Hsa/jun2011").ensembl) < 1000000
50
64
  end
51
65
 
52
66
  end
@@ -7,22 +7,74 @@ require 'rbbt/entity/genomic_mutation'
7
7
 
8
8
  class TestGenomicMutation < Test::Unit::TestCase
9
9
  MUTATION = GenomicMutation.setup("10:124745844:A:158", "Test", "Hsa/jun2011")
10
+ NON_CODING_MUTATION = GenomicMutation.setup("12:52844451:T", "Test", "Hsa/jun2011")
10
11
  SPLICING = GenomicMutation.setup("18:14787040:A", "Test", "Hsa/jun2011")
12
+ SPLICING2 = GenomicMutation.setup("3:125551372:G:1265.90:1", "test", "Hsa/jun2011", true)
13
+
14
+ FORWARD_STRAND_FIRST_EXON_START = GenomicMutation.setup("10:89622870", "Test", "Hsa/jun2011")
15
+ FORWARD_STRAND_FIRST_EXON_END = GenomicMutation.setup("10:89624305", "Test", "Hsa/jun2011")
16
+ FORWARD_STRAND_LAST_EXON_START = GenomicMutation.setup("10:89725044", "Test", "Hsa/jun2011")
17
+ FORWARD_STRAND_LAST_EXON_END = GenomicMutation.setup("10:89731687", "Test", "Hsa/jun2011")
18
+
19
+ REVERSE_STRAND_FIRST_EXON_START = GenomicMutation.setup("2:198256698", "Test", "Hsa/jun2011")
20
+ REVERSE_STRAND_FIRST_EXON_END = GenomicMutation.setup("2:198257185", "Test", "Hsa/jun2011")
21
+ REVERSE_STRAND_LAST_EXON_START = GenomicMutation.setup("2:198299696", "Test", "Hsa/jun2011")
22
+ REVERSE_STRAND_LAST_EXON_END = GenomicMutation.setup("2:198299815", "Test", "Hsa/jun2011")
23
+
11
24
 
12
25
  def test_mutated_isoforms
13
26
  assert MUTATION.mutated_isoforms.length > 1
14
- assert ["PSTK"], MUTATION.mutated_isoforms.protein.gene.to("Associated Gene Name").uniq
27
+ assert_equal ["PSTK"], MUTATION.mutated_isoforms.protein.gene.to("Associated Gene Name").uniq
15
28
  end
16
29
 
17
30
  def test_exon_junction
18
31
  assert(!(MUTATION.in_exon_junction?))
19
32
  assert SPLICING.in_exon_junction?
33
+
34
+ assert(!(FORWARD_STRAND_FIRST_EXON_START.in_exon_junction?))
35
+ assert( (FORWARD_STRAND_FIRST_EXON_END.in_exon_junction?))
36
+ assert( (FORWARD_STRAND_LAST_EXON_START.in_exon_junction?))
37
+ assert(!(FORWARD_STRAND_LAST_EXON_END.in_exon_junction?))
38
+
39
+ assert(!(REVERSE_STRAND_FIRST_EXON_START.in_exon_junction?))
40
+ assert( (REVERSE_STRAND_FIRST_EXON_END.in_exon_junction?))
41
+ assert( (REVERSE_STRAND_LAST_EXON_START.in_exon_junction?))
42
+ assert(!(REVERSE_STRAND_LAST_EXON_END.in_exon_junction?))
20
43
  end
21
44
 
22
45
  def test_over_gene
23
46
  assert MUTATION.over_gene? Gene.setup("PSTK", "Associated Gene Name", "Hsa/jun2011").ensembl
24
47
  assert(!(SPLICING.over_gene? Gene.setup("PSTK", "Associated Gene Name", "Hsa/jun2011").ensembl))
25
48
  end
49
+
50
+ def test_type
51
+ reference = "A"
52
+ mutation = GenomicMutation.setup("1:1727802:A", "Test", "Hsa/may2009", true)
53
+ assert_equal 'none', mutation.type
54
+ mutation = GenomicMutation.setup("1:1727802:C", "Test", "Hsa/may2009", true)
55
+ assert_equal 'transversion', mutation.type
56
+ mutation = GenomicMutation.setup("1:1727802:T", "Test", "Hsa/may2009", true)
57
+ assert_equal 'transversion', mutation.type
58
+ mutation = GenomicMutation.setup("1:1727802:G", "Test", "Hsa/may2009", true)
59
+ assert_equal 'transition', mutation.type
60
+ end
61
+
62
+ def test_coding
63
+ assert MUTATION.coding?
64
+ assert(!NON_CODING_MUTATION.coding?)
65
+ end
66
+
67
+ def test_masked_annotations
68
+ assert MUTATION.info.include?(:jobname)
69
+ assert(!MUTATION.info(true).include?(:jobname))
70
+ end
71
+
72
+ def test_transcripts_with_affected_splicing
73
+ assert(SPLICING.transcripts_with_affected_splicing.any?)
74
+ assert(SPLICING2.transcripts_with_affected_splicing.empty?)
75
+ end
76
+
77
+
26
78
  end
27
79
 
28
80
 
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ require 'test/unit'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+ require 'rbbt/entity/pmid'
7
+
8
+ class TestProtein < Test::Unit::TestCase
9
+
10
+ def test_pmid_id
11
+ assert_match /^PMID/, PMID.setup("21904853").docid
12
+ end
13
+
14
+ def test_pmid_text
15
+ assert_match /TET2/, PMID.setup("21904853").text
16
+ end
17
+ end
18
+
19
+
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require 'rbbt'
2
3
  require 'rbbt/entity'
3
4
  require 'rbbt/util/tmpfile'
4
5
  require 'test/unit'
@@ -30,6 +31,16 @@ module ReversableString
30
31
  $count += 1
31
32
  self.collect{|s| s.reverse}
32
33
  end
34
+
35
+ property :random => :single do
36
+ rand
37
+ end
38
+
39
+ property :annotation_list => :single do
40
+ self.chars.to_a.collect{|c|
41
+ ReversableString.setup(c)
42
+ }
43
+ end
33
44
 
34
45
  persist :reverse_text_ary_p
35
46
  persist :reverse_text_ary_p
@@ -37,10 +48,13 @@ module ReversableString
37
48
  persist :reverse_text_single_p
38
49
 
39
50
  persist :reverse_text_ary_p_array, :array, :dir => TmpFile.tmp_file
51
+
52
+ persist :annotation_list, :annotations, :dir => TmpFile.tmp_file
40
53
  end
54
+
41
55
  class TestEntity < Test::Unit::TestCase
42
56
 
43
- def test_property_ary
57
+ def _test_property_ary
44
58
  a = ["String1", "String2"]
45
59
  a.extend ReversableString
46
60
 
@@ -48,11 +62,19 @@ class TestEntity < Test::Unit::TestCase
48
62
 
49
63
  assert_equal "2gnirtS", a.reverse_text_ary.last
50
64
  assert_equal 1, $count
65
+ a._ary_property_cache.clear
51
66
  assert_equal "2gnirtS", a[1].reverse_text_ary
52
67
  assert_equal 2, $count
68
+ a._ary_property_cache.clear
69
+
70
+ $count = 0
71
+ a.each do |string|
72
+ string.reverse_text_ary
73
+ assert_equal 1, $count
74
+ end
53
75
  end
54
76
 
55
- def test_property_single
77
+ def _test_property_single
56
78
  a = ["String1", "String2"]
57
79
  a.extend ReversableString
58
80
 
@@ -64,7 +86,7 @@ class TestEntity < Test::Unit::TestCase
64
86
  assert_equal 3, $count
65
87
  end
66
88
 
67
- def test_property_ary_p
89
+ def _test_property_ary_p
68
90
  a = ["String1", "String2"]
69
91
  a.extend ReversableString
70
92
 
@@ -75,7 +97,7 @@ class TestEntity < Test::Unit::TestCase
75
97
  assert_equal 1, $count
76
98
  end
77
99
 
78
- def test_property_single_p
100
+ def _test_property_single_p
79
101
  a = ["String1", "String2"]
80
102
  a.extend ReversableString
81
103
 
@@ -87,7 +109,7 @@ class TestEntity < Test::Unit::TestCase
87
109
  assert_equal 2, $count
88
110
  end
89
111
 
90
- def test_property_ary_p_array
112
+ def _test_property_ary_p_array
91
113
  a = ["String1", "String2"]
92
114
  a.extend ReversableString
93
115
 
@@ -98,4 +120,77 @@ class TestEntity < Test::Unit::TestCase
98
120
  assert_equal "2gnirtS", a.reverse_text_ary_p_array.last
99
121
  assert_equal 1, $count
100
122
  end
123
+
124
+ def _test_unpersist
125
+ a = ["String1", "String2"]
126
+ a.extend ReversableString
127
+
128
+ # Before persist
129
+ assert(! ReversableString.persisted?(:random))
130
+
131
+ r1 = a.random
132
+ r2 = a.random
133
+ assert_not_equal r1, r2
134
+
135
+ # After persist
136
+ ReversableString.persist :random
137
+ assert(ReversableString.persisted?(:random))
138
+
139
+ r1 = a.random
140
+ r2 = a.random
141
+ assert_equal r1, r2
142
+
143
+ # After unpersist
144
+ ReversableString.unpersist :random
145
+ assert(! ReversableString.persisted?(:random))
146
+
147
+ r1 = a.random
148
+ r2 = a.random
149
+ assert_not_equal r1, r2
150
+
151
+ end
152
+
153
+ def _test_persist_annotations
154
+ string = 'aaabbbccc'
155
+ ReversableString.setup(string)
156
+ assert_equal string.length, string.annotation_list.length
157
+ assert_equal string.length, string.annotation_list.length
158
+ end
159
+
160
+ def __test_performance
161
+
162
+ require 'rbbt/workflow'
163
+ Workflow.require_workflow "StudyExplorer"
164
+
165
+ s = Study.setup("CLL")
166
+ mutations = s.cohort.metagenotype
167
+ Misc.profile_html(:min_percent => 1) do
168
+ mutated_isoforms = mutations.each{|m| m.genes.each{|g| g}}
169
+ end
170
+ end
171
+
172
+ def test_clean_annotations
173
+ require 'rbbt/workflow'
174
+ Workflow.require_workflow "StudyExplorer"
175
+
176
+ s = Study.setup("CLL")
177
+ mutations = s.cohort.metagenotype.mutated_isoforms
178
+
179
+ Misc.benchmark(100) do
180
+ mutations.each{|m| m}
181
+ end
182
+
183
+ Misc.benchmark(100) do
184
+ mutations.clean_annotations.each{|m| m}
185
+ end
186
+
187
+ m = mutations.first
188
+
189
+ assert_equal m.split(":")[1], m.position.to_s
190
+ assert_raise NoMethodError do
191
+ m.clean_annotations.position
192
+ end
193
+
194
+
195
+ end
101
196
  end