Module: Misc

Defined in:
lib/rbbt/util/tar.rb,
lib/rbbt/util/misc.rb,
lib/rbbt/util/misc/lock.rb,
lib/rbbt/util/misc/math.rb,
lib/rbbt/util/misc/omics.rb,
lib/rbbt/util/misc/pipes.rb,
lib/rbbt/util/misc/format.rb,
lib/rbbt/util/misc/system.rb,
lib/rbbt/util/misc/inspect.rb,
lib/rbbt/util/misc/objects.rb,
lib/rbbt/util/misc/options.rb,
lib/rbbt/util/misc/development.rb,
lib/rbbt/util/misc/manipulation.rb

Overview

SOURCE: gist.github.com/sinisterchipmunk/1335041 Adapted for Rbbt

Constant Summary collapse

LOCK_MUTEX =
Mutex.new
LOCK_REPO_SERIALIZER =
Marshal
Log2Multiplier =
1.0 / Math.log(2.0)
IUPAC2BASE =
{
  "A" => ["A"],
  "C" => ["C"],
  "G" => ["G"],
  "T" => ["T"],
  "U" => ["U"],
  "R" => "A or G".split(" or "),
  "Y" => "C or T".split(" or "),
  "S" => "G or C".split(" or "),
  "W" => "A or T".split(" or "),
  "K" => "G or T".split(" or "),
  "M" => "A or C".split(" or "),
  "B" => "C or G or T".split(" or "),
  "D" => "A or G or T".split(" or "),
  "H" => "A or C or T".split(" or "),
  "V" => "A or C or G".split(" or "),
  "N" => %w(A C T G),
}
BASE2COMPLEMENT =
{
  "A" => "T",
  "C" => "G",
  "G" => "C",
  "T" => "A",
  "U" => "A",
}
THREE_TO_ONE_AA_CODE =
{
  "ala" =>   "A",
  "arg" =>   "R",
  "asn" =>   "N",
  "asp" =>   "D",
  "cys" =>   "C",
  "glu" =>   "E",
  "gln" =>   "Q",
  "gly" =>   "G",
  "his" =>   "H",
  "ile" =>   "I",
  "leu" =>   "L",
  "lys" =>   "K",
  "met" =>   "M",
  "phe" =>   "F",
  "pro" =>   "P",
  "ser" =>   "S",
  "thr" =>   "T",
  "trp" =>   "W",
  "tyr" =>   "Y",
  "val" =>   "V"
}
CODON_TABLE =
{
  "ATT" => "I",
  "ATC" => "I",
  "ATA" => "I",
  "CTT" => "L",
  "CTC" => "L",
  "CTA" => "L",
  "CTG" => "L",
  "TTA" => "L",
  "TTG" => "L",
  "GTT" => "V",
  "GTC" => "V",
  "GTA" => "V",
  "GTG" => "V",
  "TTT" => "F",
  "TTC" => "F",
  "ATG" => "M",
  "TGT" => "C",
  "TGC" => "C",
  "GCT" => "A",
  "GCC" => "A",
  "GCA" => "A",
  "GCG" => "A",
  "GGT" => "G",
  "GGC" => "G",
  "GGA" => "G",
  "GGG" => "G",
  "CCT" => "P",
  "CCC" => "P",
  "CCA" => "P",
  "CCG" => "P",
  "ACT" => "T",
  "ACC" => "T",
  "ACA" => "T",
  "ACG" => "T",
  "TCT" => "S",
  "TCC" => "S",
  "TCA" => "S",
  "TCG" => "S",
  "AGT" => "S",
  "AGC" => "S",
  "TAT" => "Y",
  "TAC" => "Y",
  "TGG" => "W",
  "CAA" => "Q",
  "CAG" => "Q",
  "AAT" => "N",
  "AAC" => "N",
  "CAT" => "H",
  "CAC" => "H",
  "GAA" => "E",
  "GAG" => "E",
  "GAT" => "D",
  "GAC" => "D",
  "AAA" => "K",
  "AAG" => "K",
  "CGT" => "R",
  "CGC" => "R",
  "CGA" => "R",
  "CGG" => "R",
  "AGA" => "R",
  "AGG" => "R",
  "TAA" => "*",
  "TAG" => "*",
  "TGA" => "*",
}
PIPE_MUTEX =
Mutex.new
OPEN_PIPE_IN =
[]
COLOR_LIST =
%w(#BC80BD #CCEBC5 #FFED6F #8DD3C7 #FFFFB3 #BEBADA #FB8072 #80B1D3 #FDB462 #B3DE69 #FCCDE5 #D9D9D9)
ARRAY_MAX_LENGTH =
1000
STRING_MAX_LENGTH =
ARRAY_MAX_LENGTH * 10
HASH2MD5_MAX_STRING_LENGTH =
1000
HASH2MD5_MAX_ARRAY_LENGTH =
100

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.sensiblewrite_dirObject

Returns the value of attribute sensiblewrite_dir.



13
14
15
# File 'lib/rbbt/util/misc/pipes.rb', line 13

def sensiblewrite_dir
  @sensiblewrite_dir
end

.sensiblewrite_lock_dirObject

Returns the value of attribute sensiblewrite_lock_dir.



5
6
7
# File 'lib/rbbt/util/misc/pipes.rb', line 5

def sensiblewrite_lock_dir
  @sensiblewrite_lock_dir
end

Class Method Details

._paste_streams(streams, output, lines = nil, sep = "\t", header = nil) ⇒ Object



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/rbbt/util/misc/pipes.rb', line 360

def self._paste_streams(streams, output, lines = nil, sep = "\t", header = nil)
  output.puts header if header
  streams = streams.collect do |stream|
    if defined? Step and Step === stream
      stream.get_stream || stream.join.path.open
    else
      stream
    end
  end

  begin
    done_streams = []
    lines ||= streams.collect{|s| s.gets }
    keys = []
    parts = []
    lines.each_with_index do |line,i|
      key, *p = line.strip.split(sep, -1) 
      keys[i] = key
      parts[i] = p
    end
    sizes = parts.collect{|p| p.length }
    last_min = nil
    while lines.compact.any?
      min = keys.compact.sort.first
      str = []
      keys.each_with_index do |key,i|
        case key
        when min
          str << [parts[i] * sep]
          line = lines[i] = streams[i].gets
          if line.nil?
            keys[i] = nil
            parts[i] = nil
          else
            k, *p = line.strip.split(sep, -1)
            keys[i] = k
            parts[i] = p
          end
        else
          str << [sep * (sizes[i]-1)] if sizes[i] > 0
        end
      end

      output.puts [min, str*sep] * sep
    end
    streams.each do |stream|
      stream.join if stream.respond_to? :join
    end
  rescue 
    Log.exception $!
    streams.each do |stream|
      stream.abort if stream.respond_to? :abort
    end
    raise $!
  end
end

.add_defaults(options, defaults = {}) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rbbt/util/misc/options.rb', line 112

def self.add_defaults(options, defaults = {})
  options ||= {}
  case
  when Hash === options
    new_options = options.dup
  when String === options
    new_options = string2hash options
  else
    raise "Format of '#{options.inspect}' not understood. It should be a hash"
  end

  defaults.each do |key, value|
    next if options.include? key

    new_options[key] = value 
  end

  new_options
end

.add_libdir(dir = nil) ⇒ Object



3
4
5
6
# File 'lib/rbbt/util/misc/development.rb', line 3

def self.add_libdir(dir=nil)
  dir ||= File.join(Path.caller_lib_dir(caller.first), 'lib')
  $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include? dir
end

.append_zipped(current, new) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rbbt/util/misc/objects.rb', line 37

def self.append_zipped(current, new)
  if current.empty?
    current.replace new.collect{|e| [e]}
  else
    current.each do |v|
      n = new.shift
      if Array === n
        v.concat new
      else
        v << n
      end
    end
  end
  current
end

.array2hash(array, default = nil) ⇒ Object



24
25
26
27
28
29
30
31
# File 'lib/rbbt/util/misc/options.rb', line 24

def self.array2hash(array, default = nil)
  hash = {}
  array.each do |key, value|
    value = default.dup if value.nil? and not default.nil?
    hash[key] = value
  end
  hash
end

.benchmark(repeats = 1, message = nil) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rbbt/util/misc/development.rb', line 29

def self.benchmark(repeats = 1, message = nil)
  require 'benchmark'
  res = nil
  begin
    measure = Benchmark.measure do
      repeats.times do
        res = yield
      end
    end
    if message
      puts "#{message }: #{ repeats } repeats"
    else
      puts "Benchmark for #{ repeats } repeats"
    end
    puts measure
  rescue Exception
    puts "Benchmark aborted"
    raise $!
  end
  res
end

.binary_include?(array, elem) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/rbbt/util/misc/manipulation.rb', line 111

def self.binary_include?(array, elem)
  upper = array.size - 1
  lower = 0

  return -1 if upper < lower

  while(upper >= lower) do
    idx = lower + (upper - lower) / 2
    value = array[idx]

    case elem <=> value
    when 0
      return true
    when -1
      upper = idx - 1
    when 1
      lower = idx + 1
    else
      raise "Cannot compare #{[elem.inspect, value.inspect] * " with "}"
    end
  end

  return false
end

.bootstrap(elems, num = :current, file = nil, &block) ⇒ Object



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/rbbt/util/misc/development.rb', line 279

def self.bootstrap(elems, num = :current, file = nil, &block)
  num = :current if num.nil?
  cpus = case num
         when :current
          10
         when String
           num.to_i
         when Integer
           if num < 100
             num
           else
             32000 / num
           end
         end

  index = (0..elems.length-1).to_a.collect{|v| v.to_s }
  TSV.traverse index, :cpus => cpus, :bar => "Bootstrap in #{ cpus } cpus: #{ Misc.fingerprint Annotated.purge(elems) }", :into => Set.new do |pos|
    elem = elems[pos.to_i]
    elems.annotate elem if elems.respond_to? :annotate
    begin
      yield elem
    rescue Interrupt
      Log.warn "Process #{Process.pid} was aborted"
    end
    nil
  end
end

.camel_case(string) ⇒ Object



83
84
85
86
87
88
# File 'lib/rbbt/util/misc/format.rb', line 83

def self.camel_case(string)
  return string if string !~ /_/ && string =~ /[A-Z]+.*/
    string.split(/_|(\d+)/).map{|e| 
      (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize) 
    }.join
end

.camel_case_lower(string) ⇒ Object



90
91
92
93
94
# File 'lib/rbbt/util/misc/format.rb', line 90

def self.camel_case_lower(string)
    string.split('_').inject([]){ |buffer,e| 
      buffer.push(buffer.empty? ? e.downcase : (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize)) 
    }.join
end

.collapse_ranges(ranges) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rbbt/util/misc/manipulation.rb', line 2

def self.collapse_ranges(ranges)
  processed = []
  last = nil
  final = []
  ranges.sort_by{|range| range.begin }.each do |range|
    rbegin = range.begin
    rend = range.end
    if last.nil? or rbegin > last
      processed << [rbegin, rend]
      last = rend
    else
     new_processed = []
      processed.each do |pbegin,pend|
        if pend < rbegin
          final << [pbegin, pend]
        else
          eend = [rend, pend].max
          new_processed << [pbegin, eend]
          break
        end
      end
      processed = new_processed
      last = rend if rend > last
    end
  end

  final.concat processed
  final.collect{|b,e| (b..e)}
end

.collapse_stream(s, line = nil, sep = "\t", header = nil) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/rbbt/util/misc/pipes.rb', line 326

def self.collapse_stream(s, line = nil, sep = "\t", header = nil)
  sep ||= "\t"
  Misc.open_pipe do |sin|
    sin.puts header if header
    process_stream(s) do |s|
      line ||= s.gets

      current_parts = []
      while line 
        key, *parts = line.strip.split(sep, -1)
        current_key ||= key
        case
        when key.nil?
        when current_key == key
          parts.each_with_index do |part,i|
            if current_parts[i].nil?
              current_parts[i] = part
            else
              current_parts[i] = current_parts[i] << "|" << part
            end
          end
        when current_key != key
          sin.puts [current_key, current_parts].flatten * sep
          current_key = key
          current_parts = parts
        end
        line = s.gets
      end

      sin.puts [current_key, current_parts].flatten * sep unless current_key.nil?
    end
  end
end

.colors_for(list) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/rbbt/util/misc/format.rb', line 4

def self.colors_for(list)
  unused = COLOR_LIST.dup

  used = {}
  colors = list.collect do |elem|
    if used.include? elem
      used[elem]
    else
      color = unused.shift
      used[elem]=color
      color
    end
  end

  [colors, used]
end

.common_path(dir, file) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/rbbt/util/misc/system.rb', line 63

def self.common_path(dir, file)
  file = File.expand_path file
  dir = File.expand_path dir

  return true if file == dir
  while File.dirname(file) != file
    file = File.dirname(file)
    return true if file == dir
  end

  return false
end

.consolidate(list) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/rbbt/util/misc/objects.rb', line 26

def self.consolidate(list)
  list.inject(nil){|acc,e|
    if acc.nil?
      acc = e
    else
      acc.concat e
      acc
    end
  }
end

.consume_stream(io, in_thread = false, into = nil) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/rbbt/util/misc/pipes.rb', line 162

def self.consume_stream(io, in_thread = false, into = nil)
  return if Path === io
  return unless io.respond_to? :read 
  if io.respond_to? :closed? and io.closed?
    io.join if io.respond_to? :join
    return
  end

  if in_thread
    Thread.new do
      consume_stream(io, false)
    end
  else
    Log.medium "Consuming stream #{Misc.fingerprint io}"
    begin
      into.sync == true if IO === into
      while not io.closed? and block = io.read(2048)
        into << block if into
      end
      io.join if io.respond_to? :join
      io.close unless io.closed?
    rescue Aborted
      Log.medium "Consume stream aborted #{Misc.fingerprint io}"
      io.abort if io.respond_to? :abort
      io.close unless io.closed?
    rescue Exception
      Log.medium "Exception consuming stream: #{Misc.fingerprint io}: #{$!.message}"
      io.abort if io.respond_to? :abort
      io.close unless io.closed?
      raise $!
    end
  end
end

.correct_icgc_mutation(pos, ref, mut_str) ⇒ Object



119
120
121
122
123
124
# File 'lib/rbbt/util/misc/omics.rb', line 119

def self.correct_icgc_mutation(pos, ref, mut_str)
  mut = mut_str
  mut = '-' * (mut_str.length - 1) if mut =~/^-[ACGT]/
    mut = "+" << mut if ref == '-'
  [pos, [mut]]
end

.correct_vcf_mutation(pos, ref, mut_str) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rbbt/util/misc/omics.rb', line 126

def self.correct_vcf_mutation(pos, ref, mut_str)
  muts = mut_str.nil? ? [] : mut_str.split(',')
  muts.collect!{|m| m == '<DEL>' ? '-' : m }

  while ref.length >= 1 and muts.reject{|m| m[0] == ref[0]}.empty?
    ref = ref[1..-1]
    raise "REF nil" if ref.nil?
    pos = pos + 1
    muts = muts.collect{|m| m[1..-1]}
  end

  muts = muts.collect do |m|
    case
    when ref.empty?
      "+" << m
    when (m.length < ref.length and (m.empty? or ref.index(m)))
      "-" * (ref.length - m.length)
    when (ref.length == 1 and m.length == 1)
      m
    else
      Log.debug{"Cannot understand: #{[ref, m]} (#{ muts })"}
      '-' * ref.length + m
    end
  end

  [pos, muts]
end

.counts(array) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/rbbt/util/misc/math.rb', line 43

def self.counts(array)
  counts = {}
  array.each do |e|
    counts[e] ||= 0
    counts[e] += 1
  end

  counts
end

.digest(text) ⇒ Object



112
113
114
# File 'lib/rbbt/util/misc/inspect.rb', line 112

def self.digest(text)
  Digest::MD5.hexdigest(text)
end

.divide(array, num) ⇒ Object

Divides the array into num chunks of the same size by placing one element in each chunk iteratively.



179
180
181
182
183
184
185
186
187
188
# File 'lib/rbbt/util/misc/development.rb', line 179

def self.divide(array, num)
  num = 1 if num == 0
  chunks = []
  num.to_i.times do chunks << [] end
  array.each_with_index{|e, i|
    c = i % num
    chunks[c] << e
  }
  chunks
end

.do_once(&block) ⇒ Object



123
124
125
126
127
128
# File 'lib/rbbt/util/misc/development.rb', line 123

def self.do_once(&block)
  return nil if $__did_once
  $__did_once = true
  yield
  nil
end

.dup_stream(stream) ⇒ Object



425
426
427
428
429
430
431
432
433
434
# File 'lib/rbbt/util/misc/pipes.rb', line 425

def self.dup_stream(stream)
  stream_dup = stream.dup
  if stream.respond_to? :annotate
    stream.annotate stream_dup
    stream.clear
  end
  tee1, tee2 = Misc.tee_stream stream_dup
  stream.reopen(tee1)
  tee2
end

.ensembl_server(organism) ⇒ Object



186
187
188
189
190
191
192
193
# File 'lib/rbbt/util/misc/omics.rb', line 186

def self.ensembl_server(organism)
  date = organism.split("/")[1]
  if date.nil?
    "www.ensembl.org"
  else
    "#{ date }.archive.ensembl.org"
  end
end

.env_add(var, value, sep = ":", prepend = true) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/rbbt/util/misc/system.rb', line 38

def self.env_add(var, value, sep = ":", prepend = true)
  ENV[var] ||= ""
  return if ENV[var] =~ /(#{sep}|^)#{Regexp.quote value}(#{sep}|$)/
    if prepend
      ENV[var] = value + sep + ENV[var]
    else
      ENV[var] += sep + ENV[var]
    end
end

.field_position(fields, field, quiet = false) ⇒ Object

Raises:



63
64
65
66
67
68
69
70
# File 'lib/rbbt/util/misc/objects.rb', line 63

def self.field_position(fields, field, quiet = false)
  return field if Integer === field or Range === field
  raise FieldNotFoundError, "Field information missing" if fields.nil? && ! quiet
  fields.each_with_index{|f,i| return i if f == field}
  field_re = Regexp.new /^#{field}$/i
  fields.each_with_index{|f,i| return i if f =~ field_re}
  raise FieldNotFoundError, "Field #{ field.inspect } was not found" unless quiet
end

.filename?(string) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/rbbt/util/misc/system.rb', line 90

def self.filename?(string)
  String === string and string.length > 0 and string.length < 250 and File.exists?(string)
end

.fingerprint(obj) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rbbt/util/misc/inspect.rb', line 26

def self.fingerprint(obj)
  case obj
  when nil
    "nil"
  when (defined? Step and Step)
    obj.path || Misc.fingerprint([obj.task.name, obj.inputs])
  when TrueClass
    "true"
  when FalseClass
    "false"
  when Symbol
    ":" << obj.to_s
  when String
    if obj.length > 100
      "'" << obj.slice(0,30) << "<...#{obj.length}...>" << obj.slice(-10,30) << " " << "'"
    else 
      "'" << obj << "'"
    end
  when (defined? AnnotatedArray and AnnotatedArray)
    "<A: #{fingerprint Annotated.purge(obj)} #{fingerprint obj.info}>"
  when (defined? TSV and TSV::Parser)
    "<TSVStream:" + (obj.filename || "NOFILENAME") + "--" << Misc.fingerprint(obj.options) << ">"
  when IO
    (obj.respond_to?(:filename) and obj.filename ) ? "<IO:" + (obj.filename || obj.inspect) + ">" : obj.inspect
  when File
    "<File:" + obj.path + ">"
  when Array
    if (length = obj.length) > 10
      "[#{length}--" <<  (obj.values_at(0,1, length / 2, -2, -1).collect{|e| fingerprint(e)} * ",") << "]"
    else
      "[" << (obj.collect{|e| fingerprint(e) } * ",") << "]"
    end
  when (defined? TSV and TSV)
    obj.with_unnamed do
      "TSV:{"<< fingerprint(obj.all_fields|| []).inspect << ";" << fingerprint(obj.keys).inspect << "}"
    end
  when Hash
    if obj.length > 10
      "H:{"<< fingerprint(obj.keys) << ";" << fingerprint(obj.values) << "}"
    else
      new = "{"
      obj.each do |k,v|
        new << k.to_s << '=>' << fingerprint(v) << ' '
      end
      if new.length > 1
         new[-1] =  "}"
      else
        new << '}'
      end
      new
    end
  else
    obj.to_s
  end
end

.fixascii(string) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/rbbt/util/misc/format.rb', line 151

def self.fixascii(string)
  if string.respond_to?(:encode)
    self.fixutf8(string).encode("ASCII-8BIT") 
  else
    string
  end
end

.fixutf8(string) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/rbbt/util/misc/format.rb', line 163

def self.fixutf8(string)
  return nil if string.nil?
  return string if (string.respond_to? :valid_encoding? and string.valid_encoding?) or
  (string.respond_to? :valid_encoding and string.valid_encoding)

  if string.respond_to?(:encode)
    string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8')
  else
    require 'iconv'
    @@ic ||= Iconv.new('UTF-8//IGNORE', 'UTF-8')
    @@ic.iconv(string)
  end
end

.format_definition_list(defs, size = 80, indent = 20, color = :yellow, sep = "\n\n") ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/rbbt/util/misc/format.rb', line 74

def self.format_definition_list(defs, size = 80, indent = 20, color = :yellow, sep = "\n\n")
  entries = []
  defs.each do |dt,dd|
    text = format_definition_list_item(dt,dd,size,indent,color)
    entries << text
  end
  entries * sep 
end

.format_definition_list_item(dt, dd, size = 80, indent = 20, color = :yellow) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rbbt/util/misc/format.rb', line 56

def self.format_definition_list_item(dt, dd, size = 80, indent = 20, color = :yellow)
  dd = "" if dd.nil?
  dt = Log.color color, dt if color
  dt = dt.to_s + ":" unless dd.empty?
  len = Log.uncolor(dt).length

  if indent < 0
    text = format_paragraph(dd, size, indent.abs-1, 0)
    text = dt << "\n" << text
  else
    offset = len - indent
    offset = 0 if offset < 0
    text = format_paragraph(dd, size, indent.abs+1, offset)
    text[0..len-1] = dt
  end
  text
end

.format_paragraph(text, size = 80, indent = 0, offset = 0) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rbbt/util/misc/format.rb', line 28

def self.format_paragraph(text, size = 80, indent = 0, offset = 0)
  i = 0
  re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
    text.split(re).collect do |paragraph|
    i += 1
    str = if i % 2 == 1
            words = paragraph.gsub(/\s+/, "\s").split(" ")
            lines = []
            line = " "*offset
            word = words.shift
            while word
              word = word[0..size-indent-offset-4] + '...' if word.length >= size - indent - offset
              while word and Log.uncolor(line).length + Log.uncolor(word).length <= size - indent
                line << word << " "
                word = words.shift
              end
              lines << ((" " * indent) << line[0..-2])
              line = ""
            end
            (lines * "\n")
          else
            paragraph
          end
    offset = 0
    str
    end*""
end

.format_seconds(time, extended = false) ⇒ Object



21
22
23
24
25
26
# File 'lib/rbbt/util/misc/format.rb', line 21

def self.format_seconds(time, extended = false)
  seconds = time.to_i
  str = [seconds/3600, seconds/60 % 60, seconds % 60].map{|t|  "%02i" % t }.join(':')
  str << ".%02i" % ((time - seconds) * 100) if extended
  str
end

.GET_params2hash(string) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/rbbt/util/misc/options.rb', line 54

def self.GET_params2hash(string)
  hash = {}
  string.split('&').collect{|item|
    key, value = item.split("=").values_at 0, 1
    hash[key] = value.nil? ? "" : CGI.unescape(value)
  }
  hash
end

.google_venn(list1, list2, list3, name1 = nil, name2 = nil, name3 = nil, total = nil) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rbbt/util/misc/math.rb', line 71

def self.google_venn(list1, list2, list3, name1 = nil, name2 = nil, name3 = nil, total = nil)
  name1 ||= "list 1"
  name2 ||= "list 2"
  name3 ||= "list 3"

  sizes = [list1, list2, list3, list1 & list2, list1 & list3, list2 & list3, list1 & list2 & list3].collect{|l| l.length}

  total = total.length if Array === total

  label = "#{name1}: #{sizes[0]} (#{name2}: #{sizes[3]}, #{name3}: #{sizes[4]})"
  label << "|#{name2}: #{sizes[1]} (#{name1}: #{sizes[3]}, #{name3}: #{sizes[5]})"
    label << "|#{name3}: #{sizes[2]} (#{name1}: #{sizes[4]}, #{name2}: #{sizes[5]})"
    if total
      label << "| INTERSECTION: #{sizes[6]} TOTAL: #{total}"
    else
      label << "| INTERSECTION: #{sizes[6]}"
    end

  max = total || sizes.max
  sizes = sizes.collect{|v| (v.to_f/max * 100).to_i.to_f / 100}
  url = "https://chart.googleapis.com/chart?cht=v&chs=500x300&chd=t:#{sizes * ","}&chco=FF6342,ADDE63,63C6DE,FFFFFF&chdl=#{label}"
end

.gzip(tarfile) ⇒ Object

gzips the underlying string in the given StringIO, returning a new StringIO representing the compressed file.



66
67
68
69
70
71
72
73
74
75
# File 'lib/rbbt/util/tar.rb', line 66

def self.gzip(tarfile)
  gz = StringIO.new("")
  z = Zlib::GzipWriter.new(gz)
  z.write tarfile.string
  z.close # this is necessary!

  # z was closed to write the gzip footer, so
  # now we need a new StringIO
  StringIO.new gz.string
end

.hash2GET_params(hash) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/rbbt/util/misc/options.rb', line 63

def self.hash2GET_params(hash)
  hash.sort_by{|k,v| k.to_s}.collect{|k,v| 
    next unless %w(Symbol String Float Fixnum Integer TrueClass FalseClass Module Class Object Array).include? v.class.to_s
    v = case 
        when Symbol === v
          v.to_s
        when Array === v
          v * ","
        else
          CGI.escape(v.to_s)
        end
    [ Symbol === k ? k.to_s : k,  v] * "="
  }.compact * "&"
end

.hash2md5(hash) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rbbt/util/misc/inspect.rb', line 118

def self.hash2md5(hash)
  return "" if hash.nil? or hash.empty?

  str = ""
  keys = hash.keys
  keys = keys.clean_annotations if keys.respond_to? :clean_annotations
  keys = keys.sort_by{|k| k.to_s}

  if hash.respond_to? :unnamed
    unnamed = hash.unnamed
    hash.unnamed = true 
  end
  keys.each do |k|
    next if k == :monitor or k == "monitor" or k == :in_situ_persistence or k == "in_situ_persistence"
    v = hash[k]
    case
    when TrueClass === v
      str << k.to_s << "=>true" 
    when FalseClass === v
      str << k.to_s << "=>false" 
    when Hash === v
      str << k.to_s << "=>" << hash2md5(v)
    when Symbol === v
      str << k.to_s << "=>" << v.to_s
    when (String === v and v.length > HASH2MD5_MAX_STRING_LENGTH)
      str << k.to_s << "=>" << v[0..HASH2MD5_MAX_STRING_LENGTH] << "; #{ v.length }"
    when String === v
      str << k.to_s << "=>" << v
    when (Array === v and v.length > HASH2MD5_MAX_ARRAY_LENGTH)
      str << k.to_s << "=>[" << v[0..HASH2MD5_MAX_ARRAY_LENGTH] * "," << "; #{ v.length }]"
    when TSV::Parser === v
      str << remove_long_items(v)
    when Array === v
      str << k.to_s << "=>[" << v * "," << "]"
    when File === v
      str << k.to_s << "=>[File:" << v.path << "]"
    else
      v_ins = v.inspect

      case
      when v_ins =~ /:0x0/
        str << k.to_s << "=>" << v_ins.sub(/:0x[a-f0-9]+@/,'')
      else
        str << k.to_s << "=>" << v_ins
      end

    end

    if defined? Annotated and Annotated === v and not (defined? AssociationItem and AssociationItem === v)
      info = Annotated.purge(v.info)
      str << "_" << hash2md5(info) 
    end
  end
  hash.unnamed = unnamed if hash.respond_to? :unnamed

  if str.empty?
    ""
  else
    digest(str)
  end
end

.hash2string(hash) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/rbbt/util/misc/options.rb', line 46

def self.hash2string(hash)
  hash.sort_by{|k,v| k.to_s}.collect{|k,v| 
    next unless %w(Symbol String Float Fixnum Integer TrueClass FalseClass Module Class Object).include? v.class.to_s
    [ Symbol === k ? ":" << k.to_s : k,
      Symbol === v ? ":" << v.to_s : v] * "="
  }.compact * "#"
end

.hash_to_html_tag_attributes(hash) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rbbt/util/misc/options.rb', line 78

def self.hash_to_html_tag_attributes(hash)
  return "" if hash.nil? or hash.empty?
  hash.collect{|k,v| 
    case 
    when (k.nil? or v.nil? or (String === v and v.empty?))
      nil
    when Array === v
      [k,"'" << v * " " << "'"] * "="
    when String === v
      [k,"'" << v << "'"] * "="
    when Symbol === v
      [k,"'" << v.to_s << "'"] * "="
    when TrueClass === v
      [k,"'" << v.to_s << "'"] * "="
    when (Fixnum === v or Float === v)
      [k,"'" << v.to_s << "'"] * "="
    else
      nil
    end
  }.compact * " "
end

.hostnameObject



5
6
7
# File 'lib/rbbt/util/misc/system.rb', line 5

def self.hostname
  @hostanem ||= `hostname`.strip
end

.html_tag(tag, content = nil, params = {}) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rbbt/util/misc/options.rb', line 100

def self.html_tag(tag, content = nil, params = {})
  attr_str = hash_to_html_tag_attributes(params)
  attr_str = " " << attr_str if String === attr_str and attr_str != ""
  html = if content.nil?
    "<#{ tag }#{attr_str}/>"
  else
    "<#{ tag }#{attr_str}>#{ content }</#{ tag }>"
  end

  html
end

.humanize(value, options = {}) ⇒ Object

source: gist.github.com/ekdevdes/2450285 author: Ethan Kramer (github.com/ekdevdes)



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rbbt/util/misc/format.rb', line 108

def self.humanize(value, options = {})
  if options.empty?
    options[:format] = :sentence
  end

  values = []
  values = value.split('_')
  values.each_index do |index|
    # lower case each item in array
    # Miguel Vazquez edit: Except for acronyms
    values[index].downcase! unless values[index].match(/[a-zA-Z][A-Z]/)
  end
  if options[:format] == :allcaps
    values.each do |value|
      value.capitalize!
    end

    if options.empty?
      options[:seperator] = " "
    end

    return values.join " "
  end

  if options[:format] == :class
    values.each do |value|
      value.capitalize!
    end

    return values.join ""
  end

  if options[:format] == :sentence
    values[0].capitalize! unless values[0].match(/[a-zA-Z][A-Z]/)

    return values.join " "
  end

  if options[:format] == :nocaps
    return values.join " "
  end
end

.in_dir(dir) ⇒ Object

WARN: probably not thread safeā€¦



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rbbt/util/misc/system.rb', line 77

def self.in_dir(dir)
  old_pwd = FileUtils.pwd
  res = nil
  begin
    FileUtils.mkdir_p dir unless File.exists? dir
    FileUtils.cd dir
    res = yield
  ensure
    FileUtils.cd old_pwd
  end
  res
end

.insist(times = 3, sleep = nil, msg = nil) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/rbbt/util/misc/development.rb', line 134

def self.insist(times = 3, sleep = nil, msg = nil)
  if Array === times
    sleep_array = times
    times = sleep_array.length
    sleep = sleep_array.shift
  end
  try = 0
  begin
    yield
  rescue TryAgain
    sleep sleep
    retry
  rescue Aborted, Interrupt
    if msg
      Log.warn("Not Insisting after Aborted: #{$!.message} -- #{msg}")
    else
      Log.warn("Not Insisting after Aborted: #{$!.message}")
    end
    raise $!
  rescue Exception
    if msg
      Log.warn("Insisting after exception: #{$!.class} #{$!.message} -- #{msg}")
    else
      Log.warn("Insisting after exception:  #{$!.class} #{$!.message}")
    end 

    if sleep and try > 0
      sleep sleep
      sleep = sleep_array.shift if sleep_array
    else
      Thread.pass
    end

    try += 1
    retry if try < times
    raise $!
  end
end

.intersect_sorted_arrays(a1, a2) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rbbt/util/misc/manipulation.rb', line 60

def self.intersect_sorted_arrays(a1, a2)
  e1, e2 = a1.shift, a2.shift
  intersect = []
  while true
    break if e1.nil? or e2.nil?
    case e1 <=> e2
    when 0
      intersect << e1
      e1, e2 = a1.shift, a2.shift
    when -1
      e1 = a1.shift while not e1.nil? and e1 < e2
    when 1
      e2 = a2.shift
      e2 = a2.shift while not e2.nil? and e2 < e1
    end
  end
  intersect
end

.is_filename?(string) ⇒ Boolean

Returns:

  • (Boolean)


94
95
96
97
98
# File 'lib/rbbt/util/misc/system.rb', line 94

def self.is_filename?(string)
  return true if string.respond_to? :exists
  return true if String === string and string.length < 265 and File.exists? string
  return false
end

.IUPAC_to_base(iupac) ⇒ Object



154
155
156
# File 'lib/rbbt/util/misc/omics.rb', line 154

def self.IUPAC_to_base(iupac)
  IUPAC2BASE[iupac]
end

.lock(file, unlock = true, options = {}) ⇒ Object

def self.lock(file, unlock = true, options = {})



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rbbt/util/misc/lock.rb', line 26

def self.lock(file, unlock = true, options = {})
  unlock, options = true, unlock if Hash === unlock
  return yield if file.nil?
  FileUtils.mkdir_p File.dirname(File.expand_path(file)) unless File.exists?  File.dirname(File.expand_path(file))

  res = nil

  case options[:lock]
  when Lockfile
    lockfile = options[:lock]
    lockfile.lock unless lockfile.locked?
  when FalseClass
    unlock = false
  else
    lock_path = File.expand_path(file + '.lock')
    lockfile = Lockfile.new(lock_path, options)
    lockfile.lock 
  end

  begin
    res = yield lockfile
  rescue KeepLocked
    unlock = false
    res = $!.payload
  ensure
    if unlock 
      begin
        lockfile.unlock #if lockfile.locked?
      rescue Exception
      end
    end
  end

  res
end

.lock_in_repo(repo, key, *args) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rbbt/util/misc/lock.rb', line 64

def self.lock_in_repo(repo, key, *args)
  return yield file, *args if repo.nil? or key.nil?

  lock_key = "lock-" << key

  begin
    if repo[lock_key] and
      Misc.hostname == (info = LOCK_REPO_SERIALIZER.load(repo[lock_key]))["host"] and 
      info["pid"] and not Misc.pid_exists?(info["pid"])

      Log.info("Removing lockfile: #{lock_key}. This pid #{Process.pid}. Content: #{info.inspect}")
      repo.out lock_key 
    end
  rescue
    Log.warn("Error checking lockfile #{lock_key}: #{$!.message}. Removing. Content: #{begin repo[lock_key] rescue "Could not open file" end}")
    repo.out lock_key if repo.include? lock_key
  end

  while repo[lock_key]
    sleep 1
  end
  
  repo[lock_key] = LOCK_REPO_SERIALIZER.dump({:hostname => Misc.hostname, :pid => Process.pid})

  res = yield lock_key, *args

  repo.delete lock_key

  res
end

.log2(x) ⇒ Object



5
6
7
# File 'lib/rbbt/util/misc/math.rb', line 5

def self.log2(x)
  Math.log(x) * Log2Multiplier
end

.max(list) ⇒ Object



9
10
11
12
13
14
15
16
# File 'lib/rbbt/util/misc/math.rb', line 9

def self.max(list)
  max = nil
  list.each do |v|
    next if v.nil?
    max = v if max.nil? or v > max
  end
  max
end

.mean(list) ⇒ Object



22
23
24
# File 'lib/rbbt/util/misc/math.rb', line 22

def self.mean(list)
  sum(list) / list.compact.length
end

.memory_use(pid = nil) ⇒ Object



307
308
309
# File 'lib/rbbt/util/misc/development.rb', line 307

def self.memory_use(pid=nil)
  `ps -o rss -p #{pid || $$}`.strip.split.last.to_i
end

.memprofObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rbbt/util/misc/development.rb', line 107

def self.memprof
  require 'memprof'
  Memprof.start
  begin
    res = yield
  rescue Exception
    puts "Profiling aborted"
    raise $!
  ensure
    Memprof.stop
    print Memprof.stats
  end

  res
end

.merge_sorted_arrays(a1, a2) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/rbbt/util/misc/manipulation.rb', line 79

def self.merge_sorted_arrays(a1, a2)
  e1, e2 = a1.shift, a2.shift
  new = []
  while true
    case
    when (e1 and e2)
      case e1 <=> e2
      when 0
        new << e1 
        e1, e2 = a1.shift, a2.shift
      when -1
        new << e1
        e1 = a1.shift
      when 1
        new << e2
        e2 = a2.shift
      end
    when e2
      new << e2
      new.concat a2
      break
    when e1
      new << e1
      new.concat a1
      break
    else
      break
    end
  end
  new
end

.name2basename(file) ⇒ Object



5
6
7
# File 'lib/rbbt/util/misc/inspect.rb', line 5

def self.name2basename(file)
  sanitize_filename(file.gsub("/",'>').gsub("~", '-'))
end

.object_delta(*args) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/rbbt/util/misc/development.rb', line 245

def self.object_delta(*args)
  res, delta = nil, nil
  Thread.exclusive do
    pre = Set.new
    delta = Set.new

    GC.start
    ObjectSpace.each_object(*args) do |o|
      pre.add o
    end

    res = yield

    GC.start
    ObjectSpace.each_object(*args) do |o|
      delta.add o unless pre.include? o
    end

  end
  Log.info "Delta: #{delta.inspect}" 
  res
end

.open_pipe(do_fork = false, close = true) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rbbt/util/misc/pipes.rb', line 49

def self.open_pipe(do_fork = false, close = true)
  raise "No block given" unless block_given?

  sout, sin = Misc.pipe

  if do_fork
    parent_pid = Process.pid
    pid = Process.fork {
      purge_pipes(sin)
      sout.close
      begin
        yield sin
        sin.close if close and not sin.closed? 
      rescue
        Log.exception $!
        Process.kill :INT, parent_pid
        Kernel.exit! -1
      end
      Kernel.exit! 0
    }
    sin.close 
    ConcurrentStream.setup sout, :pids => [pid]
  else
    thread = Thread.new(Thread.current) do |parent|
      begin
        yield sin
        sin.close if close and not sin.closed?
      rescue Aborted
        Log.medium "Aborted open_pipe: #{$!.message}"
      rescue Exception
        Log.medium "Exception in open_pipe: #{$!.message}"
        parent.raise $!
        raise $!
      end
    end
    ConcurrentStream.setup sout, :threads => [thread]
  end
  sout
end

.ordered_divide(array, num) ⇒ Object

Divides the array into chunks of num same size by placing one element in each chunk iteratively.



192
193
194
195
196
197
198
199
200
201
202
# File 'lib/rbbt/util/misc/development.rb', line 192

def self.ordered_divide(array, num)
  last = array.length - 1
  chunks = []
  current = 0
  while current <= last
    next_current = [last, current + num - 1].min
    chunks << array[current..next_current]
    current = next_current + 1
  end
  chunks
end

.parse_cmd_params(str) ⇒ Object



3
4
5
6
7
8
9
# File 'lib/rbbt/util/misc/options.rb', line 3

def self.parse_cmd_params(str)
  return str if Array === str
  str.scan(/
           (?:["']([^"']*?)["']) |
           ([^"'\s]+)
  /x).flatten.compact
end

.paste_streams(streams, lines = nil, sep = "\t", header = nil) ⇒ Object



417
418
419
420
421
422
423
# File 'lib/rbbt/util/misc/pipes.rb', line 417

def self.paste_streams(streams, lines = nil, sep = "\t", header = nil)
  sep ||= "\t"
  num_streams = streams.length
  Misc.open_pipe do |sin|
    self._paste_streams(streams, sin, lines, sep, header)
  end
end

.path_relative_to(basedir, path) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rbbt/util/misc/system.rb', line 48

def self.path_relative_to(basedir, path)
  path = File.expand_path(path) unless path[0] == "/"
  basedir = File.expand_path(basedir) unless basedir[0] == "/"

  if path.index(basedir) == 0
    if basedir[-1] == "/"
      return path[basedir.length..-1]
    else
      return path[basedir.length+1..-1]
    end
  else
    return nil
  end
end

.pid_exists?(pid) ⇒ Boolean

Returns:

  • (Boolean)


9
10
11
12
13
14
15
16
17
# File 'lib/rbbt/util/misc/system.rb', line 9

def self.pid_exists?(pid)
  return false if pid.nil?
  begin
    Process.getpgid(pid.to_i)
    true
  rescue Errno::ESRCH
    false
  end
end

.pipeObject



22
23
24
25
26
27
28
29
30
# File 'lib/rbbt/util/misc/pipes.rb', line 22

def self.pipe
  OPEN_PIPE_IN.delete_if{|pipe| pipe.closed? }
  PIPE_MUTEX.synchronize do
    sout, sin = IO.pipe
    OPEN_PIPE_IN << sin

    [sout, sin]
  end
end

.positional2hash(keys, *values) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/rbbt/util/misc/options.rb', line 11

def self.positional2hash(keys, *values)
  if Hash === values.last
    extra = values.pop
    inputs = Misc.zip2hash(keys, values)
    inputs.delete_if{|k,v| v.nil? or (String === v and v.empty?)}
    inputs = Misc.add_defaults inputs, extra
    inputs.delete_if{|k,v| not keys.include?(k) and not (Symbol === k ? keys.include?(k.to_s) : keys.include?(k.to_sym))}
    inputs
  else
    Misc.zip2hash(keys, values)
  end
end

.pre_forkObject



8
9
10
11
12
13
14
15
16
# File 'lib/rbbt/util/misc/development.rb', line 8

def self.pre_fork
  Persist::CONNECTIONS.values.each do |db| db.close if db.write? end
  ObjectSpace.each_object(Mutex) do |m| 
    begin 
      m.unlock 
    rescue ThreadError
    end if m.locked? 
  end
end

.prepare_entity(entity, field, options = {}) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/rbbt/util/misc/objects.rb', line 3

def self.prepare_entity(entity, field, options = {})
  return entity unless defined? Entity
  return entity unless String === entity or Array === entity
  options ||= {}

  dup_array = options.delete :dup_array

  if Entity === field or (Entity.respond_to?(:formats) and Entity.formats.include? field)
    params = options.dup

    params[:format] ||= params.delete "format"
    params.merge!(:format => field) unless params.include?(:format) and not ((f = params[:format]).nil? or (String === f and f.empty?))

    mod = Entity === field ? field : Entity.formats[field]
    entity = mod.setup(
      ((entity.frozen? and not entity.nil?) ? entity.dup : ((Array === entity and dup_array) ? entity.collect{|e| e.nil? ? e : e.dup} : entity) ),
      params
    ) 
  end

  entity
end

.process_options(hash, *keys) ⇒ Object



132
133
134
135
136
137
138
# File 'lib/rbbt/util/misc/options.rb', line 132

def self.process_options(hash, *keys)
  if keys.length == 1
    hash.include?(keys.first.to_sym) ? hash.delete(keys.first.to_sym) : hash.delete(keys.first.to_s) 
  else
    keys.collect do |key| hash.include?(key.to_sym) ? hash.delete(key.to_sym) : hash.delete(key.to_s) end
  end
end

.process_stream(s) ⇒ Object



276
277
278
279
280
281
282
283
284
# File 'lib/rbbt/util/misc/pipes.rb', line 276

def self.process_stream(s)
  begin
    yield s
    s.join if s.respond_to? :join
  rescue
    s.abort if s.respond_to? :abort
    raise $!
  end
end

.process_to_hash(list) ⇒ Object



41
42
43
44
# File 'lib/rbbt/util/misc/options.rb', line 41

def self.process_to_hash(list)
  result = yield list
  zip2hash(list, result)
end

.profile(options = {}) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/rbbt/util/misc/development.rb', line 90

def self.profile(options = {})
  require 'ruby-prof'
  RubyProf.start
  begin
    res = yield
  rescue Exception
    puts "Profiling aborted"
    raise $!
  ensure
    result = RubyProf.stop
    printer = RubyProf::FlatPrinter.new(result)
    printer.print(STDOUT, options)
  end

  res
end

.profile_graph(options = {}) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rbbt/util/misc/development.rb', line 72

def self.profile_graph(options = {})
  require 'ruby-prof'
  RubyProf.start
  begin
    res = yield
  rescue Exception
    puts "Profiling aborted"
    raise $!
  ensure
    result = RubyProf.stop
    #result.eliminate_methods!([/annotated_array_clean_/])
    printer = RubyProf::GraphPrinter.new(result)
    printer.print(STDOUT, options)
  end

  res
end

.profile_html(options = {}) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rbbt/util/misc/development.rb', line 51

def self.profile_html(options = {})
  require 'ruby-prof'
  RubyProf.start
  begin
    res = yield
  rescue Exception
    puts "Profiling aborted"
    raise $!
  ensure
    result = RubyProf.stop
    printer = RubyProf::MultiPrinter.new(result)
    TmpFile.with_file do |dir|
      FileUtils.mkdir_p dir unless File.exists? dir
      printer.print(:path => dir, :profile => 'profile')
      CMD.cmd("firefox  -no-remote  '#{ dir }'")
    end
  end

  res
end

.proportions(array) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rbbt/util/misc/math.rb', line 53

def self.proportions(array)
  total = array.length

  proportions = Hash.new 0

  array.each do |e|
    proportions[e] += 1.0 / total
  end

  class << proportions; self;end.class_eval do
    def to_s
      sort{|a,b| a[1] == b[1] ? a[0] <=> b[0] : a[1] <=> b[1]}.collect{|k,c| "%3d\t%s" % [c, k]} * "\n"
    end
  end

  proportions
end

.pull_keys(hash, prefix) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rbbt/util/misc/options.rb', line 140

def self.pull_keys(hash, prefix)
  new = {}
  hash.keys.each do |key|
    if key.to_s =~ /#{ prefix }_(.*)/
      case
      when String === key
        new[$1] = hash.delete key
      when Symbol === key
        new[$1.to_sym] = hash.delete key
      end
    else
      if key.to_s == prefix.to_s
        new[key] = hash.delete key
      end
    end
  end

  new
end

.purge_pipes(*save) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/rbbt/util/misc/pipes.rb', line 40

def self.purge_pipes(*save)
  PIPE_MUTEX.synchronize do
    OPEN_PIPE_IN.each do |pipe|
      next if save.include? pipe
      pipe.close unless pipe.closed?
    end
  end
end

.random_sample_in_range(total, size) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rbbt/util/misc/development.rb', line 204

def self.random_sample_in_range(total, size)
  p = Set.new

  if size > total / 10
    template = (0..total - 1).to_a
    size.times do |i|
      pos = (rand * (total - i)).floor
      if pos == template.length - 1
        v = template.pop
      else
        v, n = template[pos], template[-1]
        template.pop
        template[pos] = n 
      end
      p << v
    end
  else
    size.times do 
      pos = nil
      while pos.nil? 
        pos = (rand * total).floor
        if p.include? pos
          pos = nil
        end
      end
      p << pos
    end
  end
  p
end

.read_full_stream(io) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/rbbt/util/misc/pipes.rb', line 149

def self.read_full_stream(io)
  str = ""
  begin
    while block = io.read(2048)
      str << block
    end
    io.join if io.respond_to? :join
  rescue
    io.abort if io.respond_to? :abort
  end
  str
end

.read_stream(stream, size) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/rbbt/util/misc/pipes.rb', line 196

def self.read_stream(stream, size)
  str = nil
  Thread.pass while IO.select([stream],nil,nil,1).nil?
  while not str = stream.read(size)
    IO.select([stream],nil,nil,1) 
    Thread.pass
    raise ClosedStream if stream.eof?
  end

  while str.length < size
    raise ClosedStream if stream.eof?
    IO.select([stream],nil,nil,1)
    if new = stream.read(size-str.length)
      str << new
    end
  end
  str
end

.release_pipes(*pipes) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/rbbt/util/misc/pipes.rb', line 32

def self.release_pipes(*pipes)
  PIPE_MUTEX.synchronize do
    pipes.flatten.each do |pipe|
      pipe.close unless pipe.closed?
    end
  end
end

.remove_long_items(obj) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rbbt/util/misc/inspect.rb', line 83

def self.remove_long_items(obj)
  case
  when IO === obj
    remove_long_items("IO: " + (obj.respond_to?(:filename) ? (obj.filename || obj.inspect) : obj.inspect ))
  when obj.respond_to?(:path)
    remove_long_items("File: " + obj.path)
  when TSV::Parser === obj
    remove_long_items("TSV Stream: " + obj.filename + " -- " << Misc.fingerprint(obj.options))
  when TSV === obj
    remove_long_items((obj.all_fields || []) + obj.keys.sort)
  when (Array === obj and obj.length > ARRAY_MAX_LENGTH)
    remove_long_items(obj[0..ARRAY_MAX_LENGTH-2] << "TRUNCATED at #{ ARRAY_MAX_LENGTH } (#{obj.length})")
  when (Hash === obj and obj.length > ARRAY_MAX_LENGTH)
    remove_long_items(obj.collect.compact[0..ARRAY_MAX_LENGTH-2] << ["TRUNCATED", "at #{ ARRAY_MAX_LENGTH } (#{obj.length})"])
  when (String === obj and obj.length > STRING_MAX_LENGTH)
    obj[0..STRING_MAX_LENGTH-1] << " TRUNCATED at #{STRING_MAX_LENGTH} (#{obj.length})"
  when Hash === obj
    new = {}
    obj.each do |k,v|
      new[k] = remove_long_items(v)
    end
    new
  when Array === obj
    obj.collect do |e| remove_long_items(e) end
  else
    obj
  end
end

.reset_do_onceObject



130
131
132
# File 'lib/rbbt/util/misc/development.rb', line 130

def self.reset_do_once
  $__did_once = false
end

.sample(ary, size, replacement = false) ⇒ Object



235
236
237
238
239
240
241
242
243
# File 'lib/rbbt/util/misc/development.rb', line 235

def self.sample(ary, size, replacement = false)
  if ary.respond_to? :sample
    ary.sample size
  else
    total = ary.length
    p = random_sample_in_range(total, size)
    ary.values_at *p
  end
end

.sanitize_filename(filename, length = 254) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/rbbt/util/misc/inspect.rb', line 9

def self.sanitize_filename(filename, length = 254)
  if filename.length > length
    if filename =~ /(\..{2,9})$/
      extension = $1
    else
      extension = ''
    end

    post_fix = "--#{filename.length}@#{length}_#{Misc.digest(filename)[0..4]}" + extension

    filename = filename[0..(length - post_fix.length - 1)] << post_fix
  else
    filename
  end
  filename
end

.save_stream(file, stream) ⇒ Object



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'lib/rbbt/util/misc/pipes.rb', line 436

def self.save_stream(file, stream)
  out, save = Misc.tee_stream stream

  Thread.new(Thread.current) do |parent|
    begin
      Misc.sensiblewrite(file, save)
    rescue Exception
      save.abort if save.respond_to? :abort
      stream.abort if stream.respond_to? :abort
      stream.join
      Log.medium "Exception in save_stream: #{$!.message}"
      raise $!
    end
  end

  out
end

.sd(list) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/rbbt/util/misc/math.rb', line 26

def self.sd(list)
  return nil if list.length < 3
  mean = mean(list)
  list = list.compact
  list_length = list.length

  total_square_distance = 0
  list.each do |value|
    distance = value - mean
    total_square_distance += distance * distance
  end

  variance = total_square_distance / (list_length - 1)
  Math.sqrt(variance)
  #Math.sqrt(list.compact.inject(0.0){|acc,e| d = e - mean; acc += d * d; acc}) / (list.compact.length - 1)
end

.send_email(from, to, subject, message, options = {}) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rbbt/util/misc/system.rb', line 19

def self.send_email(from, to, subject, message, options = {})
  IndiferentHash.setup(options)
  options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login

  server, port, user, pass, from_alias, to_alias, auth = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth

  msg = <<-END_OF_MESSAGE
From: #{from_alias} <#{from}>
To: #{to_alias} <#{to}>
Subject: #{subject}

#{message}
END_OF_MESSAGE

Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
smtp.send_message msg, from, to
end
end

.sensible_write_locksObject



7
8
9
# File 'lib/rbbt/util/misc/pipes.rb', line 7

def sensible_write_locks
  @sensiblewrite_locks ||= Rbbt.tmp.sensiblewrite_locks.find
end

.sensiblewrite(path, content = nil, options = {}, &block) ⇒ Object



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rbbt/util/misc/pipes.rb', line 215

def self.sensiblewrite(path, content = nil, options = {}, &block)
  force = Misc.process_options options, :force

  if Open.exists? path and not force
    Misc.consume_stream content 
    return
  end

  lock_options = Misc.pull_keys options.dup, :lock
  lock_options = lock_options[:lock] if Hash === lock_options[:lock]
  tmp_path = Persist.persistence_path(path, {:dir => Misc.sensiblewrite_dir})
  tmp_path_lock = Persist.persistence_path(path, {:dir => Misc.sensiblewrite_lock_dir})
  Misc.lock tmp_path_lock, lock_options do

    if Open.exists? path and not force
      Misc.consume_stream content 
      return
    end

    FileUtils.mkdir_p File.dirname(tmp_path) unless File.directory? File.dirname(tmp_path)
    FileUtils.rm_f tmp_path if File.exists? tmp_path
    begin
      case
      when block_given?
        File.open(tmp_path, 'wb', &block)
      when String === content
        File.open(tmp_path, 'wb') do |f| f.write content end
      when (IO === content or StringIO === content or File === content)

        Open.write(tmp_path) do |f|
          f.sync = true
          while block = content.read(2048)
            f.write block
          end
        end
      else
        File.open(tmp_path, 'wb') do |f|  end
      end

      begin
        Open.mv tmp_path, path, lock_options
      rescue
        raise $! unless File.exists? path
      end
      content.join if content.respond_to? :join
      FileUtils.touch path if File.exists? path
    rescue Aborted
      Log.medium "Aborted sensiblewrite -- #{ Log.reset << Log.color(:blue, path) }"
      content.abort if content.respond_to? :abort
      Open.rm path if File.exists? path
    rescue Exception
      Log.medium "Exception in sensiblewrite: #{$!.message} -- #{ Log.color :blue, path }"
      content.abort if content.respond_to? :abort
      Open.rm path if File.exists? path
      raise $!
    ensure
      FileUtils.rm_f tmp_path if File.exists? tmp_path
    end
  end
end

.snake_case(string) ⇒ Object



96
97
98
99
100
101
102
103
104
# File 'lib/rbbt/util/misc/format.rb', line 96

def self.snake_case(string)
  return nil if string.nil?
  string = string.to_s if Symbol === string
  string.
    gsub(/([A-Z]{2,})([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z])([A-Z])/,'\1_\2').
    gsub(/\s/,'_').gsub(/[^\w_]/, '').
    split("_").collect{|p| p.match(/[A-Z]{2,}/) ? p : p.downcase } * "_"
end

.sort_mutations(mutations) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rbbt/util/misc/omics.rb', line 159

def self.sort_mutations(mutations)
  mutations.collect do |mutation|
    chr,pos,mut = mutation.split ":"
    chr.sub!(/^chr/i,'')
    chr = 22 if chr == "Y"
    chr = 23 if chr == "X"
    chr = 24 if chr == "MT" or chr == "M"
    [chr.to_i, pos.to_i, mut, mutation]
  end.sort do |a,b|
    case a[0] <=> b[0]
    when -1
      -1
    when 1
      1
    when 0
      case a[1] <=> b[1]
      when -1
        -1
      when 1
        1
      when 0
        a[2] <=> b[2]
      end
    end
  end.collect{|p| p.last }
end

.sort_stream(stream, header_hash = "#", cmd_args = " -u ") ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/rbbt/util/misc/pipes.rb', line 286

def self.sort_stream(stream, header_hash = "#", cmd_args = " -u ")
  Misc.open_pipe do |sin|
    begin
      if defined? Step and Step === stream
        step = stream
        stream = stream.get_stream || stream.path.open
      end

      line = stream.gets
      while line =~ /^#{header_hash}/ do
        sin.puts line
        line = stream.gets
      end

      line_stream = Misc.open_pipe do |line_stream_in|
        begin
          while line
            line_stream_in.puts line
            line = stream.gets
          end
          stream.join if stream.respond_to? :join
        rescue
          stream.abort if stream.respond_to? :abort
          raise $!
        end
      end

      sorted = CMD.cmd("sort #{cmd_args || ""}", :in => line_stream, :pipe => true)

      while block = sorted.read(2048)
        sin.write block
      end
    rescue
      if defined? step and step
        step.abort
      end
    end
  end
end

.sorted_array_hits(a1, a2) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rbbt/util/misc/manipulation.rb', line 36

def self.sorted_array_hits(a1, a2)
  e1, e2 = a1.shift, a2.shift
  counter = 0
  match = []
  while true
    break if e1.nil? or e2.nil?
    case e1 <=> e2
    when 0
      match << counter
      e1, e2 = a1.shift, a2.shift
      counter += 1
    when -1
      while not e1.nil? and e1 < e2
        e1 = a1.shift 
        counter += 1
      end
    when 1
      e2 = a2.shift
      e2 = a2.shift while not e2.nil? and e2 < e1
    end
  end
  match
end

.string2const(string) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/rbbt/util/misc/development.rb', line 18

def self.string2const(string)
  return nil if string.nil?
  mod = Kernel

  string.to_s.split('::').each do |str|
    mod = mod.const_get str
  end

  mod
end

.string2hash(string) ⇒ Object

options end



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/rbbt/util/misc/options.rb', line 206

def self.string2hash(string)
  options = {}

  string.split('#').each do |str|
    key, sep, value = str.partition "="

    key = key[1..-1].to_sym if key[0] == ":"

    options[key] = true and next if value.empty?
    options[key] = value[1..-1].to_sym and next if value[0] == ":"
    options[key] = Regexp.new(/#{value[1..-2]}/) and next if value[0] == "/" and value[-1] == "/"
    options[key] = value[1..-2] and next if value =~ /^['"].*['"]$/
    options[key] = value.to_i and next if value =~ /^\d+$/
    options[key] = value.to_f and next if value =~ /^\d*\.\d+$/
    options[key] = true and next if value == "true"
    options[key] = false and next if value == "false"
    options[key] = value and next 

    options[key] = begin
                     saved_safe = $SAFE
                     $SAFE = 0
                     eval(value)
                   rescue Exception
                     value
                   ensure
                     $SAFE = saved_safe
                   end
  end

  return options

  options = {}
  string.split(/#/).each do |str|
    if str.match(/(.*)=(.*)/)
      option, value = $1, $2
    else
      option, value = str, true
    end

    option = option.sub(":",'').to_sym if option.chars.first == ':'
    value  = value.sub(":",'').to_sym if String === value and value.chars.first == ':'

    if value == true
      options[option] = option.to_s.chars.first != '!' 
    else
      options[option] = Thread.start do
        $SAFE = 0;
        case 
        when value =~ /^(?:true|T)$/i
          true
        when value =~ /^(?:false|F)$/i
          false
        when Symbol === value
          value
        when (String === value and value =~ /^\/(.*)\/$/)
          Regexp.new /#{$1}/
        else
          begin
            Kernel.const_get value
          rescue
            begin  
              raise if value =~ /[a-z]/ and defined? value
              eval(value) 
            rescue Exception
              value 
            end
          end
        end
      end.value
    end
  end

  options
end

.sum(list) ⇒ Object



18
19
20
# File 'lib/rbbt/util/misc/math.rb', line 18

def self.sum(list)
  list.compact.inject(0.0){|acc,e| acc += e}
end

.tar(path, tarfile = nil) ⇒ Object

Creates a tar file in memory recursively from the given path.

Returns a StringIO whose underlying String is the contents of the tar file.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rbbt/util/tar.rb', line 14

def self.tar(path, tarfile = nil)
  tarfile ||= StringIO.new("")

  Gem::Package::TarWriter.new(tarfile) do |tar|
    Dir[File.join(path, "**/*")].each do |file|
      mode = File.stat(file).mode
      relative_file = file.sub /^#{Regexp::escape path}\/?/, ''

      if File.directory?(file)
        tar.mkdir relative_file, mode
      else
        tar.add_file relative_file, mode do |tf|
          File.open(file, "rb") { |f| tf.write f.read }
        end
      end
    end
  end

  tarfile.rewind

  tarfile
end

.tarize(path) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rbbt/util/tar.rb', line 37

def self.tarize(path, gz = nil)
  gz ||= StringIO.new('wb')

  tar =  Misc.in_dir(path) do self.tar('.') end

  tar.rewind

  string = tar.string

  z = Zlib::GzipWriter.new(gz)
  z.write string
  z.close

  gz.reopen('read')
  gz.rewind


  gz
end

.tee_stream_thread(stream) ⇒ Object Also known as: tee_stream



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rbbt/util/misc/pipes.rb', line 89

def self.tee_stream_thread(stream)
  stream_out1, stream_in1 = Misc.pipe
  stream_out2, stream_in2 = Misc.pipe

  if ConcurrentStream === stream 
    stream.annotate stream_out1
  end

  splitter_thread = Thread.new(Thread.current) do |parent|
    begin
      skip1 = skip2 = false
      while block = stream.read(2048)
        begin 
          stream_in1.write block; 
        rescue IOError
          Log.medium("Tee stream 1 #{Misc.fingerprint stream} IOError: #{$!.message}");
          skip1 = true
        end unless skip1 

        begin 
          stream_in2.write block
        rescue IOError
          Log.medium("Tee stream 2 #{Misc.fingerprint stream} IOError: #{$!.message}");
          skip2 = true
        end unless skip2 
      end
      stream_in1.close unless stream_in1.closed?
      stream.join if stream.respond_to? :join
      stream_in2.close unless stream_in2.closed?
    rescue Aborted, Interrupt
      stream_out1.abort if stream_out1.respond_to? :abort
      stream.abort if stream.respond_to? :abort
      stream_out2.abort if stream_out2.respond_to? :abort
      Log.medium "Tee aborting #{Misc.fingerprint stream}"
      raise $!
    rescue Exception
      stream_out1.abort if stream_out1.respond_to? :abort
      stream.abort if stream.respond_to? :abort
      stream_out2.abort if stream_out2.respond_to? :abort
      Log.medium "Tee exception #{Misc.fingerprint stream}"
      raise $!
    end
  end

  ConcurrentStream.setup stream_out1, :threads => splitter_thread
  ConcurrentStream.setup stream_out2, :threads => splitter_thread

  stream_out1.callback = stream.callback if stream.respond_to? :callback
  stream_out1.abort_callback = stream.abort_callback if stream.respond_to? :abort_callback

  stream_out2.callback = stream.callback if stream.respond_to? :callback
  stream_out2.abort_callback = stream.abort_callback if stream.respond_to? :abort_callback

  [stream_out1, stream_out2]
end

.time_tickObject



268
269
270
271
272
273
274
275
276
277
# File 'lib/rbbt/util/misc/development.rb', line 268

def self.time_tick
  if $_last_time_tick.nil?
    $_last_time_tick = Time.now
    puts "Tick started: #{Time.now}"
  else
    ellapsed = Time.now - $_last_time_tick
    puts "Tick ellapsed: #{ellapsed.to_i} s. #{(ellapsed * 1000).to_i - ellapsed.to_i * 1000} ms"
    $_last_time_tick = Time.now
  end
end

.to_utf8(string) ⇒ Object



159
160
161
# File 'lib/rbbt/util/misc/format.rb', line 159

def self.to_utf8(string)
  string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8')
end

.total_length(ranges) ⇒ Object



32
33
34
# File 'lib/rbbt/util/misc/manipulation.rb', line 32

def self.total_length(ranges)
  self.collapse_ranges(ranges).inject(0) do |total,range| total += range.end - range.begin + 1 end
end

.try3times(&block) ⇒ Object



173
174
175
# File 'lib/rbbt/util/misc/development.rb', line 173

def self.try3times(&block)
  insist(3, &block)
end

.use_lock_id=(use = true) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rbbt/util/misc/lock.rb', line 2

def self.use_lock_id=(use = true)
  if use
    Log.medium "Activating lockfile ids"
    Lockfile.dont_use_lock_id = false
    Lockfile.refresh = 20 
    Lockfile.max_age = 60 * 10
    Lockfile.suspend = 10
  else
    Log.medium "De-activating lockfile ids"
    Lockfile.dont_use_lock_id = true
    Lockfile.refresh = 5
    Lockfile.max_age = 30
    Lockfile.suspend = 5
  end

  Lockfile.refresh = 3
  Lockfile.max_age = 10
  Lockfile.suspend = 2
end

.zip2hash(list1, list2) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/rbbt/util/misc/options.rb', line 33

def self.zip2hash(list1, list2)
  hash = {}
  list1.each_with_index do |e,i|
    hash[e] = list2[i]
  end
  hash
end

.zip_fields(array) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/rbbt/util/misc/objects.rb', line 53

def self.zip_fields(array)
  return [] if array.empty? or (first = array.first).nil?
  max = array.collect{|l| l.length}.max
  rest = array[1..-1].collect{|v|
    v.length == 1 & max > 1 ? v * max : v
  }
  first = first * max if first.length == 1 and max > 1
  first.zip(*rest)
end

Instance Method Details

#ungzip(tarfile) ⇒ Object

un-gzips the given IO, returning the decompressed version as a StringIO



79
80
81
82
83
84
# File 'lib/rbbt/util/tar.rb', line 79

def ungzip(tarfile)
  z = Zlib::GzipReader.new(tarfile)
  unzipped = StringIO.new(z.read)
  z.close
  unzipped
end

#untar(io, destination) ⇒ Object

untars the given IO into the specified directory



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rbbt/util/tar.rb', line 88

def untar(io, destination)
  Gem::Package::TarReader.new io do |tar|
    tar.each do |tarfile|
      destination_file = File.join destination, tarfile.full_name

      if tarfile.directory?
        FileUtils.mkdir_p destination_file
      else
        destination_directory = File.dirname(destination_file)
        FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
        File.open destination_file, "wb" do |f|
          f.print tarfile.read
        end
      end
    end
  end
end