class Radiation::Spectrum
Attributes
activity[RW]
calibration[RW]
count_correction[RW]
livetime[RW]
peaks[RW]
source[RW]
Public Class Methods
new(options={})
click to toggle source
# File lib/radiation/spectrum.rb, line 11 def initialize(options={}) @peaks = options.key?(:peaks) ? options[:peaks] : [] @source = options.key?(:source) ? options[:source] : nil @calibration= options.key?(:calibration) ? options[:calibration] : [0, 1] @livetime = options.key?(:livetime) ? options[:livetime] : 1 @activity = options.key?(:activity) ? options[:activity] : 1 @count_correction = options.key?(:count_correction) ? options[:count_correction] : 1 end
Public Instance Methods
calibrate()
click to toggle source
# File lib/radiation/spectrum.rb, line 20 def calibrate if @peaks.empty? or @peaks.select{|p| p.key?(:channel)}.empty? raise "Nothing to calibrate" end if @peaks.select{|p| p.key?(:channel) and p.key?(:energy)}.empty? if @calibration == [0,1] and @source.nil? raise "No channel <-> energy associations. Specify a Source or a preliminary calibration to improve" else self.guess_calibration end self.match_channels end @calibration = apply_linefit(@peaks) return self end
channel_efficiency(peak)
click to toggle source
# File lib/radiation/spectrum.rb, line 79 def channel_efficiency(peak) peak[:counts]*@count_correction/(peak[:intensity]*@livetime*@activity) end
channel_energy(chn)
click to toggle source
# File lib/radiation/spectrum.rb, line 47 def channel_energy(chn) @calibration[0] + @calibration[1]*chn end
efficiencies(rounding=4)
click to toggle source
# File lib/radiation/spectrum.rb, line 60 def efficiencies(rounding=4) self.match_channels @peaks.select{|p| p.key?(:intensity) and p.key?(:counts)}.each{|p| p[:efficiency] = channel_efficiency(p)} return self end
guess_calibration(energies=@source.energies, rounding=4)
click to toggle source
# File lib/radiation/spectrum.rb, line 38 def guess_calibration(energies=@source.energies, rounding=4) # Build all possible combinations of known energies and peaks arr = [energies, @peaks.collect{|peak| peak[:channel]}].comprehension # The approximate value for b in $Energy = a + b * Channel$ will be most frequent for $a \approx 0$ freq = arr.collect{|a| (a.first.to_f/a.last.to_f).round(rounding) }.flatten.inject(Hash.new(0)) { |h,v| h[v] += 1; h }.sort_by{|k,v| v} @calibration = [0, freq.last[0] ] return self end
match_channels(source=@source, rounding=4)
click to toggle source
# File lib/radiation/spectrum.rb, line 66 def match_channels(source=@source, rounding=4) @peaks.each do |peak| source.transitions.each do |transition| if channel_energy(peak[:channel]).to_f.approx_equal?(transition[:energy], rounding) peak[:energy] = transition[:energy] peak[:intensity] = transition[:intensity] if transition[:intensity] > 0 end end end return self end
parse_hdtv(file)
click to toggle source
# File lib/radiation/spectrum.rb, line 51 def parse_hdtv(file) xml = XmlSimple.xml_in(file, { 'KeyAttr' => 'name' }) @peaks = xml["fit"].collect{|p| p["peak"]}.flatten.collect{|p| p["uncal"]}.flatten.collect do |p| {:channel => p["pos"].first["value"].first.to_f.pm(p["pos"].first["error"].first.to_f), :counts => p["vol"].first["value"].first.to_f.pm(p["vol"].first["error"].first.to_f) } end return self end
Private Instance Methods
apply_linefit(peaks)
click to toggle source
# File lib/radiation/spectrum.rb, line 84 def apply_linefit(peaks) #calibrate using linefit mpeaks = peaks.delete_if{|p| p[:energy] == nil} x = mpeaks.collect{|p| p[:channel]} y = mpeaks.collect{|p| p[:energy]} lineFit = LineFit.new # Use weighted calibration when possible if mpeaks.count{|p| p[:intensity] and p[:intensity] > 0} == mpeaks.count weights = mpeaks.collect{|p| p[:intensity].nil? ? 0 : p[:intensity]} lineFit.setData(x,y,weights) else lineFit.setData(x,y) end intercept, slope = lineFit.coefficients varianceIntercept, varianceSlope = lineFit.varianceOfEstimates return [intercept.pm(Math.sqrt(varianceIntercept.abs)), slope.pm(Math.sqrt(varianceSlope.abs))] end