From 6ee824f7f46d7a2c630ab9c386bd9df9f63299a8 Mon Sep 17 00:00:00 2001 From: Nicole Deflaux Date: Wed, 29 Jul 2015 13:58:01 -0700 Subject: [PATCH] Add VariantSimilarity integration test. Also refactored reusable integration test helper code. --- .../dataflow/functions/PCoAnalysis.java | 11 ++ .../dataflow/pipelines/CountReadsITCase.java | 144 +++++++----------- .../pipelines/IntegrationTestHelper.java | 95 ++++++++++++ .../pipelines/VariantSimilarityITCase.java | 141 +++++++++++++++++ 4 files changed, 298 insertions(+), 93 deletions(-) create mode 100644 src/test/java/com/google/cloud/genomics/dataflow/pipelines/IntegrationTestHelper.java create mode 100644 src/test/java/com/google/cloud/genomics/dataflow/pipelines/VariantSimilarityITCase.java diff --git a/src/main/java/com/google/cloud/genomics/dataflow/functions/PCoAnalysis.java b/src/main/java/com/google/cloud/genomics/dataflow/functions/PCoAnalysis.java index 26c3055..3f493d9 100644 --- a/src/main/java/com/google/cloud/genomics/dataflow/functions/PCoAnalysis.java +++ b/src/main/java/com/google/cloud/genomics/dataflow/functions/PCoAnalysis.java @@ -17,6 +17,7 @@ package com.google.cloud.genomics.dataflow.functions; import com.google.api.client.util.Lists; +import com.google.api.client.util.Preconditions; import com.google.cloud.dataflow.sdk.transforms.DoFn; import com.google.cloud.dataflow.sdk.values.KV; import com.google.common.collect.BiMap; @@ -71,6 +72,16 @@ public GraphResult(String name, double x, double y) { @Override public String toString() { return String.format("%s\t\t%s\t%s", name, graphX, graphY); } + + public static GraphResult fromString(String tsv) { + Preconditions.checkNotNull(tsv); + String[] tokens = tsv.split("[\\s\t]+"); + Preconditions.checkState(3 == tokens.length, + "Expected three values in serialized GraphResult but found %d", tokens.length); + return new GraphResult(tokens[0], + Double.parseDouble(tokens[1]), + Double.parseDouble(tokens[2])); + } } private static final PCoAnalysis INSTANCE = new PCoAnalysis(); diff --git a/src/test/java/com/google/cloud/genomics/dataflow/pipelines/CountReadsITCase.java b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/CountReadsITCase.java index 72a1047..b20c6a5 100644 --- a/src/test/java/com/google/cloud/genomics/dataflow/pipelines/CountReadsITCase.java +++ b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/CountReadsITCase.java @@ -15,103 +15,83 @@ */ package com.google.cloud.genomics.dataflow.pipelines; -import com.google.api.services.storage.Storage; -import com.google.cloud.dataflow.sdk.options.GcsOptions; -import com.google.cloud.dataflow.sdk.options.PipelineOptions; -import com.google.cloud.dataflow.sdk.options.PipelineOptionsFactory; -import com.google.cloud.dataflow.sdk.util.GcsUtil; -import com.google.cloud.dataflow.sdk.util.Transport; -import com.google.cloud.dataflow.sdk.util.gcsfs.GcsPath; -import com.google.cloud.genomics.dataflow.utils.GenomicsOptions; +import java.io.BufferedReader; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Writer; -import java.nio.channels.Channels; -import java.security.GeneralSecurityException; - /** - * This test expects you to have: - * -a Google Cloud API key in the GOOGLE_API_KEY environment variable, - * -your Google Cloud project name in TEST_PROJECT, - * -a GCS folder path in TEST_OUTPUT_GCS_FOLDER to store temporary test outputs, - * -a GCS folder path in TEST_STAGING_GCS_FOLDER to store temporary files, - * GCS folder paths should be of the form "gs://bucket/folder/" + * This integration test will read and write to Cloud Storage, and call the Genomics API. * - * This test will read and write to GCS, and call the Genomics API. + * The following environment variables are required: + * - a Google Cloud API key in GOOGLE_API_KEY, + * - a Google Cloud project name in TEST_PROJECT, + * - a Cloud Storage folder path in TEST_OUTPUT_GCS_FOLDER to store temporary test outputs, + * - a Cloud Storage folder path in TEST_STAGING_GCS_FOLDER to store temporary files, + * + * Cloud Storage folder paths should be of the form "gs://bucket/folder/" * * When doing e.g. mvn install, you can skip integration tests using: - * mvn install -DskipITs + * mvn install -DskipITs + * + * To run one test: + * mvn -Dit.test=CountReadsITCase#testLocal verify + * + * See also http://maven.apache.org/surefire/maven-failsafe-plugin/examples/single-test.html */ @RunWith(JUnit4.class) public class CountReadsITCase { - final String API_KEY = System.getenv("GOOGLE_API_KEY"); - final String TEST_PROJECT = System.getenv("TEST_PROJECT"); - final String TEST_OUTPUT_GCS_FOLDER = System.getenv("TEST_OUTPUT_GCS_FOLDER"); - final String TEST_STAGING_GCS_FOLDER = System.getenv("TEST_STAGING_GCS_FOLDER"); // This file shouldn't move. - final String TEST_BAM_FNAME = "gs://genomics-public-data/ftp-trace.ncbi.nih.gov/1000genomes/ftp/pilot_data/data/NA06985/alignment/NA06985.454.MOSAIK.SRP000033.2009_11.bam"; + static final String TEST_BAM_FNAME = "gs://genomics-public-data/ftp-trace.ncbi.nih.gov/1000genomes/ftp/pilot_data/data/NA06985/alignment/NA06985.454.MOSAIK.SRP000033.2009_11.bam"; // This is the Readgroupset ID of the same file, in ReadStore. It also shouldn't move. - final String TEST_READGROUPSET = "CMvnhpKTFhDvp9zAvYj66AY"; + static final String TEST_READGROUPSET = "CMvnhpKTFhDvp9zAvYj66AY"; // The region where we're counting reads. - final String TEST_CONTIG = "1:550000:560000"; + static final String TEST_CONTIG = "1:550000:560000"; // How many reads are in that region. - final long TEST_EXPECTED = 685; + static final long TEST_EXPECTED = 685; // In this file there are no unmapped reads, so expecting the same number. - final long TEST_EXPECTED_WITH_UNMAPPED = TEST_EXPECTED; + static final long TEST_EXPECTED_WITH_UNMAPPED = TEST_EXPECTED; // Same as the above variables, but for the NA12877_S1 dataset. - final String NA12877_S1_BAM_FILENAME = "gs://genomics-public-data/platinum-genomes/bam/NA12877_S1.bam"; - final String NA12877_S1_READGROUPSET = "CMvnhpKTFhD3he72j4KZuyc"; - final String NA12877_S1_CONTIG = "chr17:41196311:41277499"; - final long NA12877_S1_EXPECTED = 45081; + static final String NA12877_S1_BAM_FILENAME = "gs://genomics-public-data/platinum-genomes/bam/NA12877_S1.bam"; + static final String NA12877_S1_READGROUPSET = "CMvnhpKTFhD3he72j4KZuyc"; + static final String NA12877_S1_CONTIG = "chr17:41196311:41277499"; + static final long NA12877_S1_EXPECTED = 45081; // How many reads are in that region if we take unmapped ones too - final long NA12877_S1_EXPECTED_WITH_UNMAPPED = 45142; - - @Before - public void voidEnsureEnvVar() { - Assert.assertNotNull("You must set the GOOGLE_API_KEY environment variable for this test.", API_KEY); - Assert.assertNotNull("You must set the TEST_PROJECT environment variable for this test.", TEST_PROJECT); - Assert.assertNotNull("You must set the TEST_OUTPUT_GCS_FOLDER environment variable for this test.", TEST_OUTPUT_GCS_FOLDER); - Assert.assertTrue("TEST_OUTPUT_GCS_FOLDER must end with '/'", TEST_OUTPUT_GCS_FOLDER.endsWith("/")); - Assert.assertTrue("TEST_OUTPUT_GCS_FOLDER must start with 'gs://'", TEST_OUTPUT_GCS_FOLDER.startsWith("gs://")); - Assert.assertNotNull("You must set the TEST_STAGING_GCS_FOLDER environment variable for this test.", TEST_STAGING_GCS_FOLDER); - Assert.assertTrue("TEST_STAGING_GCS_FOLDER must start with 'gs://'", TEST_STAGING_GCS_FOLDER.startsWith("gs://")); - // we don't care how TEST_STAGING_GCS_FOLDER ends, so no check for it. + static final long NA12877_S1_EXPECTED_WITH_UNMAPPED = 45142; + + static IntegrationTestHelper helper; + + @BeforeClass + public static void setUpBeforeClass() { + helper = new IntegrationTestHelper(); } private void testLocalBase(String outputFilename, String contig, String bamFilename, long expectedCount, boolean includeUnmapped) throws Exception { - final String OUTPUT = TEST_OUTPUT_GCS_FOLDER + outputFilename; + final String OUTPUT = helper.TEST_OUTPUT_GCS_FOLDER + outputFilename; String[] ARGS = { - "--apiKey=" + API_KEY, - "--project=" + TEST_PROJECT, + "--apiKey=" + helper.API_KEY, "--output=" + OUTPUT, "--references=" + contig, "--includeUnmapped=" + includeUnmapped, "--BAMFilePath=" + bamFilename, }; - GenomicsOptions popts = PipelineOptionsFactory.create().as(GenomicsOptions.class); - popts.setApiKey(API_KEY); - GcsUtil gcsUtil = new GcsUtil.GcsUtilFactory().create(popts); try { - touchOutput(gcsUtil, OUTPUT); + helper.touchOutput(OUTPUT); CountReads.main(ARGS); - BufferedReader reader = new BufferedReader(Channels.newReader(gcsUtil.open(GcsPath.fromUri(OUTPUT)), "UTF-8")); + BufferedReader reader = helper.openOutput(OUTPUT); long got = Long.parseLong(reader.readLine()); Assert.assertEquals(expectedCount, got); } finally { - GcsDelete(popts, OUTPUT); + helper.deleteOutput(OUTPUT); } } @@ -144,31 +124,28 @@ public void testLocalNA12877_S1_UNMAPPED() throws Exception { } private void testCloudBase(String outputFilename, String contig, String bamFilename, long expectedCount) throws Exception { - final String OUTPUT = TEST_OUTPUT_GCS_FOLDER + outputFilename; + final String OUTPUT = helper.TEST_OUTPUT_GCS_FOLDER + outputFilename; String[] ARGS = { - "--apiKey=" + API_KEY, - "--project=" + TEST_PROJECT, + "--apiKey=" + helper.API_KEY, + "--project=" + helper.TEST_PROJECT, "--output=" + OUTPUT, "--numWorkers=2", "--runner=BlockingDataflowPipelineRunner", - "--stagingLocation=" + TEST_STAGING_GCS_FOLDER, + "--stagingLocation=" + helper.TEST_STAGING_GCS_FOLDER, "--references=" + contig, "--BAMFilePath=" + bamFilename }; - GenomicsOptions popts = PipelineOptionsFactory.create().as(GenomicsOptions.class); - popts.setApiKey(API_KEY); - GcsUtil gcsUtil = new GcsUtil.GcsUtilFactory().create(popts); try { - touchOutput(gcsUtil, OUTPUT); + helper.touchOutput(OUTPUT); CountReads.main(ARGS); - BufferedReader reader = new BufferedReader(Channels.newReader(gcsUtil.open(GcsPath.fromUri(OUTPUT)), "UTF-8")); + BufferedReader reader = helper.openOutput(OUTPUT); long got = Long.parseLong(reader.readLine()); Assert.assertEquals(expectedCount, got); } finally { - GcsDelete(popts, OUTPUT); + helper.deleteOutput(OUTPUT); } } @@ -188,31 +165,28 @@ public void testCloudNA12877_S1() throws Exception { } public void testCloudWithAPIBase(String outputFilename, String contig, String readGroupSetId, long expectedCount) throws Exception { - final String OUTPUT = TEST_OUTPUT_GCS_FOLDER + outputFilename; + final String OUTPUT = helper.TEST_OUTPUT_GCS_FOLDER + outputFilename; String[] ARGS = { - "--apiKey=" + API_KEY, - "--project=" + TEST_PROJECT, + "--apiKey=" + helper.API_KEY, + "--project=" + helper.TEST_PROJECT, "--output=" + OUTPUT, "--numWorkers=2", "--runner=BlockingDataflowPipelineRunner", - "--stagingLocation=" + TEST_STAGING_GCS_FOLDER, + "--stagingLocation=" + helper.TEST_STAGING_GCS_FOLDER, "--references=" + contig, "--readGroupSetId=" + readGroupSetId }; - GenomicsOptions popts = PipelineOptionsFactory.create().as(GenomicsOptions.class); - popts.setApiKey(API_KEY); - GcsUtil gcsUtil = new GcsUtil.GcsUtilFactory().create(popts); try { - touchOutput(gcsUtil, OUTPUT); + helper.touchOutput(OUTPUT); CountReads.main(ARGS); - BufferedReader reader = new BufferedReader(Channels.newReader(gcsUtil.open(GcsPath.fromUri(OUTPUT)), "UTF-8")); + BufferedReader reader = helper.openOutput(OUTPUT); long got = Long.parseLong(reader.readLine()); Assert.assertEquals(expectedCount, got); } finally { - GcsDelete(popts, OUTPUT); + helper.deleteOutput(OUTPUT); } } @@ -231,22 +205,6 @@ public void testCloudWithAPI_NA12877_S1() throws Exception { NA12877_S1_CONTIG, NA12877_S1_READGROUPSET, NA12877_S1_EXPECTED); } - /** - * Make sure we can get to the output. - */ - private void touchOutput(GcsUtil gcsUtil, String outputGcsPath) throws IOException { - try (Writer writer = Channels.newWriter(gcsUtil.create(GcsPath.fromUri(outputGcsPath), "text/plain"), "UTF-8")) { - writer.write("output will go here"); - } - } - private static void GcsDelete(PipelineOptions popts, String gcsPath) throws IOException, GeneralSecurityException { - // boilerplate - GcsPath path = GcsPath.fromUri(gcsPath); - GcsOptions gcsOptions = (GcsOptions)popts.as(GcsOptions.class); - Storage storage = Transport.newStorageClient(gcsOptions).build(); - // do the actual work - storage.objects().delete(path.getBucket(), path.getObject()).execute(); - } } \ No newline at end of file diff --git a/src/test/java/com/google/cloud/genomics/dataflow/pipelines/IntegrationTestHelper.java b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/IntegrationTestHelper.java new file mode 100644 index 0000000..dd5e1c7 --- /dev/null +++ b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/IntegrationTestHelper.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * 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 com.google.cloud.genomics.dataflow.pipelines; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Writer; +import java.nio.channels.Channels; +import java.security.GeneralSecurityException; + +import org.junit.Assert; + +import com.google.api.services.storage.Storage; +import com.google.cloud.dataflow.sdk.options.GcsOptions; +import com.google.cloud.dataflow.sdk.options.PipelineOptionsFactory; +import com.google.cloud.dataflow.sdk.util.GcsUtil; +import com.google.cloud.dataflow.sdk.util.Transport; +import com.google.cloud.dataflow.sdk.util.gcsfs.GcsPath; +import com.google.cloud.genomics.dataflow.utils.GenomicsOptions; + +public class IntegrationTestHelper { + + // Test configuration constants + final String API_KEY = System.getenv("GOOGLE_API_KEY"); + final String TEST_PROJECT = System.getenv("TEST_PROJECT"); + final String TEST_OUTPUT_GCS_FOLDER = System.getenv("TEST_OUTPUT_GCS_FOLDER"); + final String TEST_STAGING_GCS_FOLDER = System.getenv("TEST_STAGING_GCS_FOLDER"); + + // Variant test configuration constants + static final String PLATINUM_GENOMES_DATASET = "3049512673186936334"; + static final String PLATINUM_GENOMES_BRCA1_REFERENCES = "chr17:41196311:41277499"; + static final int PLATINUM_GENOMES_NUMBER_OF_SAMPLES = 17; + + GenomicsOptions popts = PipelineOptionsFactory.create().as(GenomicsOptions.class); + GcsUtil gcsUtil; + + public IntegrationTestHelper() { + Assert.assertNotNull("You must set the GOOGLE_API_KEY environment variable for this test.", API_KEY); + Assert.assertNotNull("You must set the TEST_PROJECT environment variable for this test.", TEST_PROJECT); + Assert.assertNotNull("You must set the TEST_OUTPUT_GCS_FOLDER environment variable for this test.", TEST_OUTPUT_GCS_FOLDER); + Assert.assertNotNull("You must set the TEST_STAGING_GCS_FOLDER environment variable for this test.", TEST_STAGING_GCS_FOLDER); + Assert.assertTrue("TEST_OUTPUT_GCS_FOLDER must end with '/'", TEST_OUTPUT_GCS_FOLDER.endsWith("/")); + Assert.assertTrue("TEST_OUTPUT_GCS_FOLDER must start with 'gs://'", TEST_OUTPUT_GCS_FOLDER.startsWith("gs://")); + Assert.assertTrue("TEST_STAGING_GCS_FOLDER must start with 'gs://'", TEST_STAGING_GCS_FOLDER.startsWith("gs://")); + // we don't care how TEST_STAGING_GCS_FOLDER ends, so no check for it. + + popts.setApiKey(API_KEY); + gcsUtil = new GcsUtil.GcsUtilFactory().create(popts); + } + + /** + * Make sure we can get to the output. + * + * Also write a sentinel value to the file. This protects against the possibility of prior + * test output causing a newly failing test to appear to succeed. + */ + public void touchOutput(String outputPath) throws IOException { + try (Writer writer = Channels.newWriter(gcsUtil.create(GcsPath.fromUri(outputPath), "text/plain"), "UTF-8")) { + writer.write("output will go here"); + } + } + + /** + * Open test output for reading. + */ + public BufferedReader openOutput(String outputPath) throws IOException { + return new BufferedReader(Channels.newReader(gcsUtil.open(GcsPath.fromUri(outputPath)), "UTF-8")); + } + + /** + * Delete test output. + */ + public void deleteOutput(String outputPath) throws IOException, GeneralSecurityException { + // boilerplate + GcsPath path = GcsPath.fromUri(outputPath); + GcsOptions gcsOptions = (GcsOptions)popts.as(GcsOptions.class); + Storage storage = Transport.newStorageClient(gcsOptions).build(); + // do the actual work + storage.objects().delete(path.getBucket(), path.getObject()).execute(); + } + +} diff --git a/src/test/java/com/google/cloud/genomics/dataflow/pipelines/VariantSimilarityITCase.java b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/VariantSimilarityITCase.java new file mode 100644 index 0000000..e0f27c6 --- /dev/null +++ b/src/test/java/com/google/cloud/genomics/dataflow/pipelines/VariantSimilarityITCase.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * 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 com.google.cloud.genomics.dataflow.pipelines; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.List; + +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.api.client.util.Lists; +import com.google.cloud.genomics.dataflow.functions.PCoAnalysis.GraphResult; + +/** + * This integration test will call the Genomics API and write to Cloud Storage. + * + * The following environment variables are required: + * - a Google Cloud API key in GOOGLE_API_KEY, + * - a Google Cloud project name in TEST_PROJECT, + * - a Cloud Storage folder path in TEST_OUTPUT_GCS_FOLDER to store temporary test outputs, + * - a Cloud Storage folder path in TEST_STAGING_GCS_FOLDER to store temporary files, + * + * Cloud Storage folder paths should be of the form "gs://bucket/folder/" + * + * When doing e.g. mvn install, you can skip integration tests using: + * mvn install -DskipITs + * + * To run one test: + * mvn -Dit.test=VariantSimilarityITCase#testLocal verify + * + * See also http://maven.apache.org/surefire/maven-failsafe-plugin/examples/single-test.html + */ +public class VariantSimilarityITCase { + + static final String OUTPUT_SUFFIX = "-00000-of-00001"; + + static String outputPrefix; + static IntegrationTestHelper helper; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + helper = new IntegrationTestHelper(); + outputPrefix = helper.TEST_OUTPUT_GCS_FOLDER + "variantSimilarity"; + } + + @Before + public void setUp() throws Exception { + helper.touchOutput(outputPrefix + OUTPUT_SUFFIX); + } + + @After + public void tearDown() throws Exception { + helper.deleteOutput(outputPrefix + OUTPUT_SUFFIX); + } + + @Test + public void testLocal() throws IOException, GeneralSecurityException { + String[] ARGS = { + "--apiKey=" + helper.API_KEY, + "--references=" + helper.PLATINUM_GENOMES_BRCA1_REFERENCES, + "--datasetId=" + helper.PLATINUM_GENOMES_DATASET, + "--output=" + outputPrefix, + }; + testBase(ARGS); + } + + @Test + public void testCloud() throws IOException, GeneralSecurityException { + String[] ARGS = { + "--apiKey=" + helper.API_KEY, + "--references=" + helper.PLATINUM_GENOMES_BRCA1_REFERENCES, + "--datasetId=" + helper.PLATINUM_GENOMES_DATASET, + "--output=" + outputPrefix, + "--project=" + helper.TEST_PROJECT, + "--numWorkers=1", // Use only a single worker to ensure a single output file. + "--runner=BlockingDataflowPipelineRunner", + "--stagingLocation=" + helper.TEST_STAGING_GCS_FOLDER, + }; + testBase(ARGS); + } + + private void testBase(String[] ARGS) throws IOException, GeneralSecurityException { + // Run the pipeline. + VariantSimilarity.main(ARGS); + + // Download the pipeline results. + BufferedReader reader = helper.openOutput(outputPrefix + OUTPUT_SUFFIX); + List results = Lists.newArrayList(); + for (String line = reader.readLine(); line != null; line = reader.readLine()) { + results.add(GraphResult.fromString(line)); + } + + // Check the pipeline results. + assertEquals(helper.PLATINUM_GENOMES_NUMBER_OF_SAMPLES, results.size()); + + /* TODO place a stable sort on the samples to achieve reproducible results + assertThat(results, + IsIterableContainingInAnyOrder.containsInAnyOrder( + new GraphResult("NA12887", 7.43, -1.7), + new GraphResult("NA12886", -5.29, 0.13), + new GraphResult("NA12885", -5.22, -1.08), + new GraphResult("NA12878", 7.38, 1.69), + new GraphResult("NA12884", -5.34, -0.96), + new GraphResult("NA12883", 7.56, 3.72), + new GraphResult("NA12881", -5.28, 1.05), + new GraphResult("NA12888", 7.46, -2.73), + new GraphResult("NA12889", 7.33, -1.66), + new GraphResult("NA12891", -5.25, 0.87), + new GraphResult("NA12882", -5.22, -1.2), + new GraphResult("NA12892", 7.63, -2.11), + new GraphResult("NA12890", -5.05, 1.6), + new GraphResult("NA12877", -5.19, -0.23), + new GraphResult("NA12893", -5.19, 1.17), + new GraphResult("NA12880", 7.4, 2.73), + new GraphResult("NA12879", -5.27, -1.38))); + */ + } +} + +