class TimeSeries

TimeSeries Class

Attributes

duration[R]
name[R]
resolution[R]

Public Class Methods

new(name, options={}) click to toggle source

Create Timeseries.

@param [String] name The timeseries name. @param [Hash] options The options hash. @option options [String] :resolution The time resolution: :year, :month, :day, :hour, :minute, :second @option options [Integer] :duration Duration is under development. It will allow for example 10, 20 or 30 seconds keys. Now only keys with :minute resolution are available.

Calls superclass method RedisConnection::new
# File lib/time_series.rb, line 25
def initialize name, options={}
  super # initialize RedisConnection
  
  @name = name
  @prefix="#{$app_prefix}:ts:#{@name}:"
  
  # parse the resolution option
  if options.has_key? :resolution
    @resolution = options[:resolution]
    resolutions = [:year, :month, :day, :hour, :minute, :second]
    #if the resolution option is invalid raise an exception
    unless resolutions.include?(@resolution) #or @resolution.is_a?(Integer)
      raise ArgumentError.new("resolution can be either :year or :month or :day or :hour or :minute or :second")
    end  
  elsif keys.empty? # default resolution is :minute
        @resolution = :minute
  else # try to guess resolution from existing keys
    max_res = 0
    keys.each do |k|
      res = k.count(':')
      max_res = res if res > max_res
    end
    
    case max_res
      when 8 then @resolution = :second
      when 7 then @resolution = :minute
      when 6 then @resolution = :hour
      when 5 then @resolution = :day
      when 4 then @resolution = :month
      when 3 then @resolution = :year
      else raise ArgumentError.new("Cannot guess resolution from existing keys")
    end #case
  end # if
  
  # define the @duration based on @resolution
  case @resolution
    when :year   then @duration = 12*30*24*3600
    when :month  then @duration = 30*24*3600
    when :day    then @duration = 24*3600
    when :hour   then @duration = 3600
    when :minute then @duration = 60
    when :second then @duration = options[:duration] ||= 20
  end
end

Public Instance Methods

all() click to toggle source

Returns the contents of all the keys TODO Considering to remove this method

@return [Hash] contents of all the keys

# File lib/time_series.rb, line 137
def all
  all = Hash.new
  keys.each{ |k| all[k.gsub(/#{@prefix}/,'')]=k.get}
  return all
end
array_older_than(array, time) click to toggle source

Removes recent keys from a key array

@param [Array] array Array of Keys @param [Integer] Number of seconds that a key is considered recent @return [Array] The new array

# File lib/time_series.rb, line 190
def array_older_than array, time
  array.keep_if { |k| k.time <= Time.now - time }
end
clear() click to toggle source

Deletes all the keys

@return Number of keys deleted

# File lib/time_series.rb, line 127
def clear
  i = 0
  keys.each{|k| @redis.del k; i+=1}
  return i 
end
compress(keys) click to toggle source

Compress keys Key compression merges the given keys of the same resolution to keys of greater resolution. For example seconds are merged into minutes and days are merged into months. The values of the keys are merged too. After the merge the keys are deleted.

@param [Array] keys to be compressed @return [Integer] Number of keys compressed

# File lib/time_series.rb, line 289
def compress keys
  parents = []
  keys.each do |key|
    unless key.recent? or key.year?
      parent = key.parent
      parents << parent unless parents.include? parent
    end
  end
  
  i = 0
  parents.each do |parent|
    unless parent.recent?
      children = parent.persistant_children
      @redis.zunionstore parent, children
      children.each{|k| @redis.del k; i+=1}
    end
  end
  return i 
end
current_key() click to toggle source

Returns the current key

@return [String] current key

# File lib/time_series.rb, line 99
def current_key
  time_to_key current_time, @resolution
end
current_time() click to toggle source

Returns the current time.

@return [Time] the current time

# File lib/time_series.rb, line 73
def current_time
  time=Time.at(Time.now.to_i) # this way nsec and usec is 0
  if @resolution == :second
    sec = time.strftime("%S").to_i % @duration
    time = time - sec
  end  
  return time
end
day(time;) click to toggle source
# File lib/time_series.rb, line 333
def day time;    time_to_key(time, :day).get end
days(*time) click to toggle source

Keys with day resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 240
def days *time
  array = keys.keep_if { |k| k.day? and k.persistant?}
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end    
end
hour(time;) click to toggle source
# File lib/time_series.rb, line 334
def hour time;   time_to_key(time, :hour).get end
hours(*time) click to toggle source

Keys with hour resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 226
def hours *time
  array = keys.keep_if { |k| k.hour? and k.persistant?}
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end    
end
keys() click to toggle source

Returns all the keys

@return [Array] all the keys in a String Array

# File lib/time_series.rb, line 120
def keys
  return @redis.keys"#{$app_prefix}:ts:#{@name}:*"
end
last() click to toggle source

Returns the contents of the last key

@return [Hash] contents of the last key

# File lib/time_series.rb, line 146
def last
  last_key.get
end
last_key() click to toggle source

Returns the last key

@return [String] last key

# File lib/time_series.rb, line 106
def last_key
  time_to_key last_time, @resolution
end
last_time() click to toggle source

Returns the time of the last key.

@return [Time] the last key's time

# File lib/time_series.rb, line 85
def last_time
  current_time - @duration
end
minute(time;) click to toggle source
# File lib/time_series.rb, line 335
def minute time; time_to_key(time, :minute).get end
minutes(*time) click to toggle source

Keys with minute resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 212
def minutes *time
  array = keys.keep_if { |k| k.minute? and k.persistant?}
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end    
end
month(time;) click to toggle source
# File lib/time_series.rb, line 332
def month time;  time_to_key(time, :month).get end
months(*time) click to toggle source

Keys with month resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 254
def months *time
  array = keys.keep_if { |k| k.month? and k.persistant?}  
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end  

end
previous() click to toggle source

Returns the contents of the previous key

@return [Hash] contents of the previous key

# File lib/time_series.rb, line 153
def previous
  previous_key.get
end
previous_key() click to toggle source

Returns the previous key

@return [String] previous key

# File lib/time_series.rb, line 113
def previous_key
 time_to_key previous_time, @resolution
end
previous_time() click to toggle source

Returns the time of the previous key.

@return [Time] the previous key's time

# File lib/time_series.rb, line 92
def previous_time
  current_time - 2 * @duration
end
push(term) click to toggle source

Push a new Term into the Timeseries

# File lib/time_series.rb, line 158
def push term
  @redis.zincrby current_key, 1, term
end
remove_by_score(keys, *population) click to toggle source

Remove terms with low scores

@param [Array] keys that will be examined @return [Array] Number of keys the operation took place, it doesn't mean that something changed

# File lib/time_series.rb, line 313
def remove_by_score keys, *population
  if population.empty?
    population = 1
  else
    population = population.first
  end
  i = 0    
  keys.each {|k| @redis.zremrangebyscore(k, '-inf', population); i+=1} # TODO What zremrangebyscore returns?
  return i     
end
second(time;) click to toggle source
# File lib/time_series.rb, line 336
def second time; time_to_key(time, :second).get end
seconds(*time) click to toggle source

Keys with second resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 198
def seconds *time
  array = keys.keep_if { |k| k.second? and k.persistant?}
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end
end
time_to_key(time, *resolution) click to toggle source

Convert a Time object to the respective Key TODO Refactoring

@param [Time] time The Time @option [String] resolution The time resolution: :year, :month, :day, :hour, :minute, :second @return [String] The Key

# File lib/time_series.rb, line 168
def time_to_key time, *resolution
  if resolution.empty?
    return time.strftime("#{@prefix}%Y:%m:%d:%H:%M:%S")
  else
    resolution = resolution.first
    case resolution
      when :year   then return time.strftime("#{@prefix}%Y")
      when :month  then return time.strftime("#{@prefix}%Y:%m")
      when :day    then return time.strftime("#{@prefix}%Y:%m:%d")
      when :hour   then return time.strftime("#{@prefix}%Y:%m:%d:%H")
      when :minute then return time.strftime("#{@prefix}%Y:%m:%d:%H:%M")
      when :second then return time.strftime("#{@prefix}%Y:%m:%d:%H:%M:%S")
      else puts red "wrong resolution in time_to_key"
    end
  end
end
year(time;) click to toggle source

def term_weights terms, factor

terms.each do |term, value|
  terms[term]=value*factor
end
return terms

end

# File lib/time_series.rb, line 331
def year time;   time_to_key(time, :year).get end
years(*time) click to toggle source

Keys with year resolution

@param [Array] time @return [Array] Array with the keys

# File lib/time_series.rb, line 269
def years *time
  array = keys.keep_if { |k| k.year? and k.persistant?}  
  if time.empty?
    return array
  else
    time = time.first
    return array_older_than array, time
  end  

end