Skip to content

Instantly share code, notes, and snippets.

@neggert
Created May 4, 2012 07:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neggert/2593138 to your computer and use it in GitHub Desktop.
Save neggert/2593138 to your computer and use it in GitHub Desktop.
def get_seu_logs()
# get the portion of the logs relevant to the seu
logs = []
Dir['**/PixelFEDSupervisor_*.log'].each do |path|
contents = File.read(path)
regex = /Message : Detected soft error using FED channel monitoring(.*?)Message : New state is:Running/m
matches = contents.scan(regex)
if (matches != nil)
(0..matches.size-1).each do |i|
logs << matches[i][0]
end
end
end
return logs
end
def get_seu_channel( seulogstring)
# get the SEU channel from the log text
regex = /A disabled channel found in FED (?<fed>\d{2}) mask bits: (?<N>\h+) (?<NC>\h+) (?<SC>\h+) (?<S>\h+) expected (?<Ne>\h+) (?<NCe>\h+) (?<SCe>\h+) (?<Se>\h+)/
offset = 0
fed = 0
channel = -1
seulogstring.split("\n").each do |line|
data = seulogstring.match(regex)
if (data != nil)
# find the mismatch
if (data[:N] != data[:Ne])
mask = data[:N].hex ^ data[:Ne].hex
offsset = 0
elsif (data[:NC] != data[:NCe])
mask = data[:NC].hex ^ data[:NCe].hex
offsset = 9
elsif (data[:SC] != data[:SCe])
mask = data[:SC].hex ^ data[:SCe].hex
offsset = 18
elsif (data[:S] != data[:Se])
mask = data[:S].hex ^ data[:Se].hex
offsset = 27
end
fed = data[:fed]
channel = offset + get_channels_from_word(mask)
end
end
return fed, channel
end
def get_channels_from_word( hex )
# note, this assumes only 1 entry is 1
(0..8).each do |i|
if ((hex >> i) % 2 == 1)
return i+1
end
end
end
def get_time( string )
# parse the string and get the timestamp at the beginning
if (/\A\s*?(?<day>\d{2})\s(?<month>\w*?)\s(?<year>\d{4})\s(?<hour>\d{2}):(?<min>\d{2}):(?<sec>\d{2}\.\d*)/ =~ string)
Time.local(year, month, day, hour, min, sec)
else
false
end
end
def get_start_time( seu_log_string)
# get the first timestamp in the SEU log
seu_log_string.split("\n").each do | line |
time = get_time( line )
if (time)
return time
end
end
return false
end
def get_end_time( seu_log_string)
# get the last timestamp in the SEU log
seu_log_string.split("\n").reverse.each do | line |
time = get_time( line )
if (time)
return time
end
end
return false
end
def get_run_with_times()
# get the times runs started and stopped
starttimes = []
stoptimes = []
runs = []
outarray = []
Dir['**/PixelSupervisor.log'].each do |path|
begin
File.open(path) do |f|
f.readlines.each do |line|
if (/\s\-\sStart Run (?<run>\d*)/ =~ line)
starttimes << get_time(line)
runs << run
elsif (/\s\-\sEntering transition STOP/ =~ line)
stoptimes << get_time(line)
end
end
end
rescue ArgumentError
# puts "Error parsing file #{path}"
next
end
end
# figure out which stop times correspond to which stop times
(0..starttimes.count-1).each do |i|
possible_end_times = []
if (i == starttimes.count-1)
possible_end_times = stoptimes.select{ |item| item > starttimes[i]}
else
possible_end_times = stoptimes.select{ |item| item > starttimes[i] and item < starttimes[i+1]}
end
if (possible_end_times.count > 0)
#possible_end_times.sort!
end_time = possible_end_times[0]
out = {:start => starttimes[i], :end => end_time, :run => runs[i]}
outarray << out
end
end
return outarray
end
def get_seu_run( seulogstring )
# get the run number the SEU occured in
seutime = get_time(seulogstring)
get_run_with_times().each do |run|
if ((run[:start] < seutime) and (seutime < run[:end]))
return run[:run]
end
end
return nil
end
require 'mechanize'
require 'highline/import'
class WBMScraper
def initialize()
@agent = Mechanize.new
end
def login!()
@page = @agent.get("https://cmswbm.web.cern.ch/cmswbm/cmsdb/servlet/RunSummary")
if (@page.title =~ /CERN Authentication v2/)
# we need to login
loginform = @page.form('aspnetForm')
puts "Login to retrieve run info from WBM"
username = ask("CERN User Name: ")
userpw = ask("CERN Password (this will not be stored): ") { |q| q.echo = false }
loginform['ctl00$ContentPlaceHolder1$txtFormsLogin'] = username
loginform['ctl00$ContentPlaceHolder1$txtFormsPassword'] = userpw
loginform.checkbox_with(:name=>'ctl00$ContentPlaceHolder1$chkRememberLogin').check
@page = @agent.submit(loginform, loginform.buttons.first)
# click through the login page
@page = @agent.submit(@page.form('hiddenform'), @page.form('hiddenform').buttons.first)
end
checkpage!()
end
def checkpage!()
if (not (@page.title =~ /CMS RunSummary/))
raise 'Page title is not \'CMS RunSumarry\'. It is #{@page.title}'
end
end
def run_was_good?( run )
@page = @agent.get("https://cmswbm.web.cern.ch/cmswbm/cmsdb/servlet/RunSummary?RUN=#{run}")
# click on the fill report
link = @page.links_with(:href=>/FillReport/)[0]
if (link == nil)
return false # no run in RunSummary
end
@page = link.click
# now use a regex to try to find the start time of stable beams
regexp = /BeginTime \(stable\)<\/th><td><a href=".*?">.*?<\/a><\/td><\/tr>/
if ( regexp =~ @page.content )
return true
else
# if we couldn't find it, there were no stable beams
return false
end
end
end
class Seu
attr_accessor :starttime, :stoptime, :run, :fed, :channel, :stable
def initialize( starttime, stoptime, run, fed, channel, stable)
# do some validation
raise ArgumentError, 'Invalid fed, channel, or run' unless (fed != 0 and channel != -1 and run != nil)
@starttime = starttime
@stoptime = stoptime
@run = run
@fed = fed
@channel = channel
@stable = stable
end
def to_s
"#{@starttime} - #{elapsed_sec}s Run: #{@run} FED: #{@fed}, channel #{@channel} StableBeam: #{@stable}"
end
def elapsed_sec
@stoptime - @starttime
end
end
s = WBMScraper.new
s.login!()
get_seu_logs().each do | seulog |
starttime = get_start_time(seulog)
stoptime = get_end_time(seulog)
run = get_seu_run(seulog)
fed, channel = get_seu_channel(seulog)
stable = s.run_was_good?( run)
begin
seu = Seu.new(starttime, stoptime, run, fed, channel, stable)
rescue ArgumentError
next # go to next seu
end
puts seu
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment