asciichem 0.3.1 → 0.3.3

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,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f025579767518b2551359a0817e2019c19bec299f0a7c77c16264dd98342df25
4
- data.tar.gz: c092bfffa44620c0bb2ef20abdba849732eaaaa01ae2f0039bf8c22a4d57baad
3
+ metadata.gz: 9dcc9efdb2f096fa1b8e71fa12f23df5ff2c7246d017d71fe3cf87309ed65504
4
+ data.tar.gz: f64ddf08f74a2c38fcce98bae1cd4010b4ae55ede0f38bbf0f248fea475dead6
5
5
  SHA512:
6
- metadata.gz: 63957c098bb2df1785ce770d6e375c1f54c771e847f01f7de5b03cfd88a4321cf9c6abd6d93c5a5b6f43b1239887f1da80ec48d46d62351071ab25632bfd766f
7
- data.tar.gz: 82f5b7dda4a1f9461e5fe68dfc8566328ab2a4541101b33605582620be59651b61f358a7053e3361b5022587d3dc83be4ad1039615673076a492167025321fa0
6
+ metadata.gz: 283b735f960be1ab4cc2f3d4b98977dc8ef49dab16e19305ab64cd5054ac09a6f69e942c56a93705c48f6e9710ecf7c3e6f462bdd12e0a0081a58eea8b7bc8aa
7
+ data.tar.gz: 2c9d3f021372984bd52177269bcae201f2b176393883c774533232a2e21b3498e083d2874b1ccb1c06a8d6596cf8d309c88aed2fd457e92b8a0b6c78ea714423
@@ -23,6 +23,8 @@ module AsciiChem
23
23
  translation = AsciiChem::ModelAdapter.to_canonical_with_mapping(formula)
24
24
  xml = translation.document.to_xml
25
25
  xml = inject_atom_extensions(xml, translation.atom_mapping)
26
+ xml = inject_reaction_conditions(xml, formula)
27
+ xml = inject_metadata(xml, formula)
26
28
  inject_molecule_extensions(xml, formula, translation)
27
29
  end
28
30
 
@@ -31,10 +33,14 @@ module AsciiChem
31
33
  top_level = Extensions.extract_top_level(xml)
32
34
  atom_extensions = Extensions.extract(xml)
33
35
  group_extensions = GroupExtensions.extract(xml)
36
+ metadata_map = extract_metadata(xml)
37
+ reaction_conditions = extract_reaction_conditions(xml)
34
38
  wire_doc = Chemicalml::Cml::Document.from_xml(xml)
35
39
  formula = AsciiChem::ModelAdapter.from_canonical(wire_doc)
36
40
  Extensions.restore(formula, wire_doc, atom_extensions)
37
41
  GroupExtensions.restore(formula, wire_doc, group_extensions)
42
+ restore_reaction_conditions(formula, reaction_conditions)
43
+ restore_metadata(formula, metadata_map)
38
44
  Extensions.restore_top_level(formula, top_level)
39
45
  formula
40
46
  end
@@ -57,6 +63,120 @@ module AsciiChem
57
63
  Extensions.inject(xml, extensions)
58
64
  end
59
65
 
66
+ # Inject reaction conditions via aci: attributes. Each Reaction
67
+ # in the formula with conditions produces aci:conditionsAbove
68
+ # and aci:conditionsBelow attributes on its <reaction> element.
69
+ def inject_reaction_conditions(xml, formula)
70
+ require 'nokogiri'
71
+ doc = Nokogiri::XML(xml)
72
+ root = doc.root
73
+ reactions = formula.nodes.select { |n| n.is_a?(AsciiChem::Model::Reaction) }
74
+ return xml if reactions.empty?
75
+
76
+ root.add_namespace(Extensions::PREFIX, Extensions::NAMESPACE) unless root.namespaces.value?(Extensions::NAMESPACE)
77
+ reactions.each_with_index do |reaction, idx|
78
+ next unless reaction.conditions
79
+
80
+ reaction_el = root.at_xpath("//cml:reaction[@id='r#{idx + 1}']", cml: Extensions::CML_NS)
81
+ next unless reaction_el
82
+
83
+ reaction_el["#{Extensions::PREFIX}:conditionsAbove"] = reaction.conditions.above if reaction.conditions.above
84
+ reaction_el["#{Extensions::PREFIX}:conditionsBelow"] = reaction.conditions.below if reaction.conditions.below
85
+ end
86
+ doc.to_xml
87
+ end
88
+
89
+ def extract_reaction_conditions(xml)
90
+ require 'nokogiri'
91
+ doc = Nokogiri::XML(xml)
92
+ result = {}
93
+ doc.xpath("//cml:reaction", cml: Extensions::CML_NS).each do |el|
94
+ id = el['id']
95
+ next unless id
96
+
97
+ above = el["#{Extensions::PREFIX}:conditionsAbove"]
98
+ below = el["#{Extensions::PREFIX}:conditionsBelow"]
99
+ result[id] = { above: above, below: below } if above || below
100
+ end
101
+ result
102
+ end
103
+
104
+ def restore_reaction_conditions(formula, conditions)
105
+ return formula if conditions.empty?
106
+
107
+ formula.nodes.each_with_index do |node, idx|
108
+ next unless node.is_a?(AsciiChem::Model::Reaction)
109
+
110
+ data = conditions["r#{idx + 1}"]
111
+ next unless data
112
+
113
+ node.conditions = AsciiChem::Model::Reaction::Conditions.new(
114
+ above: data[:above],
115
+ below: data[:below]
116
+ )
117
+ end
118
+ formula
119
+ end
120
+
121
+ # Inject molecule metadata via aci: attributes on <molecule>.
122
+ # Each {name: "k", content: "v"} produces aci:meta-k="v".
123
+ def inject_metadata(xml, formula)
124
+ require 'nokogiri'
125
+ doc = Nokogiri::XML(xml)
126
+ root = doc.root
127
+ molecules = formula.nodes.select { |n| n.is_a?(AsciiChem::Model::Molecule) }
128
+ has_meta = molecules.any? { |m| !m.metadata.empty? }
129
+ return xml unless has_meta
130
+
131
+ root.add_namespace(Extensions::PREFIX, Extensions::NAMESPACE) unless root.namespaces.value?(Extensions::NAMESPACE)
132
+ molecules.each_with_index do |mol, idx|
133
+ next if mol.metadata.empty?
134
+
135
+ mol_el = root.at_xpath("//cml:molecule[@id='m#{idx + 1}']", cml: Extensions::CML_NS)
136
+ next unless mol_el
137
+
138
+ mol.metadata.each do |m|
139
+ mol_el["#{Extensions::PREFIX}:meta-#{m[:name]}"] = m[:content]
140
+ end
141
+ end
142
+ doc.to_xml
143
+ end
144
+
145
+ def extract_metadata(xml)
146
+ require 'nokogiri'
147
+ doc = Nokogiri::XML(xml)
148
+ result = {}
149
+ doc.xpath("//cml:molecule", cml: Extensions::CML_NS).each do |el|
150
+ id = el['id']
151
+ next unless id
152
+
153
+ meta = {}
154
+ el.attributes.each do |name, attr|
155
+ next unless name.start_with?('meta-')
156
+ next unless attr.namespace && attr.namespace.prefix == Extensions::PREFIX
157
+
158
+ key = name.sub('meta-', '')
159
+ meta[key] = attr.value
160
+ end
161
+ result[id] = meta unless meta.empty?
162
+ end
163
+ result
164
+ end
165
+
166
+ def restore_metadata(formula, metadata_map)
167
+ return formula if metadata_map.empty?
168
+
169
+ formula.nodes.each_with_index do |node, idx|
170
+ next unless node.is_a?(AsciiChem::Model::Molecule)
171
+
172
+ meta = metadata_map["m#{idx + 1}"]
173
+ next unless meta
174
+
175
+ meta.each { |name, content| node.metadata << { name: name, content: content } }
176
+ end
177
+ formula
178
+ end
179
+
60
180
  def inject_molecule_extensions(xml, formula, translation)
61
181
  xml = inject_groups(xml, formula, translation)
62
182
  inject_top_level(xml, formula)
@@ -104,7 +104,7 @@ module AsciiChem
104
104
  canonical_properties.map do |p|
105
105
  {
106
106
  title: p.title,
107
- value: extract_scalar_value(p.value),
107
+ value: extract_scalar_value(p.scalar),
108
108
  dict_ref: p.dict_ref,
109
109
  convention: p.convention
110
110
  }
@@ -113,7 +113,7 @@ module AsciiChem
113
113
 
114
114
  def extract_scalar_value(value)
115
115
  return nil if value.nil?
116
- return value.value if value.is_a?(Chemicalml::Cml::Scalar)
116
+ return value.content if value.is_a?(Chemicalml::Cml::Scalar)
117
117
 
118
118
  value.to_s
119
119
  end
@@ -130,7 +130,7 @@ module AsciiChem
130
130
  properties.map do |p|
131
131
  Chemicalml::Cml::Property.new(
132
132
  title: p[:title],
133
- value: build_scalar(p[:value]),
133
+ scalar: build_scalar(p[:value]),
134
134
  dict_ref: p[:dict_ref],
135
135
  convention: p[:convention]
136
136
  )
@@ -141,7 +141,7 @@ module AsciiChem
141
141
  return nil if value.nil?
142
142
 
143
143
  Chemicalml::Cml::Scalar.new(
144
- value: value.to_s,
144
+ content: value.to_s,
145
145
  dict_ref: nil
146
146
  )
147
147
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AsciiChem
4
- VERSION = "0.3.1"
4
+ VERSION = "0.3.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciichem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.