rbbt-util 5.44.0 → 6.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rbbt +67 -90
  3. data/etc/app.d/base.rb +3 -3
  4. data/etc/app.d/semaphores.rb +3 -3
  5. data/lib/rbbt/annotations/annotated_array.rb +207 -207
  6. data/lib/rbbt/annotations/refactor.rb +27 -0
  7. data/lib/rbbt/annotations/util.rb +282 -282
  8. data/lib/rbbt/annotations.rb +343 -320
  9. data/lib/rbbt/association/database.rb +200 -225
  10. data/lib/rbbt/association/index.rb +294 -291
  11. data/lib/rbbt/association/item.rb +227 -227
  12. data/lib/rbbt/association/open.rb +35 -34
  13. data/lib/rbbt/association/util.rb +0 -169
  14. data/lib/rbbt/association.rb +2 -4
  15. data/lib/rbbt/entity/identifiers.rb +119 -118
  16. data/lib/rbbt/entity/refactor.rb +12 -0
  17. data/lib/rbbt/entity.rb +319 -315
  18. data/lib/rbbt/hpc/batch.rb +72 -53
  19. data/lib/rbbt/hpc/lsf.rb +2 -2
  20. data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
  21. data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
  22. data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
  23. data/lib/rbbt/hpc/orchestrate.rb +19 -13
  24. data/lib/rbbt/hpc/slurm.rb +18 -18
  25. data/lib/rbbt/knowledge_base/entity.rb +13 -5
  26. data/lib/rbbt/knowledge_base/query.rb +2 -2
  27. data/lib/rbbt/knowledge_base/registry.rb +32 -31
  28. data/lib/rbbt/knowledge_base/traverse.rb +1 -1
  29. data/lib/rbbt/knowledge_base.rb +1 -1
  30. data/lib/rbbt/monitor.rb +36 -25
  31. data/lib/rbbt/persist/refactor.rb +166 -0
  32. data/lib/rbbt/persist/tsv/sharder.rb +1 -1
  33. data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
  34. data/lib/rbbt/persist/tsv.rb +187 -185
  35. data/lib/rbbt/persist.rb +556 -551
  36. data/lib/rbbt/refactor.rb +20 -0
  37. data/lib/rbbt/resource/path/refactor.rb +178 -0
  38. data/lib/rbbt/resource/path.rb +317 -497
  39. data/lib/rbbt/resource/util.rb +0 -48
  40. data/lib/rbbt/resource.rb +3 -390
  41. data/lib/rbbt/tsv/accessor.rb +2 -838
  42. data/lib/rbbt/tsv/attach.rb +303 -299
  43. data/lib/rbbt/tsv/change_id.rb +244 -245
  44. data/lib/rbbt/tsv/csv.rb +87 -85
  45. data/lib/rbbt/tsv/dumper.rb +2 -100
  46. data/lib/rbbt/tsv/excel.rb +26 -24
  47. data/lib/rbbt/tsv/field_index.rb +4 -1
  48. data/lib/rbbt/tsv/filter.rb +3 -2
  49. data/lib/rbbt/tsv/index.rb +2 -284
  50. data/lib/rbbt/tsv/manipulate.rb +750 -747
  51. data/lib/rbbt/tsv/marshal.rb +3 -3
  52. data/lib/rbbt/tsv/matrix.rb +2 -2
  53. data/lib/rbbt/tsv/parallel/through.rb +2 -1
  54. data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
  55. data/lib/rbbt/tsv/parser.rb +678 -678
  56. data/lib/rbbt/tsv/refactor.rb +195 -0
  57. data/lib/rbbt/tsv/stream.rb +253 -251
  58. data/lib/rbbt/tsv/util.rb +420 -420
  59. data/lib/rbbt/tsv.rb +210 -208
  60. data/lib/rbbt/util/R/eval.rb +4 -4
  61. data/lib/rbbt/util/R/plot.rb +62 -166
  62. data/lib/rbbt/util/R.rb +21 -18
  63. data/lib/rbbt/util/cmd.rb +2 -318
  64. data/lib/rbbt/util/color.rb +269 -269
  65. data/lib/rbbt/util/colorize.rb +89 -89
  66. data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
  67. data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
  68. data/lib/rbbt/util/concurrency/processes.rb +389 -386
  69. data/lib/rbbt/util/config.rb +169 -167
  70. data/lib/rbbt/util/iruby.rb +20 -0
  71. data/lib/rbbt/util/log/progress/report.rb +241 -241
  72. data/lib/rbbt/util/log/progress/util.rb +99 -99
  73. data/lib/rbbt/util/log/progress.rb +102 -102
  74. data/lib/rbbt/util/log/refactor.rb +49 -0
  75. data/lib/rbbt/util/log.rb +486 -532
  76. data/lib/rbbt/util/migrate.rb +1 -1
  77. data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
  78. data/lib/rbbt/util/misc/development.rb +12 -11
  79. data/lib/rbbt/util/misc/exceptions.rb +117 -112
  80. data/lib/rbbt/util/misc/format.rb +2 -230
  81. data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
  82. data/lib/rbbt/util/misc/inspect.rb +2 -476
  83. data/lib/rbbt/util/misc/lock.rb +109 -106
  84. data/lib/rbbt/util/misc/omics.rb +10 -1
  85. data/lib/rbbt/util/misc/pipes.rb +765 -793
  86. data/lib/rbbt/util/misc/refactor.rb +20 -0
  87. data/lib/rbbt/util/misc/ssw.rb +308 -0
  88. data/lib/rbbt/util/misc/system.rb +0 -15
  89. data/lib/rbbt/util/misc.rb +39 -20
  90. data/lib/rbbt/util/named_array/refactor.rb +4 -0
  91. data/lib/rbbt/util/named_array.rb +3 -220
  92. data/lib/rbbt/util/open/refactor.rb +7 -0
  93. data/lib/rbbt/util/open.rb +3 -857
  94. data/lib/rbbt/util/procpath.rb +6 -6
  95. data/lib/rbbt/util/python/paths.rb +27 -0
  96. data/lib/rbbt/util/python/run.rb +115 -0
  97. data/lib/rbbt/util/python/script.rb +110 -0
  98. data/lib/rbbt/util/python/util.rb +3 -3
  99. data/lib/rbbt/util/python.rb +22 -81
  100. data/lib/rbbt/util/semaphore.rb +152 -148
  101. data/lib/rbbt/util/simpleopt.rb +9 -8
  102. data/lib/rbbt/util/ssh/refactor.rb +19 -0
  103. data/lib/rbbt/util/ssh.rb +122 -118
  104. data/lib/rbbt/util/tar.rb +117 -115
  105. data/lib/rbbt/util/tmpfile.rb +69 -67
  106. data/lib/rbbt/util/version.rb +2 -0
  107. data/lib/rbbt/workflow/refactor/entity.rb +11 -0
  108. data/lib/rbbt/workflow/refactor/export.rb +66 -0
  109. data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
  110. data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
  111. data/lib/rbbt/workflow/refactor/task_info.rb +65 -0
  112. data/lib/rbbt/workflow/refactor.rb +153 -0
  113. data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
  114. data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
  115. data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
  116. data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
  117. data/lib/rbbt/workflow/remote_workflow.rb +6 -1
  118. data/lib/rbbt/workflow/step/info.rb +2 -2
  119. data/lib/rbbt/workflow/step/run.rb +766 -766
  120. data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
  121. data/lib/rbbt/workflow/step.rb +2 -362
  122. data/lib/rbbt/workflow/task.rb +118 -118
  123. data/lib/rbbt/workflow/usage.rb +289 -287
  124. data/lib/rbbt/workflow/util/archive.rb +6 -5
  125. data/lib/rbbt/workflow/util/data.rb +1 -1
  126. data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
  127. data/lib/rbbt/workflow/util/trace.rb +79 -44
  128. data/lib/rbbt/workflow.rb +4 -882
  129. data/lib/rbbt-util.rb +21 -13
  130. data/lib/rbbt.rb +16 -3
  131. data/python/rbbt/__init__.py +19 -1
  132. data/share/Rlib/plot.R +37 -37
  133. data/share/Rlib/svg.R +22 -5
  134. data/share/install/software/lib/install_helpers +1 -1
  135. data/share/rbbt_commands/hpc/list +2 -3
  136. data/share/rbbt_commands/hpc/orchestrate +4 -4
  137. data/share/rbbt_commands/hpc/tail +2 -0
  138. data/share/rbbt_commands/hpc/task +10 -7
  139. data/share/rbbt_commands/lsf/list +2 -3
  140. data/share/rbbt_commands/lsf/orchestrate +4 -4
  141. data/share/rbbt_commands/lsf/tail +2 -0
  142. data/share/rbbt_commands/lsf/task +10 -7
  143. data/share/rbbt_commands/migrate +1 -1
  144. data/share/rbbt_commands/pbs/list +2 -3
  145. data/share/rbbt_commands/pbs/orchestrate +4 -4
  146. data/share/rbbt_commands/pbs/tail +2 -0
  147. data/share/rbbt_commands/pbs/task +10 -7
  148. data/share/rbbt_commands/resource/produce +8 -1
  149. data/share/rbbt_commands/slurm/list +2 -3
  150. data/share/rbbt_commands/slurm/orchestrate +4 -4
  151. data/share/rbbt_commands/slurm/tail +2 -0
  152. data/share/rbbt_commands/slurm/task +10 -7
  153. data/share/rbbt_commands/system/clean +5 -5
  154. data/share/rbbt_commands/system/status +5 -5
  155. data/share/rbbt_commands/tsv/get +2 -3
  156. data/share/rbbt_commands/tsv/info +10 -13
  157. data/share/rbbt_commands/tsv/keys +18 -14
  158. data/share/rbbt_commands/tsv/slice +2 -2
  159. data/share/rbbt_commands/tsv/transpose +6 -2
  160. data/share/rbbt_commands/workflow/info +20 -24
  161. data/share/rbbt_commands/workflow/list +1 -1
  162. data/share/rbbt_commands/workflow/prov +20 -13
  163. data/share/rbbt_commands/workflow/server +16 -1
  164. data/share/rbbt_commands/workflow/task +76 -71
  165. data/share/rbbt_commands/workflow/write_info +26 -9
  166. data/share/software/opt/ssw/ssw.c +861 -0
  167. data/share/software/opt/ssw/ssw.h +130 -0
  168. data/share/workflow_config.ru +3 -3
  169. metadata +42 -3
@@ -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