rbbt-util 5.44.1 → 6.0.4
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/LICENSE +1 -1
- data/bin/rbbt +67 -90
- data/bin/rbbt_exec.rb +2 -2
- data/etc/app.d/base.rb +2 -2
- data/etc/app.d/semaphores.rb +3 -3
- data/lib/rbbt/annotations/annotated_array.rb +207 -207
- data/lib/rbbt/annotations/refactor.rb +27 -0
- data/lib/rbbt/annotations/util.rb +282 -282
- data/lib/rbbt/annotations.rb +343 -320
- data/lib/rbbt/association/database.rb +200 -225
- data/lib/rbbt/association/index.rb +294 -291
- data/lib/rbbt/association/item.rb +227 -227
- data/lib/rbbt/association/open.rb +35 -34
- data/lib/rbbt/association/util.rb +0 -169
- data/lib/rbbt/association.rb +2 -4
- data/lib/rbbt/entity/identifiers.rb +119 -118
- data/lib/rbbt/entity/refactor.rb +12 -0
- data/lib/rbbt/entity.rb +319 -315
- data/lib/rbbt/hpc/batch.rb +72 -53
- data/lib/rbbt/hpc/lsf.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
- data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
- data/lib/rbbt/hpc/orchestrate.rb +19 -13
- data/lib/rbbt/hpc/slurm.rb +18 -18
- data/lib/rbbt/knowledge_base/entity.rb +13 -5
- data/lib/rbbt/knowledge_base/query.rb +2 -2
- data/lib/rbbt/knowledge_base/registry.rb +32 -31
- data/lib/rbbt/knowledge_base/traverse.rb +1 -1
- data/lib/rbbt/knowledge_base.rb +1 -1
- data/lib/rbbt/monitor.rb +36 -25
- data/lib/rbbt/persist/refactor.rb +166 -0
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
- data/lib/rbbt/persist/tsv.rb +187 -185
- data/lib/rbbt/persist.rb +556 -551
- data/lib/rbbt/refactor.rb +20 -0
- data/lib/rbbt/resource/path/refactor.rb +178 -0
- data/lib/rbbt/resource/path.rb +317 -497
- data/lib/rbbt/resource/util.rb +0 -48
- data/lib/rbbt/resource.rb +3 -390
- data/lib/rbbt/tsv/accessor.rb +2 -838
- data/lib/rbbt/tsv/attach.rb +303 -299
- data/lib/rbbt/tsv/change_id.rb +244 -245
- data/lib/rbbt/tsv/csv.rb +87 -85
- data/lib/rbbt/tsv/dumper.rb +2 -100
- data/lib/rbbt/tsv/excel.rb +26 -24
- data/lib/rbbt/tsv/field_index.rb +4 -1
- data/lib/rbbt/tsv/filter.rb +3 -2
- data/lib/rbbt/tsv/index.rb +2 -284
- data/lib/rbbt/tsv/manipulate.rb +750 -747
- data/lib/rbbt/tsv/marshal.rb +3 -3
- data/lib/rbbt/tsv/matrix.rb +2 -2
- data/lib/rbbt/tsv/parallel/through.rb +2 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
- data/lib/rbbt/tsv/parser.rb +678 -678
- data/lib/rbbt/tsv/refactor.rb +195 -0
- data/lib/rbbt/tsv/stream.rb +253 -251
- data/lib/rbbt/tsv/util.rb +420 -420
- data/lib/rbbt/tsv.rb +210 -208
- data/lib/rbbt/util/R/eval.rb +4 -4
- data/lib/rbbt/util/R/plot.rb +62 -166
- data/lib/rbbt/util/R.rb +21 -18
- data/lib/rbbt/util/cmd.rb +2 -318
- data/lib/rbbt/util/color.rb +269 -269
- data/lib/rbbt/util/colorize.rb +89 -89
- data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
- data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +389 -386
- data/lib/rbbt/util/config.rb +169 -167
- data/lib/rbbt/util/filecache.rb +1 -1
- data/lib/rbbt/util/iruby.rb +20 -0
- data/lib/rbbt/util/log/progress/report.rb +241 -241
- data/lib/rbbt/util/log/progress/util.rb +99 -99
- data/lib/rbbt/util/log/progress.rb +102 -102
- data/lib/rbbt/util/log/refactor.rb +49 -0
- data/lib/rbbt/util/log.rb +486 -532
- data/lib/rbbt/util/migrate.rb +2 -2
- data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
- data/lib/rbbt/util/misc/development.rb +12 -11
- data/lib/rbbt/util/misc/exceptions.rb +117 -112
- data/lib/rbbt/util/misc/format.rb +2 -230
- data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
- data/lib/rbbt/util/misc/inspect.rb +2 -476
- data/lib/rbbt/util/misc/lock.rb +109 -106
- data/lib/rbbt/util/misc/omics.rb +9 -1
- data/lib/rbbt/util/misc/pipes.rb +765 -793
- data/lib/rbbt/util/misc/refactor.rb +20 -0
- data/lib/rbbt/util/misc/ssw.rb +27 -17
- data/lib/rbbt/util/misc/system.rb +92 -105
- data/lib/rbbt/util/misc.rb +39 -20
- data/lib/rbbt/util/named_array/refactor.rb +4 -0
- data/lib/rbbt/util/named_array.rb +3 -220
- data/lib/rbbt/util/open/refactor.rb +7 -0
- data/lib/rbbt/util/open.rb +3 -857
- data/lib/rbbt/util/procpath.rb +6 -6
- data/lib/rbbt/util/python/paths.rb +27 -0
- data/lib/rbbt/util/python/run.rb +115 -0
- data/lib/rbbt/util/python/script.rb +110 -0
- data/lib/rbbt/util/python/util.rb +3 -3
- data/lib/rbbt/util/python.rb +22 -81
- data/lib/rbbt/util/semaphore.rb +152 -148
- data/lib/rbbt/util/simpleopt.rb +9 -8
- data/lib/rbbt/util/ssh/refactor.rb +19 -0
- data/lib/rbbt/util/ssh.rb +122 -118
- data/lib/rbbt/util/tar.rb +117 -115
- data/lib/rbbt/util/tmpfile.rb +69 -67
- data/lib/rbbt/util/version.rb +2 -0
- data/lib/rbbt/workflow/refactor/entity.rb +11 -0
- data/lib/rbbt/workflow/refactor/export.rb +66 -0
- data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
- data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
- data/lib/rbbt/workflow/refactor/task_info.rb +66 -0
- data/lib/rbbt/workflow/refactor.rb +150 -0
- data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +1 -2
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
- data/lib/rbbt/workflow/remote_workflow.rb +6 -1
- data/lib/rbbt/workflow/step/run.rb +766 -766
- data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
- data/lib/rbbt/workflow/step.rb +2 -362
- data/lib/rbbt/workflow/task.rb +118 -118
- data/lib/rbbt/workflow/usage.rb +289 -287
- data/lib/rbbt/workflow/util/archive.rb +6 -5
- data/lib/rbbt/workflow/util/data.rb +1 -1
- data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
- data/lib/rbbt/workflow/util/trace.rb +79 -44
- data/lib/rbbt/workflow.rb +4 -882
- data/lib/rbbt-util.rb +21 -13
- data/lib/rbbt.rb +16 -3
- data/python/rbbt/__init__.py +96 -4
- data/python/rbbt/workflow/remote.py +104 -0
- data/python/rbbt/workflow.py +64 -0
- data/python/test.py +10 -0
- data/share/Rlib/plot.R +37 -37
- data/share/Rlib/svg.R +22 -5
- data/share/install/software/lib/install_helpers +1 -1
- data/share/rbbt_commands/hpc/list +2 -3
- data/share/rbbt_commands/hpc/orchestrate +4 -4
- data/share/rbbt_commands/hpc/tail +2 -0
- data/share/rbbt_commands/hpc/task +10 -7
- data/share/rbbt_commands/lsf/list +2 -3
- data/share/rbbt_commands/lsf/orchestrate +4 -4
- data/share/rbbt_commands/lsf/tail +2 -0
- data/share/rbbt_commands/lsf/task +10 -7
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/pbs/list +2 -3
- data/share/rbbt_commands/pbs/orchestrate +4 -4
- data/share/rbbt_commands/pbs/tail +2 -0
- data/share/rbbt_commands/pbs/task +10 -7
- data/share/rbbt_commands/resource/produce +8 -1
- data/share/rbbt_commands/slurm/list +2 -3
- data/share/rbbt_commands/slurm/orchestrate +4 -4
- data/share/rbbt_commands/slurm/tail +2 -0
- data/share/rbbt_commands/slurm/task +10 -7
- data/share/rbbt_commands/system/clean +5 -5
- data/share/rbbt_commands/system/status +5 -5
- data/share/rbbt_commands/tsv/get +2 -3
- data/share/rbbt_commands/tsv/info +10 -13
- data/share/rbbt_commands/tsv/keys +18 -14
- data/share/rbbt_commands/tsv/slice +2 -2
- data/share/rbbt_commands/tsv/transpose +6 -2
- data/share/rbbt_commands/workflow/info +20 -24
- data/share/rbbt_commands/workflow/list +1 -1
- data/share/rbbt_commands/workflow/prov +20 -13
- data/share/rbbt_commands/workflow/retry +43 -0
- data/share/rbbt_commands/workflow/server +12 -2
- data/share/rbbt_commands/workflow/task +80 -73
- data/share/rbbt_commands/workflow/write_info +26 -9
- data/share/software/opt/ssw/ssw.c +861 -0
- data/share/software/opt/ssw/ssw.h +130 -0
- data/share/workflow_config.ru +3 -3
- metadata +45 -6
@@ -1,282 +1,282 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Annotated
|
4
|
-
|
5
|
-
def self.flatten(array)
|
6
|
-
return array unless Array === array and not array.empty?
|
7
|
-
array.extend AnnotatedArray if Annotated === array
|
8
|
-
return array.flatten if AnnotatedArray === array
|
9
|
-
begin
|
10
|
-
return array if array.compact.collect{|e| e.info }.uniq.length > 1
|
11
|
-
rescue
|
12
|
-
return array
|
13
|
-
end
|
14
|
-
array.compact.first.annotate(array.flatten).tap{|a| a.extend AnnotatedArray }
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.load_entity(object, info)
|
18
|
-
annotation_types = info.delete(:annotation_types) || info.delete("annotation_types") || []
|
19
|
-
annotation_types = annotation_types.split("|") if String === annotation_types
|
20
|
-
|
21
|
-
return object if annotation_types.nil? or annotation_types.empty?
|
22
|
-
|
23
|
-
annotated_array = false
|
24
|
-
annotated_array = true if (info.delete(:annotated_array) || info.delete("annotated_array")).to_s == "true"
|
25
|
-
entity_id = info.delete(:entity_id) || info.delete("entity_id")
|
26
|
-
|
27
|
-
annotation_types.each do |mod|
|
28
|
-
begin
|
29
|
-
mod = Misc.string2const(mod) if String === mod
|
30
|
-
object.extend mod unless mod === object
|
31
|
-
rescue Exception
|
32
|
-
Log.warn "Exception loading annotation into object: #{$!.message}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
object.instance_variable_set(:@annotation_values, info)
|
37
|
-
|
38
|
-
object.instance_variable_set(:@id, entity_id) if entity_id
|
39
|
-
|
40
|
-
object.extend AnnotatedArray if annotated_array and Array === object
|
41
|
-
|
42
|
-
object
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.resolve_array(entry)
|
46
|
-
if String === entry && entry =~ /^Array:/
|
47
|
-
entry["Array:".length..-1].split("|")
|
48
|
-
else
|
49
|
-
entry
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.load_info(fields, values)
|
54
|
-
info = {}
|
55
|
-
fields.each_with_index do |field,i|
|
56
|
-
next if field == "literal"
|
57
|
-
case field
|
58
|
-
when "JSON"
|
59
|
-
JSON.parse(values[i]).each do |key, value|
|
60
|
-
info[key.to_sym] = value
|
61
|
-
end
|
62
|
-
when nil
|
63
|
-
next
|
64
|
-
else
|
65
|
-
info[field.to_sym] = resolve_array(values[i])
|
66
|
-
end
|
67
|
-
end
|
68
|
-
info
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.load_tsv_values(id, values, *fields)
|
72
|
-
fields = fields.flatten
|
73
|
-
literal_pos = fields.index "literal"
|
74
|
-
|
75
|
-
object = case
|
76
|
-
when literal_pos
|
77
|
-
values[literal_pos].tap{|o| o.force_encoding(Encoding.default_external)}
|
78
|
-
else
|
79
|
-
id.dup
|
80
|
-
end
|
81
|
-
|
82
|
-
object = resolve_array(object)
|
83
|
-
|
84
|
-
if Array === values.first
|
85
|
-
Misc.zip_fields(values).collect do |v|
|
86
|
-
info = load_info(fields, v)
|
87
|
-
end
|
88
|
-
else
|
89
|
-
info = load_info(fields, values)
|
90
|
-
end
|
91
|
-
|
92
|
-
self.load_entity(object, info)
|
93
|
-
|
94
|
-
object
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.load_tsv(tsv)
|
98
|
-
tsv.with_unnamed do
|
99
|
-
annotated_entities = tsv.collect do |id, values|
|
100
|
-
Annotated.load_tsv_values(id, values, tsv.fields)
|
101
|
-
end
|
102
|
-
|
103
|
-
case tsv.key_field
|
104
|
-
when "List"
|
105
|
-
annotated_entities.first
|
106
|
-
else
|
107
|
-
annotated_entities
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
def self.tsv(annotations, *fields)
|
114
|
-
return nil if annotations.nil?
|
115
|
-
|
116
|
-
fields = case
|
117
|
-
|
118
|
-
when ((fields.compact.empty?) && ! annotations.empty?)
|
119
|
-
fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
|
120
|
-
fields << :annotation_types
|
121
|
-
|
122
|
-
when (fields == [:literal] and ! annotations.compact.empty?)
|
123
|
-
fields << :literal
|
124
|
-
|
125
|
-
when (fields == [:all] && Annotated === annotations)
|
126
|
-
annotation_names = annotations.annotations
|
127
|
-
annotation_names += annotations.first.annotations if Annotated === annotations.first
|
128
|
-
fields = [:annotation_types] + annotation_names.uniq
|
129
|
-
fields << :annotated_array if AnnotatedArray === annotations
|
130
|
-
fields << :literal
|
131
|
-
|
132
|
-
when (fields == [:all] && ! annotations.compact.empty?)
|
133
|
-
raise "Input array must be annotated or its elements must be" if not Annotated === annotations.compact.first and not Array === annotations.compact.first
|
134
|
-
raise "Input array must be annotated or its elements must be. No double arrays of singly annotated entities." if not Annotated === annotations.compact.first and Array === annotations.compact.first
|
135
|
-
fields = [:annotation_types] + (Annotated === annotations ?
|
136
|
-
annotations.annotations:
|
137
|
-
annotations.compact.first.annotations)
|
138
|
-
fields << :literal
|
139
|
-
|
140
|
-
when annotations.empty?
|
141
|
-
[:annotation_types, :literal]
|
142
|
-
|
143
|
-
else
|
144
|
-
fields.flatten
|
145
|
-
|
146
|
-
end
|
147
|
-
|
148
|
-
fields = fields.collect{|f| f.to_s}.uniq
|
149
|
-
|
150
|
-
case
|
151
|
-
when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
|
152
|
-
tsv = TSV.setup({}, :key_field => "List", :fields => fields, :type => :list, :unnamed => true)
|
153
|
-
|
154
|
-
annot_id = annotations.id
|
155
|
-
annot_id = annot_id * "," if Array === annot_id
|
156
|
-
tsv[annot_id] = annotations.tsv_values(*fields).dup
|
157
|
-
|
158
|
-
when Array === annotations
|
159
|
-
tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
|
160
|
-
|
161
|
-
annotations.compact.each_with_index do |annotation,i|
|
162
|
-
tsv[annotation.id + "#" << i.to_s] = annotation.tsv_values(*fields).dup
|
163
|
-
end
|
164
|
-
|
165
|
-
else
|
166
|
-
raise "Annotations need to be an Array to create TSV"
|
167
|
-
end
|
168
|
-
|
169
|
-
tsv
|
170
|
-
end
|
171
|
-
|
172
|
-
def tsv_values(*fields)
|
173
|
-
if Array === self and (not AnnotatedArray === self or self.double_array)
|
174
|
-
Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
|
175
|
-
else
|
176
|
-
fields = fields.flatten
|
177
|
-
|
178
|
-
info = self.info
|
179
|
-
|
180
|
-
values = []
|
181
|
-
|
182
|
-
fields.each do |field|
|
183
|
-
values << case
|
184
|
-
|
185
|
-
when Proc === field
|
186
|
-
field.call(self)
|
187
|
-
|
188
|
-
when field == "JSON"
|
189
|
-
if AnnotatedArray === self
|
190
|
-
info.merge(:annotated_array => true).to_json
|
191
|
-
else
|
192
|
-
info.to_json
|
193
|
-
end
|
194
|
-
|
195
|
-
when field == "annotation_types"
|
196
|
-
annotation_types.collect{|t| t.to_s} * "|"
|
197
|
-
|
198
|
-
when field == "annotated_array"
|
199
|
-
AnnotatedArray === self
|
200
|
-
|
201
|
-
when field == "literal"
|
202
|
-
(Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
|
203
|
-
|
204
|
-
when info.include?(field.to_sym)
|
205
|
-
res = info[field.to_sym]
|
206
|
-
Array === res ? "Array:" << res * "|" : res
|
207
|
-
|
208
|
-
when self.respond_to?(field)
|
209
|
-
res = self.send(field)
|
210
|
-
Array === res ? "Array:"<< res * "|" : res
|
211
|
-
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
|
216
|
-
values
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def self.to_hash(e)
|
221
|
-
hash = {}
|
222
|
-
if Array === e && AnnotatedArray === e
|
223
|
-
hash[:literal] = Annotated.purge(e)
|
224
|
-
hash[:info] = e.info
|
225
|
-
elsif Array === e
|
226
|
-
hash = e.collect do |_e|
|
227
|
-
_hash = {}
|
228
|
-
_hash[:literal] = _e.dup
|
229
|
-
_hash[:info] = _e.info if _e.respond_to?(:info)
|
230
|
-
_hash
|
231
|
-
end
|
232
|
-
else
|
233
|
-
hash[:literal] = e.dup
|
234
|
-
hash[:info] = e.info
|
235
|
-
end
|
236
|
-
hash
|
237
|
-
end
|
238
|
-
|
239
|
-
def self.load_hash(hash)
|
240
|
-
if Array === hash
|
241
|
-
hash.collect{|h| load_hash(h) }
|
242
|
-
else
|
243
|
-
literal = hash[:literal]
|
244
|
-
info = hash[:info]
|
245
|
-
info[:annotation_types].each do |type|
|
246
|
-
type = Kernel.const_get(type) if String === type
|
247
|
-
type.setup(literal, info)
|
248
|
-
end
|
249
|
-
literal
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def marshal_dump
|
254
|
-
Annotated.to_hash(self)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
class String
|
259
|
-
def marshal_load(hash)
|
260
|
-
if Hash === hash
|
261
|
-
e = Annotated.load_hash(hash)
|
262
|
-
self.replace e
|
263
|
-
e.annotate(self)
|
264
|
-
self
|
265
|
-
else
|
266
|
-
self.replace hash
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
class Array
|
272
|
-
def marshal_load(hash)
|
273
|
-
if Hash === hash
|
274
|
-
e = Annotated.load_hash(hash)
|
275
|
-
self.replace e
|
276
|
-
e.annotate(self)
|
277
|
-
self
|
278
|
-
else
|
279
|
-
self.replace hash
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
1
|
+
#require 'json'
|
2
|
+
#
|
3
|
+
#module Annotated
|
4
|
+
#
|
5
|
+
# def self.flatten(array)
|
6
|
+
# return array unless Array === array and not array.empty?
|
7
|
+
# array.extend AnnotatedArray if Annotated === array
|
8
|
+
# return array.flatten if AnnotatedArray === array
|
9
|
+
# begin
|
10
|
+
# return array if array.compact.collect{|e| e.info }.uniq.length > 1
|
11
|
+
# rescue
|
12
|
+
# return array
|
13
|
+
# end
|
14
|
+
# array.compact.first.annotate(array.flatten).tap{|a| a.extend AnnotatedArray }
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def self.load_entity(object, info)
|
18
|
+
# annotation_types = info.delete(:annotation_types) || info.delete("annotation_types") || []
|
19
|
+
# annotation_types = annotation_types.split("|") if String === annotation_types
|
20
|
+
#
|
21
|
+
# return object if annotation_types.nil? or annotation_types.empty?
|
22
|
+
#
|
23
|
+
# annotated_array = false
|
24
|
+
# annotated_array = true if (info.delete(:annotated_array) || info.delete("annotated_array")).to_s == "true"
|
25
|
+
# entity_id = info.delete(:entity_id) || info.delete("entity_id")
|
26
|
+
#
|
27
|
+
# annotation_types.each do |mod|
|
28
|
+
# begin
|
29
|
+
# mod = Misc.string2const(mod) if String === mod
|
30
|
+
# object.extend mod unless mod === object
|
31
|
+
# rescue Exception
|
32
|
+
# Log.warn "Exception loading annotation into object: #{$!.message}"
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# object.instance_variable_set(:@annotation_values, info)
|
37
|
+
#
|
38
|
+
# object.instance_variable_set(:@id, entity_id) if entity_id
|
39
|
+
#
|
40
|
+
# object.extend AnnotatedArray if annotated_array and Array === object
|
41
|
+
#
|
42
|
+
# object
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# def self.resolve_array(entry)
|
46
|
+
# if String === entry && entry =~ /^Array:/
|
47
|
+
# entry["Array:".length..-1].split("|")
|
48
|
+
# else
|
49
|
+
# entry
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# def self.load_info(fields, values)
|
54
|
+
# info = {}
|
55
|
+
# fields.each_with_index do |field,i|
|
56
|
+
# next if field == "literal"
|
57
|
+
# case field
|
58
|
+
# when "JSON"
|
59
|
+
# JSON.parse(values[i]).each do |key, value|
|
60
|
+
# info[key.to_sym] = value
|
61
|
+
# end
|
62
|
+
# when nil
|
63
|
+
# next
|
64
|
+
# else
|
65
|
+
# info[field.to_sym] = resolve_array(values[i])
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# info
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# def self.load_tsv_values(id, values, *fields)
|
72
|
+
# fields = fields.flatten
|
73
|
+
# literal_pos = fields.index "literal"
|
74
|
+
#
|
75
|
+
# object = case
|
76
|
+
# when literal_pos
|
77
|
+
# values[literal_pos].tap{|o| o.force_encoding(Encoding.default_external)}
|
78
|
+
# else
|
79
|
+
# id.dup
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# object = resolve_array(object)
|
83
|
+
#
|
84
|
+
# if Array === values.first
|
85
|
+
# Misc.zip_fields(values).collect do |v|
|
86
|
+
# info = load_info(fields, v)
|
87
|
+
# end
|
88
|
+
# else
|
89
|
+
# info = load_info(fields, values)
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# self.load_entity(object, info)
|
93
|
+
#
|
94
|
+
# object
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# def self.load_tsv(tsv)
|
98
|
+
# tsv.with_unnamed do
|
99
|
+
# annotated_entities = tsv.collect do |id, values|
|
100
|
+
# Annotated.load_tsv_values(id, values, tsv.fields)
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# case tsv.key_field
|
104
|
+
# when "List"
|
105
|
+
# annotated_entities.first
|
106
|
+
# else
|
107
|
+
# annotated_entities
|
108
|
+
# end
|
109
|
+
# end
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
#
|
113
|
+
# def self.tsv(annotations, *fields)
|
114
|
+
# return nil if annotations.nil?
|
115
|
+
#
|
116
|
+
# fields = case
|
117
|
+
#
|
118
|
+
# when ((fields.compact.empty?) && ! annotations.empty?)
|
119
|
+
# fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
|
120
|
+
# fields << :annotation_types
|
121
|
+
#
|
122
|
+
# when (fields == [:literal] and ! annotations.compact.empty?)
|
123
|
+
# fields << :literal
|
124
|
+
#
|
125
|
+
# when (fields == [:all] && Annotated === annotations)
|
126
|
+
# annotation_names = annotations.annotations
|
127
|
+
# annotation_names += annotations.first.annotations if Annotated === annotations.first
|
128
|
+
# fields = [:annotation_types] + annotation_names.uniq
|
129
|
+
# fields << :annotated_array if AnnotatedArray === annotations
|
130
|
+
# fields << :literal
|
131
|
+
#
|
132
|
+
# when (fields == [:all] && ! annotations.compact.empty?)
|
133
|
+
# raise "Input array must be annotated or its elements must be" if not Annotated === annotations.compact.first and not Array === annotations.compact.first
|
134
|
+
# raise "Input array must be annotated or its elements must be. No double arrays of singly annotated entities." if not Annotated === annotations.compact.first and Array === annotations.compact.first
|
135
|
+
# fields = [:annotation_types] + (Annotated === annotations ?
|
136
|
+
# annotations.annotations:
|
137
|
+
# annotations.compact.first.annotations)
|
138
|
+
# fields << :literal
|
139
|
+
#
|
140
|
+
# when annotations.empty?
|
141
|
+
# [:annotation_types, :literal]
|
142
|
+
#
|
143
|
+
# else
|
144
|
+
# fields.flatten
|
145
|
+
#
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# fields = fields.collect{|f| f.to_s}.uniq
|
149
|
+
#
|
150
|
+
# case
|
151
|
+
# when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
|
152
|
+
# tsv = TSV.setup({}, :key_field => "List", :fields => fields, :type => :list, :unnamed => true)
|
153
|
+
#
|
154
|
+
# annot_id = annotations.id
|
155
|
+
# annot_id = annot_id * "," if Array === annot_id
|
156
|
+
# tsv[annot_id] = annotations.tsv_values(*fields).dup
|
157
|
+
#
|
158
|
+
# when Array === annotations
|
159
|
+
# tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
|
160
|
+
#
|
161
|
+
# annotations.compact.each_with_index do |annotation,i|
|
162
|
+
# tsv[annotation.id + "#" << i.to_s] = annotation.tsv_values(*fields).dup
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# else
|
166
|
+
# raise "Annotations need to be an Array to create TSV"
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# tsv
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# def tsv_values(*fields)
|
173
|
+
# if Array === self and (not AnnotatedArray === self or self.double_array)
|
174
|
+
# Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
|
175
|
+
# else
|
176
|
+
# fields = fields.flatten
|
177
|
+
#
|
178
|
+
# info = self.info
|
179
|
+
#
|
180
|
+
# values = []
|
181
|
+
#
|
182
|
+
# fields.each do |field|
|
183
|
+
# values << case
|
184
|
+
#
|
185
|
+
# when Proc === field
|
186
|
+
# field.call(self)
|
187
|
+
#
|
188
|
+
# when field == "JSON"
|
189
|
+
# if AnnotatedArray === self
|
190
|
+
# info.merge(:annotated_array => true).to_json
|
191
|
+
# else
|
192
|
+
# info.to_json
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# when field == "annotation_types"
|
196
|
+
# annotation_types.collect{|t| t.to_s} * "|"
|
197
|
+
#
|
198
|
+
# when field == "annotated_array"
|
199
|
+
# AnnotatedArray === self
|
200
|
+
#
|
201
|
+
# when field == "literal"
|
202
|
+
# (Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
|
203
|
+
#
|
204
|
+
# when info.include?(field.to_sym)
|
205
|
+
# res = info[field.to_sym]
|
206
|
+
# Array === res ? "Array:" << res * "|" : res
|
207
|
+
#
|
208
|
+
# when self.respond_to?(field)
|
209
|
+
# res = self.send(field)
|
210
|
+
# Array === res ? "Array:"<< res * "|" : res
|
211
|
+
#
|
212
|
+
# end
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
#
|
216
|
+
# values
|
217
|
+
# end
|
218
|
+
# end
|
219
|
+
#
|
220
|
+
# def self.to_hash(e)
|
221
|
+
# hash = {}
|
222
|
+
# if Array === e && AnnotatedArray === e
|
223
|
+
# hash[:literal] = Annotated.purge(e)
|
224
|
+
# hash[:info] = e.info
|
225
|
+
# elsif Array === e
|
226
|
+
# hash = e.collect do |_e|
|
227
|
+
# _hash = {}
|
228
|
+
# _hash[:literal] = _e.dup
|
229
|
+
# _hash[:info] = _e.info if _e.respond_to?(:info)
|
230
|
+
# _hash
|
231
|
+
# end
|
232
|
+
# else
|
233
|
+
# hash[:literal] = e.dup
|
234
|
+
# hash[:info] = e.info
|
235
|
+
# end
|
236
|
+
# hash
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# def self.load_hash(hash)
|
240
|
+
# if Array === hash
|
241
|
+
# hash.collect{|h| load_hash(h) }
|
242
|
+
# else
|
243
|
+
# literal = hash[:literal]
|
244
|
+
# info = hash[:info]
|
245
|
+
# info[:annotation_types].each do |type|
|
246
|
+
# type = Kernel.const_get(type) if String === type
|
247
|
+
# type.setup(literal, info)
|
248
|
+
# end
|
249
|
+
# literal
|
250
|
+
# end
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# def marshal_dump
|
254
|
+
# Annotated.to_hash(self)
|
255
|
+
# end
|
256
|
+
#end
|
257
|
+
#
|
258
|
+
#class String
|
259
|
+
# def marshal_load(hash)
|
260
|
+
# if Hash === hash
|
261
|
+
# e = Annotated.load_hash(hash)
|
262
|
+
# self.replace e
|
263
|
+
# e.annotate(self)
|
264
|
+
# self
|
265
|
+
# else
|
266
|
+
# self.replace hash
|
267
|
+
# end
|
268
|
+
# end
|
269
|
+
#end
|
270
|
+
#
|
271
|
+
#class Array
|
272
|
+
# def marshal_load(hash)
|
273
|
+
# if Hash === hash
|
274
|
+
# e = Annotated.load_hash(hash)
|
275
|
+
# self.replace e
|
276
|
+
# e.annotate(self)
|
277
|
+
# self
|
278
|
+
# else
|
279
|
+
# self.replace hash
|
280
|
+
# end
|
281
|
+
# end
|
282
|
+
#end
|