scout-gear 7.3.0 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +20 -9
  3. data/VERSION +1 -1
  4. data/bin/scout +6 -3
  5. data/lib/rbbt-scout.rb +1 -0
  6. data/lib/scout/cmd.rb +1 -1
  7. data/lib/scout/concurrent_stream.rb +26 -23
  8. data/lib/scout/config.rb +1 -1
  9. data/lib/scout/log/color.rb +4 -1
  10. data/lib/scout/log/progress/report.rb +1 -1
  11. data/lib/scout/log/progress/util.rb +58 -54
  12. data/lib/scout/log/progress.rb +1 -1
  13. data/lib/scout/log/trap.rb +107 -0
  14. data/lib/scout/log.rb +56 -21
  15. data/lib/scout/meta_extension.rb +13 -6
  16. data/lib/scout/misc/digest.rb +1 -1
  17. data/lib/scout/misc/format.rb +12 -0
  18. data/lib/scout/misc/insist.rb +1 -1
  19. data/lib/scout/misc/monitor.rb +11 -0
  20. data/lib/scout/misc/system.rb +10 -0
  21. data/lib/scout/named_array.rb +65 -3
  22. data/lib/scout/open/lock/lockfile.rb +587 -0
  23. data/lib/scout/open/lock.rb +28 -2
  24. data/lib/scout/open/remote.rb +4 -0
  25. data/lib/scout/open/stream.rb +90 -15
  26. data/lib/scout/open/util.rb +13 -3
  27. data/lib/scout/path/find.rb +9 -1
  28. data/lib/scout/path/util.rb +35 -0
  29. data/lib/scout/persist/serialize.rb +18 -5
  30. data/lib/scout/persist.rb +28 -12
  31. data/lib/scout/resource/path.rb +53 -0
  32. data/lib/scout/resource/produce.rb +0 -8
  33. data/lib/scout/resource/util.rb +2 -1
  34. data/lib/scout/tmpfile.rb +7 -8
  35. data/lib/scout/tsv/attach.rb +177 -0
  36. data/lib/scout/tsv/change_id.rb +40 -0
  37. data/lib/scout/tsv/dumper.rb +72 -46
  38. data/lib/scout/tsv/index.rb +69 -13
  39. data/lib/scout/tsv/open.rb +138 -84
  40. data/lib/scout/tsv/parser.rb +135 -80
  41. data/lib/scout/tsv/path.rb +1 -2
  42. data/lib/scout/tsv/persist/adapter.rb +15 -45
  43. data/lib/scout/tsv/persist/fix_width_table.rb +3 -0
  44. data/lib/scout/tsv/persist/tokyocabinet.rb +4 -1
  45. data/lib/scout/tsv/persist.rb +4 -0
  46. data/lib/scout/tsv/transformer.rb +141 -0
  47. data/lib/scout/tsv/traverse.rb +96 -92
  48. data/lib/scout/tsv/util/filter.rb +9 -0
  49. data/lib/scout/tsv/util/reorder.rb +81 -0
  50. data/lib/scout/tsv/util/select.rb +78 -33
  51. data/lib/scout/tsv/util/unzip.rb +86 -0
  52. data/lib/scout/tsv/util.rb +60 -11
  53. data/lib/scout/tsv.rb +26 -3
  54. data/lib/scout/work_queue/socket.rb +6 -1
  55. data/lib/scout/work_queue/worker.rb +5 -2
  56. data/lib/scout/work_queue.rb +15 -8
  57. data/lib/scout/workflow/definition.rb +21 -2
  58. data/lib/scout/workflow/step/dependencies.rb +24 -4
  59. data/lib/scout/workflow/step/info.rb +36 -5
  60. data/lib/scout/workflow/step/provenance.rb +8 -7
  61. data/lib/scout/workflow/step/status.rb +45 -0
  62. data/lib/scout/workflow/step.rb +100 -34
  63. data/lib/scout/workflow/task/inputs.rb +14 -20
  64. data/lib/scout/workflow/task.rb +81 -46
  65. data/lib/scout/workflow/usage.rb +8 -6
  66. data/scout-gear.gemspec +24 -20
  67. data/scout_commands/workflow/task +34 -7
  68. data/test/scout/open/test_stream.rb +60 -58
  69. data/test/scout/path/test_find.rb +10 -1
  70. data/test/scout/resource/test_produce.rb +15 -0
  71. data/test/scout/test_meta_extension.rb +25 -0
  72. data/test/scout/test_named_array.rb +18 -0
  73. data/test/scout/test_persist.rb +6 -0
  74. data/test/scout/test_tsv.rb +212 -2
  75. data/test/scout/test_work_queue.rb +21 -19
  76. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  77. data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
  78. data/test/scout/tsv/test_attach.rb +227 -0
  79. data/test/scout/tsv/test_change_id.rb +98 -0
  80. data/test/scout/tsv/test_dumper.rb +1 -1
  81. data/test/scout/tsv/test_index.rb +35 -3
  82. data/test/scout/tsv/test_open.rb +160 -2
  83. data/test/scout/tsv/test_parser.rb +19 -2
  84. data/test/scout/tsv/test_persist.rb +2 -0
  85. data/test/scout/tsv/test_transformer.rb +108 -0
  86. data/test/scout/tsv/test_traverse.rb +88 -3
  87. data/test/scout/tsv/test_util.rb +1 -0
  88. data/test/scout/tsv/util/test_reorder.rb +94 -0
  89. data/test/scout/tsv/util/test_select.rb +25 -11
  90. data/test/scout/tsv/util/test_unzip.rb +112 -0
  91. data/test/scout/work_queue/test_socket.rb +0 -1
  92. data/test/scout/workflow/step/test_status.rb +31 -0
  93. data/test/scout/workflow/task/test_inputs.rb +14 -14
  94. data/test/scout/workflow/test_step.rb +3 -3
  95. data/test/scout/workflow/test_task.rb +168 -32
  96. data/test/scout/workflow/test_usage.rb +33 -6
  97. metadata +20 -6
@@ -1,8 +1,9 @@
1
1
  require_relative '../../open/lock'
2
+ require_relative '../../meta_extension'
2
3
  require_relative 'serialize'
3
4
 
4
5
  module TSVAdapter
5
- attr_accessor :persistence_path, :persistence_class, :serializer, :closed, :writable
6
+ attr_accessor :persistence_path, :persistence_class, :closed, :writable, :serializer
6
7
 
7
8
  class << self
8
9
  attr_accessor :lock_dir
@@ -19,23 +20,15 @@ module TSVAdapter
19
20
  end
20
21
 
21
22
  def load_extension_attr_hash
22
- EXTENSION_ATTR_HASH_SERIALIZER.load(StringIO.new(self[EXTENSION_ATTR_HASH_KEY]))
23
+ EXTENSION_ATTR_HASH_SERIALIZER.load(StringIO.new(self.orig_get(EXTENSION_ATTR_HASH_KEY)))
23
24
  end
24
25
 
25
26
  def save_extension_attr_hash
26
- self[EXTENSION_ATTR_HASH_KEY]= EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash)
27
+ self.orig_set(EXTENSION_ATTR_HASH_KEY, EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash))
27
28
  end
28
29
 
29
30
  def self.extended(base)
30
- if ! TSVAdapter === base
31
- if (! TSVAdapter === base) && base.include?(EXTENSION_ATTR_HASH_KEY)
32
- TSV.setup(base, base.load_extension_attr_hash)
33
- elsif TSV === base
34
- base[EXTENSION_ATTR_HASH_KEY] = EXTENSION_ATTR_HASH_SERIALIZER.dump(base.extension_attr_hash)
35
- end
36
- end
37
-
38
- base.serializer = SERIALIZER_ALIAS[base.type]
31
+ return if base.respond_to?(:orig_set)
39
32
 
40
33
  class << base
41
34
  alias orig_set []=
@@ -54,45 +47,22 @@ module TSVAdapter
54
47
  end
55
48
 
56
49
  def load_value(str)
50
+ return nil if str.nil?
57
51
  serializer.load(str)
58
52
  end
59
53
 
60
54
  def save_value(value)
61
55
  serializer.dump(value)
62
56
  end
63
-
64
-
65
57
  end
66
58
 
67
- #case base.type
68
- #when :single
69
- # class << base
70
- # def load_value(value)
71
- # value
72
- # end
73
- # def save_value(value)
74
- # value
75
- # end
76
- # end
77
- #when :list, :flat
78
- # class << base
79
- # def load_value(value)
80
- # value.nil? ? nil : value.split("\t")
81
- # end
82
- # def save_value(value)
83
- # value * "\t"
84
- # end
85
- # end
86
- #when :double
87
- # class << base
88
- # def load_value(value)
89
- # value.nil? ? nil : value.split("\t").collect{|v| v.split("|") }
90
- # end
91
- # def save_value(value)
92
- # value.collect{|v| v * "|" } * "\t"
93
- # end
94
- # end
95
- #end
59
+ if base.include?(EXTENSION_ATTR_HASH_KEY)
60
+ TSV.setup(base, base.load_extension_attr_hash)
61
+ else
62
+ base.instance_variable_get(:@extension_attrs).push :serializer
63
+ base.serializer = SERIALIZER_ALIAS[base.type] if base.serializer.nil?
64
+ base.save_extension_attr_hash
65
+ end
96
66
  end
97
67
 
98
68
  def keys(*args)
@@ -101,9 +71,9 @@ module TSVAdapter
101
71
  end
102
72
 
103
73
  if k[0] == EXTENSION_ATTR_HASH_KEY
104
- k.slice(1,k.length-1)
74
+ k.slice(1,k.length)
105
75
  elsif k[-1] == EXTENSION_ATTR_HASH_KEY
106
- k.slice(0,k.length-2)
76
+ k.slice(0,k.length-1)
107
77
  else
108
78
  k - [EXTENSION_ATTR_HASH_KEY]
109
79
  end
@@ -2,6 +2,7 @@ class FixWidthTable
2
2
 
3
3
  attr_accessor :filename, :file, :value_size, :record_size, :range, :size, :mask, :write
4
4
  def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true)
5
+ filename = filename.find if Path === filename
5
6
  @filename = filename
6
7
 
7
8
  if update || %w(memory stringio).include?(filename.to_s.downcase) || ! File.exist?(filename)
@@ -312,6 +313,8 @@ class FixWidthTable
312
313
  acc.concat(new)
313
314
  end
314
315
  end
316
+
317
+ alias length size
315
318
  end
316
319
 
317
320
  Persist.save_drivers[:fwt] = proc do |file, content|
@@ -16,10 +16,13 @@ module ScoutCabinet
16
16
  dir = File.dirname(File.expand_path(path))
17
17
  Open.mkdir(dir) unless File.exist?(dir)
18
18
 
19
+ tokyocabinet_class = tokyocabinet_class.to_s if Symbol === tokyocabinet_class
19
20
  tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
20
21
  tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
21
22
 
22
- database = Persist::CONNECTIONS[path] ||= tokyocabinet_class.new
23
+ # Hack - Ignore warning: undefining the allocator of T_DATA class
24
+ # TokyoCabinet::HDB_data
25
+ database = Log.ignore_stderr do Persist::CONNECTIONS[path] ||= tokyocabinet_class.new end
23
26
 
24
27
  if big and not Open.exists?(path)
25
28
  database.tune(nil,nil,nil,tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
@@ -6,6 +6,10 @@ Persist.save_drivers[:tsv] = proc do |file,content|
6
6
  content
7
7
  elsif content.respond_to?(:stream)
8
8
  content.stream
9
+ elsif content.respond_to?(:dumper_stream)
10
+ content.dumper_stream
11
+ else
12
+ content
9
13
  end
10
14
  Open.sensible_write(file, stream)
11
15
  end
@@ -0,0 +1,141 @@
1
+ module TSV
2
+ class Transformer
3
+ attr_accessor :unnamed, :parser, :dumper
4
+
5
+ def initialize(parser, dumper = nil, unnamed: false)
6
+ if TSV::Parser === parser
7
+ @parser = parser
8
+ elsif TSV === parser
9
+ @parser = parser
10
+ else
11
+ @parser = TSV::Parser.new parser
12
+ end
13
+ @unnamed = unnamed
14
+ if dumper.nil?
15
+ @dumper = TSV::Dumper.new(@parser)
16
+ @dumper.sep = "\t"
17
+ else
18
+ @dumper = dumper
19
+ end
20
+ end
21
+
22
+ def key_field=(key_field)
23
+ @dumper.key_field = key_field
24
+ end
25
+
26
+ def fields=(fields)
27
+ @dumper.fields = fields
28
+ end
29
+
30
+ def type=(type)
31
+ @dumper.type = type
32
+ end
33
+
34
+ def type
35
+ @dumper.type
36
+ end
37
+
38
+ def sep=(sep)
39
+ @dumper.sep = sep
40
+ end
41
+
42
+ def include?(*args)
43
+ false
44
+ end
45
+
46
+ def key_field
47
+ @dumper.key_field
48
+ end
49
+
50
+ def fields
51
+ @dumper.fields
52
+ end
53
+
54
+ def all_fields
55
+ return nil if fields.nil?
56
+ [key_field] + fields
57
+ end
58
+
59
+ def options
60
+ @dumper.options
61
+ end
62
+
63
+ def identify_field(name)
64
+ TSV.identify_field key_field, fields, name
65
+ end
66
+
67
+ def traverse(*args, **kwargs, &block)
68
+ kwargs[:into] = @dumper
69
+ kwargs[:bar] = "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @target}" if TrueClass === kwargs[:bar]
70
+ @dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
71
+ Log.debug "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @dumper}"
72
+ Open.traverse(@parser, *args, **kwargs) do |k,v|
73
+ NamedArray.setup(v, @parser.fields, k) unless @unnamed
74
+ block.call k, v
75
+ end
76
+ end
77
+
78
+ def each(*args, **kwargs, &block)
79
+ kwargs[:into] = @dumper
80
+ kwargs[:bar] = "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @target}" if TrueClass === kwargs[:bar]
81
+ @dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
82
+ Open.traverse(@parser, *args, **kwargs) do |k,v|
83
+ NamedArray.setup(v, @parser.fields, k) unless @unnamed
84
+ block.call k, v
85
+ [k, v]
86
+ end
87
+ end
88
+
89
+ def with_unnamed
90
+ begin
91
+ old_unnamed = @unnamed
92
+ @unnamed = true
93
+ yield
94
+ ensure
95
+ @unnamed = old_unnamed
96
+ end
97
+ end
98
+
99
+ def []=(key, value)
100
+ @dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
101
+ @dumper.add key, value
102
+ end
103
+
104
+ def stream
105
+ @dumper.stream
106
+ end
107
+
108
+ def tsv(*args)
109
+ TSV === @dumper ? @dumper : TSV.open(stream, *args)
110
+ end
111
+ end
112
+
113
+ def to_list
114
+ res = self.annotate({})
115
+ transformer = Transformer.new self, res
116
+ transformer.type = :list
117
+ transformer.traverse do |k,v|
118
+ case self.type
119
+ when :single
120
+ [k, [v]]
121
+ when :double
122
+ [k, v.collect{|v| v.first }]
123
+ when :flat
124
+ [k, v.slice(0,1)]
125
+ end
126
+ end
127
+ res
128
+ end
129
+
130
+ def to_single
131
+ res = self.annotate({})
132
+ transformer = Transformer.new self, res
133
+ transformer.type = :single
134
+ transformer.traverse do |k,v|
135
+ v = v.first while Array === v
136
+ [k, v]
137
+ end
138
+ res
139
+ end
140
+ end
141
+
@@ -1,22 +1,14 @@
1
1
  require_relative 'parser'
2
2
  module TSV
3
- def self.identify_field(key_field, fields, name)
4
- return :key if name == :key || key_field.start_with?(name.to_s)
5
- name.collect!{|n| key_field == n ? :key : n } if Array === name
6
- NamedArray.identify_name(fields, name)
7
- end
8
-
9
- def identify_field(name)
10
- TSV.identify_field(@key_field, @fields, name)
11
- end
12
-
13
- def traverse(key_field_pos = :key, fields_pos = nil, type: nil, one2one: false, unnamed: false, key_field: nil, fields: nil, &block)
3
+ def traverse(key_field_pos = :key, fields_pos = nil, type: nil, one2one: false, unnamed: false, key_field: nil, fields: nil, bar: false, cast: nil, select: nil, &block)
14
4
  key_field = key_field_pos if key_field.nil?
15
- fields = fields_pos if fields.nil?
5
+ fields = fields_pos.dup if fields.nil?
16
6
  type = @type if type.nil?
17
7
  key_pos = self.identify_field(key_field)
8
+ fields = self.all_fields if fields == :all
18
9
  fields = [fields] unless fields.nil? || Array === fields
19
- positions = fields.nil? ? nil : self.identify_field(fields)
10
+ positions = fields.nil? || fields == :all ? nil : self.identify_field(fields)
11
+
20
12
 
21
13
  if key_pos == :key
22
14
  key_name = @key_field
@@ -33,7 +25,7 @@ module TSV
33
25
  field_names = @fields
34
26
  elsif positions.nil? && key_pos != :key
35
27
  field_names = @fields.dup
36
- field_names.delete_at key_pos
28
+ field_names.delete_at key_pos unless fields == :all
37
29
  elsif positions.include?(:key)
38
30
  field_names = positions.collect{|p| p == :key ? @key_field : @fields[p] }
39
31
  else
@@ -43,98 +35,110 @@ module TSV
43
35
  key_index = positions.index :key if positions
44
36
  positions.delete :key if positions
45
37
 
46
- each do |key,values|
47
- values = [values] if @type == :single
48
- if positions.nil?
49
- if key_pos != :key
50
- values = values.dup
51
- key = values.delete_at(key_pos)
52
- end
53
- else
54
- orig_key = key
55
- key = values[key_pos] if key_pos != :key
38
+ log_message = "Traverse #{Log.fingerprint self}"
39
+ Log.debug log_message
40
+ bar = log_message if TrueClass === bar
56
41
 
57
- values = values.values_at(*positions)
58
- if key_index
59
- if @type == :double
60
- values.insert key_index, [orig_key]
61
- else
62
- values.insert key_index, orig_key
42
+ Log::ProgressBar.with_obj_bar(self, bar) do |bar|
43
+ with_unnamed unnamed do
44
+ each do |key,values|
45
+ bar.tick if bar
46
+ values = [values] if @type == :single
47
+ if positions.nil?
48
+ if key_pos != :key
49
+ values = values.dup
50
+ key = values.delete_at(key_pos)
51
+ end
52
+ else
53
+ orig_key = key
54
+ key = values[key_pos] if key_pos != :key
55
+
56
+ values = values.values_at(*positions)
57
+ if key_index
58
+ if @type == :double
59
+ values.insert key_index, [orig_key]
60
+ else
61
+ values.insert key_index, orig_key
62
+ end
63
+ end
63
64
  end
64
- end
65
- end
66
65
 
67
- if Array === key
68
- if @type == :double && one2one
69
- if one2one == :fill
70
- key.each_with_index do |key_i,i|
71
- if type == :double
72
- v_i = values.collect{|v| [v[i] || v.first] }
66
+ values = TSV.cast_value(values, cast) if cast
67
+
68
+ if Array === key
69
+ if @type == :double && one2one
70
+ if one2one == :strict
71
+ key.each_with_index do |key_i,i|
72
+ if type == :double
73
+ v_i = values.collect{|v| [v[i]] }
74
+ else
75
+ v_i = values.collect{|v| v[i] }
76
+ end
77
+ yield key_i, v_i
78
+ end
73
79
  else
74
- v_i = values.collect{|v| v[i] || v.first }
80
+ key.each_with_index do |key_i,i|
81
+ if type == :double
82
+ v_i = values.collect{|v| [v[i] || v.first] }
83
+ else
84
+ v_i = values.collect{|v| v[i] || v.first }
85
+ end
86
+ yield key_i, v_i, @fields
87
+ end
88
+ end
89
+ else
90
+ key.each_with_index do |key_i, i|
91
+ if type == :double
92
+ yield key_i, values
93
+ elsif type == :list
94
+ yield key_i, values.collect{|v| v[i] }
95
+ elsif type == :flat
96
+ yield key_i, values.flatten
97
+ elsif type == :single
98
+ yield key_i, values.first
99
+ end
75
100
  end
76
- yield key_i, v_i
77
101
  end
78
102
  else
79
- key.each_with_index do |key_i,i|
80
- if type == :double
81
- v_i = values.collect{|v| [v[i]] }
103
+ if type == @type
104
+ if type == :single
105
+ yield key, values.first
82
106
  else
83
- v_i = values.collect{|v| v[i] }
107
+ yield key, values
108
+ end
109
+ else
110
+ case [type, @type]
111
+ when [:double, :list]
112
+ yield key, values.collect{|v| [v] }
113
+ when [:double, :flat]
114
+ yield key, [values]
115
+ when [:double, :single]
116
+ yield key, [values]
117
+ when [:list, :double]
118
+ yield key, values.collect{|v| v.first }
119
+ when [:list, :flat]
120
+ yield key, [values.first]
121
+ when [:list, :single]
122
+ yield key, values
123
+ when [:flat, :double]
124
+ yield key, values.flatten
125
+ when [:flat, :list]
126
+ yield key, values.flatten
127
+ when [:flat, :single]
128
+ yield key, values
129
+ when [:single, :double]
130
+ yield key, values.flatten.first
131
+ when [:single, :list]
132
+ yield key, values.first
133
+ when [:single, :flat]
134
+ yield key, values.first
84
135
  end
85
- yield key_i, v_i
86
- end
87
- end
88
- else
89
- key.each_with_index do |key_i, i|
90
- if type == :double
91
- yield key_i, values
92
- elsif type == :list
93
- yield key_i, values.collect{|v| v[i] }
94
- elsif type == :flat
95
- yield key_i, values.flatten
96
- elsif type == :single
97
- yield key_i, values.first
98
136
  end
99
137
  end
100
138
  end
101
- else
102
- if type == @type
103
- if type == :single
104
- yield key, values.first
105
- else
106
- yield key, values
107
- end
108
- else
109
- case [type, @type]
110
- when [:double, :list]
111
- yield key, values.collect{|v| [v] }
112
- when [:double, :flat]
113
- yield key, [values]
114
- when [:double, :single]
115
- yield key, [values]
116
- when [:list, :double]
117
- yield key, values.collect{|v| v.first }
118
- when [:list, :flat]
119
- yield key, [values.first]
120
- when [:list, :single]
121
- yield key, values
122
- when [:flat, :double]
123
- yield key, values.flatten
124
- when [:flat, :list]
125
- yield key, values.flatten
126
- when [:flat, :single]
127
- yield key, values
128
- when [:single, :double]
129
- yield key, values.flatten.first
130
- when [:single, :list]
131
- yield key, values.first
132
- when [:single, :flat]
133
- yield key, values.first
134
- end
135
- end
136
139
  end
137
140
  end
141
+
138
142
 
139
143
  [key_name, field_names]
140
144
  end
@@ -299,5 +299,14 @@ module TSV
299
299
  FileUtils.rm f
300
300
  end
301
301
  end
302
+
303
+ def with_filters(filters, &block)
304
+ filter
305
+ begin
306
+ filters.each{|field,value| add_filter field, value }
307
+ ensure
308
+ reset_filters
309
+ end
310
+ end
302
311
  end
303
312
 
@@ -0,0 +1,81 @@
1
+ require 'matrix'
2
+
3
+ module TSV
4
+ def reorder(key_field = nil, fields = nil, merge: true, one2one: true, **kwargs)
5
+ res = self.annotate({})
6
+ res.type = kwargs[:type] if kwargs.include?(:type)
7
+ kwargs[:one2one] = one2one
8
+ key_field_name, field_names = traverse key_field, fields, **kwargs do |k,v|
9
+ if @type == :double && merge && res.include?(k)
10
+ current = res[k]
11
+ if merge == :concat
12
+ v.each_with_index do |new,i|
13
+ next if new.empty?
14
+ current[i].concat(new)
15
+ end
16
+ else
17
+ merged = []
18
+ v.each_with_index do |new,i|
19
+ next if new.empty?
20
+ merged[i] = current[i] + new
21
+ end
22
+ res[k] = merged
23
+ end
24
+ else
25
+ res[k] = v
26
+ end
27
+ end
28
+ res.key_field = key_field_name
29
+ res.fields = field_names
30
+ res
31
+ end
32
+
33
+ def slice(fields, **kwargs)
34
+ reorder :key, fields, **kwargs
35
+ end
36
+
37
+ def column(field, **kwargs)
38
+ new_type = case type
39
+ when :double, :flat
40
+ :flat
41
+ else
42
+ :single
43
+ end
44
+
45
+ kwargs[:type] = new_type
46
+ slice(field, **kwargs)
47
+ end
48
+
49
+ def transpose_list(key_field="Unkown ID")
50
+ new_fields = keys.dup
51
+ new = self.annotate({})
52
+ TSV.setup(new, :key_field => key_field, :fields => new_fields, :type => type, :filename => filename, :identifiers => identifiers)
53
+
54
+ m = Matrix.rows values
55
+ new_rows = m.transpose.to_a
56
+
57
+ fields.zip(new_rows) do |key,row|
58
+ new[key] = row
59
+ end
60
+
61
+ new
62
+ end
63
+
64
+ def transpose_double(key_field = "Unkown ID")
65
+ sep = "-!SEP--#{rand 10000}!-"
66
+ tmp = self.to_list{|v| v * sep}
67
+ new = tmp.transpose_list(key_field)
68
+ new.to_double{|v| v.split(sep)}
69
+ end
70
+
71
+ def transpose(key_field = "Unkown ID")
72
+ case type
73
+ when :single, :flat
74
+ self.to_list.transpose_list key_field
75
+ when :list
76
+ transpose_list key_field
77
+ when :double
78
+ transpose_double key_field
79
+ end
80
+ end
81
+ end