Class: Chemicalml::Cml::Translator

Inherits:
Object
  • Object
show all
Extended by:
ValueTranslations::ClassMethods
Defined in:
lib/chemicalml/cml/translator.rb,
lib/chemicalml/cml/translator/value_translations.rb

Overview

Adapter between the canonical Chemicalml::Model and the CML XML wire-format layer (Chemicalml::Cml::* lutaml-model classes).

Pure transformation. No I/O. Two class methods, one per direction. Adding a new CML element means updating the translator's mapping rules; the canonical classes and the CML wire classes stay independent.

Defined Under Namespace

Modules: ValueTranslations

Constant Summary collapse

ORDER_TO_KIND =

-- Lookup tables -----------------------------------------------

{
  "S" => :single, "D" => :double, "T" => :triple,
  "Q" => :quadruple, "A" => :aromatic, "W" => :wedge,
  "H" => :hash, "DG" => :dative, "V" => :wavy
}.freeze
TYPE_TO_ARROW =
{
  "forward" => :forward,
  "reverse" => :reverse,
  "equilibrium" => :equilibrium,
  "resonance" => :resonance
}.freeze

Class Method Summary collapse

Methods included from ValueTranslations::ClassMethods

array_from_canonical, array_to_canonical, formula_from_canonical, formula_to_canonical, label_from_canonical, label_to_canonical, matrix_from_canonical, matrix_to_canonical, metadata_from_canonical, metadata_to_canonical, parameter_from_canonical, parameter_to_canonical, property_from_canonical, property_to_canonical, scalar_from_canonical, scalar_to_canonical, value_container_from_canonical, value_container_to_canonical

Class Method Details

.atom_from_canonical(atom) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/chemicalml/cml/translator.rb', line 142

def self.atom_from_canonical(atom)
  Cml::Atom.new(
    id: atom.id,
    element_type: atom.element,
    formal_charge: atom.formal_charge,
    isotope: atom.isotope,
    count: atom.count,
    hydrogen_count: atom.hydrogen_count,
    spin_multiplicity: atom.spin_multiplicity,
    title: atom.title
  )
end

.atom_to_canonical(cml_atom) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/chemicalml/cml/translator.rb', line 59

def self.atom_to_canonical(cml_atom)
  Model::Atom.new(
    id: cml_atom.id,
    element: cml_atom.element_type,
    formal_charge: cml_atom.formal_charge,
    isotope: cml_atom.isotope,
    count: cml_atom.count,
    hydrogen_count: cml_atom.hydrogen_count,
    spin_multiplicity: cml_atom.spin_multiplicity,
    title: cml_atom.title
  )
end

.bond_from_canonical(bond) ⇒ Object



155
156
157
158
159
160
161
# File 'lib/chemicalml/cml/translator.rb', line 155

def self.bond_from_canonical(bond)
  Cml::Bond.new(
    id: bond.id,
    atom_refs2: bond.atom_refs.join(" "),
    order: bond.cml_order
  )
end

.bond_to_canonical(cml_bond) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/chemicalml/cml/translator.rb', line 72

def self.bond_to_canonical(cml_bond)
  Model::Bond.new(
    id: cml_bond.id,
    atom_refs: cml_bond.atom_refs2&.split(" ") || [],
    kind: cml_order_to_kind(cml_bond.order)
  )
end

.from_canonical(document, schema: :schema3) ⇒ Object

Canonical -> CML wire format. schema: selects the target version (:schema3 default, or :schema24).



26
27
28
29
30
31
32
# File 'lib/chemicalml/cml/translator.rb', line 26

def self.from_canonical(document, schema: :schema3)
  wire_class = document_class_for(schema)
  wire_class.new(
    molecules: document.molecules.map { |m| molecule_from_canonical(m) },
    reactions: document.reactions.map { |r| reaction_from_canonical(r) }
  )
end

.molecule_from_canonical(mol) ⇒ Object

-- Canonical -> CML --------------------------------------------



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/chemicalml/cml/translator.rb', line 125

def self.molecule_from_canonical(mol)
  Cml::Molecule.new(
    id: mol.id,
    atom_array: mol.atoms.empty? ? nil : Cml::AtomArray.new(
      atoms: mol.atoms.map { |a| atom_from_canonical(a) }
    ),
    bond_array: mol.bonds.empty? ? nil : Cml::BondArray.new(
      bonds: mol.bonds.map { |b| bond_from_canonical(b) }
    ),
    names: mol.names.map { |n| Cml::Name.new(content: n.content, convention: n.convention, dict_ref: n.dict_ref) },
    identifiers: mol.identifiers.map { |i| Cml::Identifier.new(value: i.value, convention: i.convention, dict_ref: i.dict_ref) },
    count: mol.count,
    formal_charge: mol.formal_charge,
    title: mol.title
  )
end

.molecule_to_canonical(cml_mol) ⇒ Object

-- CML -> canonical --------------------------------------------



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/chemicalml/cml/translator.rb', line 46

def self.molecule_to_canonical(cml_mol)
  Model::Molecule.new(
    id: cml_mol.id,
    atoms: cml_mol.atom_array&.atoms&.map { |a| atom_to_canonical(a) } || [],
    bonds: cml_mol.bond_array&.bonds&.map { |b| bond_to_canonical(b) } || [],
    names: cml_mol.names.map { |n| Model::Name.new(content: n.content, convention: n.convention, dict_ref: n.dict_ref) },
    identifiers: cml_mol.identifiers.map { |i| Model::Identifier.new(value: i.value, convention: i.convention, dict_ref: i.dict_ref) },
    count: cml_mol.count,
    formal_charge: cml_mol.formal_charge,
    title: cml_mol.title
  )
end

.product_list_from_canonical(list) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/chemicalml/cml/translator.rb', line 187

def self.product_list_from_canonical(list)
  Cml::ProductList.new(
    products: list.products.map do |p|
      Cml::Product.new(
        substance: Cml::Substance.new(
          molecule: molecule_from_canonical(p.substance.molecule),
          title: p.substance.title,
          role: p.substance.role
        )
      )
    end
  )
end

.product_list_to_canonical(cml_list) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/chemicalml/cml/translator.rb', line 107

def self.product_list_to_canonical(cml_list)
  return Model::ProductList.new unless cml_list

  Model::ProductList.new(
    products: cml_list.products.map do |p|
      Model::Product.new(
        substance: Model::Substance.new(
          molecule: molecule_to_canonical(p.substance.molecule),
          title: p.substance.title,
          role: p.substance.role
        )
      )
    end
  )
end

.reactant_list_from_canonical(list) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/chemicalml/cml/translator.rb', line 173

def self.reactant_list_from_canonical(list)
  Cml::ReactantList.new(
    reactants: list.reactants.map do |r|
      Cml::Reactant.new(
        substance: Cml::Substance.new(
          molecule: molecule_from_canonical(r.substance.molecule),
          title: r.substance.title,
          role: r.substance.role
        )
      )
    end
  )
end

.reactant_list_to_canonical(cml_list) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/chemicalml/cml/translator.rb', line 91

def self.reactant_list_to_canonical(cml_list)
  return Model::ReactantList.new unless cml_list

  Model::ReactantList.new(
    reactants: cml_list.reactants.map do |r|
      Model::Reactant.new(
        substance: Model::Substance.new(
          molecule: molecule_to_canonical(r.substance.molecule),
          title: r.substance.title,
          role: r.substance.role
        )
      )
    end
  )
end

.reaction_from_canonical(rxn) ⇒ Object



163
164
165
166
167
168
169
170
171
# File 'lib/chemicalml/cml/translator.rb', line 163

def self.reaction_from_canonical(rxn)
  Cml::Reaction.new(
    id: rxn.id,
    title: rxn.title || rxn.arrow.to_s,
    type: rxn.type || rxn.arrow.to_s,
    reactant_list: reactant_list_from_canonical(rxn.reactant_list),
    product_list: product_list_from_canonical(rxn.product_list)
  )
end

.reaction_to_canonical(cml_rxn) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/chemicalml/cml/translator.rb', line 80

def self.reaction_to_canonical(cml_rxn)
  Model::Reaction.new(
    id: cml_rxn.id,
    reactant_list: reactant_list_to_canonical(cml_rxn.reactant_list),
    product_list: product_list_to_canonical(cml_rxn.product_list),
    arrow: type_to_arrow(cml_rxn.type || cml_rxn.title),
    title: cml_rxn.title,
    type: cml_rxn.type
  )
end

.to_canonical(document) ⇒ Object

CML wire format -> canonical. Accepts either Schema3 or Schema24 wire documents; dispatches based on class.



17
18
19
20
21
22
# File 'lib/chemicalml/cml/translator.rb', line 17

def self.to_canonical(document)
  Model::Document.new(
    molecules: document.molecules.map { |m| molecule_to_canonical(m) },
    reactions: document.reactions.map { |r| reaction_to_canonical(r) }
  )
end