radiation 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YjYxM2U4YjVkYWQxNzM2YTM0MjBiNWQwYTMzNDAwYzU5MTdhYzNkNg==
5
- data.tar.gz: !binary |-
6
- NjE0ZTlkNGM1OTg4ZjU5YjVlZWFhZGM5NTBlODcyMjA4OTYwMTBiMA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MjdjZTVkYmUwZDljOGM0MWVjYjEyMzBiYzVmZjc1YjE1ZTYxYzQ0OGUzNjhl
10
- Yjc4OWZjOWI2NmM1OGY2NjZmYzg2YTlhNzdjYzFjMjllMzVhZjJjMGFmNmNl
11
- OGZjMDZmM2FkZmM3Njg0MjJhOWZiOWJhYTk4ZTdiYzk4N2U4MjE=
12
- data.tar.gz: !binary |-
13
- MTk2ZTFhY2E0ZWVkZGExYzUxN2U4MTc5NWQ2MjAyMGY0ZGEyNTQ5NTA0ZDEy
14
- MjkwMzk5ZDdkMWYzNjM4NDZjNzU2NzFmN2YxYzE1NzVjOTI4ZTIyMGQ3YTkw
15
- MWM4MzkxNzgyYjY4ODliYzc2ZDQ1M2M2NGUyYTY2MTU0NGFjYWI=
2
+ SHA1:
3
+ metadata.gz: f4777bfcdb25af513bc85c5a8a87a9402d2c7116
4
+ data.tar.gz: 8e38aeb601be484f3d3b9642d873ce7f95247881
5
+ SHA512:
6
+ metadata.gz: 3c36ef60bbad784228d316ba6a7253b8db45cb4c442ae3613d722cabdfe67ab8f13b119f23e56120ae1348b5a46ab53efc58f1e0c30df51f9cac44ebed237fca
7
+ data.tar.gz: ba9770278d22456442c173032169457978bab3f12fd6f38088afc36ae6c8cb445699963d0e3ccf30fa7f5e65046c214d5cf8ea8623706fca68794bc8e626009e
data/.gitignore CHANGED
@@ -1,17 +1,17 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec CHANGED
@@ -1 +1 @@
1
- #--color
1
+ #--color
data/.travis.yml CHANGED
@@ -1,9 +1,7 @@
1
- language: ruby
2
- rvm:
3
- #- "1.8.7"
4
- - "1.9.2"
5
- - "1.9.3"
6
- #- jruby-18mode # JRuby in 1.8 mode
7
- - jruby-19mode # JRuby in 1.9 mode
8
- #- rbx-18mode
9
- - rbx-19mode
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "1.9.3"
5
+ - "2.0.0"
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ - rbx-19mode
data/CHANGELOG.md CHANGED
@@ -1,12 +1,12 @@
1
- ## v0.0.3
2
-
3
- * Added basic parsing for hdtv xml files
4
- * Changed dependency for linefit
5
-
6
- ## v0.0.2
7
-
8
- * Added spectrum class with energy calibration options
9
-
10
- ## v0.0.1
11
-
12
- * initial release
1
+ ## v0.0.3
2
+
3
+ * Added basic parsing for hdtv xml files
4
+ * Changed dependency for linefit
5
+
6
+ ## v0.0.2
7
+
8
+ * Added spectrum class with energy calibration options
9
+
10
+ ## v0.0.1
11
+
12
+ * initial release
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
- source 'https://rubygems.org'
2
-
3
- #gem "linefit", git: "https://github.com/janmayer/linefit.git"
4
- # Specify your gem's dependencies in radiation.gemspec
5
- gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ #gem "linefit", git: "https://github.com/janmayer/linefit.git"
4
+ # Specify your gem's dependencies in radiation.gemspec
5
+ gemspec
data/LICENSE.txt CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2013 Jan Mayer
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2013 Jan Mayer
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,45 +1,45 @@
1
- # Radiation
2
- [![Gem Version](https://badge.fury.io/rb/radiation.png)](http://badge.fury.io/rb/radiation)
3
- [![Build Status](https://travis-ci.org/janmayer/radiation.png?branch=master)](https://travis-ci.org/janmayer/radiation)
4
- [![Code Climate](https://codeclimate.com/github/janmayer/radiation.png)](https://codeclimate.com/github/janmayer/radiation)
5
-
6
- This gem provides easy access to energies and intensities from the decay of radioactive nuclei.
7
- Currently two data sources are accessible: Internal (see bib files in `./data/`) and recommended values
8
- by [Laboratoire National Henri Becquerel](http://www.nucleide.org/DDEP_WG/DDEPdata.htm).
9
-
10
- ## Example Usage
11
-
12
- ### Command line interface
13
-
14
- $> radiation
15
-
16
- ### In your ruby files:
17
-
18
- require "radiation"
19
- Radiation::Source.new(nuclide: "Ra-226").energies.collect{|e| e.value}
20
-
21
- See also files in `./samples/`.
22
-
23
- ## Planned features
24
-
25
- * Efficiency calibration for given peaks or spectra
26
- * Better access to resources
27
-
28
-
29
- ## Installation
30
-
31
- Requirement is a (local) ruby with rubygems. Using rvm is recommended
32
-
33
- $ \curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
34
-
35
- Add this line to your application's Gemfile:
36
-
37
- gem 'radiation'
38
-
39
- And then execute:
40
-
41
- $ bundle
42
-
43
- Or install it yourself as:
44
-
45
- $ gem install radiation
1
+ # Radiation
2
+ [![Gem Version](https://badge.fury.io/rb/radiation.png)](http://badge.fury.io/rb/radiation)
3
+ [![Build Status](https://travis-ci.org/janmayer/radiation.png?branch=master)](https://travis-ci.org/janmayer/radiation)
4
+ [![Code Climate](https://codeclimate.com/github/janmayer/radiation.png)](https://codeclimate.com/github/janmayer/radiation)
5
+
6
+ This gem provides easy access to energies and intensities from the decay of radioactive nuclei.
7
+ Currently two data sources are accessible: Internal (see bib files in `./data/`) and recommended values
8
+ by [Laboratoire National Henri Becquerel](http://www.nucleide.org/DDEP_WG/DDEPdata.htm).
9
+
10
+ ## Example Usage
11
+
12
+ ### Command line interface
13
+
14
+ $> radiation
15
+
16
+ ### In your ruby files:
17
+
18
+ require "radiation"
19
+ Radiation::Source.new(nuclide: "Ra-226").energies.collect{|e| e.value}
20
+
21
+ See also files in `./samples/`.
22
+
23
+ ## Planned features
24
+
25
+ * Efficiency calibration for given peaks or spectra
26
+ * Better access to resources
27
+
28
+
29
+ ## Installation
30
+
31
+ Requirement is a (local) ruby with rubygems. Using rvm is recommended
32
+
33
+ $ \curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
34
+
35
+ Add this line to your application's Gemfile:
36
+
37
+ gem 'radiation'
38
+
39
+ And then execute:
40
+
41
+ $ bundle
42
+
43
+ Or install it yourself as:
44
+
45
+ $ gem install radiation
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require 'rspec/core/rake_task'
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task default: :spec
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/lib/radiation/cli.rb CHANGED
@@ -34,5 +34,27 @@ class CLI < Thor
34
34
  spectrum.calibrate.calibration.each{|c| puts c}
35
35
  end
36
36
 
37
+ option :resource
38
+ option :mini
39
+ desc "efficiency NUCLIDE SPECTRUM.xml", "calculate efficiencies for a spectrum"
40
+ long_desc <<-LONGDESC
41
+ Calculates relative full-peak efficiencies for a spectrum that has been analysed with HDTV. Stored peak fits in HDTV can be stored with hdtv>fit write filname.xml
42
+ Example: \n
43
+ $>radiation efficiency Ra-226 Ge00.xml
44
+ With --resource=nucleide.org more decay radiation sources are available.
45
+ With --mini=value transitions with small intensities can be supressed (default 0.3)
46
+ LONGDESC
47
+ def efficiency(nuclide, file)
48
+ resource = options[:resource] ? options[:resource] : "internal"
49
+ mini = options[:mini] ? options[:mini] : 0.3
50
+ source = Radiation::Source.new(nuclide: nuclide, resource: resource)
51
+ spectrum = Radiation::Spectrum.new(source: source ).parse_hdtv(file)
52
+ puts ["E_ɣ", "I_ɣ", "ΔI_ɣ", "e", "Δe"].join("\t")
53
+ spectrum.calibrate.efficiencies.select{|p| p[:intensity] > mini}.sort_by{|k| k[:energy]}.each do |p|
54
+ puts [ p[:energy].to_f.round(1), p[:intensity].value, p[:intensity].delta, p[:efficiency].value.round(1), p[:efficiency].delta.round(1) ].join("\t")
55
+ end
56
+ end
57
+
58
+
37
59
  end
38
60
  end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'csv'
3
+
4
+ module Radiation::Resource
5
+ class Internal < Base
6
+
7
+ def fetch(nuclide)
8
+ @nuclide = nuclide
9
+ begin
10
+ path = File.join(File.dirname(__FILE__), "../../../data")
11
+ @data[:nuclide] = @nuclide.to_s
12
+ @data[:transitions] = CSV.read("#{path}/#{@nuclide}.csv", {col_sep: ';', converters: :numeric}).collect{|row| {:energy => row[0].pm(0), :intensity => row[1].pm(row[2])} }
13
+ rescue
14
+ raise "No Data for #{nuclide}"
15
+ end
16
+ self
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ require 'plusminus'
3
+ require 'open-uri'
4
+ require 'open-uri/cached'
5
+ require 'tmpdir'
6
+
7
+
8
+ module Radiation::Resource
9
+ class Nucleideorg < Base
10
+
11
+ def fetch(nuclide)
12
+ @nuclide = nuclide
13
+ @nuclide = "Ra-226D" if @nuclide == "Ra-226" #Ra-226 in equilibrium with daughters
14
+ begin
15
+ @data[:nuclide] = @nuclide.to_s
16
+
17
+ @data[:reference] = "A. Pluquet et al. (2013). Recommended data for #{@nuclide} by the Decay Data Evaluation Project working group. Decay Data Evaluation Project, Laboratoire National Henri Becquerel, C.E. Saclay. Retrieved from http://www.nucleide.org/DDEP_WG/Nuclides/#{@nuclide}.lara.txt"
18
+
19
+ OpenURI::Cache.cache_path = "#{Dir.tmpdir}/radiation/"
20
+ uri = open("http://www.nucleide.org/DDEP_WG/Nuclides/#{@nuclide}.lara.txt").readlines
21
+ start = 0
22
+ uri.each_with_index do |line, lineno|
23
+ if line.start_with?("Half-life (s)")
24
+ row = line.split(' ; ')
25
+ @data[:halflife] = row[1].to_f.pm(row[2].to_f)
26
+ end
27
+ if line.start_with?("------")
28
+ start = lineno + 2
29
+ break
30
+ end
31
+ end
32
+ return @data[:transitions] = [] if start == 0 or uri.count < start
33
+ @data[:transitions] = uri[start...-1].collect{|line| line.split(' ; ')}.select!{|row| row[4] == "g"}.collect do |row|
34
+ {:energy => row[0].to_f.pm(row[1].to_f), :intensity => row[2].to_f.pm(row[3].to_f)}
35
+ end
36
+ rescue
37
+ raise "No Data for #{@nuclide}"
38
+ end
39
+ self
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module Radiation
4
+ module Resource
5
+ class Base
6
+ attr_reader :data
7
+
8
+ def initialize()
9
+ @data = {}
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -1,37 +1,53 @@
1
1
  # encoding: utf-8
2
- require 'radiation/source/resource'
3
2
  require 'combinatorics'
4
3
 
5
-
6
4
  module Radiation
7
- class Source
8
- attr_reader :data
9
-
10
- def initialize(options={})
11
- @resource = options.key?(:resource) ? options[:resource].to_s : "internal"
12
- fetch(options[:nuclide].to_s) if options.key?(:nuclide)
13
- end
14
-
15
- def fetch(nuclide)
16
- raise "Nuclide :#{nuclide} is not valid." unless is_nuclide?(nuclide)
17
- @data = Resource.new(@resource).data(nuclide)
5
+ class Source
6
+ attr_reader :resource, :nuclide, :halflife, :reference, :description, :transitions
7
+
8
+ def initialize(options={})
9
+ @resource = options.key?(:resource) ? options[:resource].to_s : "internal"
10
+ @nuclide = options[:nuclide].to_s if options.key?(:nuclide)
11
+ fetch if @resource and @nuclide
12
+ end
13
+
14
+ def fetch(options={})
15
+ @resource = options[:resource].to_s if options.key?(:resource)
16
+ @nuclide = options[:nuclide].to_s if options.key?(:nuclide)
17
+ raise "Nuclide: #{@nuclide} is not valid." unless is_nuclide?(@nuclide)
18
+ data = case @resource
19
+ when "internal" then Radiation::Resource::Internal.new.fetch(@nuclide).data
20
+ when "nucleide.org" then Radiation::Resource::Nucleideorg.new.fetch(@nuclide).data
21
+ else raise "Unknown Datasource"
22
+ end
23
+ build(data)
24
+ return self
25
+ end
26
+
27
+ def read(options={})
28
+ @resource = "external"
29
+ build(options)
30
+ return self
31
+ end
32
+
33
+ def energies
34
+ self.transitions.collect{|line| line[:energy]}
35
+ end
36
+
37
+ def intensities
38
+ self.transitions.select{|line| line[:intensity] > 0}.collect{|line| {:energy => line[:energy], :intensity => line[:intensity]} }
39
+ end
40
+
41
+ def is_nuclide?(nuclide)
42
+ !!(nuclide =~ /\A[a-zA-Z]{1,2}-\d{1,3}\z/)
43
+ end
44
+
45
+ private
46
+ def build(data)
47
+ [:nuclide, :halflife, :reference, :description, :transitions].each do |key|
48
+ instance_variable_set("@#{key}", data[key]) if data.key?(key)
49
+ end
50
+ end
51
+
18
52
  end
19
-
20
- def nuclide
21
- @data[:nuclide]
22
- end
23
-
24
- def energies
25
- @data[:lines].collect{|line| line[:energy]}
26
- end
27
-
28
- def intensities
29
- @data[:lines].select{|line| line[:intensity] > 0}.collect{|line| {:energy => line[:energy], :intensity => line[:intensity]} }
30
- end
31
-
32
- def is_nuclide?(nuclide)
33
- !!(nuclide =~ /\A[a-zA-Z]{1,2}-\d{1,3}\z/)
34
- end
35
-
36
- end
37
53
  end
@@ -3,76 +3,93 @@ require "linefit"
3
3
  require "plusminus"
4
4
  require "xmlsimple"
5
5
 
6
- module Radiation
7
- class Spectrum
8
- attr_accessor :peaks, :source, :calibration
9
-
10
- def initialize(options={})
11
- @peaks = options.key?(:peaks) ? options[:peaks] : []
12
- @source = options.key?(:source) ? options[:source] : nil
13
- @calibration= options.key?(:calibration) ? options[:calibration] : [0, 1]
14
- end
15
-
16
- def calibrate
17
- if @peaks.empty? or @peaks.select{|p| p.key?(:channel)}.empty?
18
- raise "Nothing to calibrate"
6
+ module Radiation
7
+ class Spectrum
8
+ attr_accessor :peaks, :source, :calibration
9
+
10
+ def initialize(options={})
11
+ @peaks = options.key?(:peaks) ? options[:peaks] : []
12
+ @source = options.key?(:source) ? options[:source] : nil
13
+ @calibration= options.key?(:calibration) ? options[:calibration] : [0, 1]
19
14
  end
20
-
21
- if @peaks.select{|p| p.key?(:channel) and p.key?(:energy)}.empty?
22
- if @calibration == [0,1] and @source.nil?
23
- raise "No channel <-> energy associations. Specify a Source or a preleminary calibration to improve"
24
- else
25
- self.guess_calibration
15
+
16
+ def calibrate
17
+ if @peaks.empty? or @peaks.select{|p| p.key?(:channel)}.empty?
18
+ raise "Nothing to calibrate"
19
+ end
20
+
21
+ if @peaks.select{|p| p.key?(:channel) and p.key?(:energy)}.empty?
22
+ if @calibration == [0,1] and @source.nil?
23
+ raise "No channel <-> energy associations. Specify a Source or a preleminary calibration to improve"
24
+ else
25
+ self.guess_calibration
26
+ end
27
+ self.match_channels
26
28
  end
27
- self.match_channels
29
+ #calibrate using linefit
30
+ mpeaks = @peaks.delete_if{|p| p[:energy] == nil}
31
+ x = mpeaks.collect{|p| p[:channel]}
32
+ y = mpeaks.collect{|p| p[:energy]}
33
+ lineFit = LineFit.new
34
+ lineFit.setData(x,y)
35
+ intercept, slope = lineFit.coefficients
36
+ varianceIntercept, varianceSlope = lineFit.varianceOfEstimates
37
+ @calibration = [intercept.pm(Math.sqrt(varianceIntercept)), slope.pm(Math.sqrt(varianceSlope))]
38
+ return self
28
39
  end
29
- #calibrate using linefit
30
- mpeaks = @peaks.delete_if{|p| p[:energy] == nil}
31
- x = mpeaks.collect{|p| p[:channel]}
32
- y = mpeaks.collect{|p| p[:energy]}
33
- lineFit = LineFit.new
34
- lineFit.setData(x,y)
35
- intercept, slope = lineFit.coefficients
36
- varianceIntercept, varianceSlope = lineFit.varianceOfEstimates
37
- @calibration = [intercept.pm(Math.sqrt(varianceIntercept)), slope.pm(Math.sqrt(varianceSlope))]
38
- return self
39
- end
40
-
41
- def match_channels(energies=@source.energies, rounding=4)
42
- @peaks.each do |peak|
43
- energies.each do |energy|
44
- peak[:energy] = energy if channel_energy(peak[:channel]).to_f.approx_equal?(energy, rounding)
40
+
41
+ def match_channels(energies=@source.energies, rounding=4)
42
+ @peaks.each do |peak|
43
+ energies.each do |energy|
44
+ peak[:energy] = energy if channel_energy(peak[:channel]).to_f.approx_equal?(energy, rounding)
45
+ end
45
46
  end
47
+ return self
48
+ end
49
+
50
+ def guess_calibration(energies=@source.energies, rounding=4)
51
+ # Build all possible combinations of known energies and peaks
52
+ arr = [energies, @peaks.collect{|peak| peak[:channel]}].comprehension
53
+ # The approximate value for b in $Energy = a + b * Channel$ will be most frequent for $a \approx 0$
54
+ 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}
55
+ @calibration = [0, freq.last[0] ]
56
+ return self
57
+ end
58
+
59
+ def channel_energy(chn)
60
+ @calibration[0] + @calibration[1]*chn
61
+ end
62
+
63
+ def parse_hdtv(file)
64
+ xml = XmlSimple.xml_in(file, { 'KeyAttr' => 'name' })
65
+ @peaks = xml["fit"].collect{|p| p["peak"]}.flatten.collect{|p| p["uncal"]}.flatten.collect do |p|
66
+ {:channel => p["pos"].first["value"].first.to_f.pm(p["pos"].first["error"].first.to_f),
67
+ :counts => p["vol"].first["value"].first.to_f.pm(p["vol"].first["error"].first.to_f) }
68
+ end
69
+ return self
70
+ end
71
+
72
+ def efficiencies(rounding=4)
73
+ @peaks.each do |peak|
74
+ @source.transitions.each do |transition|
75
+ if channel_energy(peak[:channel]).to_f.approx_equal?(transition[:energy], rounding)
76
+ peak[:energy] = transition[:energy]
77
+ peak[:intensity] = transition[:intensity] if transition[:intensity] > 0
78
+ end
79
+ end
80
+ end
81
+ @peaks.select{|p| p.key?(:intensity) and p.key?(:counts)}.each{|p| p[:efficiency] = channel_efficiency(p)}
46
82
  end
47
- return self
48
- end
49
-
50
- def guess_calibration(energies=@source.energies, rounding=4)
51
- # Build all possible combinations of known energies and peaks
52
- arr = [energies, @peaks.collect{|peak| peak[:channel]}].comprehension
53
- # The approximate value for b in $Energy = a + b * Channel$ will be most frequent for $a \approx 0$
54
- 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}
55
- @calibration = [0, freq.last[0] ]
56
- return self
57
- end
58
-
59
- def channel_energy(chn)
60
- @calibration[0] + @calibration[1]*chn
61
- end
62
83
 
63
- def parse_hdtv(file)
64
- xml = XmlSimple.xml_in(file, { 'KeyAttr' => 'name' })
65
- @peaks = xml["fit"].collect{|p| p["peak"]}.flatten.collect{|p| p["uncal"]}.flatten.collect do |p|
66
- {:channel => p["pos"].first["value"].first.to_f.pm(p["pos"].first["error"].first.to_f),
67
- :counts => p["vol"].first["value"].first.to_f.pm(p["vol"].first["error"].first.to_f) }
84
+ private
85
+ def channel_efficiency(peak)
86
+ peak[:counts]/peak[:intensity]
68
87
  end
69
- return self
70
- end
71
88
 
89
+ end
72
90
  end
73
- end
74
-
75
-
91
+
92
+
76
93
  class Float
77
94
  def approx_equal?(other,threshold=0.5)
78
95
  if (self-other).abs < threshold # "<" not exact either
@@ -1,3 +1,3 @@
1
- module Radiation
2
- VERSION = "0.0.4"
3
- end
1
+ module Radiation
2
+ VERSION = "0.1.0"
3
+ end
data/lib/radiation.rb CHANGED
@@ -1,7 +1,10 @@
1
- require "radiation/version"
2
- require "radiation/source"
3
- require "radiation/spectrum"
4
-
5
- module Radiation
6
- # Your code goes here...
7
- end
1
+ require "radiation/version"
2
+ require "radiation/source"
3
+ require "radiation/spectrum"
4
+ require "radiation/resource"
5
+ require 'radiation/resource/internal'
6
+ require 'radiation/resource/nucleideorg'
7
+
8
+ module Radiation
9
+ # Your code goes here...
10
+ end