ElementTable.java
/*
* Copyright 2021 Dominik Kopczynski, Nils Hoffmann.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lifstools.jgoslin.domain;
import java.util.EnumMap;
/**
* Accounting table for chemical element frequency. This is used to calculate
* sum formulas and total masses for a given chemical element distribution, e.g.
* in a lipid.
*
* @author Dominik Kopczynski
* @author Nils Hoffmann
*/
public final class ElementTable extends EnumMap<Element, Integer> {
private ElementTable(Class<Element> keyType) {
super(keyType);
}
/**
* Create a new element table.
*/
public ElementTable() {
this(Element.class);
Elements.ELEMENT_MASSES.keySet().forEach(e -> {
put(e, 0);
});
}
/**
* Create a new element table from the provided entries.
* @param entries the entries
* @return a new element table.
*/
public static ElementTable of(Entry<Element, Integer>... entries) {
ElementTable et = new ElementTable();
for (Entry<Element, Integer> e : entries) {
et.put(e.getKey(), e.getValue());
}
return et;
}
/**
* Add all elements and counts to those in this element table.
*
* @param elements the table to add to this one.
*/
public void add(ElementTable elements) {
elements.entrySet().forEach(kv -> {
put(kv.getKey(), get(kv.getKey()) + kv.getValue());
});
}
/**
* Add all alements and counts to those in this element table, but use the
* count argument to multiply count values in the provided table.
*
* @param elements
* @param multiplier
*/
public void add(ElementTable elements, int multiplier) {
elements.entrySet().forEach(kv -> {
put(kv.getKey(), get(kv.getKey()) + kv.getValue() * multiplier);
});
}
/**
* Copy all entries in this element table. The copy will be completely
* independent of this instance.
*
* @return a copy of this element table.
*/
public ElementTable copy() {
ElementTable e = new ElementTable();
entrySet().forEach(kv -> {
e.put(kv.getKey(), kv.getValue());
});
return e;
}
/**
* Returns the sum formula for all elements in this table.
*
* @return the sum formula. Returns an empty string if the table is empty.
*/
public String getSumFormula() {
StringBuilder ss = new StringBuilder();
Elements.ELEMENT_ORDER.stream().map(e -> {
if (get(e) > 0) {
ss.append(Elements.ELEMENT_SHORTCUT.get(e));
}
return e;
}).filter(e -> (get(e) > 1)).forEachOrdered(e -> {
ss.append(get(e));
});
return ss.toString();
}
/**
* Returns the individual total mass for the provided element.
*
* @param element the element to calculate the total mass for.
* @return the total mass for the given element, or 0.
*/
public Double getMass(Element element) {
Integer count = getOrDefault(element, 0);
return count.doubleValue() * Elements.ELEMENT_MASSES.get(element);
}
/**
* Returns the total summed mass per number of elements.
*
* @return the total summed mass for this element table. Returns 0 if the
* table is empty.
*/
public Double getMass() {
return keySet().stream().map((key) -> {
return getMass(key);
}).reduce(0.0d, Double::sum);
}
/**
* Returns the total summed mass per number of elements, corrected for charge counts * electron rest mass.
*
* @param charge the charge of the molecule
* @return the total summed mass for this element table. Returns 0 if the
* table is empty.
*/
public Double getChargedMass(int charge) {
Double mass = getMass();
if (charge != 0) {
mass = (mass - charge * Elements.ELECTRON_REST_MASS) / Math.abs(charge);
}
return mass;
}
}