Skip to content

Instantly share code, notes, and snippets.

@R167
Created April 28, 2017 13:44
Show Gist options
  • Save R167/6034b446e1dfd20294ccdc6b020db170 to your computer and use it in GitHub Desktop.
Save R167/6034b446e1dfd20294ccdc6b020db170 to your computer and use it in GitHub Desktop.
For AP Bio
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'csv'
MATCHER = /\Adata\/(?<deg>\d+)\/(?<bug>L\d)\.txt\z/.freeze
files = Hash.new { |h, k| h[k] = Hash.new }
Dir['data/*/*.txt'].each do |s|
match = s.match(MATCHER)
files[match['deg']][match['bug'].to_sym] = {file: s}
end
class Point < Struct.new(:t, :x, :y)
def self.average(points)
Point.new(*points.map(&:to_a).transpose.map{|x| x.reduce(0.0, :+) / points.length})
end
def distance(point)
Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2)
end
end
files.each do |temp, bugs|
bugs.each do |bug, info|
info[:total] = 0
info[:total_reg] = 0
info[:start] = nil
CSV.foreach(info[:file], skip_lines: /^L\d/, headers: true, col_sep: "\t", converters: [:float]).each_cons(3).map do |rows|
info[:total_reg] += Point.new(*rows.first.fields).distance(Point.new(*rows[1].fields))
Point.average(rows.map do |r|
Point.new(*r.fields('t', 'x', 'y'))
end)
end.each_cons(2) do |p1, p2|
info[:start] ||= p1.t
info[:total] += p1.distance(p2)
info[:end] = p2.t
end
info[:time] = info[:end] - info[:start]
info[:speed] = info[:total] / info[:time]
puts "#{temp} #{bug} #{info[:total] / info[:time]}"
end
end
tab = CSV.generate(col_sep: ',', headers: ['Temp', 'Bug', 'Distance', 'Time', 'Speed'], write_headers: true) do |t|
files.each do |temp, bugs|
bugs.each do |bug, info|
row = [temp, bug] + info.values_at(:total, :time, :speed).map{|v| "%6.5e" % v}
t.add_row(row)
end
end
end
File.open('output.csv', 'w') {|f| f.write(tab)}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment