Class: Sequencer::Sequence
- Inherits:
-
Object
- Object
- Sequencer::Sequence
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/sequencer.rb
Instance Attribute Summary collapse
-
#directory ⇒ Object
readonly
Returns the value of attribute directory.
-
#pattern ⇒ Object
readonly
Returns the value of attribute pattern.
Instance Method Summary collapse
- #<=>(another) ⇒ Object
-
#bulk_rename(with_pattern, into_directory = nil, &operation) ⇒ Object
Apply a bulk rename.
-
#each ⇒ Object
Yields the filename of each file to the block.
-
#each_path ⇒ Object
Yield each absolute path to a file in the sequence to the block.
- #expected_frames ⇒ Object
-
#file_count ⇒ Object
(also: #length)
Returns the actual file count in the sequence.
-
#first_frame_no ⇒ Object
Returns the number of the first frame in the sequence.
- #gap_count ⇒ Object
-
#gaps? ⇒ Boolean
Returns true if this sequence has gaps.
-
#include?(base_filename) ⇒ Boolean
Check if this sequencer includes a file.
-
#initialize(directory, filenames) ⇒ Sequence
constructor
A new instance of Sequence.
- #inspect ⇒ Object
-
#last_frame_no ⇒ Object
Returns the number of the last frame in the sequence.
-
#missing_frames ⇒ Object
Returns the number of frames that the sequence should contain to be continuous.
-
#numbered? ⇒ Boolean
Returns true if the files in the sequence can have numbers.
- #segment_count ⇒ Object
-
#single_file? ⇒ Boolean
Tells whether this is a single frame sequence.
-
#to_a ⇒ Object
Returns the array of filenames.
-
#to_paths ⇒ Object
Returns paths to the files.
- #to_s ⇒ Object
-
#to_sequences ⇒ Object
If this Sequence has gaps, this method will return an array of all subsequences that it contains s # => #<broken_seq.[123..568, 578..702].tif> s.to_sequences # => [#<broken_seq..tif>, #<broken_seq..tif>].
Constructor Details
#initialize(directory, filenames) ⇒ Sequence
Returns a new instance of Sequence.
118 119 120 121 122 123 124 125 |
# File 'lib/sequencer.rb', line 118 def initialize(directory, filenames) raise "Cannot create a Sequence with no files" if filenames.empty? @directory, @filenames = directory, natural_sort(filenames) @directory.freeze @filenames.freeze detect_gaps! detect_pattern! end |
Instance Attribute Details
#directory ⇒ Object (readonly)
Returns the value of attribute directory.
116 117 118 |
# File 'lib/sequencer.rb', line 116 def directory @directory end |
#pattern ⇒ Object (readonly)
Returns the value of attribute pattern.
115 116 117 |
# File 'lib/sequencer.rb', line 115 def pattern @pattern end |
Instance Method Details
#<=>(another) ⇒ Object
283 284 285 |
# File 'lib/sequencer.rb', line 283 def <=>(another) to_paths <=> another.to_paths end |
#bulk_rename(with_pattern, into_directory = nil, &operation) ⇒ Object
Apply a bulk rename
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 280 281 |
# File 'lib/sequencer.rb', line 235 def bulk_rename(with_pattern, into_directory = nil, &operation) # Check if the pattern includes a number. If it doesnt, add one and the # extension unless with_pattern.include?("%") padz = last_frame_no.to_s.length with_pattern = [with_pattern, ".%0#{padz}d", File.extname(pattern)].join end rename_map = @filenames.inject({}) do | map, filename | frame_no = filename.scan(NUMBERS_AT_END).flatten.shift.to_i map.merge(filename => (with_pattern % frame_no)) end destination = into_directory || directory # Ensure it's there if (!File.exist?(destination)) raise "The destination #{destination} does not exist" end # Ensure it's a dir if (!File.directory?(destination)) raise "The destination #{destination} is not a directory" end # Ensure we will not produce dupes if (rename_map.values.uniq.length != rename_map.length) raise "This would would produce non-unique files" end if (error = (rename_map.keys & rename_map.values)).any? raise "This would overwrite old files with the renamed ones (#{error[0..1]}.join(',')..)" end if (error = (Dir.entries(destination) & rename_map.values)).any? raise "Files that will be created by the rename are already in place (#{error[0..1]}.join(',')..)" end rename_map.each_pair do | from_path, to_path | src, dest = File.join(directory, from_path), File.join(destination, to_path) File.rename(src, dest) #yield(src, dest) end self.class.new(destination, rename_map.values) end |
#each ⇒ Object
Yields the filename of each file to the block
205 206 207 |
# File 'lib/sequencer.rb', line 205 def each @filenames.each {|f| yield(f) } end |
#each_path ⇒ Object
Yield each absolute path to a file in the sequence to the block
210 211 212 |
# File 'lib/sequencer.rb', line 210 def each_path @filenames.each{|f| yield(File.join(@directory, f))} end |
#expected_frames ⇒ Object
176 177 178 |
# File 'lib/sequencer.rb', line 176 def expected_frames @expected_frames ||= ((@ranges[-1].end - @ranges[0].begin) + 1) end |
#file_count ⇒ Object Also known as: length
Returns the actual file count in the sequence
194 195 196 |
# File 'lib/sequencer.rb', line 194 def file_count @file_count ||= @filenames.length end |
#first_frame_no ⇒ Object
Returns the number of the first frame in the sequence
225 226 227 |
# File 'lib/sequencer.rb', line 225 def first_frame_no @ranges[0].begin end |
#gap_count ⇒ Object
180 181 182 |
# File 'lib/sequencer.rb', line 180 def gap_count @ranges.length - 1 end |
#gaps? ⇒ Boolean
Returns true if this sequence has gaps
133 134 135 |
# File 'lib/sequencer.rb', line 133 def gaps? @ranges.length > 1 end |
#include?(base_filename) ⇒ Boolean
Check if this sequencer includes a file
200 201 202 |
# File 'lib/sequencer.rb', line 200 def include?(base_filename) @filenames.include?(base_filename) end |
#inspect ⇒ Object
142 143 144 |
# File 'lib/sequencer.rb', line 142 def inspect '#<%s>' % to_s end |
#last_frame_no ⇒ Object
Returns the number of the last frame in the sequence
230 231 232 |
# File 'lib/sequencer.rb', line 230 def last_frame_no @ranges[-1].end end |
#missing_frames ⇒ Object
Returns the number of frames that the sequence should contain to be continuous
189 190 191 |
# File 'lib/sequencer.rb', line 189 def missing_frames expected_frames - file_count end |
#numbered? ⇒ Boolean
Returns true if the files in the sequence can have numbers
128 129 130 |
# File 'lib/sequencer.rb', line 128 def numbered? @numbered ||= !!(@filenames[0] =~ NUMBERS_AT_END) end |
#segment_count ⇒ Object
184 185 186 |
# File 'lib/sequencer.rb', line 184 def segment_count @ranges.length end |
#single_file? ⇒ Boolean
Tells whether this is a single frame sequence
138 139 140 |
# File 'lib/sequencer.rb', line 138 def single_file? @filenames.length == 1 end |
#to_a ⇒ Object
Returns the array of filenames
215 216 217 |
# File 'lib/sequencer.rb', line 215 def to_a @filenames.dup end |
#to_paths ⇒ Object
Returns paths to the files
220 221 222 |
# File 'lib/sequencer.rb', line 220 def to_paths @filenames.map{|f| File.join(@directory, f) } end |
#to_s ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/sequencer.rb', line 163 def to_s return @filenames[0] if (!numbered? || single_file?) printable = unless single_file? @ranges.map do | r | "%d..%d" % [r.begin, r.end] end.join(', ') else @ranges[0].begin end @inspect_pattern % "[#{printable}]" end |
#to_sequences ⇒ Object
If this Sequence has gaps, this method will return an array of all subsequences that it contains
s # => #<broken_seq.[123..568, 578..702].tif>
s.to_sequences # => [#<broken_seq.[123..568].tif>, #<broken_seq.[578..702].tif>]
149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/sequencer.rb', line 149 def to_sequences return [self] unless gaps? last_offset = 0 @ranges.map do | frame_range | frames_in_seg = frame_range.end - frame_range.begin seg_filenames = @filenames[last_offset..(last_offset + frames_in_seg)] last_offset = last_offset + frames_in_seg + 1 s = self.class.new(@directory, seg_filenames) end end |