rubychem 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ *.log
2
+ tmp/**/*
3
+ pkg
4
+ doc
5
+ Manifest
6
+ .DS_Store
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Justin Zollars
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ # RubyChem is a Rails Plugin that allows you to calculate molecular mass from the chemical formula. The script iterates through the chemical formula and breaks the formula down into species. Then calculates molar mass.
2
+
3
+ Example:
4
+
5
+ * H2SO4 -> ["H2", "S", "O4"]
6
+ * -> 97.99
7
+
8
+ ***************************************************************************
9
+
10
+ # Installation
11
+
12
+ * cd vendor/plugins
13
+ * git clone
14
+ * git://github.com/fogonthedowns/rubychem.git
15
+ * ruby script/generate scaffold chem formula:string
16
+ * rake db:migrate
17
+ * Add "include RubyChem" in the application_controller.rb
18
+ * in views/chems/show.html.erb add the following code: Molecular Mass: <%= RubyChem::Chemical.new(@chem.formula.to_s).fw %>
@@ -0,0 +1,36 @@
1
+ # The goal is for beta.rb to run faster
2
+
3
+ load 'benchmark'
4
+ load 'ruby_chem.rb'
5
+ load 'rubychem.rb'
6
+
7
+ iterations = 10000
8
+
9
+ a = Benchmark.measure do
10
+ for i in 1..iterations do
11
+ RubyChem::Chemical.new("H2O").fw
12
+ end
13
+ end
14
+
15
+ b = Benchmark.measure do
16
+ for i in 1..iterations do
17
+ RubyChemBeta::Chemical.new("H2O")
18
+ end
19
+ end
20
+
21
+ c = Benchmark.measure do
22
+ for i in 1..iterations do
23
+ RubyChem::Chemical.new("H2SO4").fw
24
+ end
25
+ end
26
+
27
+ d = Benchmark.measure do
28
+ for i in 1..iterations do
29
+ RubyChemBeta::Chemical.new("H2SO4")
30
+ end
31
+ end
32
+
33
+ puts a
34
+ puts b
35
+ puts c
36
+ puts d
@@ -0,0 +1,62 @@
1
+ module RubyChem
2
+ class Chemical
3
+
4
+ MASSES = { :H => 1.01, :He => 4.00, :Li => 6.94, :Be => 9.01, :B => 10.81, :C => 12.01, :N => 14.01, :F => 19.00, :Ne => 20.18, :S => 32.01, :O => 15.99,
5
+ :Na => 22.99, :Mg => 24.31, :Al => 26.98, :Si => 28.09, :P => 30.97, :Cl => 35.45, :Ar => 39.95, :K => 39.1, :Ca => 40.08, :Sc => 44.96, :Ti => 47.88, :V => 50.94,
6
+ :Cr => 52.00, :Mn => 54.94, :Fe => 55.85, :Co => 58.93, :Ni => 58.69, :Cu => 63.55, :Zn => 65.39, :Ga => 69.72, :Ge=> 72.61, :As => 74.92, :Se => 78.96,
7
+ :Br => 79.90, :Kr => 83.80, :Rb => 85.47, :Sr => 87.62, :Y => 88.91, :Zr => 91.22, :Nb => 92.91, :Mo => 95.94, :Te => 98, :Ru => 101.07, :Rh => 102.91,
8
+ :Pd => 106.42, :Ag => 107.87, :Cd => 112.41, :In => 114.82, :Sn => 118.71, :Sb => 121.76, :Te => 127.6, :I => 126.9, :Xe => 131.29, :Cs => 132.9, :Ba => 137.3,
9
+ :La => 138.9, :Hf => 178.5, :Ta => 180.9, :W => 183.9, :Re => 186.2, :Os => 190.2, :Ir => 192.2, :Pt => 195.1, :Au => 197.0, :Hg => 200.6, :Ti => 204.4,
10
+ :Pb => 207.2, :Bi => 209, :Po => 209, :At => 210, :Rn => 222, :Fr => 223, :Ra => 226, :Ac => 227, :Rf => 261, :Db => 262, :Sg => 263, :Bh => 264, :Hs => 265,
11
+ :Mt => 268, :Ds => 271, :Rg => 272 }
12
+
13
+ attr_accessor :chem_species, :mm
14
+
15
+ def initialize(formula)
16
+ if formula.scan(/\d+$/) == []
17
+ x = formula.gsub(/$/, '1').scan(/[A-za-z]*\d+/)
18
+ speciate(x)
19
+ else
20
+ x = formula.scan(/[A-za-z]*\d+/)
21
+ speciate(x)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def speciate(x)
28
+ @chem_species = x.map { |chem| chem.scan(/[A-Z][^A-Z]*/) }.flatten
29
+ @chem_species.map! {|chem| chem.scan /[A-Z]+|\d+/i }
30
+ atom_masses = @chem_species.map { |(elem, coeff)| MASSES[elem.to_sym] * (coeff || 1).to_f }
31
+ x = atom_masses.map { |int| int.to_f }
32
+ @mm = x.inject(0) { |s,v| s+= v }
33
+ end
34
+ end
35
+
36
+ class BalanceChem
37
+ attr_accessor :balanced, :lefteq, :righteq, :leftfw, :rightfw, :count
38
+
39
+ ##
40
+ # Checks if two formulas are balanced.
41
+ #
42
+ def initialize(lefteq, righteq)
43
+ @lefteq = lefteq
44
+ @righteq = righteq
45
+ @balanced = ( RubyChem::Chemical.new(@lefteq).mm - RubyChem::Chemical.new(@righteq).mm ).abs < 0.00001
46
+ end
47
+
48
+ def balanceit
49
+ @count = 0
50
+ @leftfw = @leftfw.fw
51
+ @rightfw = @rightfw.fw
52
+ until @balanced == true
53
+ @rightfw = @rightfw * 2
54
+ @balanced = (@leftfw - @rightfw).abs < 0.00001
55
+ @count += 1
56
+ end
57
+ puts "#{@lefteq} (#{@leftfw}) -> #{@righteq} (#{@rightfw}) is a balanced equation; #{@count} iterations"
58
+ end
59
+
60
+
61
+ end
62
+ end
@@ -0,0 +1,98 @@
1
+ module RubyChemOld
2
+ class Chemical
3
+
4
+ MASSES = { :H => 1.01, :He => 4.00, :Li => 6.94, :Be => 9.01, :B => 10.81, :C => 12.01, :N => 14.01, :F => 19.00, :Ne => 20.18, :S => 32.01, :O => 15.99,
5
+ :Na => 22.99, :Mg => 24.31, :Al => 26.98, :Si => 28.09, :P => 30.97, :Cl => 35.45, :Ar => 39.95, :K => 39.1, :Ca => 40.08, :Sc => 44.96, :Ti => 47.88, :V => 50.94,
6
+ :Cr => 52.00, :Mn => 54.94, :Fe => 55.85, :Co => 58.93, :Ni => 58.69, :Cu => 63.55, :Zn => 65.39, :Ga => 69.72, :Ge=> 72.61, :As => 74.92, :Se => 78.96,
7
+ :Br => 79.90, :Kr => 83.80, :Rb => 85.47, :Sr => 87.62, :Y => 88.91, :Zr => 91.22, :Nb => 92.91, :Mo => 95.94, :Te => 98, :Ru => 101.07, :Rh => 102.91,
8
+ :Pd => 106.42, :Ag => 107.87, :Cd => 112.41, :In => 114.82, :Sn => 118.71, :Sb => 121.76, :Te => 127.6, :I => 126.9, :Xe => 131.29, :Cs => 132.9, :Ba => 137.3,
9
+ :La => 138.9, :Hf => 178.5, :Ta => 180.9, :W => 183.9, :Re => 186.2, :Os => 190.2, :Ir => 192.2, :Pt => 195.1, :Au => 197.0, :Hg => 200.6, :Ti => 204.4,
10
+ :Pb => 207.2, :Bi => 209, :Po => 209, :At => 210, :Rn => 222, :Fr => 223, :Ra => 226, :Ac => 227, :Rf => 261, :Db => 262, :Sg => 263, :Bh => 264, :Hs => 265,
11
+ :Mt => 268, :Ds => 271, :Rg => 272 }
12
+
13
+ attr_accessor :chem_species, :mm, :fw
14
+
15
+ def initialize(formula)
16
+ # Checks if the last element is monatomic; adds '1' if it is.
17
+ # This is a comparison, true or false, is there no trailing digit?
18
+ # the scan method is used to iterate through text, scan accepts 1 argument,
19
+ # in this case "match any digit \d, Match one or more occurrences of the preceding character +,
20
+ # anchor for the end of line $"
21
+ if formula.scan(/\d+$/) == []
22
+ # if there is no digit, .gsub adds the trailing digit, 1)
23
+
24
+ # This method scans for the range [A-za-z] and any digit \d, Matching one or more
25
+ # occurrences of the preceding character +
26
+ # so H2SO4 => ["H2, "SO4""]
27
+ x = formula.gsub(/$/, '1').scan(/[A-za-z]*\d+/)
28
+ # Calls the speciate private method, passes the variable x as the argument
29
+ speciate(x)
30
+ else
31
+ x = formula.scan(/[A-za-z]*\d+/)
32
+ speciate(x)
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Calculates the molecular mass.
38
+ #
39
+ def fw
40
+ # .map allows iteration and conversion of elements of an array. .scan will split the array elements between a letter(range A-Z) that matches, and a digit that matches
41
+ # /i makes the whole regex case insensative. ! saves it immediately, from ["H2", "S", "O4"] the result => [["H", "2"], ["S"], ["O", "4"]]
42
+ @chem_species.map! {|chem| chem.scan /[A-Z]+|\d+/i }
43
+ # .map allows iteration and conversion of elements of an array. The current array [["H", "2"], ["S"], ["O", "4"]]
44
+ # is iterated through elem, and coeff. The element is converted to a symbol and is multiplied by the coeff floating point
45
+ # if there is no coefficient 1 is substituted, using (coeff || 1). Result => [2.02, 32.01, 63.96]
46
+ atom_masses = @chem_species.map { |(elem, coeff)| MASSES[elem.to_sym] * (coeff || 1).to_f }
47
+ # Converts all elements within the array to floating point, althought I'm not sure if this is needed.
48
+ x = atom_masses.map { |int| int.to_f }
49
+ # the .inject combines the elements of enum, s = s + v
50
+ @mm = x.inject(0) { |s,v| s+= v }
51
+ end
52
+
53
+ ##
54
+ # Places formula species into an array.
55
+ #
56
+
57
+ private
58
+
59
+ def speciate(x)
60
+ # This method breaks apart chemical compounds into species. It does so by
61
+ # first using the .map method, which allows iteratation and conversion of elements of an array.
62
+ # The elemeonts of the array are modified using the .scan method. Each element of the
63
+ # array is scanned for two consecutive letters, for instance ["H2", "SO4"] is scanned for the range of [A-Z] and an
64
+ # anchor at the beginning of the second character (range [A-Z]) ^. Returns => [["H2"], ["S", "O4"]]
65
+ # The .flatten method returns ["H2", "S", "O4"]
66
+ @chem_species = x.map { |chem| chem.scan(/[A-Z][^A-Z]*/) }.flatten
67
+ end
68
+ end
69
+
70
+ class BalanceChem
71
+ attr_accessor :balanced, :lefteq, :righteq, :leftfw, :rightfw, :count
72
+
73
+ ##
74
+ # Checks if two formulas are balanced.
75
+ #
76
+ def initialize(lefteq, righteq)
77
+ @lefteq = lefteq
78
+ @righteq = righteq
79
+ @leftfw = RubyChem::Chemical.new(@lefteq)
80
+ @rightfw = RubyChem::Chemical.new(@righteq)
81
+ @balanced = ( RubyChem::Chemical.new(@lefteq).fw - RubyChem::Chemical.new(@righteq).fw ).abs < 0.00001
82
+ end
83
+
84
+ def balanceit
85
+ @count = 0
86
+ @leftfw = @leftfw.fw
87
+ @rightfw = @rightfw.fw
88
+ until @balanced == true
89
+ @rightfw = @rightfw * 2
90
+ @balanced = (@leftfw - @rightfw).abs < 0.00001
91
+ @count += 1
92
+ end
93
+ puts "#{@lefteq} (#{@leftfw}) -> #{@righteq} (#{@rightfw}) is a balanced equation; #{@count} iterations"
94
+ end
95
+
96
+
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubychem
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Justin Zollars
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-11-05 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: This is an open source library of chemistry, goodies. I'm dedicating this code to my major professor Arthur Brecher and Graduate PI Dr. Rogers of Bowling Green State University'
22
+ email:
23
+ - justin.zollars@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .DS_Store
32
+ - .gitignore
33
+ - LICENSE
34
+ - README.markdown
35
+ - lib/.DS_Store
36
+ - lib/benchmark.rb
37
+ - lib/beta.rb
38
+ - lib/ruby_chem.rb
39
+ has_rdoc: true
40
+ homepage: http://www.justinzollars.com
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project: rubychem
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A ruby chemistry library
71
+ test_files: []
72
+