<commit_before>/*
 * The MIT License
 *
 * Copyright (c) 2009 The Broad Institute
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package picard.sam;

import htsjdk.samtools.BAMRecordCodec;
import htsjdk.samtools.SAMFileHeader;
import htsjdk.samtools.SAMFileHeader.SortOrder;
import htsjdk.samtools.SAMFileWriter;
import htsjdk.samtools.SAMFileWriterFactory;
import htsjdk.samtools.SAMReadGroupRecord;
import htsjdk.samtools.SAMRecord;
import htsjdk.samtools.SAMRecordQueryNameComparator;
import htsjdk.samtools.SAMTag;
import htsjdk.samtools.SamReader;
import htsjdk.samtools.SamReaderFactory;
import htsjdk.samtools.ValidationStringency;
import htsjdk.samtools.filter.FilteringSamIterator;
import htsjdk.samtools.filter.SamRecordFilter;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.FastqQualityFormat;
import htsjdk.samtools.util.IOUtil;
import htsjdk.samtools.util.Log;
import htsjdk.samtools.util.PeekableIterator;
import htsjdk.samtools.util.ProgressLogger;
import htsjdk.samtools.util.QualityEncodingDetector;
import htsjdk.samtools.util.SolexaQualityConverter;
import htsjdk.samtools.util.SortingCollection;
import picard.PicardException;
import picard.cmdline.CommandLineProgram;
import picard.cmdline.CommandLineProgramProperties;
import picard.cmdline.Option;
import picard.cmdline.StandardOptionDefinitions;
import picard.cmdline.programgroups.SamOrBam;
import picard.util.TabbedTextFileWithHeaderParser;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Reverts a SAM file by optionally restoring original quality scores and by removing
 * all alignment information.
 */
@CommandLineProgramProperties(
        usage = RevertSam.USAGE_SUMMARY + RevertSam.USAGE_DETAILS,
        usageShort = RevertSam.USAGE_SUMMARY,
        programGroup = SamOrBam.class
)
public class RevertSam extends CommandLineProgram {
    static final String USAGE_SUMMARY ="Reverts SAM or BAM files to a previous state.  ";
    static final String USAGE_DETAILS ="This tool removes or restores certain properties of the SAM records, including alignment " +
            "information, which can be used to produce an unmapped BAM (uBAM) from a previously aligned BAM. It is also capable of " +
            "restoring the original quality scores of a BAM file that has already undergone base quality score recalibration (BQSR) if the" +
            "original qualities were retained." +
            "<h4>Example with single output:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     O=reverted.bam" +
            "</pre>" +
            "Output format is BAM by default, or SAM or CRAM if the input path ends with '.sam' or '.cram', respectively." +
            "<h4>Example outputting by read group with output map:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     OUTPUT_BY_READGROUP=true \\<br />" +
            "     OUTPUT_MAP=reverted_bam_paths.tsv" +
            "</pre>" +
            "Will output a BAM/SAM file per read group. By default, all outputs will be in BAM format. " +
            "However, a SAM file will be produced instead for any read group mapped in OUTPUT_MAP to a path ending with '.sam'. " +
            "A CRAM file will be produced for any read group mapped to a path ending with '.cram'. " +
            "<h4>Example outputting by read group without output map:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     OUTPUT_BY_READGROUP=true \\<br />" +
            "     O=/write/reverted/read/group/bams/in/this/dir" +
            "</pre>" +
            "Will output a BAM/SAM file per read group. By default, all outputs will be in BAM format. " +
            "However, outputs will be in SAM format if the input path ends with '.sam', or CRAM format if it ends with '.cram'." +
            " This behaviour can be overriden with OUTPUT_BY_READGROUP_FILE_FORMAT option."+
            "<hr />";
    @Option(shortName = StandardOptionDefinitions.INPUT_SHORT_NAME, doc = "The input SAM/BAM file to revert the state of.")
    public File INPUT;

    @Option(mutex = {"OUTPUT_MAP"}, shortName = StandardOptionDefinitions.OUTPUT_SHORT_NAME, doc = "The output SAM/BAM file to create, or an output directory if OUTPUT_BY_READGROUP is true.")
    public File OUTPUT;
    
    @Option(mutex = {"OUTPUT"}, shortName = "OM", doc = "Tab separated file with two columns, READ_GROUP_ID and OUTPUT, providing file mapping only used if OUTPUT_BY_READGROUP is true.")
    public File OUTPUT_MAP;

    @Option(shortName = "OBR", doc = "When true, outputs each read group in a separate file.")
    public boolean OUTPUT_BY_READGROUP = false;

    public static enum FileType {sam, bam, cram,dynamic}
    @Option(shortName = "OBRFF", doc = "When using OUTPUT_BY_READGROUP, the output file format can be set to a certain format." )
    public FileType  OUTPUT_BY_READGROUP_FILE_FORMAT=FileType.dynamic;

    @Option(shortName = "SO", doc = "The sort order to create the reverted output file with.")<commit_msg>Add a doc note to change VALIDATION_STRINGENCY if validation error<commit_after>/*
 * The MIT License
 *
 * Copyright (c) 2009 The Broad Institute
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package picard.sam;

import htsjdk.samtools.BAMRecordCodec;
import htsjdk.samtools.SAMFileHeader;
import htsjdk.samtools.SAMFileHeader.SortOrder;
import htsjdk.samtools.SAMFileWriter;
import htsjdk.samtools.SAMFileWriterFactory;
import htsjdk.samtools.SAMReadGroupRecord;
import htsjdk.samtools.SAMRecord;
import htsjdk.samtools.SAMRecordQueryNameComparator;
import htsjdk.samtools.SAMTag;
import htsjdk.samtools.SamReader;
import htsjdk.samtools.SamReaderFactory;
import htsjdk.samtools.ValidationStringency;
import htsjdk.samtools.filter.FilteringSamIterator;
import htsjdk.samtools.filter.SamRecordFilter;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.FastqQualityFormat;
import htsjdk.samtools.util.IOUtil;
import htsjdk.samtools.util.Log;
import htsjdk.samtools.util.PeekableIterator;
import htsjdk.samtools.util.ProgressLogger;
import htsjdk.samtools.util.QualityEncodingDetector;
import htsjdk.samtools.util.SolexaQualityConverter;
import htsjdk.samtools.util.SortingCollection;
import picard.PicardException;
import picard.cmdline.CommandLineProgram;
import picard.cmdline.CommandLineProgramProperties;
import picard.cmdline.Option;
import picard.cmdline.StandardOptionDefinitions;
import picard.cmdline.programgroups.SamOrBam;
import picard.util.TabbedTextFileWithHeaderParser;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Reverts a SAM file by optionally restoring original quality scores and by removing
 * all alignment information.
 */
@CommandLineProgramProperties(
        usage = RevertSam.USAGE_SUMMARY + RevertSam.USAGE_DETAILS,
        usageShort = RevertSam.USAGE_SUMMARY,
        programGroup = SamOrBam.class
)
public class RevertSam extends CommandLineProgram {
    static final String USAGE_SUMMARY ="Reverts SAM or BAM files to a previous state.  ";
    static final String USAGE_DETAILS ="This tool removes or restores certain properties of the SAM records, including alignment " +
            "information, which can be used to produce an unmapped BAM (uBAM) from a previously aligned BAM. It is also capable of " +
            "restoring the original quality scores of a BAM file that has already undergone base quality score recalibration (BQSR) if the" +
            "original qualities were retained." +
            "<h4>Example with single output:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     O=reverted.bam" +
            "</pre>" +
            "Output format is BAM by default, or SAM or CRAM if the input path ends with '.sam' or '.cram', respectively." +
            "<h4>Example outputting by read group with output map:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     OUTPUT_BY_READGROUP=true \\<br />" +
            "     OUTPUT_MAP=reverted_bam_paths.tsv" +
            "</pre>" +
            "Will output a BAM/SAM file per read group. By default, all outputs will be in BAM format. " +
            "However, a SAM file will be produced instead for any read group mapped in OUTPUT_MAP to a path ending with '.sam'. " +
            "A CRAM file will be produced for any read group mapped to a path ending with '.cram'. " +
            "<h4>Example outputting by read group without output map:</h4>" +
            "<pre>" +
            "java -jar picard.jar RevertSam \\<br />" +
            "     I=input.bam \\<br />" +
            "     OUTPUT_BY_READGROUP=true \\<br />" +
            "     O=/write/reverted/read/group/bams/in/this/dir" +
            "</pre>" +
            "Will output a BAM/SAM file per read group. By default, all outputs will be in BAM format. " +
            "However, outputs will be in SAM format if the input path ends with '.sam', or CRAM format if it ends with '.cram'." +
            " This behaviour can be overriden with OUTPUT_BY_READGROUP_FILE_FORMAT option."+
            "<p>Note: If the program fails due to a SAM validation error, consider setting the VALIDATION_STRINGENCY option to " +
            "LENIENT or SILENT if the failures are expected to be obviated by the reversion process " +
            "(e.g. invalid alignment information will be obviated when the REMOVE_ALIGNMENT_INFORMATION option is used).</p>" +
            "<hr />";
    @Option(shortName = StandardOptionDefinitions.INPUT_SHORT_NAME, doc = "The input SAM/BAM file to revert the state of.")
    public File INPUT;

    @Option(mutex = {"OUTPUT_MAP"}, shortName = StandardOptionDefinitions.OUTPUT_SHORT_NAME, doc = "The output SAM/BAM file to create, or an output directory if OUTPUT_BY_READGROUP is true.")
    public File OUTPUT;
    
    @Option(mutex = {"OUTPUT"}, shortName = "OM", doc = "Tab separated file with two columns, READ_GROUP_ID and OUTPUT, providing file mapping only used if OUTPUT_BY_READGROUP is true.")
    public File OUTPUT_MAP;

    @Option(shortName = "OBR", doc = "When true, outputs each read group in a separate file.")
    public boolean OUTPUT_BY_READGROUP = false;

    public static enum FileType {sam, bam, cram,dynamic}
    @Option(shortName = "OBRFF", doc = "When using OUTPUT_BY_READGROUP, the output file format can be set to a certain format." )
    public FileType  OUTPUT_BY_READGROUP_FILE_FORMAT=FileType.dynamic;

    @Option(shortName = "SO", doc = "The sort order to create the reverted output file with.")
{'fraction_non_alphanumeric': 0.08652981720107882, 'fraction_numerical': 0.0014983518130056938, 'mean_word_length': 3.388231426692965, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5615184', 'n_tokens_mistral': 3941, 'n_tokens_neox': 3834, 'n_words': 1363}