Class: Sequin::Listing

Inherits:
Object
  • Object
show all
Defined in:
lib/listing.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(files) ⇒ Listing

Returns a new instance of Listing.



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
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/listing.rb', line 57

def initialize(files)
  @sequences = Hash.new  

  # make a hash containing a signature key for all possible sequences
  all_seqs = all_possible_sequences files

  # now select from that hash the best sequences according
  # to the strategy outlined above
  select_best_sequences(all_seqs, files)

  # we need to make a note of the padding because
  # we will be converting the number part to integers
  each_sequence { |k,v| v[:padding] = v[:numbers].min.length } 

  # convert the number part to integers and sort them
  # so we can figure out the range, by_frame, and missing frames
  each_sequence { |k,v| v[:numbers].collect! {|el| el.to_i} } 
  each_sequence { |k,v| v[:numbers].sort! } 

  # find the by_frame so that we can figure out which
  # frames are missing, if any. If we don't get 
  # the by_frame for a sequence that is by 2 for example, we would
  # think that every other frame was missing.
  each_sequence {|k,v| v[:by] = calc_by_frame v[:numbers]}

  # now we know the by frame, we can find out which frames 
  # are missing because the user will want to know this. 
  each_sequence do |k,v| 
    range =  v[:numbers].min..v[:numbers].max
    v[:missing] = []
    range.step(v[:by]) do |val| 
      v[:missing]  << val unless  v[:numbers].include? val
    end    
  end

  # we no longer need the filenames. We have enough info to
  # recreate them if necessary
  each_sequence {|k,v| v.delete(:names) }

  # here we change the hash sequence keys (which are arrays). We make the number slot
  # represent the padding. This is so we can create a sequence key 
  # by simply calling join on the array elements
  each_sequence { |k,v|  k[v[:numbers_index]] = ("#" *v[:padding]) } 
end

Class Method Details

.match_matrix(regex, key, seq) ⇒ Object

match a sequence against a regex. create an array where each element is a sub array of the form

“filename”, <:matched|:failed>, frame_number

The sequence is more managable as a single array as it can be sorted.



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/listing.rb', line 148

def self.match_matrix(regex, key , seq)
  prefix, suffix = key.join().split(/#+/)
  matrix = [] 
  seq[:numbers].each do |n|
    fn =  [prefix , ("%0#{seq[:padding]}d" % n)  , suffix].join()
    unless regex.match(File.basename(fn)).nil?
      matrix << [fn,:matched,n]
    else
      matrix << [fn,:failed,n]
    end
  end
  matrix.sort! { |a,b|  a[2] <=> b[2] }
end

Instance Method Details

#assessment_message(fn_matrix, k, v) ⇒ Object

make a one line message describing the result of this matching a regex against all files in a sequence. Most of the info we need is in the fn_matrix array, but we also need the sequence key/value pair to create the signature.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/listing.rb', line 170

def assessment_message(fn_matrix,k,v)
  matched = fn_matrix.count { |el| el[1] == :matched }
  failed = fn_matrix.count - matched

  msg = "#{matched} MATCHED"
  msg = "#{msg}, #{failed} FAILED" if failed > 0
  msg = "(#{msg})"
  msg = "#{msg} / #{fn_matrix.count} files" if failed > 0 &&  matched > 0

  if failed == 0
    msg = msg.green
  elsif matched == 0    
    msg = msg.red
  else
    msg = msg.yellow
  end

  fn = sequence_signature(k,v,0)
  message = "#{fn} #{msg}"
end

#each_sequenceObject

takes a block and iterates through sequence keys, ignoring single files



221
222
223
224
225
# File 'lib/listing.rb', line 221

def each_sequence
  @sequences.each do |k,v|
    yield(k,v)  unless k == :single   
  end
end

#each_singleObject

takes a block and iterates through single files, ignoring . and .. and sequences



229
230
231
232
233
234
235
# File 'lib/listing.rb', line 229

def each_single
  @sequences.each do |k,v|
    if k == :single   
      v.each  { |f|  yield(f) unless( f =="." || f == "..") }
    end
  end
end

#inspectObject

for debugging



104
105
106
# File 'lib/listing.rb', line 104

def inspect
  pp @sequences
end

#list(verbose = 1) ⇒ Object

simple listing of single files and sequences



131
132
133
134
135
136
137
138
# File 'lib/listing.rb', line 131

def list(verbose=1)
  each_single {|f| puts f}
  
  each_sequence do |k,v|
    str = sequence_signature(k,v,verbose)
    puts str
  end
end

#match(the_regex, options = {}) ⇒ Object

this proc is called from the main script. Matches a regex against all single files and all sequences in the @sequences object and outputs information according to verbosity options



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/listing.rb', line 196

def match(the_regex, options ={})
  re = Regexp.new(the_regex)
  puts "Testing against regular expression: /#{the_regex}/".cyan

  each_single do |f| 
    msg = re.match(File.basename(f)).nil? ? 'FAILED'.red : 'PASSED'.green
    puts "#{f} #{msg}"
  end

  each_sequence do |k,v| 
    fn_matrix = Sequin::Listing.match_matrix(re, k,v)
    puts "#{assessment_message(fn_matrix,k,v)}"
    unless  options["show_all"].nil? &&  options["show_matched"].nil? &&  options["show_failed"].nil?
      fn_matrix.each do  |el|
        key =  "show_#{el[1].to_s}" 
        puts el[0].send(Sequin::Listing.alert_colors[el[1]]) unless options[key].nil? && options["show_all"].nil?
      end
    end
  end

end

#sequence_signature(k, v, verbose = 1) ⇒ Object

a sequence string describes the sequence like so. filename [ <start> to <end> by <by_frame> ] - missing [ <missing frames> ] This is what gets printed out in a listing, and can also be used as input to other seq commands such as seq pad, seq renumber, seq substitute The missing frames section is optional. When a sequence_signature is used as input the missing frames will be determined by seq internally.



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/listing.rb', line 116

def sequence_signature(k,v,verbose=1)
  range_str= "[#{v[:numbers].min} to #{v[:numbers].max} by #{v[:by]}]"
  unless v[:missing].empty? 
    range_str = "#{range_str} - missing: [ #{v[:missing].count} frames ]" if  verbose == 1
    range_str = "#{range_str} - missing: [ #{v[:missing].join(",")} ]"if  verbose == 2
    range_str = range_str.red
  else
    range_str = range_str.green
  end
  str = "#{k.join()} #{range_str}"
end