001/*
002 * Copyright 2019 nils.hoffmann.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.isas.lipidomics.domain;
017
018import static de.isas.lipidomics.domain.LipidLevel.ISOMERIC_SUBSPECIES;
019import static de.isas.lipidomics.domain.LipidLevel.MOLECULAR_SUBSPECIES;
020import static de.isas.lipidomics.domain.LipidLevel.SPECIES;
021import static de.isas.lipidomics.domain.LipidLevel.STRUCTURAL_SUBSPECIES;
022import lombok.AllArgsConstructor;
023import lombok.Data;
024
025/**
026 * Base class for lipid names parsed using the different grammars. This can
027 * contain a lipid, an adduct, a sum formula and a fragment.
028 *
029 * @author nils.hoffmann
030 * @see LipidSpecies
031 * @see Adduct
032 * @see Fragment
033 */
034@AllArgsConstructor
035@Data
036public class LipidAdduct {
037
038    private LipidSpecies lipid;
039    private Adduct adduct;
040    private Fragment fragment;
041
042    /**
043     * Calculates the mass based on the elements of this lipid adduct.
044     *
045     * @return the mass (in Dalton).
046     */
047    public Double getMass() {
048        ElementTable elements = getElements();
049        int charge = 0;
050        double mass = 0;
051
052        if (adduct != null) {
053            charge = adduct.getCharge();
054        }
055
056        mass = elements.getMass();
057
058        if (charge != 0) {
059            mass = (mass - charge * Element.ELECTRON_REST_MASS) / Math.abs(charge);
060        }
061
062        return mass;
063    }
064
065    /**
066     * Returns the elemental composition table.
067     *
068     * @return the elemental composition table.
069     */
070    public ElementTable getElements() {
071        ElementTable elements = new ElementTable();
072        if (lipid != null) {
073            elements.add(lipid.getElements());
074        }
075        if (adduct != null) {
076            if (lipid != null && lipid.getInfo().isPresent()) {
077                LipidSpeciesInfo info = lipid.getInfo().orElse(LipidSpeciesInfo.NONE);
078                //only add elements on species level or below
079                //higher levels will not return a mass 
080                switch (info.getLevel()) {
081                    case ISOMERIC_SUBSPECIES:
082                    case MOLECULAR_SUBSPECIES:
083                    case STRUCTURAL_SUBSPECIES:
084                    case SPECIES:
085                        elements.add(adduct.getElements());
086                        break;
087                }
088            }
089        }
090        return elements;
091    }
092
093    /**
094     * Returns the sum formula.
095     *
096     * @return the sum formula.
097     */
098    public String getSumFormula() {
099        return getElements().getSumFormula();
100    }
101
102    /**
103     * Returns the non-normalized (original head group) lipid name for the
104     * native level of this lipid.
105     *
106     * @return the non-normalized lipid name with adduct.
107     */
108    public String getLipidString() {
109        if (lipid != null) {
110            return getLipidString(lipid.getInfo().orElse(LipidSpeciesInfo.NONE).getLevel());
111        }
112        return "";
113    }
114
115    /**
116     * Returns the non-normalized (original head group) lipid name for the given
117     * level.
118     *
119     * @param level the lipid level to generate the name on.
120     * @return the non-normalized lipid name with adduct.
121     */
122    public String getLipidString(LipidLevel level) {
123        StringBuilder sb = new StringBuilder();
124        if (lipid != null) {
125            sb.append(lipid.getLipidString(level));
126        } else {
127            return "";
128        }
129
130        if (adduct != null && !adduct.getLipidString().isEmpty()) {
131            sb.append(adduct.getLipidString());
132        }
133        return sb.toString();
134    }
135
136    /**
137     * Returns the normalized (class name as head group) lipid name for the
138     * native level of this lipid.
139     *
140     * @return the normalized lipid name with adduct.
141     */
142    public String getNormalizedLipidString() {
143        if (lipid != null) {
144            return getNormalizedLipidString(lipid.getInfo().orElse(LipidSpeciesInfo.NONE).getLevel());
145        }
146        return "";
147    }
148
149    /**
150     * Returns the normalized (class name as head group) lipid name for the
151     * given level.
152     *
153     * @param level the lipid level to generate the name on.
154     * @return the normalized lipid name with adduct.
155     */
156    public String getNormalizedLipidString(LipidLevel level) {
157        StringBuilder sb = new StringBuilder();
158        if (lipid != null) {
159            sb.append(lipid.getLipidString(level, true));
160        } else {
161            return "";
162        }
163
164        if (adduct != null && !adduct.getLipidString().isEmpty()) {
165            sb.append(adduct.getLipidString());
166        }
167        return sb.toString();
168    }
169
170    /**
171     * Returns the class name for this lipid adduct.
172     *
173     * @return the class name.
174     */
175    public String getClassName() {
176        if (lipid != null) {
177            return lipid.getLipidClass().orElse(LipidClass.UNDEFINED).getAbbreviation();
178        } else {
179            return "";
180        }
181    }
182
183    /**
184     * Returns the non-normalized lipid adduct name (original head group) with
185     * fragment, if available, for the given level.
186     *
187     * @param level the lipid level to generate the name on.
188     * @return the non-normalized lipid name with adduct and fragment.
189     */
190    public String getLipidFragmentString(LipidLevel level) {
191        StringBuilder sb = new StringBuilder();
192        if (lipid != null) {
193            sb.append(getLipidString(level));
194        } else {
195            return "";
196        }
197        if (adduct != null && !adduct.getLipidString().isEmpty()) {
198            sb.append(adduct.getLipidString());
199        }
200        if (fragment != null && !fragment.getLipidString().isEmpty()) {
201            sb.append(" - ").append(fragment.getLipidString());
202        }
203        return sb.toString();
204    }
205
206    /**
207     * Returns the normalized lipid adduct name (class name as head group) with
208     * fragment for the given level.
209     *
210     * @param level the lipid level to generate the name on.
211     * @return the normalized lipid name with adduct and fragment.
212     */
213    public String getNormalizedLipidFragmentString(LipidLevel level) {
214        StringBuilder sb = new StringBuilder();
215        if (lipid != null) {
216            sb.append(getNormalizedLipidString(level));
217        } else {
218            return "";
219        }
220        if (adduct != null && !adduct.getLipidString().isEmpty()) {
221            sb.append(adduct.getLipidString());
222        }
223        if (fragment != null && !fragment.getLipidString().isEmpty()) {
224            sb.append(" - ").append(fragment.getLipidString());
225        }
226        return sb.toString();
227    }
228
229    @Override
230    public String toString() {
231        if (lipid != null) {
232            return getLipidFragmentString(lipid.getInfo().orElse(LipidSpeciesInfo.NONE).getLevel());
233        }
234        return "";
235    }
236
237}