{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/171909211","pull_request_review_id":100849167,"id":171909211,"diff_hunk":"@@ -0,0 +1,764 @@\n+package org.broadinstitute.hellbender.tools.funcotator.mafOutput;\n+\n+import htsjdk.variant.variantcontext.Allele;\n+import htsjdk.variant.variantcontext.VariantContext;\n+import htsjdk.variant.vcf.VCFHeader;\n+import htsjdk.variant.vcf.VCFHeaderLine;\n+import org.broadinstitute.hellbender.exceptions.UserException;\n+import org.broadinstitute.hellbender.tools.funcotator.DataSourceFuncotationFactory;\n+import org.broadinstitute.hellbender.tools.funcotator.Funcotation;\n+import org.broadinstitute.hellbender.tools.funcotator.Funcotator;\n+import org.broadinstitute.hellbender.tools.funcotator.OutputRenderer;\n+import org.broadinstitute.hellbender.tools.funcotator.vcfOutput.VcfOutputRenderer;\n+import org.broadinstitute.hellbender.utils.Utils;\n+\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+import java.nio.file.Files;\n+import java.nio.file.Path;\n+import java.text.SimpleDateFormat;\n+import java.util.*;\n+import java.util.stream.Collectors;\n+\n+/**\n+ * A Funcotator output renderer for writing to MAF files.\n+ * Complies with version 2.4 of the MAF standard found here:\n+ * https://wiki.nci.nih.gov/display/TCGA/Mutation+Annotation+Format+%28MAF%29+Specification+-+v2.4\n+ * Created by jonn on 12/5/17.\n+ */\n+public class MafOutputRenderer extends OutputRenderer {\n+\n+    //==================================================================================================================\n+    // Public Static Members:\n+\n+    /**\n+     * Version of the MAF standard that this {@link MafOutputRenderer} writes.\n+     */\n+    public static String VERSION = \"2.4\";\n+\n+    //==================================================================================================================\n+    // Private Static Members:\n+\n+    /**\n+     * The string representing a comment in a MAF file.\n+     */\n+    protected static final String COMMENT_STRING = \"#\";\n+\n+    /**\n+     * Value to insert into columns with unspecified annotations.\n+     */\n+    protected static final String UNKNOWN_VALUE_STRING = \"__UNKNOWN__\";\n+\n+    /**\n+     * Value to insert into unused annotation columns.\n+     */\n+    protected static final String UNUSED_STRING = \"NA\";\n+\n+    /**\n+     * Default set of columns to include in this {@link MafOutputRenderer}.\n+     * Order of the columns is preserved by the {@link LinkedHashMap}, while still being able to access each field via\n+     * the associated key.\n+     */\n+    private static final LinkedHashMap<String, String> defaultMap = new LinkedHashMap<>();\n+\n+    /**\n+     * Map for: outputFieldName -> dataSourceFieldName1, dataSourceFieldName2 ...\n+     *\n+     * This map informs how to fill out outputFields using the input funcotations.\n+     *\n+     * Strings in the value list are in order of priority for use in the outputField.\n+     * That is, if both dataSourceFieldName1 and dataSourceFieldName2 are present as funcotation fields, then only\n+     * dataSourceFieldName1 will be used as the outputField.\n+     */\n+    private static final Map<String, List<String>> outputFieldNameMap = new LinkedHashMap<>();\n+\n+    /**\n+     * Delimiter for fields in the output MAF file.\n+     */\n+    private static final String FIELD_DELIMITER = \"\\t\";\n+\n+    //==================================================================================================================\n+    // Private Members:\n+\n+    /** Flag to see if the header has been written to the output file yet. */\n+    private boolean hasWrittenHeader = false;\n+\n+    /**\n+     * {@link Path} to the resulting MAF output file for this {@link MafOutputRenderer}.\n+     */\n+    private final Path outputFilePath;\n+\n+    /**\n+     * {@link java.io.PrintWriter} to which to write the output MAF file.\n+     */\n+    private PrintWriter printWriter;\n+\n+    /**\n+     * Tool header information to go into the header.\n+     */\n+    private final LinkedHashSet<String> toolHeaderLines;\n+\n+    /**\n+     * Existing header from the input file to preserve in the output.\n+     */\n+    private final VCFHeader inputFileHeader;\n+\n+    /** Override annotation list from the user. */\n+    private final LinkedHashMap<String, String> overrideAnnotations;\n+\n+    //==================================================================================================================\n+    // Constructors:\n+\n+    /**\n+     * Create a {@link MafOutputRenderer}.\n+     * @param outputFilePath {@link Path} to output file (must not be null).\n+     * @param dataSources {@link List} of {@link DataSourceFuncotationFactory} to back our annotations (must not be null).\n+     * @param unaccountedForDefaultAnnotations {@link LinkedHashMap} of default annotations that must be added.\n+     * @param unaccountedForOverrideAnnotations {@link LinkedHashMap} of override annotations that must be added.\n+     */\n+    public MafOutputRenderer(final Path outputFilePath,\n+                             final List<DataSourceFuncotationFactory> dataSources,\n+                             final LinkedHashMap<String, String> unaccountedForDefaultAnnotations,\n+                             final LinkedHashMap<String, String> unaccountedForOverrideAnnotations) {\n+        this(outputFilePath, dataSources, unaccountedForDefaultAnnotations, unaccountedForOverrideAnnotations, new VCFHeader(Collections.emptySet()), new LinkedHashSet<>());\n+    }\n+\n+    /**\n+     * Create a {@link MafOutputRenderer}.\n+     * @param outputFilePath {@link Path} to output file (must not be null).\n+     * @param dataSources {@link List} of {@link DataSourceFuncotationFactory} to back our annotations (must not be null).\n+     * @param unaccountedForDefaultAnnotations {@link LinkedHashMap} of default annotations that must be added.\n+     * @param unaccountedForOverrideAnnotations {@link LinkedHashMap} of override annotations that must be added.\n+     * @param inputFileHeader {@link VCFHeader} of input VCF file to preserve.\n+     * @param toolHeaderLines Lines to add to the header with information about Funcotator.\n+     */\n+    public MafOutputRenderer(final Path outputFilePath,\n+                             final List<DataSourceFuncotationFactory> dataSources,\n+                             final LinkedHashMap<String, String> unaccountedForDefaultAnnotations,\n+                             final LinkedHashMap<String, String> unaccountedForOverrideAnnotations,\n+                             final VCFHeader inputFileHeader,\n+                             final Set<String> toolHeaderLines) {\n+\n+        // Set our internal variables from the input:\n+        this.outputFilePath = outputFilePath;\n+        this.toolHeaderLines = new LinkedHashSet<>(toolHeaderLines);\n+        this.inputFileHeader = inputFileHeader;\n+        dataSourceFactories = dataSources;\n+\n+        // Merge the default annotations into our manualAnnotations:\n+        manualAnnotations = new LinkedHashMap<>();\n+        if ( unaccountedForDefaultAnnotations != null ) {\n+            manualAnnotations.putAll(unaccountedForDefaultAnnotations);\n+        }\n+\n+        // Handle our override annotations a little differently:\n+        this.overrideAnnotations = unaccountedForOverrideAnnotations;\n+\n+        // Fill in our default output map:\n+        initializeDefaultMapWithKeys();\n+\n+        // Fill in our default map for outputField -> funcotation name:\n+        initializeOutputFieldNameMap();\n+\n+        // TODO: Make this FASTER!\n+        // Update our defaultMap with the dataSourceFactories:\n+        for ( final DataSourceFuncotationFactory funcotationFactory : dataSourceFactories ) {\n+            for ( final String field : funcotationFactory.getSupportedFuncotationFields() ) {\n+\n+                // Check if it's in our output map already:\n+                if ( !defaultMap.containsKey(field) ) {\n+                    boolean found = false;\n+\n+                    // Now check our field assignment/translation map:\n+                    for ( final Map.Entry<String, List<String>> entry : outputFieldNameMap.entrySet() ) {\n+                        if ( entry.getValue().contains(field) ) {\n+                            found = true;\n+                            break;\n+                        }\n+                    }\n+                    if ( !found ) {\n+                        defaultMap.put(field, UNKNOWN_VALUE_STRING);\n+                    }\n+                }\n+            }\n+        }\n+\n+        // Update the Default map with manual annotations that we have\n+        // and remove those annotations from the manual map:\n+        // NOTE: We must check the outputFieldNameMap in case we override an aliased output field:\n+        final Iterator<Map.Entry<String, String>> it = manualAnnotations.entrySet().iterator();\n+        while ( it.hasNext() ) {\n+            final Map.Entry<String, String> manualAnnotation = it.next();\n+            if ( defaultMap.containsKey(manualAnnotation.getKey()) ) {\n+                defaultMap.put(manualAnnotation.getKey(), manualAnnotation.getValue());\n+                it.remove();\n+            }\n+            else {\n+                // Check the aliased output fields.\n+                // NOTE: A field may be aliased many times, so we should check ALL fields before\n+                //       removing the iterator and moving to the next value:\n+                boolean isAliasedName = false;\n+                for ( final Map.Entry<String, List<String>> entry : outputFieldNameMap.entrySet() ) {\n+                    if ( entry.getValue().contains(manualAnnotation.getKey())) {\n+                        isAliasedName = true;\n+                        defaultMap.put( entry.getKey(), manualAnnotation.getValue() );\n+                    }\n+                }\n+                if (isAliasedName) {\n+                    it.remove();\n+                }\n+            }\n+        }\n+\n+        // Set values for unused fields:\n+        defaultMap.put(\"Score\", UNUSED_STRING);\n+        defaultMap.put(\"BAM_File\", UNUSED_STRING);\n+\n+        // Cache the manual annotation string so we can pass it easily into any Funcotations:\n+        manualAnnotationSerializedString = (manualAnnotations.size() != 0 ? FIELD_DELIMITER + String.join( FIELD_DELIMITER, manualAnnotations.values() ) + FIELD_DELIMITER : \"\");\n+    }\n+\n+    //==================================================================================================================\n+    // Override Methods:\n+\n+    @Override\n+    public void open() {\n+        try {\n+            printWriter = new PrintWriter(Files.newOutputStream(outputFilePath));\n+        }\n+        catch (final IOException ex) {\n+            throw new UserException(\"Error opening output file path: \" + outputFilePath.toUri().toString(), ex);\n+        }\n+    }\n+\n+    @Override\n+    public void close() {\n+        printWriter.flush();\n+        printWriter.close();\n+    }\n+\n+    @Override\n+    public void write(final VariantContext variant, final List<Funcotation> funcotations) {\n+\n+        // Loop through each alt allele in our variant:\n+        for ( final Allele altAllele : variant.getAlternateAlleles() ) {\n+\n+            // Create our output maps:\n+            final LinkedHashMap<String, Object> outputMap = new LinkedHashMap<>(defaultMap);\n+            final LinkedHashMap<String, Object> extraFieldOutputMap = new LinkedHashMap<>();\n+\n+            // Get our funcotations for this allele and add them to the output maps:\n+            for ( final Funcotation funcotation : funcotations ) {\n+                if ( funcotation.getAltAllele().equals(altAllele) ) {\n+                    // Add all the fields from the other funcotations into the extra field output:\n+                    for ( final String field : funcotation.getFieldNames() ) {\n+                        setField(extraFieldOutputMap, field, funcotation.getField(field));\n+                    }\n+                }\n+            }\n+\n+            // Now add in our annotation overrides so they can be aliased correctly with the outputFieldNameMap:\n+            extraFieldOutputMap.putAll(overrideAnnotations);\n+\n+            // Go through all output fields and see if any of the names in the value list are in our extraFieldOutputMap.\n+            // For any that match, we remove them from our extraFieldOutputMap and add them to the outputMap with the\n+            // correct key.\n+            for ( final Map.Entry<String, List<String>> entry : outputFieldNameMap.entrySet() ) {\n+                for ( final String fieldName : entry.getValue() ) {\n+                    if ( extraFieldOutputMap.containsKey(fieldName) ) {\n+                        outputMap.put(entry.getKey(), extraFieldOutputMap.remove(fieldName));\n+                        break;\n+                    }\n+                }\n+            }\n+\n+            // Merge our output maps together:\n+            outputMap.putAll(extraFieldOutputMap);\n+\n+            // Now translate fields to the field names that MAF likes:\n+            final LinkedHashMap<String, String> mafCompliantOutputMap = replaceFuncotationValuesWithMafCompliantValues(outputMap);\n+\n+            // Write our header if we have to:\n+            if ( ! hasWrittenHeader ) {\n+                writeHeader(mafCompliantOutputMap);\n+            }\n+\n+            // Write the output (with manual annotations at the end):\n+            writeLine(\n+                    mafCompliantOutputMap.values().stream().collect(Collectors.joining(FIELD_DELIMITER))\n+                    + manualAnnotationSerializedString\n+            );\n+        }\n+    }\n+\n+\n+    //==================================================================================================================\n+    // Static Methods:\n+\n+    //==================================================================================================================\n+    // Instance Methods:\n+\n+    /**\n+     * Ensures each value in the given {@code outputMap} is compliant with MAF-expected values.\n+     * @param outputMap The {@link Map} of output field -> values to be checked for MAF compliance.\n+     * @return A {@link LinkedHashMap} of output field strings -> values to be written to the MAF file.\n+     */\n+    private LinkedHashMap<String, String> replaceFuncotationValuesWithMafCompliantValues(final Map<String, Object> outputMap ) {\n+\n+        final LinkedHashMap<String, String> finalOutMap = new LinkedHashMap<>(outputMap.size());\n+\n+        // Massage individual Key/Value pairs:\n+        for ( final String key : outputMap.keySet() ) {\n+            finalOutMap.put(key, mafTransform(key, outputMap.get(key).toString()) );\n+        }\n+\n+        // Massage the OtherTranscripts field:\n+        finalOutMap.put(\"Other_Transcripts\", finalOutMap.get(\"Other_Transcripts\").replaceAll(VcfOutputRenderer.OTHER_TRANSCRIPT_DELIMITER, \"|\"));\n+\n+        // Massage the start/end/alleles in the case of INDELs\n+        // (Because MAF has different conventions from VCF for start/end positions of INDELs)\n+        if ( finalOutMap.get(\"Variant_Type\").equals(\"INS\") || finalOutMap.get(\"Variant_Type\").equals(\"DEL\") ) {\n+\n+            final int refAlleleLength = finalOutMap.get(\"Reference_Allele\").length();\n+            final int altAlleleLength = finalOutMap.get(\"Tumor_Seq_Allele2\").length();\n+\n+            // TODO: port these changes to GencodeFuncotationFactory (issue: https://github.com/broadinstitute/gatk/issues/4378)\n+            // Check to see if it's an insertion:\n+            if ( refAlleleLength < altAlleleLength ) {\n+                // We must:\n+                //    Remove the first N bases from the ALT_allele where N = length(ref_allele)\n+                //    Replace the ref_allele with \"-\"\n+                //    Replace the Tumor_Seq_Allele1 with \"-\"\n+                //    Set the End_Position to be Start_Position + 1 (All Insertions should have length 1 to represent the bases between which the insertion occurs).\n+                finalOutMap.put(\"Tumor_Seq_Allele2\", finalOutMap.get(\"Tumor_Seq_Allele2\").substring(refAlleleLength));\n+                finalOutMap.put(\"Reference_Allele\", \"-\");\n+                finalOutMap.put(\"Tumor_Seq_Allele1\", \"-\");\n+                finalOutMap.put(\"End_Position\", String.valueOf(Integer.valueOf(finalOutMap.get(\"Start_Position\")) + 1));\n+            }\n+            // Check to see if it's a deletion:\n+            else if ( refAlleleLength > altAlleleLength ) {\n+                // We must:\n+                //    Remove the first N bases from the REF_allele where N = length(alt_allele)\n+                //    Remove the first N bases from the Tumor_Seq_Allele1\n+                //    Replace the alt_allele with \"-\"\n+                //    Increment the Start_Position by 1 (start position should be inclusive of the first base deleted)\n+                //    Increment the End_Position by M-1 where M = length(ref_allele) (end position should be inclusive of the last base deleted)\n+                finalOutMap.put(\"Reference_Allele\", finalOutMap.get(\"Reference_Allele\").substring(altAlleleLength));\n+                finalOutMap.put(\"Tumor_Seq_Allele1\", finalOutMap.get(\"Tumor_Seq_Allele1\").substring(altAlleleLength));\n+                finalOutMap.put(\"Tumor_Seq_Allele2\", \"-\");\n+                finalOutMap.put(\"Start_Position\", String.valueOf(Integer.valueOf(finalOutMap.get(\"Start_Position\")) + 1));\n+                finalOutMap.put(\"End_Position\", String.valueOf(Integer.valueOf(finalOutMap.get(\"End_Position\")) + refAlleleLength - 1));\n+            }\n+        }\n+\n+        return finalOutMap;\n+    }\n+\n+    /**\n+     * Transforms a given {@code value} to the equivalent MAF-valid value based on the given {@code key}.\n+     * @param key The {@code key} off of which to base the transformation.  This key is the final (transformed) key for output (i.e. the column name in the MAF file).\n+     * @param value The {@code value} to transform into a MAF-valid value.\n+     * @return The MAF-valid equivalent of the given {@code value}.\n+     */\n+    private String mafTransform(final String key, final String value) {\n+        if ( key.equals(\"Variant_Classification\") ) {\n+            switch(value) {\n+                case \"IN_FRAME_DEL\":             return \"In_Frame_Del\";\n+                case \"IN_FRAME_INS\":             return \"In_Frame_Ins\";\n+                case \"FRAME_SHIFT_INS\":          return \"Frame_Shift_Ins\";\n+                case \"FRAME_SHIFT_DEL\":          return \"Frame_Shift_Del\";\n+                case \"MISSENSE\":                 return \"Missense_Mutation\";\n+                case \"NONSENSE\":                 return \"Nonsense_Mutation\";\n+                case \"SILENT\":                   return \"Silent\";\n+                case \"SPLICE_SITE\":              return \"Splice_Site\";\n+                case \"DE_NOVO_START_IN_FRAME\":\n+                case \"DE_NOVO_START_OUT_FRAME\":\n+                case \"START_CODON_SNP\":\n+                case \"START_CODON_INS\":\n+                case \"START_CODON_DEL\":          return \"Translation_Start_Site\";\n+                case \"NONSTOP\":                  return \"Nonstop_Mutation\";\n+                case \"FIVE_PRIME_UTR\":           return \"5'UTR\";\n+                case \"THREE_PRIME_UTR\":          return \"3'UTR\";\n+                case \"FIVE_PRIME_FLANK\":         return \"5'Flank\";\n+                case \"INTRON\":                   return \"Intron\";\n+                case \"LINCRNA\":                  return \"RNA\";\n+            }\n+        }\n+        else if ( key.equals(\"Chromosome\") ) {\n+            if ( value.equals(\"chrM\") ) {\n+                return \"MT\";\n+            }\n+            else if (value.startsWith(\"chr\")) {\n+                return value.substring(3);\n+            }\n+        }\n+        else if ( key.equals(\"Other_Transcripts\") ) {\n+            return value.replaceAll(\"IN_FRAME_DEL\", \"In_Frame_Del\")\n+                .replaceAll( \"IN_FRAME_DEL\", \"In_Frame_Del\" )\n+                .replaceAll( \"IN_FRAME_INS\", \"In_Frame_Ins\" )\n+                .replaceAll( \"FRAME_SHIFT_INS\", \"Frame_Shift_Ins\" )\n+                .replaceAll( \"FRAME_SHIFT_DEL\", \"Frame_Shift_Del\" )\n+                .replaceAll( \"MISSENSE\", \"Missense_Mutation\" )\n+                .replaceAll( \"NONSENSE\", \"Nonsense_Mutation\" )\n+                .replaceAll( \"SILENT\", \"Silent\" )\n+                .replaceAll( \"SPLICE_SITE\", \"Splice_Site\" )\n+                .replaceAll( \"DE_NOVO_START_IN_FRAME\", \"Translation_Start_Site\" )\n+                .replaceAll( \"DE_NOVO_START_OUT_FRAME\", \"Translation_Start_Site\" )\n+                .replaceAll( \"START_CODON_SNP\", \"Translation_Start_Site\" )\n+                .replaceAll( \"START_CODON_INS\", \"Translation_Start_Site\" )\n+                .replaceAll( \"START_CODON_DEL\", \"Translation_Start_Site\" )\n+                .replaceAll( \"NONSTOP\", \"Nonstop_Mutation\" )\n+                .replaceAll( \"FIVE_PRIME_UTR\", \"5'UTR\" )\n+                .replaceAll( \"THREE_PRIME_UTR\", \"3'UTR\" )\n+                .replaceAll( \"FIVE_PRIME_FLANK\", \"5'Flank\" )\n+                .replaceAll( \"INTRON\", \"Intron\" )\n+                .replaceAll( \"LINCRNA\", \"RNA\" );\n+        }\n+\n+        return value;\n+     }\n+\n+    /**\n+     * Set the field in the given {@code outputMap} specified by the given {@code key} to the given {@code value}.\n+     * Checks the given {@code key} to see if the given {@code value} must be transformed to be a valid MAF field.\n+     * Will only set this field if the given {@code value} is not {@code null}.\n+     * @param outputMap {@link Map} of {@link String} to {@link Object} to hold output annotations.  Must not be {@code null}.\n+     * @param key {@link String} key to add to the output map.  Must not be {@code null}.\n+     * @param value {@link Object} value for the output map.\n+     */\n+    private void setField(final Map<String, Object> outputMap, final String key, final Object value) {\n+        Utils.nonNull(outputMap);\n+        Utils.nonNull(key);\n+\n+        if ( value != null ) {\n+            outputMap.put(key, value);\n+        }\n+        else {\n+            outputMap.put(key, UNKNOWN_VALUE_STRING);\n+        }\n+    }\n+\n+    /**\n+     * Write the given line to the {@link #printWriter}.\n+     * @param line The {@link String} to write as a line to the {@link #printWriter}.\n+     */\n+    private void writeLine(final String line) {\n+        printWriter.write(line + System.lineSeparator());\n+    }\n+\n+    /**\n+     * Write the header to the output file.\n+     * @param outputMap A populated output map from which to derive the header columns.\n+     */\n+    protected void writeHeader(final LinkedHashMap<String, String> outputMap) {\n+        // Write out version:\n+        writeLine(COMMENT_STRING + \"version \" + VERSION);\n+        writeLine(COMMENT_STRING + COMMENT_STRING);\n+\n+        // Write previous header info:\n+        for ( final VCFHeaderLine line : inputFileHeader.getMetaDataInInputOrder() ) {\n+            printWriter.write(COMMENT_STRING);\n+            printWriter.write(COMMENT_STRING);\n+            printWriter.write(\" \");\n+            writeLine( line.toString() );\n+        }\n+\n+        // Write any default tool header lines:\n+        for ( final String line : toolHeaderLines ) {\n+            printWriter.write(COMMENT_STRING);\n+            printWriter.write(COMMENT_STRING);\n+            printWriter.write(\" \");\n+            writeLine(line);\n+        }\n+\n+        // Write tool name and the data sources with versions:\n+        printWriter.write(COMMENT_STRING);\n+        printWriter.write(COMMENT_STRING);\n+        printWriter.write(\" \");\n+        printWriter.write(\" Funcotator \");\n+        printWriter.write(Funcotator.VERSION);\n+        printWriter.write(\" | Date \");\n+        printWriter.write(new SimpleDateFormat(\"yyyymmdd'T'hhmmss\").format(new Date()));\n+        printWriter.write(getDataSourceInfoString());\n+        writeLine(\"\");\n+\n+        // Write the column headers for our output set and our manual annotations:\n+        printWriter.write( outputMap.keySet().stream().collect(Collectors.joining(FIELD_DELIMITER)) );\n+        writeLine(FIELD_DELIMITER + manualAnnotations.keySet().stream().collect(Collectors.joining(FIELD_DELIMITER)));\n+\n+        // Make sure we keep track of the fact that we've now written the header:\n+        hasWrittenHeader = true;\n+    }\n+\n+    /**\n+     * Initializes {@link MafOutputRenderer#defaultMap} with the default keys for the columns in a MAF file.\n+     */\n+    protected void initializeDefaultMapWithKeys() {","path":"src/main/java/org/broadinstitute/hellbender/tools/funcotator/mafOutput/MafOutputRenderer.java","position":496,"original_position":496,"commit_id":"be54487cca04764e22d0ce3bceadb68001ca724b","original_commit_id":"be54487cca04764e22d0ce3bceadb68001ca724b","user":{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false},"body":"Yeah - the plan is to have a config file for funcotator that can have all these fields in it, but there needs to be a hard-coded default in the case of no config.","created_at":"2018-03-02T17:21:46Z","updated_at":"2018-03-02T17:21:47Z","html_url":"https://github.com/broadinstitute/gatk/pull/4472#discussion_r171909211","pull_request_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/171909211"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/4472#discussion_r171909211"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472"}},"in_reply_to_id":171442713},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472","id":172008675,"html_url":"https://github.com/broadinstitute/gatk/pull/4472","diff_url":"https://github.com/broadinstitute/gatk/pull/4472.diff","patch_url":"https://github.com/broadinstitute/gatk/pull/4472.patch","issue_url":"https://api.github.com/repos/broadinstitute/gatk/issues/4472","number":4472,"state":"open","locked":false,"title":"Adding in a prototype MafOutputRenderer for Funcotator (and many fixes)","user":{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false},"body":"Added in argument for MAF out.\r\nAdded more \"required\" MAF fields.\r\nAdded Funcotation::getDataSourceName\r\nAdded contig name overrides for hg19 VS B37\r\nAdded in code to convert VCF INDEL positions to MAF INDEL positions.\r\nAdded start/stop positions for IGRs.\r\nAdded argument to ignore filtered variants at the front of processing to save time.\r\nAdded a script to fully retrieve the COSMIC data sources.\r\n\r\nFixed how the MafOutputRenderer handles mapping fields to values.\r\nFixed a bug in LocatableXsv and COSMIC parsers (was missing name and\r\n    version).\r\nIn Gencode: Now TumorSeqAllele1 is the refAllele, not the AltAllele.\r\nFixed some problems with VCF output.\r\nUpdated VCF outputs to have better header info.\r\nRefactored header output for OutputRenderers.\r\nChanged the logic for creating alt protein sequences.\r\nFixed a bug in the LocatableXsvFuncotationFactory that caused annotations to be incorrectly associated with a factory.\r\nFixed several bugs in the GencodeFuncotationFactory.\r\nFixed bugx in the handling of UTR variants.\r\nFixed the Transcript Selection Mode ordering.\r\nFixed an issue with splice sites.\r\n\r\nMinor speed fix to GencodeFuncotationFactory.\r\n\r\nNow CosmicFuncotationFactory opens the database in read-only mode.\r\n\r\nBugfix - now LocatableXsvFuncotationFactories use overrides.\r\n\r\nNow the reference should properly align with ALL indels regardless of\r\nlength.\r\n\r\nReferenceContext now always rendered on + strand.\r\n\r\nNow will create funcotations for transcripts without fasta sequences.\r\n\r\nMinor changes to FuncotatorIntegrationTest.\r\n\r\n- Added in more integration test files.  These are as yet unused - must\r\nrefactor the files themselves to actually reflect what should be correct\r\nas far as produced funcotations.\r\n\r\n- Updated LocatableXsvFuncotationFactoryUnitTest.java and SimpleKeyXsvFuncotationFactoryUnitTest.java\r\nto reflect the change to funcotation factories to always produce the\r\nexpected funcotations (rather than only producing funcotations when\r\n    there are data that match the target variant).\r\n\r\nFixed an issue with the new VariantClassification code.\r\n\r\nFixed issue #4410\r\n\r\nFixed #4022\r\n\r\nFixed #4420\r\n\r\nFixed #3922","created_at":"2018-02-28T16:43:37Z","updated_at":"2018-03-02T17:21:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3b5077b365caf58bd908b89ba6fc35c26cbc3cbf","assignee":{"login":"LeeTL1220","id":2152339,"avatar_url":"https://avatars0.githubusercontent.com/u/2152339?v=4","gravatar_id":"","url":"https://api.github.com/users/LeeTL1220","html_url":"https://github.com/LeeTL1220","followers_url":"https://api.github.com/users/LeeTL1220/followers","following_url":"https://api.github.com/users/LeeTL1220/following{/other_user}","gists_url":"https://api.github.com/users/LeeTL1220/gists{/gist_id}","starred_url":"https://api.github.com/users/LeeTL1220/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LeeTL1220/subscriptions","organizations_url":"https://api.github.com/users/LeeTL1220/orgs","repos_url":"https://api.github.com/users/LeeTL1220/repos","events_url":"https://api.github.com/users/LeeTL1220/events{/privacy}","received_events_url":"https://api.github.com/users/LeeTL1220/received_events","type":"User","site_admin":false},"assignees":[{"login":"LeeTL1220","id":2152339,"avatar_url":"https://avatars0.githubusercontent.com/u/2152339?v=4","gravatar_id":"","url":"https://api.github.com/users/LeeTL1220","html_url":"https://github.com/LeeTL1220","followers_url":"https://api.github.com/users/LeeTL1220/followers","following_url":"https://api.github.com/users/LeeTL1220/following{/other_user}","gists_url":"https://api.github.com/users/LeeTL1220/gists{/gist_id}","starred_url":"https://api.github.com/users/LeeTL1220/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LeeTL1220/subscriptions","organizations_url":"https://api.github.com/users/LeeTL1220/orgs","repos_url":"https://api.github.com/users/LeeTL1220/repos","events_url":"https://api.github.com/users/LeeTL1220/events{/privacy}","received_events_url":"https://api.github.com/users/LeeTL1220/received_events","type":"User","site_admin":false},{"login":"lbergelson","id":4700332,"avatar_url":"https://avatars3.githubusercontent.com/u/4700332?v=4","gravatar_id":"","url":"https://api.github.com/users/lbergelson","html_url":"https://github.com/lbergelson","followers_url":"https://api.github.com/users/lbergelson/followers","following_url":"https://api.github.com/users/lbergelson/following{/other_user}","gists_url":"https://api.github.com/users/lbergelson/gists{/gist_id}","starred_url":"https://api.github.com/users/lbergelson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lbergelson/subscriptions","organizations_url":"https://api.github.com/users/lbergelson/orgs","repos_url":"https://api.github.com/users/lbergelson/repos","events_url":"https://api.github.com/users/lbergelson/events{/privacy}","received_events_url":"https://api.github.com/users/lbergelson/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"lbergelson","id":4700332,"avatar_url":"https://avatars3.githubusercontent.com/u/4700332?v=4","gravatar_id":"","url":"https://api.github.com/users/lbergelson","html_url":"https://github.com/lbergelson","followers_url":"https://api.github.com/users/lbergelson/followers","following_url":"https://api.github.com/users/lbergelson/following{/other_user}","gists_url":"https://api.github.com/users/lbergelson/gists{/gist_id}","starred_url":"https://api.github.com/users/lbergelson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lbergelson/subscriptions","organizations_url":"https://api.github.com/users/lbergelson/orgs","repos_url":"https://api.github.com/users/lbergelson/repos","events_url":"https://api.github.com/users/lbergelson/events{/privacy}","received_events_url":"https://api.github.com/users/lbergelson/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":649053904,"url":"https://api.github.com/repos/broadinstitute/gatk/labels/Funcotator","name":"Funcotator","color":"0e8a16","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/issues/4472/comments","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/be54487cca04764e22d0ce3bceadb68001ca724b","head":{"label":"broadinstitute:jts_funcotator_maf_output_renderer_3922","ref":"jts_funcotator_maf_output_renderer_3922","sha":"be54487cca04764e22d0ce3bceadb68001ca724b","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"Official code repository for GATK versions 4 and up","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2018-03-02T02:53:09Z","pushed_at":"2018-03-02T16:59:10Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"https://software.broadinstitute.org/gatk","size":211647,"stargazers_count":345,"watchers_count":345,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":131,"mirror_url":null,"archived":false,"open_issues_count":836,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":131,"open_issues":836,"watchers":345,"default_branch":"master"}},"base":{"label":"broadinstitute:master","ref":"master","sha":"63f6f20ec0dfb78ec1f3676df7091abc3770f949","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"Official code repository for GATK versions 4 and up","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2018-03-02T02:53:09Z","pushed_at":"2018-03-02T16:59:10Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"https://software.broadinstitute.org/gatk","size":211647,"stargazers_count":345,"watchers_count":345,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":131,"mirror_url":null,"archived":false,"open_issues_count":836,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":131,"open_issues":836,"watchers":345,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/4472"},"issue":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/4472"},"comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/4472/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/4472/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/gatk/statuses/be54487cca04764e22d0ce3bceadb68001ca724b"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"jonn-smith"}}