radiation 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/.gitignore +17 -17
- data/.rspec +1 -1
- data/.travis.yml +7 -9
- data/CHANGELOG.md +12 -12
- data/Gemfile +5 -5
- data/LICENSE.txt +22 -22
- data/README.md +45 -45
- data/Rakefile +6 -6
- data/lib/radiation/cli.rb +22 -0
- data/lib/radiation/resource/internal.rb +20 -0
- data/lib/radiation/resource/nucleideorg.rb +43 -0
- data/lib/radiation/resource.rb +14 -0
- data/lib/radiation/source.rb +47 -31
- data/lib/radiation/spectrum.rb +78 -61
- data/lib/radiation/version.rb +3 -3
- data/lib/radiation.rb +10 -7
- data/radiation.gemspec +32 -32
- data/samples/B0-Ra226.xml +4721 -4721
- data/samples/efficiencies.rb +10 -0
- data/spec/radiation_spec.rb +14 -4
- metadata +24 -23
- data/lib/radiation/source/resource/internal.rb +0 -17
- data/lib/radiation/source/resource/nucleideorg.rb +0 -36
- data/lib/radiation/source/resource.rb +0 -25
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
4
|
-
- "1.9.
|
5
|
-
- "
|
6
|
-
|
7
|
-
-
|
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
|
data/lib/radiation/source.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
data/lib/radiation/spectrum.rb
CHANGED
@@ -3,76 +3,93 @@ require "linefit"
|
|
3
3
|
require "plusminus"
|
4
4
|
require "xmlsimple"
|
5
5
|
|
6
|
-
module Radiation
|
7
|
-
class Spectrum
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
22
|
-
if @
|
23
|
-
raise "
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
data/lib/radiation/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Radiation
|
2
|
-
VERSION = "0.0
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|