com.act.lcms.MassCalculator.java Source code

Java tutorial

Introduction

Here is the source code for com.act.lcms.MassCalculator.java

Source

/*************************************************************************
*                                                                        *
*  This file is part of the 20n/act project.                             *
*  20n/act enables DNA prediction for synthetic biology/bioengineering.  *
*  Copyright (C) 2017 20n Labs, Inc.                                     *
*                                                                        *
*  Please direct all queries to act@20n.com.                             *
*                                                                        *
*  This program is free software: you can redistribute it and/or modify  *
*  it under the terms of the GNU General Public License as published by  *
*  the Free Software Foundation, either version 3 of the License, or     *
*  (at your option) any later version.                                   *
*                                                                        *
*  This program is distributed in the hope that it will be useful,       *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*  GNU General Public License for more details.                          *
*                                                                        *
*  You should have received a copy of the GNU General Public License     *
*  along with this program.  If not, see <http://www.gnu.org/licenses/>. *
*                                                                        *
*************************************************************************/

package com.act.lcms;

import com.ggasoftware.indigo.Indigo;
import com.ggasoftware.indigo.IndigoInchi;
import com.ggasoftware.indigo.IndigoObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Adapted from Chris's org.twentyn.services.emerald.IonChooser#calculateMass in the Experimental project.
 *
 * For additional masses and confirmation of the values used below, see
 * http://www.sisweb.com/referenc/tools/exactmass.js (the js that drives
 * http://www.sisweb.com/referenc/tools/exactmass.htm).
 */
public class MassCalculator {
    private static final Indigo indigo = new Indigo();
    private static final IndigoInchi iinchi = new IndigoInchi(indigo);;

    public static Pair<Double, Integer> calculateMassAndCharge(String inchi) {
        IndigoObject mol = iinchi.loadMolecule(inchi);
        Double mass = calculateMass(mol);
        Integer charge = calculateCharge(mol);
        return Pair.of(mass, charge);
    }

    public static Integer calculateCharge(String inchi) {
        return calculateCharge(iinchi.loadMolecule(inchi));
    }

    public static Integer calculateCharge(IndigoObject mol) {
        int out = 0;
        for (int i = 0; i < mol.countAtoms(); i++) {
            IndigoObject atom = mol.getAtom(i);
            int charge = atom.charge();
            out += charge;
        }
        return out;
    }

    public static final Map<String, Double> ATOMIC_WEIGHTS = Collections
            .unmodifiableMap(new HashMap<String, Double>() {
                {
                    put("Ag", 106.905095d);
                    put("Al", 26.981541d);
                    put("Ar", 39.962383d);
                    put("As", 74.921596d);
                    put("Au", 196.966560d);
                    put("B", 11.009305d);
                    put("Ba", 137.905236d);
                    put("Be", 9.012183d);
                    put("Bi", 208.980388d);
                    put("Br", 78.918336d);
                    put("C", 12.000000d);
                    put("Ca", 39.962591d);
                    put("Cd", 113.903361d);
                    put("Ce", 139.905442d);
                    put("Cl", 34.968853d);
                    put("Co", 58.933198d);
                    put("Cr", 51.940510d);
                    put("Cs", 132.905433d);
                    put("Cu", 62.929599d);
                    put("Dy", 163.929183d);
                    put("Er", 165.930305d);
                    put("Eu", 152.921243d);
                    put("F", 18.998403d);
                    put("Fe", 55.934939d);
                    put("Ga", 68.925581d);
                    put("Gd", 157.924111d);
                    put("Ge", 73.921179d);
                    put("H", 1.007825d);
                    put("He", 4.002603d);
                    put("Hf", 179.946561d);
                    put("Hg", 201.970632d);
                    put("Ho", 164.930332d);
                    put("I", 126.904477d);
                    put("In", 114.903875d);
                    put("Ir", 192.962942d);
                    put("K", 38.963708d);
                    put("Kr", 83.911506d);
                    put("La", 138.906355d);
                    put("Li", 7.016005d);
                    put("Lu", 174.940785d);
                    put("Mg", 23.985045d);
                    put("Mn", 54.938046d);
                    put("Mo", 97.905405d);
                    put("N", 14.003074d);
                    put("Na", 22.989770d);
                    put("Nb", 92.906378d);
                    put("Nd", 141.907731d);
                    put("Ne", 19.992439d);
                    put("Ni", 57.935347d);
                    put("O", 15.994915d);
                    put("Os", 191.961487d);
                    put("P", 30.973763d);
                    put("Pb", 207.976641d);
                    put("Pd", 105.903475d);
                    put("Pr", 140.907657d);
                    put("Pt", 194.964785d);
                    put("Rb", 84.911800d);
                    put("Re", 186.955765d);
                    put("Rh", 102.905503d);
                    put("Ru", 101.90434d);
                    put("S", 31.972072d);
                    put("Sb", 120.903824d);
                    put("Sc", 44.955914d);
                    put("Se", 79.916521d);
                    put("Si", 27.976928d);
                    put("Sm", 151.919741d);
                    put("Sn", 119.902199d);
                    put("Sr", 87.905625d);
                    put("Ta", 180.948014d);
                    put("Tb", 158.925350d);
                    put("Te", 129.906229d);
                    put("Th", 232.038054d);
                    put("Ti", 47.947947d);
                    put("Tl", 204.974410d);
                    put("Tm", 168.934225d);
                    put("U", 238.050786d);
                    put("V", 50.943963d);
                    put("W", 183.950953d);
                    put("Xe", 131.904148d);
                    put("Y", 88.905856d);
                    put("Yb", 173.938873d);
                    put("Zn", 63.929145d);
                    put("Zr", 89.904708d);
                }
            });

    public static Double calculateMass(String inchi) {
        return calculateMass(iinchi.loadMolecule(inchi));
    }

    private static final Pattern MOL_COUNT_PATTERN = Pattern.compile("^([A-Za-z]+)(\\d+)?$");

    public static Double calculateMass(IndigoObject mol) {
        String formula = mol.grossFormula();
        double out = 0.0;
        String[] molCounts = StringUtils.split(formula, " ");
        for (String atomEntry : molCounts) {
            //Extract the atom count
            Matcher matcher = MOL_COUNT_PATTERN.matcher(atomEntry);
            if (!matcher.matches()) {
                throw new RuntimeException("Found unexpected malformed atomEntry: " + atomEntry);
            }
            String element = matcher.group(1);
            String countStr = matcher.group(2);

            Integer count = 1;
            if (countStr != null && !countStr.isEmpty()) {
                count = Integer.parseInt(countStr);
            }

            if (!ATOMIC_WEIGHTS.containsKey(element)) {
                throw new RuntimeException("Atomic weights table is missing an expected element: " + element);
            }

            out += ATOMIC_WEIGHTS.get(element) * count.doubleValue();
        }

        // TODO: log difference between mol.molecularWeight(), mol.monoisotopicMass(), and our value.
        return out;
    }

    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            System.err.format("Usage: %s [InChI [...]]\n", MassCalculator.class.getCanonicalName());
            return;
        }

        System.out.format("InChI\tMass\tCharge\n");
        for (String arg : args) {
            Pair<Double, Integer> massCharge = calculateMassAndCharge(arg);
            System.out.format("%s\t%.6f\t%d\n", arg, massCharge.getLeft(), massCharge.getRight());
        }
    }

}