/*************************************************************************
* *
* 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.biointerpretation.networkanalysis;
import com.act.lcms.MS1;
import com.act.lcms.v2.DetectedPeak;
import com.act.lcms.v2.Ion;
import com.act.lcms.v2.IonCalculator;
import com.act.lcms.v2.LcmsIon;
import com.act.lcms.v2.Metabolite;
import com.act.lcms.v2.MolecularStructure;
import com.act.lcms.v2.PeakSpectrum;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.junit.Assert.assertEquals;
/**
* Tests for class PrecursorReport.
*/
public class PrecursorReportTest {
private static final String INCHI_1 = "A";
private static final String INCHI_2 = "B";
private static final Double MASS_1 = 10.0;
private static final Double MASS_2 = 30.0;
private static final Ion MET_1_ION_1 = new LcmsIon(15.0, Mockito.mock(MS1.MetlinIonMass.class));
private static final Ion MET_1_ION_2 = new LcmsIon(20.0, Mockito.mock(MS1.MetlinIonMass.class));
private static final Ion MET_2_ION_1 = new LcmsIon(25.0, Mockito.mock(MS1.MetlinIonMass.class));
private static Metabolite METABOLITE_1;
private static Metabolite METABOLITE_2;
private static List<NetworkNode> nodes = new ArrayList<>();
private static Map<String, Integer> inchiToID = new HashMap<>();
private static final Double MASS_TOLERANCE = 0.01;
private static final Set<String> ions = new HashSet<String>() {{
add("M+H");
add("M+Na");
}};
private static final List<DetectedPeak> NO_PEAKS = Collections.EMPTY_LIST;
private static final List<DetectedPeak> SOME_PEAKS = new ArrayList<DetectedPeak>() {{
add(Mockito.mock(DetectedPeak.class));
}};
private IonCalculator mockIonCalculator = Mockito.mock(IonCalculator.class);
@Before
public void createMockNodes() {
METABOLITE_1 = getMockMetabolite(INCHI_1, MASS_1);
METABOLITE_2 = getMockMetabolite(INCHI_2, MASS_2);
Mockito.when(mockIonCalculator.getSelectedIons(METABOLITE_1, ions, MS1.IonMode.POS)).thenReturn(
Arrays.asList(MET_1_ION_1, MET_1_ION_2));
Mockito.when(mockIonCalculator.getSelectedIons(METABOLITE_2, ions, MS1.IonMode.POS)).thenReturn(
Arrays.asList(MET_2_ION_1));
nodes.add(new NetworkNode(METABOLITE_1));
nodes.add(new NetworkNode(METABOLITE_2));
nodes.forEach(n -> inchiToID.put(n.getMetabolite().getStructure().get().getInchi(), n.getUID()));
}
private Metabolite getMockMetabolite(String s, double mass) {
MolecularStructure structure = Mockito.mock(MolecularStructure.class);
Mockito.when(structure.getInchi()).thenReturn(s);
Mockito.when(structure.getMonoIsotopicMass()).thenReturn(mass);
Metabolite m = Mockito.mock(Metabolite.class);
Mockito.when(m.getStructure()).thenReturn(Optional.of(structure));
Mockito.when(m.getMonoIsotopicMass()).thenReturn(mass);
return m;
}
/**
* Ensures that the process of matching peaks from a PeakSpectrum to nodes in a PrecursorReport is done properly.
* If any of a node's ions matches a peak, it should come out as a hit.
* if none of a node's ions match any peak, it should come out as a miss.
*/
@Test
public void testAddLcmsData() {
// Arrange
MetabolismNetwork network = new MetabolismNetwork();
nodes.forEach(network::addNode);
network.addEdgeFromInchis(Arrays.asList(INCHI_1), Arrays.asList(INCHI_2));
NetworkNode node1 = network.getNodeByInchi(INCHI_1);
NetworkNode node2 = network.getNodeByInchi(INCHI_2);
PrecursorReport report = network.getPrecursorReport(node2, 1);
PeakSpectrum spectrum = Mockito.mock(PeakSpectrum.class);
Mockito.when(spectrum.getPeaksByMZ(Mockito.any(), Mockito.any())).thenReturn(NO_PEAKS);
Mockito.when(spectrum.getPeaksByMZ(MET_1_ION_1.getMzValue(), 1.0)).thenReturn(SOME_PEAKS);
// Act
report.addLcmsData(spectrum, mockIonCalculator, ions);
// Assert
assertEquals("Metabolite 1, matching at one ion, is positive.", new Double(1.0), report.getLcmsConfidence(node1));
assertEquals("Metabolite 2, matching at no ions, is negative.", new Double(0.0), report.getLcmsConfidence(node2));
}
}